diff --git a/.gitignore b/.gitignore index 8339fd61d3..5a9d62efd4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -# Add no patterns to .hgignore except for files generated by the build. +# Add no patterns to .gitignore except for files generated by the build. last-change diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 2b00ddba0d..0000000000 --- a/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at https://tip.golang.org/AUTHORS. diff --git a/CONTRIBUTORS b/CONTRIBUTORS deleted file mode 100644 index 1fbd3e976f..0000000000 --- a/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/LICENSE b/LICENSE index 6a66aea5ea..2a7cf70da6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index c9d6fecd1e..f69c623ff8 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,18 @@ # Go Cryptography -This repository holds supplementary Go cryptography libraries. +[![Go Reference](https://pkg.go.dev/badge/golang.org/x/crypto.svg)](https://pkg.go.dev/golang.org/x/crypto) -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You -can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`. +This repository holds supplementary Go cryptography packages. ## Report Issues / Send Patches This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/crypto. The main issue tracker for the crypto repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the +https://go.dev/issues. Prefix your issue with "x/crypto:" in the subject line, so it is easy to find. Note that contributions to the cryptography package receive additional scrutiny diff --git a/acme/acme.go b/acme/acme.go index fa365b7b6a..7a51284f91 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -3,14 +3,20 @@ // license that can be found in the LICENSE file. // Package acme provides an implementation of the -// Automatic Certificate Management Environment (ACME) spec. -// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details. +// Automatic Certificate Management Environment (ACME) spec, +// most famously used by Let's Encrypt. +// +// The initial implementation of this package was based on an early version +// of the spec. The current implementation supports only the modern +// RFC 8555 but some of the old API surface remains for compatibility. +// While code using the old API will still compile, it will return an error. +// Note the deprecation comments to update your code. +// +// See https://tools.ietf.org/html/rfc8555 for the spec. // // Most common scenarios will want to use autocert subdirectory instead, // which provides automatic access to certificates from Let's Encrypt // and any other ACME-based CA. -// -// This package is a work in progress and makes no API stability promises. package acme import ( @@ -25,14 +31,11 @@ import ( "crypto/x509/pkix" "encoding/asn1" "encoding/base64" - "encoding/hex" "encoding/json" - "encoding/pem" "errors" "fmt" - "io" - "io/ioutil" "math/big" + "net" "net/http" "strings" "sync" @@ -41,7 +44,7 @@ import ( const ( // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. - LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" + LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory" // ALPNProto is the ALPN protocol name used by a CA server when validating // tls-alpn-01 challenges. @@ -52,12 +55,16 @@ const ( ALPNProto = "acme-tls/1" ) -// 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} +// idPeACMEIdentifier is the OID for the ACME extension for the TLS-ALPN challenge. +// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1 +var idPeACMEIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} const ( 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 DER bytes + // Used for decoding certs from application/pem-certificate-chain response, + // the default when in RFC mode. + maxCertChainSize = maxCertSize * maxChainLen // Max number of collected nonces kept in memory. // Expect usual peak of 1 or 2. @@ -65,22 +72,22 @@ const ( ) // Client is an ACME client. +// // The only required field is Key. An example of creating a client with a new key // is as follows: // -// key, err := rsa.GenerateKey(rand.Reader, 2048) -// if err != nil { -// log.Fatal(err) -// } -// client := &Client{Key: key} -// +// key, err := rsa.GenerateKey(rand.Reader, 2048) +// if err != nil { +// log.Fatal(err) +// } +// client := &Client{Key: key} type Client struct { // Key is the account key used to register with a CA and sign requests. // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey. // // The following algorithms are supported: // RS256, ES256, ES384 and ES512. - // See RFC7518 for more details about the algorithms. + // See RFC 7518 for more details about the algorithms. Key crypto.Signer // HTTPClient optionally specifies an HTTP client to use @@ -116,21 +123,49 @@ type Client struct { // identifiable by the server, in case they are causing issues. UserAgent string - dirMu sync.Mutex // guards writes to dir - dir *Directory // cached result of Client's Discover method + cacheMu sync.Mutex + dir *Directory // cached result of Client's Discover method + // KID is the key identifier provided by the CA. If not provided it will be + // retrieved from the CA by making a call to the registration endpoint. + KID KeyID noncesMu sync.Mutex nonces map[string]struct{} // nonces collected from previous responses } +// accountKID returns a key ID associated with c.Key, the account identity +// provided by the CA during RFC based registration. +// It assumes c.Discover has already been called. +// +// accountKID requires at most one network roundtrip. +// It caches only successful result. +// +// When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID +// returns noKeyID. +func (c *Client) accountKID(ctx context.Context) KeyID { + c.cacheMu.Lock() + defer c.cacheMu.Unlock() + if c.KID != noKeyID { + return c.KID + } + a, err := c.getRegRFC(ctx) + if err != nil { + return noKeyID + } + c.KID = KeyID(a.URI) + return c.KID +} + +var errPreRFC = errors.New("acme: server does not support the RFC 8555 version of ACME") + // Discover performs ACME server discovery using c.DirectoryURL. // // It caches successful result. So, subsequent calls will not result in // a network round-trip. This also means mutating c.DirectoryURL after successful call // of this method will have no effect. func (c *Client) Discover(ctx context.Context) (Directory, error) { - c.dirMu.Lock() - defer c.dirMu.Unlock() + c.cacheMu.Lock() + defer c.cacheMu.Unlock() if c.dir != nil { return *c.dir, nil } @@ -143,27 +178,36 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) { c.addNonce(res.Header) var v struct { - Reg string `json:"new-reg"` - Authz string `json:"new-authz"` - Cert string `json:"new-cert"` - Revoke string `json:"revoke-cert"` - Meta struct { - Terms string `json:"terms-of-service"` - Website string `json:"website"` - CAA []string `json:"caa-identities"` + Reg string `json:"newAccount"` + Authz string `json:"newAuthz"` + Order string `json:"newOrder"` + Revoke string `json:"revokeCert"` + Nonce string `json:"newNonce"` + KeyChange string `json:"keyChange"` + Meta struct { + Terms string `json:"termsOfService"` + Website string `json:"website"` + CAA []string `json:"caaIdentities"` + ExternalAcct bool `json:"externalAccountRequired"` } } if err := json.NewDecoder(res.Body).Decode(&v); err != nil { return Directory{}, err } + if v.Order == "" { + return Directory{}, errPreRFC + } c.dir = &Directory{ - RegURL: v.Reg, - AuthzURL: v.Authz, - CertURL: v.Cert, - RevokeURL: v.Revoke, - Terms: v.Meta.Terms, - Website: v.Meta.Website, - CAA: v.Meta.CAA, + RegURL: v.Reg, + AuthzURL: v.Authz, + OrderURL: v.Order, + RevokeURL: v.Revoke, + NonceURL: v.Nonce, + KeyChangeURL: v.KeyChange, + Terms: v.Meta.Terms, + Website: v.Meta.Website, + CAA: v.Meta.CAA, + ExternalAccountRequired: v.Meta.ExternalAcct, } return *c.dir, nil } @@ -175,69 +219,28 @@ func (c *Client) directoryURL() string { return LetsEncryptURL } -// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format. -// The exp argument indicates the desired certificate validity duration. CA may issue a certificate -// with a different duration. -// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain. -// -// In the case where CA server does not provide the issued certificate in the response, -// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips. -// In such a scenario, the caller can cancel the polling with ctx. +// CreateCert was part of the old version of ACME. It is incompatible with RFC 8555. // -// CreateCert returns an error if the CA's response or chain was unreasonably large. -// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features. +// Deprecated: this was for the pre-RFC 8555 version of ACME. Callers should use CreateOrderCert. func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) { - if _, err := c.Discover(ctx); err != nil { - return nil, "", err - } - - req := struct { - Resource string `json:"resource"` - CSR string `json:"csr"` - NotBefore string `json:"notBefore,omitempty"` - NotAfter string `json:"notAfter,omitempty"` - }{ - Resource: "new-cert", - CSR: base64.RawURLEncoding.EncodeToString(csr), - } - now := timeNow() - req.NotBefore = now.Format(time.RFC3339) - if exp > 0 { - req.NotAfter = now.Add(exp).Format(time.RFC3339) - } - - res, err := c.post(ctx, c.Key, c.dir.CertURL, req, wantStatus(http.StatusCreated)) - if err != nil { - return nil, "", err - } - defer res.Body.Close() - - curl := res.Header.Get("Location") // cert permanent URL - if res.ContentLength == 0 { - // no cert in the body; poll until we get it - cert, err := c.FetchCert(ctx, curl, bundle) - return cert, curl, err - } - // slurp issued cert and CA chain, if requested - cert, err := c.responseCert(ctx, res, bundle) - return cert, curl, err + return nil, "", errPreRFC } // FetchCert retrieves already issued certificate from the given url, in DER format. // It retries the request until the certificate is successfully retrieved, // context is cancelled by the caller or an error response is received. // -// The returned value will also contain the CA (issuer) certificate if the bundle argument is true. +// If the bundle argument is true, the returned value also contains the CA (issuer) +// certificate chain. // // FetchCert returns an error if the CA's response or chain was unreasonably large. // Callers are encouraged to parse the returned value to ensure the certificate is valid // and has expected features. func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { - res, err := c.get(ctx, url, wantStatus(http.StatusOK)) - if err != nil { + if _, err := c.Discover(ctx); err != nil { return nil, err } - return c.responseCert(ctx, res, bundle) + return c.fetchCertRFC(ctx, url, bundle) } // RevokeCert revokes a previously issued certificate cert, provided in DER format. @@ -250,88 +253,87 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, if _, err := c.Discover(ctx); err != nil { return err } - - body := &struct { - Resource string `json:"resource"` - Cert string `json:"certificate"` - Reason int `json:"reason"` - }{ - Resource: "revoke-cert", - Cert: base64.RawURLEncoding.EncodeToString(cert), - Reason: int(reason), - } - if key == nil { - key = c.Key - } - res, err := c.post(ctx, key, c.dir.RevokeURL, body, wantStatus(http.StatusOK)) - if err != nil { - return err - } - defer res.Body.Close() - return nil + return c.revokeCertRFC(ctx, key, cert, reason) } // AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service // during account registration. See Register method of Client for more details. func AcceptTOS(tosURL string) bool { return true } -// Register creates a new account registration by following the "new-reg" flow. -// It returns the registered account. The account is not modified. +// Register creates a new account with the CA using c.Key. +// It returns the registered account. The account acct is not modified. // // The registration may require the caller to agree to the CA's Terms of Service (TOS). // If so, and the account has not indicated the acceptance of the terms (see Account for details), // Register calls prompt with a TOS URL provided by the CA. Prompt should report // whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS. -func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) { - if _, err := c.Discover(ctx); err != nil { - return nil, err +// +// When interfacing with an RFC-compliant CA, non-RFC 8555 fields of acct are ignored +// and prompt is called if Directory's Terms field is non-zero. +// Also see Error's Instance field for when a CA requires already registered accounts to agree +// to an updated Terms of Service. +func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { + if c.Key == nil { + return nil, errors.New("acme: client.Key must be set to Register") } - - var err error - if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil { + if _, err := c.Discover(ctx); err != nil { return nil, err } - var accept bool - if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms { - accept = prompt(a.CurrentTerms) - } - if accept { - a.AgreedTerms = a.CurrentTerms - a, err = c.UpdateReg(ctx, a) - } - return a, err + return c.registerRFC(ctx, acct, prompt) } -// GetReg retrieves an existing registration. -// The url argument is an Account URI. +// GetReg retrieves an existing account associated with c.Key. +// +// The url argument is a legacy artifact of the pre-RFC 8555 API +// and is ignored. func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) { - a, err := c.doReg(ctx, url, "reg", nil) - if err != nil { + if _, err := c.Discover(ctx); err != nil { return nil, err } - a.URI = url - return a, nil + return c.getRegRFC(ctx) } // UpdateReg updates an existing registration. // It returns an updated account copy. The provided account is not modified. -func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) { - uri := a.URI - a, err := c.doReg(ctx, uri, "reg", a) - if err != nil { +// +// The account's URI is ignored and the account URL associated with +// c.Key is used instead. +func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) { + if _, err := c.Discover(ctx); err != nil { return nil, err } - a.URI = uri - return a, nil + return c.updateRegRFC(ctx, acct) } -// Authorize performs the initial step in an authorization flow. +// AccountKeyRollover attempts to transition a client's account key to a new key. +// On success client's Key is updated which is not concurrency safe. +// On failure an error will be returned. +// The new key is already registered with the ACME provider if the following is true: +// - error is of type acme.Error +// - StatusCode should be 409 (Conflict) +// - Location header will have the KID of the associated account +// +// More about account key rollover can be found at +// https://tools.ietf.org/html/rfc8555#section-7.3.5. +func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error { + return c.accountKeyRollover(ctx, newKey) +} + +// Authorize performs the initial step in the pre-authorization flow, +// as opposed to order-based flow. // The caller will then need to choose from and perform a set of returned // challenges using c.Accept in order to successfully complete authorization. // +// Once complete, the caller can use AuthorizeOrder which the CA +// should provision with the already satisfied authorization. +// For pre-RFC CAs, the caller can proceed directly to requesting a certificate +// using CreateCert method. +// // If an authorization has been previously granted, the CA may return -// a valid authorization (Authorization.Status is StatusValid). If so, the caller -// need not fulfill any challenge and can proceed to requesting a certificate. +// a valid authorization which has its Status field set to StatusValid. +// +// More about pre-authorization can be found at +// https://tools.ietf.org/html/rfc8555#section-7.4.1. func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) { return c.authorize(ctx, "dns", domain) } @@ -350,6 +352,10 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization if _, err := c.Discover(ctx); err != nil { return nil, err } + if c.dir.AuthzURL == "" { + // Pre-Authorization is unsupported + return nil, errPreAuthorizationNotSupported + } type authzID struct { Type string `json:"type"` @@ -362,7 +368,7 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization Resource: "new-authz", Identifier: authzID{Type: typ, Value: val}, } - res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) + res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) if err != nil { return nil, err } @@ -383,7 +389,11 @@ func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization // If a caller needs to poll an authorization until its status is final, // see the WaitAuthorization method. func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { - res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) + if _, err := c.Discover(ctx); err != nil { + return nil, err + } + + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) if err != nil { return nil, err } @@ -400,11 +410,15 @@ func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorizati // The url argument is an Authorization.URI value. // // If successful, the caller will be required to obtain a new authorization -// using the Authorize method before being able to request a new certificate -// for the domain associated with the authorization. +// using the Authorize or AuthorizeOrder methods before being able to request +// a new certificate for the domain associated with the authorization. // // It does not revoke existing certificates. func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { + if _, err := c.Discover(ctx); err != nil { + return err + } + req := struct { Resource string `json:"resource"` Status string `json:"status"` @@ -414,7 +428,7 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { Status: "deactivated", Delete: true, } - res, err := c.post(ctx, c.Key, url, req, wantStatus(http.StatusOK)) + res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) if err != nil { return err } @@ -430,8 +444,11 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { // In all other cases WaitAuthorization returns an error. // If the Status is StatusInvalid, the returned error is of type *AuthorizationError. func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { + if _, err := c.Discover(ctx); err != nil { + return nil, err + } for { - res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } @@ -453,7 +470,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat // 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 + // Given that the fastest challenges TLS-ALPN 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. @@ -474,10 +491,15 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat // // A client typically polls a challenge status using this method. func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { - res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) + if _, err := c.Discover(ctx); err != nil { + return nil, err + } + + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) if err != nil { return nil, err } + defer res.Body.Close() v := wireChallenge{URI: url} if err := json.NewDecoder(res.Body).Decode(&v); err != nil { @@ -491,21 +513,15 @@ func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, erro // // The server will then perform the validation asynchronously. func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) { - auth, err := keyAuth(c.Key.Public(), chal.Token) - if err != nil { + if _, err := c.Discover(ctx); err != nil { return nil, err } - req := struct { - Resource string `json:"resource"` - Type string `json:"type"` - Auth string `json:"keyAuthorization"` - }{ - Resource: "challenge", - Type: chal.Type, - Auth: auth, + payload := json.RawMessage("{}") + if len(chal.Payload) != 0 { + payload = chal.Payload } - res, err := c.post(ctx, c.Key, chal.URI, req, wantStatus( + res, err := c.post(ctx, nil, chal.URI, payload, wantStatus( http.StatusOK, // according to the spec http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md) )) @@ -555,72 +571,28 @@ func (c *Client) HTTP01ChallengePath(token string) string { } // TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response. -// Servers can present the certificate to validate the challenge and prove control -// over a domain name. -// -// The implementation is incomplete in that the returned value is a single certificate, -// computed only for Z0 of the key authorization. ACME CAs are expected to update -// their implementations to use the newer version, TLS-SNI-02. -// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3. -// -// The token argument is a Challenge.Token value. -// If a WithKey option is provided, its private part signs the returned cert, -// and the public part is used to specify the signee. -// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. +// Always returns an error. // -// 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. -func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { - ka, err := keyAuth(c.Key.Public(), token) - if err != nil { - return tls.Certificate{}, "", err - } - b := sha256.Sum256([]byte(ka)) - h := hex.EncodeToString(b[:]) - name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:]) - cert, err = tlsChallengeCert([]string{name}, opt) - if err != nil { - return tls.Certificate{}, "", err - } - return cert, name, nil +// Deprecated: This challenge type was only present in pre-standardized ACME +// protocol drafts and is insecure for use in shared hosting environments. +func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error) { + return tls.Certificate{}, "", errPreRFC } // TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response. -// Servers can present the certificate to validate the challenge and prove control -// over a domain name. For more details on TLS-SNI-02 see -// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3. -// -// The token argument is a Challenge.Token value. -// If a WithKey option is provided, its private part signs the returned cert, -// and the public part is used to specify the signee. -// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. +// Always returns an error. // -// 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. -func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { - b := sha256.Sum256([]byte(token)) - h := hex.EncodeToString(b[:]) - sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:]) - - ka, err := keyAuth(c.Key.Public(), token) - if err != nil { - return tls.Certificate{}, "", err - } - b = sha256.Sum256([]byte(ka)) - h = hex.EncodeToString(b[:]) - sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:]) - - cert, err = tlsChallengeCert([]string{sanA, sanB}, opt) - if err != nil { - return tls.Certificate{}, "", err - } - return cert, sanA, nil +// Deprecated: This challenge type was only present in pre-standardized ACME +// protocol drafts and is insecure for use in shared hosting environments. +func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error) { + return tls.Certificate{}, "", errPreRFC } // 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 +// over an identifier (either a DNS name or the textual form of an IPv4 or IPv6 +// address). For more details on TLS-ALPN-01 see +// https://www.rfc-editor.org/rfc/rfc8737 and https://www.rfc-editor.org/rfc/rfc8738 // // The token argument is a Challenge.Token value. // If a WithKey option is provided, its private part signs the returned cert, @@ -628,9 +600,13 @@ func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tl // 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 +// the server name in the TLS ClientHello matches the identifier, 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) { +// +// Validation requests for IP address identifiers will use the reverse DNS form in the server name +// in the TLS ClientHello since the SNI extension is not supported for IP addresses. +// See RFC 8738 Section 6 for more information. +func (c *Client) TLSALPN01ChallengeCert(token, identifier string, opt ...CertOption) (cert tls.Certificate, err error) { ka, err := keyAuth(c.Key.Public(), token) if err != nil { return tls.Certificate{}, err @@ -641,7 +617,7 @@ func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) return tls.Certificate{}, err } acmeExtension := pkix.Extension{ - Id: idPeACMEIdentifierV1, + Id: idPeACMEIdentifier, Critical: true, Value: extValue, } @@ -660,73 +636,20 @@ func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) } tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension) newOpt = append(newOpt, WithTemplate(tmpl)) - return tlsChallengeCert([]string{domain}, newOpt) -} - -// doReg sends all types of registration requests. -// The type of request is identified by typ argument, which is a "resource" -// in the ACME spec terms. -// -// A non-nil acct argument indicates whether the intention is to mutate data -// of the Account. Only Contact and Agreement of its fields are used -// in such cases. -func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) { - req := struct { - Resource string `json:"resource"` - Contact []string `json:"contact,omitempty"` - Agreement string `json:"agreement,omitempty"` - }{ - Resource: typ, - } - if acct != nil { - req.Contact = acct.Contact - req.Agreement = acct.AgreedTerms - } - res, err := c.post(ctx, c.Key, url, req, wantStatus( - http.StatusOK, // updates and deletes - http.StatusCreated, // new account creation - http.StatusAccepted, // Let's Encrypt divergent implementation - )) - if err != nil { - return nil, err - } - defer res.Body.Close() - - var v struct { - Contact []string - Agreement string - Authorizations string - Certificates string - } - if err := json.NewDecoder(res.Body).Decode(&v); err != nil { - return nil, fmt.Errorf("acme: invalid response: %v", err) - } - var tos string - if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 { - tos = v[0] - } - var authz string - if v := linkHeader(res.Header, "next"); len(v) > 0 { - authz = v[0] - } - return &Account{ - URI: res.Header.Get("Location"), - Contact: v.Contact, - AgreedTerms: v.Agreement, - CurrentTerms: tos, - Authz: authz, - Authorizations: v.Authorizations, - Certificates: v.Certificates, - }, nil + return tlsChallengeCert(identifier, newOpt) } // popNonce returns a nonce value previously stored with c.addNonce -// or fetches a fresh one from a URL by issuing a HEAD request. -// It first tries c.directoryURL() and then the provided url if the former fails. +// or fetches a fresh one from c.dir.NonceURL. +// If NonceURL is empty, it first tries c.directoryURL() and, failing that, +// the provided url. func (c *Client) popNonce(ctx context.Context, url string) (string, error) { c.noncesMu.Lock() defer c.noncesMu.Unlock() if len(c.nonces) == 0 { + if c.dir != nil && c.dir.NonceURL != "" { + return c.fetchNonce(ctx, c.dir.NonceURL) + } dirURL := c.directoryURL() v, err := c.fetchNonce(ctx, dirURL) if err != nil && url != dirURL { @@ -790,78 +713,6 @@ func nonceFromHeader(h http.Header) string { return h.Get("Replay-Nonce") } -func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) { - b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1)) - if err != nil { - return nil, fmt.Errorf("acme: response stream: %v", err) - } - if len(b) > maxCertSize { - return nil, errors.New("acme: certificate is too big") - } - cert := [][]byte{b} - if !bundle { - return cert, nil - } - - // Append CA chain cert(s). - // At least one is required according to the spec: - // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1 - up := linkHeader(res.Header, "up") - if len(up) == 0 { - return nil, errors.New("acme: rel=up link not found") - } - if len(up) > maxChainLen { - return nil, errors.New("acme: rel=up link is too large") - } - for _, url := range up { - cc, err := c.chainCert(ctx, url, 0) - if err != nil { - return nil, err - } - cert = append(cert, cc...) - } - return cert, nil -} - -// chainCert fetches CA certificate chain recursively by following "up" links. -// Each recursive call increments the depth by 1, resulting in an error -// if the recursion level reaches maxChainLen. -// -// First chainCert call starts with depth of 0. -func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) { - if depth >= maxChainLen { - return nil, errors.New("acme: certificate chain is too deep") - } - - res, err := c.get(ctx, url, wantStatus(http.StatusOK)) - if err != nil { - return nil, err - } - defer res.Body.Close() - b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1)) - if err != nil { - return nil, err - } - if len(b) > maxCertSize { - return nil, errors.New("acme: certificate is too big") - } - chain := [][]byte{b} - - uplink := linkHeader(res.Header, "up") - if len(uplink) > maxChainLen { - return nil, errors.New("acme: certificate chain is too large") - } - for _, up := range uplink { - cc, err := c.chainCert(ctx, up, depth+1) - if err != nil { - return nil, err - } - chain = append(chain, cc...) - } - - return chain, nil -} - // linkHeader returns URI-Reference values of all Link headers // with relation-type rel. // See https://tools.ietf.org/html/rfc5988#section-5 for details. @@ -903,11 +754,15 @@ func defaultTLSChallengeCertTemplate() *x509.Certificate { } } -// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges -// with the given SANs and auto-generated public/private key pair. -// The Subject Common Name is set to the first SAN to aid debugging. +// tlsChallengeCert creates a temporary certificate for TLS-ALPN challenges +// for the given identifier, using an auto-generated public/private key pair. +// +// If the provided identifier is a domain name, it will be used as a DNS type SAN and for the +// subject common name. If the provided identifier is an IP address it will be used as an IP type +// SAN. +// // To create a cert with a custom key pair, specify WithKey option. -func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { +func tlsChallengeCert(identifier string, opt []CertOption) (tls.Certificate, error) { var key crypto.Signer tmpl := defaultTLSChallengeCertTemplate() for _, o := range opt { @@ -931,9 +786,12 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { return tls.Certificate{}, err } } - tmpl.DNSNames = san - if len(san) > 0 { - tmpl.Subject.CommonName = san[0] + + if ip := net.ParseIP(identifier); ip != nil { + tmpl.IPAddresses = []net.IP{ip} + } else { + tmpl.DNSNames = []string{identifier} + tmpl.Subject.CommonName = identifier } der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key) @@ -946,11 +804,5 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { }, nil } -// encodePEM returns b encoded as PEM with block of type typ. -func encodePEM(typ string, b []byte) []byte { - pb := &pem.Block{Type: typ, Bytes: b} - return pem.EncodeToMemory(pb) -} - -// timeNow is useful for testing for fixed current time. +// timeNow is time.Now, except in tests which can mess with it. var timeNow = time.Now diff --git a/acme/acme_test.go b/acme/acme_test.go index 99a4bf892b..a3118f4cb5 100644 --- a/acme/acme_test.go +++ b/acme/acme_test.go @@ -9,29 +9,38 @@ import ( "context" "crypto/rand" "crypto/rsa" - "crypto/tls" "crypto/x509" "crypto/x509/pkix" "encoding/base64" "encoding/hex" "encoding/json" + "errors" "fmt" + "io" "math/big" "net/http" "net/http/httptest" "reflect" - "sort" - "strings" "testing" "time" ) +// newTestClient creates a client with a non-nil Directory so that it skips +// the discovery which is otherwise done on the first call of almost every +// exported method. +func newTestClient() *Client { + return &Client{ + Key: testKeyEC, + dir: &Directory{}, // skip discovery + } +} + // Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided // interface. -func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) { +func decodeJWSRequest(t *testing.T, v interface{}, r io.Reader) { // Decode request var req struct{ Payload string } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + if err := json.NewDecoder(r).Decode(&req); err != nil { t.Fatal(err) } payload, err := base64.RawURLEncoding.DecodeString(req.Payload) @@ -47,12 +56,14 @@ func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) { type jwsHead struct { Alg string Nonce string + URL string `json:"url"` + KID string `json:"kid"` JWK map[string]string `json:"jwk"` } -func decodeJWSHead(r *http.Request) (*jwsHead, error) { +func decodeJWSHead(r io.Reader) (*jwsHead, error) { var req struct{ Protected string } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + if err := json.NewDecoder(r).Decode(&req); err != nil { return nil, err } b, err := base64.RawURLEncoding.DecodeString(req.Protected) @@ -66,232 +77,28 @@ func decodeJWSHead(r *http.Request) (*jwsHead, error) { return &head, nil } -func TestDiscover(t *testing.T) { - const ( - reg = "https://example.com/acme/new-reg" - authz = "https://example.com/acme/new-authz" - cert = "https://example.com/acme/new-cert" - revoke = "https://example.com/acme/revoke-cert" - ) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Replay-Nonce", "testnonce") - fmt.Fprintf(w, `{ - "new-reg": %q, - "new-authz": %q, - "new-cert": %q, - "revoke-cert": %q - }`, reg, authz, cert, revoke) - })) - defer ts.Close() - c := Client{DirectoryURL: ts.URL} - dir, err := c.Discover(context.Background()) - if err != nil { - t.Fatal(err) - } - if dir.RegURL != reg { - t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg) - } - if dir.AuthzURL != authz { - t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz) - } - if dir.CertURL != cert { - t.Errorf("dir.CertURL = %q; want %q", dir.CertURL, cert) - } - if dir.RevokeURL != revoke { - t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke) - } - if _, exist := c.nonces["testnonce"]; !exist { - t.Errorf("c.nonces = %q; want 'testnonce' in the map", c.nonces) - } -} - -func TestRegister(t *testing.T) { - contacts := []string{"mailto:admin@example.com"} - +func TestRegisterWithoutKey(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "HEAD" { w.Header().Set("Replay-Nonce", "test-nonce") return } - if r.Method != "POST" { - t.Errorf("r.Method = %q; want POST", r.Method) - } - - var j struct { - Resource string - Contact []string - Agreement string - } - decodeJWSRequest(t, &j, r) - - // Test request - if j.Resource != "new-reg" { - t.Errorf("j.Resource = %q; want new-reg", j.Resource) - } - if !reflect.DeepEqual(j.Contact, contacts) { - t.Errorf("j.Contact = %v; want %v", j.Contact, contacts) - } - - w.Header().Set("Location", "https://ca.tld/acme/reg/1") - w.Header().Set("Link", `;rel="next"`) - w.Header().Add("Link", `;rel="recover"`) - w.Header().Add("Link", `;rel="terms-of-service"`) w.WriteHeader(http.StatusCreated) - b, _ := json.Marshal(contacts) - fmt.Fprintf(w, `{"contact": %s}`, b) + fmt.Fprint(w, `{}`) })) defer ts.Close() - - prompt := func(url string) bool { - const terms = "https://ca.tld/acme/terms" - if url != terms { - t.Errorf("prompt url = %q; want %q", url, terms) - } - return false - } - + // First verify that using a complete client results in success. c := Client{ Key: testKeyEC, DirectoryURL: ts.URL, dir: &Directory{RegURL: ts.URL}, } - a := &Account{Contact: contacts} - var err error - if a, err = c.Register(context.Background(), a, prompt); err != nil { - t.Fatal(err) - } - if a.URI != "https://ca.tld/acme/reg/1" { - t.Errorf("a.URI = %q; want https://ca.tld/acme/reg/1", a.URI) + if _, err := c.Register(context.Background(), &Account{}, AcceptTOS); err != nil { + t.Fatalf("c.Register() = %v; want success with a complete test client", err) } - if a.Authz != "https://ca.tld/acme/new-authz" { - t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz) - } - if a.CurrentTerms != "https://ca.tld/acme/terms" { - t.Errorf("a.CurrentTerms = %q; want https://ca.tld/acme/terms", a.CurrentTerms) - } - if !reflect.DeepEqual(a.Contact, contacts) { - t.Errorf("a.Contact = %v; want %v", a.Contact, contacts) - } -} - -func TestUpdateReg(t *testing.T) { - const terms = "https://ca.tld/acme/terms" - contacts := []string{"mailto:admin@example.com"} - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "HEAD" { - w.Header().Set("Replay-Nonce", "test-nonce") - return - } - if r.Method != "POST" { - t.Errorf("r.Method = %q; want POST", r.Method) - } - - var j struct { - Resource string - Contact []string - Agreement string - } - decodeJWSRequest(t, &j, r) - - // Test request - if j.Resource != "reg" { - t.Errorf("j.Resource = %q; want reg", j.Resource) - } - if j.Agreement != terms { - t.Errorf("j.Agreement = %q; want %q", j.Agreement, terms) - } - if !reflect.DeepEqual(j.Contact, contacts) { - t.Errorf("j.Contact = %v; want %v", j.Contact, contacts) - } - - w.Header().Set("Link", `;rel="next"`) - w.Header().Add("Link", `;rel="recover"`) - w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms)) - w.WriteHeader(http.StatusOK) - b, _ := json.Marshal(contacts) - fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms) - })) - defer ts.Close() - - c := Client{Key: testKeyEC} - a := &Account{URI: ts.URL, Contact: contacts, AgreedTerms: terms} - var err error - if a, err = c.UpdateReg(context.Background(), a); err != nil { - t.Fatal(err) - } - if a.Authz != "https://ca.tld/acme/new-authz" { - t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz) - } - if a.AgreedTerms != terms { - t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms) - } - if a.CurrentTerms != terms { - t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms) - } - if a.URI != ts.URL { - t.Errorf("a.URI = %q; want %q", a.URI, ts.URL) - } -} - -func TestGetReg(t *testing.T) { - const terms = "https://ca.tld/acme/terms" - const newTerms = "https://ca.tld/acme/new-terms" - contacts := []string{"mailto:admin@example.com"} - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "HEAD" { - w.Header().Set("Replay-Nonce", "test-nonce") - return - } - if r.Method != "POST" { - t.Errorf("r.Method = %q; want POST", r.Method) - } - - var j struct { - Resource string - Contact []string - Agreement string - } - decodeJWSRequest(t, &j, r) - - // Test request - if j.Resource != "reg" { - t.Errorf("j.Resource = %q; want reg", j.Resource) - } - if len(j.Contact) != 0 { - t.Errorf("j.Contact = %v", j.Contact) - } - if j.Agreement != "" { - t.Errorf("j.Agreement = %q", j.Agreement) - } - - w.Header().Set("Link", `;rel="next"`) - w.Header().Add("Link", `;rel="recover"`) - w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms)) - w.WriteHeader(http.StatusOK) - b, _ := json.Marshal(contacts) - fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms) - })) - defer ts.Close() - - c := Client{Key: testKeyEC} - a, err := c.GetReg(context.Background(), ts.URL) - if err != nil { - t.Fatal(err) - } - if a.Authz != "https://ca.tld/acme/new-authz" { - t.Errorf("a.AuthzURL = %q; want https://ca.tld/acme/new-authz", a.Authz) - } - if a.AgreedTerms != terms { - t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms) - } - if a.CurrentTerms != newTerms { - t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms) - } - if a.URI != ts.URL { - t.Errorf("a.URI = %q; want %q", a.URI, ts.URL) + c.Key = nil + if _, err := c.Register(context.Background(), &Account{}, AcceptTOS); err == nil { + t.Error("c.Register() from client without key succeeded, wanted error") } } @@ -318,7 +125,7 @@ func TestAuthorize(t *testing.T) { Value string } } - decodeJWSRequest(t, &j, r) + decodeJWSRequest(t, &j, r.Body) // Test request if j.Resource != "new-authz" { @@ -445,79 +252,54 @@ func TestAuthorizeValid(t *testing.T) { } } -func TestGetAuthorization(t *testing.T) { +func TestAuthorizeUnsupported(t *testing.T) { + const ( + nonce = "https://example.com/acme/new-nonce" + reg = "https://example.com/acme/new-acct" + order = "https://example.com/acme/new-order" + revoke = "https://example.com/acme/revoke-cert" + keychange = "https://example.com/acme/key-change" + metaTerms = "https://example.com/acme/terms/2017-5-30" + metaWebsite = "https://www.example.com/" + metaCAA = "example.com" + ) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method != "GET" { - t.Errorf("r.Method = %q; want GET", r.Method) + w.Header().Set("Replay-Nonce", "nonce") + if r.Method == http.MethodHead { + return + } + switch r.URL.Path { + case "/": // Directory + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, `{ + "newNonce": %q, + "newAccount": %q, + "newOrder": %q, + "revokeCert": %q, + "keyChange": %q, + "meta": { + "termsOfService": %q, + "website": %q, + "caaIdentities": [%q], + "externalAccountRequired": true + } + }`, nonce, reg, order, revoke, keychange, metaTerms, metaWebsite, metaCAA) + w.WriteHeader(http.StatusOK) + case "/acme/new-authz": + w.WriteHeader(http.StatusBadRequest) } - - w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, `{ - "identifier": {"type":"dns","value":"example.com"}, - "status":"pending", - "challenges":[ - { - "type":"http-01", - "status":"pending", - "uri":"https://ca.tld/acme/challenge/publickey/id1", - "token":"token1" - }, - { - "type":"tls-sni-01", - "status":"pending", - "uri":"https://ca.tld/acme/challenge/publickey/id2", - "token":"token2" - } - ], - "combinations":[[0],[1]]}`) })) defer ts.Close() - - cl := Client{Key: testKeyEC} - auth, err := cl.GetAuthorization(context.Background(), ts.URL) + client := &Client{Key: testKey, DirectoryURL: ts.URL} + dir, err := client.Discover(context.Background()) if err != nil { t.Fatal(err) } - - if auth.Status != "pending" { - t.Errorf("Status = %q; want pending", auth.Status) - } - if auth.Identifier.Type != "dns" { - t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type) - } - if auth.Identifier.Value != "example.com" { - t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value) - } - - if n := len(auth.Challenges); n != 2 { - t.Fatalf("len(set.Challenges) = %d; want 2", n) - } - - c := auth.Challenges[0] - if c.Type != "http-01" { - t.Errorf("c.Type = %q; want http-01", c.Type) - } - if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { - t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) - } - if c.Token != "token1" { - t.Errorf("c.Token = %q; want token1", c.Token) - } - - c = auth.Challenges[1] - if c.Type != "tls-sni-01" { - t.Errorf("c.Type = %q; want tls-sni-01", c.Type) - } - if c.URI != "https://ca.tld/acme/challenge/publickey/id2" { - t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI) + if dir.AuthzURL != "" { + t.Fatalf("expected AuthzURL to be empty, got %q", dir.AuthzURL) } - if c.Token != "token2" { - t.Errorf("c.Token = %q; want token2", c.Token) - } - - combs := [][]int{{0}, {1}} - if !reflect.DeepEqual(auth.Combinations, combs) { - t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs) + if _, err := client.Authorize(context.Background(), "example.com"); !errors.Is(err, errPreAuthorizationNotSupported) { + t.Errorf("expected err to indicate pre-authorization is unsupported, got %+v", err) } } @@ -548,6 +330,45 @@ func TestWaitAuthorization(t *testing.T) { t.Errorf("err is %v (%T); want non-nil *AuthorizationError", err, err) } }) + t.Run("invalid status with error returns the authorization error", func(t *testing.T) { + _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, `{ + "type": "dns-01", + "status": "invalid", + "error": { + "type": "urn:ietf:params:acme:error:caa", + "detail": "CAA record for prevents issuance", + "status": 403 + }, + "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/xxx/xxx", + "token": "xxx", + "validationRecord": [ + { + "hostname": "" + } + ] + }`) + }) + + want := &AuthorizationError{ + Errors: []error{ + (&wireError{ + Status: 403, + Type: "urn:ietf:params:acme:error:caa", + Detail: "CAA record for prevents issuance", + }).error(nil), + }, + } + + _, ok := err.(*AuthorizationError) + if !ok { + t.Errorf("err is %T; want non-nil *AuthorizationError", err) + } + + if err.Error() != want.Error() { + t.Errorf("err is %v; want %v", err, want) + } + }) t.Run("non-retriable error", func(t *testing.T) { const code = http.StatusBadRequest _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { @@ -582,38 +403,34 @@ func TestWaitAuthorization(t *testing.T) { }) } t.Run("context cancel", func(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() _, err := runWaitAuthorization(ctx, t, func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Retry-After", "60") fmt.Fprintf(w, `{"status":"pending"}`) + time.AfterFunc(1*time.Millisecond, cancel) }) if err == nil { t.Error("err is nil") } }) } + func runWaitAuthorization(ctx context.Context, t *testing.T, h http.HandlerFunc) (*Authorization, error) { t.Helper() - ts := httptest.NewServer(h) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", fmt.Sprintf("bad-test-nonce-%v", time.Now().UnixNano())) + h(w, r) + })) defer ts.Close() - type res struct { - authz *Authorization - err error - } - ch := make(chan res, 1) - go func() { - var client Client - a, err := client.WaitAuthorization(ctx, ts.URL) - ch <- res{a, err} - }() - select { - case <-time.After(3 * time.Second): - t.Fatal("WaitAuthorization took too long to return") - case v := <-ch: - return v.authz, v.err + + client := &Client{ + Key: testKey, + DirectoryURL: ts.URL, + dir: &Directory{}, + KID: "some-key-id", // set to avoid lookup attempt } - panic("runWaitAuthorization: out of select") + return client.WaitAuthorization(ctx, ts.URL) } func TestRevokeAuthorization(t *testing.T) { @@ -629,7 +446,7 @@ func TestRevokeAuthorization(t *testing.T) { Status string Delete bool } - decodeJWSRequest(t, &req, r) + decodeJWSRequest(t, &req, r.Body) if req.Resource != "authz" { t.Errorf("req.Resource = %q; want authz", req.Resource) } @@ -644,7 +461,11 @@ func TestRevokeAuthorization(t *testing.T) { } })) defer ts.Close() - client := &Client{Key: testKey} + client := &Client{ + Key: testKey, + DirectoryURL: ts.URL, // don't dial outside of localhost + dir: &Directory{}, // don't do discovery + } ctx := context.Background() if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil { t.Errorf("err = %v", err) @@ -654,241 +475,19 @@ func TestRevokeAuthorization(t *testing.T) { } } -func TestPollChallenge(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method != "GET" { - t.Errorf("r.Method = %q; want GET", r.Method) - } - - w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, `{ - "type":"http-01", - "status":"pending", - "uri":"https://ca.tld/acme/challenge/publickey/id1", - "token":"token1"}`) - })) - defer ts.Close() - - cl := Client{Key: testKeyEC} - chall, err := cl.GetChallenge(context.Background(), ts.URL) - if err != nil { - t.Fatal(err) - } - - if chall.Status != "pending" { - t.Errorf("Status = %q; want pending", chall.Status) - } - if chall.Type != "http-01" { - t.Errorf("c.Type = %q; want http-01", chall.Type) - } - if chall.URI != "https://ca.tld/acme/challenge/publickey/id1" { - t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", chall.URI) - } - if chall.Token != "token1" { - t.Errorf("c.Token = %q; want token1", chall.Token) - } -} - -func TestAcceptChallenge(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "HEAD" { - w.Header().Set("Replay-Nonce", "test-nonce") - return - } - if r.Method != "POST" { - t.Errorf("r.Method = %q; want POST", r.Method) - } - - var j struct { - Resource string - Type string - Auth string `json:"keyAuthorization"` - } - decodeJWSRequest(t, &j, r) - - // Test request - if j.Resource != "challenge" { - t.Errorf(`resource = %q; want "challenge"`, j.Resource) - } - if j.Type != "http-01" { - t.Errorf(`type = %q; want "http-01"`, j.Type) - } - keyAuth := "token1." + testKeyECThumbprint - if j.Auth != keyAuth { - t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth) - } - - // Respond to request - w.WriteHeader(http.StatusAccepted) - fmt.Fprintf(w, `{ - "type":"http-01", - "status":"pending", - "uri":"https://ca.tld/acme/challenge/publickey/id1", - "token":"token1", - "keyAuthorization":%q - }`, keyAuth) - })) - defer ts.Close() - - cl := Client{Key: testKeyEC} - c, err := cl.Accept(context.Background(), &Challenge{ - URI: ts.URL, - Token: "token1", - Type: "http-01", - }) - if err != nil { - t.Fatal(err) - } - - if c.Type != "http-01" { - t.Errorf("c.Type = %q; want http-01", c.Type) - } - if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { - t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) - } - if c.Token != "token1" { - t.Errorf("c.Token = %q; want token1", c.Token) - } -} - -func TestNewCert(t *testing.T) { - notBefore := time.Now() - notAfter := notBefore.AddDate(0, 2, 0) - timeNow = func() time.Time { return notBefore } - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "HEAD" { - w.Header().Set("Replay-Nonce", "test-nonce") - return - } - if r.Method != "POST" { - t.Errorf("r.Method = %q; want POST", r.Method) - } - - var j struct { - Resource string `json:"resource"` - CSR string `json:"csr"` - NotBefore string `json:"notBefore,omitempty"` - NotAfter string `json:"notAfter,omitempty"` - } - decodeJWSRequest(t, &j, r) - - // Test request - if j.Resource != "new-cert" { - t.Errorf(`resource = %q; want "new-cert"`, j.Resource) - } - if j.NotBefore != notBefore.Format(time.RFC3339) { - t.Errorf(`notBefore = %q; wanted %q`, j.NotBefore, notBefore.Format(time.RFC3339)) - } - if j.NotAfter != notAfter.Format(time.RFC3339) { - t.Errorf(`notAfter = %q; wanted %q`, j.NotAfter, notAfter.Format(time.RFC3339)) - } - - // Respond to request - template := x509.Certificate{ - SerialNumber: big.NewInt(int64(1)), - Subject: pkix.Name{ - Organization: []string{"goacme"}, - }, - NotBefore: notBefore, - NotAfter: notAfter, - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - } - - sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKeyEC.PublicKey, testKeyEC) - if err != nil { - t.Fatalf("Error creating certificate: %v", err) - } - - w.Header().Set("Location", "https://ca.tld/acme/cert/1") - w.WriteHeader(http.StatusCreated) - w.Write(sampleCert) - })) - defer ts.Close() - - csr := x509.CertificateRequest{ - Version: 0, - Subject: pkix.Name{ - CommonName: "example.com", - Organization: []string{"goacme"}, - }, - } - csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKeyEC) - if err != nil { - t.Fatal(err) - } - - c := Client{Key: testKeyEC, dir: &Directory{CertURL: ts.URL}} - cert, certURL, err := c.CreateCert(context.Background(), csrb, notAfter.Sub(notBefore), false) - if err != nil { - t.Fatal(err) - } - if cert == nil { - t.Errorf("cert is nil") - } - if certURL != "https://ca.tld/acme/cert/1" { - t.Errorf("certURL = %q; want https://ca.tld/acme/cert/1", certURL) - } -} - -func TestFetchCert(t *testing.T) { - var count byte - var ts *httptest.Server - ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - count++ - if count < 3 { - up := fmt.Sprintf("<%s>;rel=up", ts.URL) - w.Header().Set("Link", up) - } - w.Write([]byte{count}) - })) - defer ts.Close() - res, err := (&Client{}).FetchCert(context.Background(), ts.URL, true) - if err != nil { - t.Fatalf("FetchCert: %v", err) - } - cert := [][]byte{{1}, {2}, {3}} - if !reflect.DeepEqual(res, cert) { - t.Errorf("res = %v; want %v", res, cert) - } -} - -func TestFetchCertRetry(t *testing.T) { - var count int - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if count < 1 { - w.Header().Set("Retry-After", "0") - w.WriteHeader(http.StatusTooManyRequests) - count++ - return - } - w.Write([]byte{1}) - })) - defer ts.Close() - res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false) - if err != nil { - t.Fatalf("FetchCert: %v", err) - } - cert := [][]byte{{1}} - if !reflect.DeepEqual(res, cert) { - t.Errorf("res = %v; want %v", res, cert) - } -} - func TestFetchCertCancel(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + <-r.Context().Done() w.Header().Set("Retry-After", "0") - w.WriteHeader(http.StatusAccepted) + w.WriteHeader(http.StatusBadRequest) })) defer ts.Close() ctx, cancel := context.WithCancel(context.Background()) done := make(chan struct{}) var err error go func() { - _, err = (&Client{}).FetchCert(ctx, ts.URL, false) + cl := newTestClient() + _, err = cl.FetchCert(ctx, ts.URL, false) close(done) }() cancel() @@ -911,7 +510,8 @@ func TestFetchCertDepth(t *testing.T) { w.Write([]byte{count}) })) defer ts.Close() - _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true) + cl := newTestClient() + _, err := cl.FetchCert(context.Background(), ts.URL, true) if err == nil { t.Errorf("err is nil") } @@ -926,7 +526,8 @@ func TestFetchCertBreadth(t *testing.T) { w.Write([]byte{1}) })) defer ts.Close() - _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true) + cl := newTestClient() + _, err := cl.FetchCert(context.Background(), ts.URL, true) if err == nil { t.Errorf("err is nil") } @@ -938,48 +539,13 @@ func TestFetchCertSize(t *testing.T) { w.Write(b) })) defer ts.Close() - _, err := (&Client{}).FetchCert(context.Background(), ts.URL, false) + cl := newTestClient() + _, err := cl.FetchCert(context.Background(), ts.URL, false) if err == nil { t.Errorf("err is nil") } } -func TestRevokeCert(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "HEAD" { - w.Header().Set("Replay-Nonce", "nonce") - return - } - - var req struct { - Resource string - Certificate string - Reason int - } - decodeJWSRequest(t, &req, r) - if req.Resource != "revoke-cert" { - t.Errorf("req.Resource = %q; want revoke-cert", req.Resource) - } - if req.Reason != 1 { - t.Errorf("req.Reason = %d; want 1", req.Reason) - } - // echo -n cert | base64 | tr -d '=' | tr '/+' '_-' - cert := "Y2VydA" - if req.Certificate != cert { - t.Errorf("req.Certificate = %q; want %q", req.Certificate, cert) - } - })) - defer ts.Close() - client := &Client{ - Key: testKeyEC, - dir: &Directory{RevokeURL: ts.URL}, - } - ctx := context.Background() - if err := client.RevokeCert(ctx, nil, []byte("cert"), CRLReasonKeyCompromise); err != nil { - t.Fatal(err) - } -} - func TestNonce_add(t *testing.T) { var c Client c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) @@ -1023,7 +589,7 @@ func TestNonce_fetch(t *testing.T) { defer ts.Close() for ; i < len(tests); i++ { test := tests[i] - c := &Client{} + c := newTestClient() n, err := c.fetchNonce(context.Background(), ts.URL) if n != test.nonce { t.Errorf("%d: n=%q; want %q", i, n, test.nonce) @@ -1042,7 +608,7 @@ func TestNonce_fetchError(t *testing.T) { w.WriteHeader(http.StatusTooManyRequests) })) defer ts.Close() - c := &Client{} + c := newTestClient() _, err := c.fetchNonce(context.Background(), ts.URL) e, ok := err.(*Error) if !ok { @@ -1100,65 +666,6 @@ func TestNonce_popWhenEmpty(t *testing.T) { } } -func TestNonce_postJWS(t *testing.T) { - var count int - seen := make(map[string]bool) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - count++ - w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) - if r.Method == "HEAD" { - // We expect the client do a HEAD request - // but only to fetch the first nonce. - return - } - // Make client.Authorize happy; we're not testing its result. - defer func() { - w.WriteHeader(http.StatusCreated) - w.Write([]byte(`{"status":"valid"}`)) - }() - - head, err := decodeJWSHead(r) - if err != nil { - t.Errorf("decodeJWSHead: %v", err) - return - } - if head.Nonce == "" { - t.Error("head.Nonce is empty") - return - } - if seen[head.Nonce] { - t.Errorf("nonce is already used: %q", head.Nonce) - } - seen[head.Nonce] = true - })) - defer ts.Close() - - client := Client{ - Key: testKey, - DirectoryURL: ts.URL, // nonces are fetched from here first - dir: &Directory{AuthzURL: ts.URL}, - } - if _, err := client.Authorize(context.Background(), "example.com"); err != nil { - t.Errorf("client.Authorize 1: %v", err) - } - // The second call should not generate another extra HEAD request. - if _, err := client.Authorize(context.Background(), "example.com"); err != nil { - t.Errorf("client.Authorize 2: %v", err) - } - - if count != 3 { - t.Errorf("total requests count: %d; want 3", count) - } - if n := len(client.nonces); n != 1 { - t.Errorf("len(client.nonces) = %d; want 1", n) - } - for k := range seen { - if _, exist := client.nonces[k]; exist { - t.Errorf("used nonce %q in client.nonces", k) - } - } -} - func TestLinkHeader(t *testing.T) { h := http.Header{"Link": { `;rel="next"`, @@ -1182,73 +689,6 @@ func TestLinkHeader(t *testing.T) { } } -func TestTLSSNI01ChallengeCert(t *testing.T) { - const ( - token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" - // echo -n | shasum -a 256 - san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid" - ) - - client := &Client{Key: testKeyEC} - tlscert, name, err := client.TLSSNI01ChallengeCert(token) - if err != nil { - t.Fatal(err) - } - - if n := len(tlscert.Certificate); n != 1 { - t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) - } - cert, err := x509.ParseCertificate(tlscert.Certificate[0]) - if err != nil { - t.Fatal(err) - } - if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san { - t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san) - } - if cert.DNSNames[0] != name { - t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name) - } - if cn := cert.Subject.CommonName; cn != san { - t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san) - } -} - -func TestTLSSNI02ChallengeCert(t *testing.T) { - const ( - token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" - // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256 - sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid" - // echo -n | shasum -a 256 - sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid" - ) - - client := &Client{Key: testKeyEC} - tlscert, name, err := client.TLSSNI02ChallengeCert(token) - if err != nil { - t.Fatal(err) - } - - if n := len(tlscert.Certificate); n != 1 { - t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) - } - cert, err := x509.ParseCertificate(tlscert.Certificate[0]) - if err != nil { - t.Fatal(err) - } - names := []string{sanA, sanB} - if !reflect.DeepEqual(cert.DNSNames, names) { - t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) - } - sort.Strings(cert.DNSNames) - i := sort.SearchStrings(cert.DNSNames, name) - if i >= len(cert.DNSNames) || cert.DNSNames[i] != name { - t.Errorf("%v doesn't have %q", cert.DNSNames, name) - } - if cn := cert.Subject.CommonName; cn != sanA { - t.Errorf("CommonName = %q; want %q", cn, sanA) - } -} - func TestTLSALPN01ChallengeCert(t *testing.T) { const ( token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" @@ -1263,8 +703,7 @@ func TestTLSALPN01ChallengeCert(t *testing.T) { t.Fatal(err) } - client := &Client{Key: testKeyEC} - tlscert, err := client.TLSALPN01ChallengeCert(token, domain) + tlscert, err := newTestClient().TLSALPN01ChallengeCert(token, domain) if err != nil { t.Fatal(err) } @@ -1285,7 +724,7 @@ func TestTLSALPN01ChallengeCert(t *testing.T) { } acmeExts := []pkix.Extension{} for _, ext := range cert.Extensions { - if idPeACMEIdentifierV1.Equal(ext.Id) { + if idPeACMEIdentifier.Equal(ext.Id) { acmeExts = append(acmeExts, ext) } } @@ -1302,10 +741,11 @@ func TestTLSALPN01ChallengeCert(t *testing.T) { } func TestTLSChallengeCertOpt(t *testing.T) { - key, err := rsa.GenerateKey(rand.Reader, 512) + key, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { t.Fatal(err) } + domain := "example.com" tmpl := &x509.Certificate{ SerialNumber: big.NewInt(2), Subject: pkix.Name{Organization: []string{"Test"}}, @@ -1313,53 +753,44 @@ func TestTLSChallengeCertOpt(t *testing.T) { } opts := []CertOption{WithKey(key), WithTemplate(tmpl)} - client := &Client{Key: testKeyEC} - cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...) + client := newTestClient() + cert, err := client.TLSALPN01ChallengeCert("token", domain, opts...) if err != nil { t.Fatal(err) } - cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...) + + // verify generated cert private key + tlskey, ok := cert.PrivateKey.(*rsa.PrivateKey) + if !ok { + t.Fatalf("tlscert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey) + } + if tlskey.D.Cmp(key.D) != 0 { + t.Errorf("tlskey.D = %v; want %v", tlskey.D, key.D) + } + // verify generated cert public key + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) if err != nil { t.Fatal(err) } - - for i, tlscert := range []tls.Certificate{cert1, cert2} { - // verify generated cert private key - tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey) - if !ok { - t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey) - continue - } - if tlskey.D.Cmp(key.D) != 0 { - t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D) - } - // verify generated cert public key - x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0]) - if err != nil { - t.Errorf("%d: %v", i, err) - continue - } - tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey) - if !ok { - t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey) - continue - } - if tlspub.N.Cmp(key.N) != 0 { - t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N) - } - // verify template option - sn := big.NewInt(2) - if x509Cert.SerialNumber.Cmp(sn) != 0 { - t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn) - } - org := []string{"Test"} - if !reflect.DeepEqual(x509Cert.Subject.Organization, org) { - t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org) - } - for _, v := range x509Cert.DNSNames { - if !strings.HasSuffix(v, ".acme.invalid") { - t.Errorf("%d: invalid DNSNames element: %q", i, v) - } + tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey) + if !ok { + t.Fatalf("x509Cert.PublicKey is %T; want *rsa.PublicKey", x509Cert.PublicKey) + } + if tlspub.N.Cmp(key.N) != 0 { + t.Errorf("tlspub.N = %v; want %v", tlspub.N, key.N) + } + // verify template option + sn := big.NewInt(2) + if x509Cert.SerialNumber.Cmp(sn) != 0 { + t.Errorf("SerialNumber = %v; want %v", x509Cert.SerialNumber, sn) + } + org := []string{"Test"} + if !reflect.DeepEqual(x509Cert.Subject.Organization, org) { + t.Errorf("Subject.Organization = %+v; want %+v", x509Cert.Subject.Organization, org) + } + for _, v := range x509Cert.DNSNames { + if v != domain { + t.Errorf("invalid DNSNames element: %q", v) } } } @@ -1371,7 +802,7 @@ func TestHTTP01Challenge(t *testing.T) { value = token + "." + testKeyECThumbprint urlpath = "/.well-known/acme-challenge/" + token ) - client := &Client{Key: testKeyEC} + client := newTestClient() val, err := client.HTTP01ChallengeResponse(token) if err != nil { t.Fatal(err) @@ -1390,8 +821,7 @@ func TestDNS01ChallengeRecord(t *testing.T) { // base64 | tr -d '=' | tr '/+' '_-' const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo" - client := &Client{Key: testKeyEC} - val, err := client.DNS01ChallengeRecord("xxx") + val, err := newTestClient().DNS01ChallengeRecord("xxx") if err != nil { t.Fatal(err) } diff --git a/acme/autocert/autocert.go b/acme/autocert/autocert.go index 5256bc3105..ccd5b7e3a1 100644 --- a/acme/autocert/autocert.go +++ b/acme/autocert/autocert.go @@ -35,6 +35,9 @@ import ( "golang.org/x/net/idna" ) +// DefaultACMEDirectory is the default ACME Directory URL used when the Manager's Client is nil. +const DefaultACMEDirectory = "https://acme-v02.api.letsencrypt.org/directory" + // createCertRetryAfter is how much time to wait before removing a failed state // entry due to an unsuccessful createCert call. // This is a variable instead of a const for testing. @@ -44,6 +47,8 @@ var createCertRetryAfter = time.Minute // pseudoRand is safe for concurrent use. var pseudoRand *lockedMathRand +var errPreRFC = errors.New("autocert: ACME server doesn't support RFC 8555") + func init() { src := mathrand.NewSource(time.Now().UnixNano()) pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} @@ -135,9 +140,10 @@ type Manager struct { // Client is used to perform low-level operations, such as account registration // and requesting new certificates. // - // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL - // as directory endpoint. If the Client.Key is nil, a new ECDSA P-256 key is - // generated and, if Cache is not nil, stored in cache. + // If Client is nil, a zero-value acme.Client is used with DefaultACMEDirectory + // as the directory endpoint. + // If the Client.Key is nil, a new ECDSA P-256 key is generated and, + // if Cache is not nil, stored in cache. // // Mutating the field after the first call of GetCertificate method will have no effect. Client *acme.Client @@ -164,6 +170,11 @@ type Manager struct { // in the template's ExtraExtensions field as is. ExtraExtensions []pkix.Extension + // ExternalAccountBinding optionally represents an arbitrary binding to an + // account of the CA to which the ACME server is tied. + // See RFC 8555, Section 7.3.4 for more details. + ExternalAccountBinding *acme.ExternalAccountBinding + clientMu sync.Mutex client *acme.Client // initialized by acmeClient method @@ -174,8 +185,8 @@ type Manager struct { renewalMu sync.Mutex renewal map[certKey]*domainRenewal - // tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens. - tokensMu sync.RWMutex + // challengeMu guards tryHTTP01, certTokens and httpTokens. + challengeMu sync.RWMutex // tryHTTP01 indicates whether the Manager should try "http-01" challenge type // during the authorization flow. tryHTTP01 bool @@ -188,6 +199,7 @@ type Manager struct { // and is keyed by the domain name which matches the ClientHello server name. // The entries are stored for the duration of the authorization flow. certTokens map[string]*tls.Certificate + // nowFunc, if not nil, returns the current time. This may be set for // testing purposes. nowFunc func() time.Time @@ -267,8 +279,8 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, // Check whether this is a token cert requested for TLS-ALPN challenge. if wantsTokenCert(hello) { - m.tokensMu.RLock() - defer m.tokensMu.RUnlock() + m.challengeMu.RLock() + defer m.challengeMu.RUnlock() if cert := m.certTokens[name]; cert != nil { return cert, nil } @@ -280,6 +292,10 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, } // regular domain + if err := m.hostPolicy()(ctx, name); err != nil { + return nil, err + } + ck := certKey{ domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114 isRSA: !supportsECDSA(hello), @@ -293,9 +309,6 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, } // first-time - if err := m.hostPolicy()(ctx, name); err != nil { - return nil, err - } cert, err = m.createCert(ctx, ck) if err != nil { return nil, err @@ -376,8 +389,8 @@ func supportsECDSA(hello *tls.ClientHelloInfo) bool { // If HTTPHandler is never called, the Manager will only use the "tls-alpn-01" // challenge for domain verification. func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { - m.tokensMu.Lock() - defer m.tokensMu.Unlock() + m.challengeMu.Lock() + defer m.challengeMu.Unlock() m.tryHTTP01 = true if fallback == nil { @@ -451,7 +464,7 @@ func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error leaf: cert.Leaf, } m.state[ck] = s - go m.renew(ck, s.key, s.leaf.NotAfter) + m.startRenew(ck, s.key, s.leaf.NotAfter) return cert, nil } @@ -577,8 +590,9 @@ func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, if err != nil { // Remove the failed state after some time, // making the manager call createCert again on the following TLS hello. + didRemove := testDidRemoveState // The lifetime of this timer is untracked, so copy mutable local state to avoid races. time.AfterFunc(createCertRetryAfter, func() { - defer testDidRemoveState(ck) + defer didRemove(ck) m.stateMu.Lock() defer m.stateMu.Unlock() // Verify the state hasn't changed and it's still invalid @@ -596,7 +610,7 @@ func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, } state.cert = der state.leaf = leaf - go m.renew(ck, state.key, state.leaf.NotAfter) + m.startRenew(ck, state.key, state.leaf.NotAfter) return state.tlscert() } @@ -640,120 +654,152 @@ func (m *Manager) certState(ck certKey) (*certState, error) { // authorizedCert starts the domain ownership verification process and requests a new cert upon success. // The key argument is the certificate private key. func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) { - client, err := m.acmeClient(ctx) + csr, err := certRequest(key, ck.domain, m.ExtraExtensions) if err != nil { return nil, nil, err } - if err := m.verify(ctx, client, ck.domain); err != nil { + client, err := m.acmeClient(ctx) + if err != nil { return nil, nil, err } - csr, err := certRequest(key, ck.domain, m.ExtraExtensions) + dir, err := client.Discover(ctx) if err != nil { return nil, nil, err } - der, _, err = client.CreateCert(ctx, csr, 0, true) + if dir.OrderURL == "" { + return nil, nil, errPreRFC + } + + o, err := m.verifyRFC(ctx, client, ck.domain) if err != nil { return nil, nil, err } - leaf, err = validCert(ck, der, key, m.now()) + chain, _, err := client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) if err != nil { return nil, nil, err } - 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) + leaf, err = validCert(ck, chain, key, m.now()) if err != nil { - return - } - for _, u := range uri { - client.RevokeAuthorization(ctx, u) + return nil, nil, err } + return chain, leaf, nil } -// verify runs the identifier (domain) authorization flow +// verifyRFC runs the identifier (domain) order-based authorization flow for RFC compliant CAs // using each applicable ACME challenge type. -func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error { - // The list of challenge types we'll try to fulfill - // in this specific order. - challengeTypes := []string{"tls-alpn-01"} - m.tokensMu.RLock() - if m.tryHTTP01 { - challengeTypes = append(challengeTypes, "http-01") - } - 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) - } - }() - - // errs accumulates challenge failure errors, printed if all fail - errs := make(map[*acme.Challenge]error) - var nextTyp int // challengeType index of the next challenge type to try +func (m *Manager) verifyRFC(ctx context.Context, client *acme.Client, domain string) (*acme.Order, error) { + // Try each supported challenge type starting with a new order each time. + // The nextTyp index of the next challenge type to try is shared across + // all order authorizations: if we've tried a challenge type once and it didn't work, + // it will most likely not work on another order's authorization either. + challengeTypes := m.supportedChallengeTypes() + nextTyp := 0 // challengeTypes index +AuthorizeOrderLoop: for { - // Start domain authorization and get the challenge. - authz, err := client.Authorize(ctx, domain) + o, err := client.AuthorizeOrder(ctx, acme.DomainIDs(domain)) if err != nil { - return err + return nil, err } - // No point in accepting challenges if the authorization status - // is in a final state. - switch authz.Status { - case acme.StatusValid: - return nil // already authorized - case acme.StatusInvalid: - return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI) + // Remove all hanging authorizations to reduce rate limit quotas + // after we're done. + defer func(urls []string) { + go m.deactivatePendingAuthz(urls) + }(o.AuthzURLs) + + // Check if there's actually anything we need to do. + switch o.Status { + case acme.StatusReady: + // Already authorized. + return o, nil + case acme.StatusPending: + // Continue normal Order-based flow. + default: + return nil, fmt.Errorf("acme/autocert: invalid new order status %q; order URL: %q", o.Status, o.URI) } - pendingAuthzs[authz.URI] = true - - // Pick the next preferred challenge. - var chal *acme.Challenge - for chal == nil && nextTyp < len(challengeTypes) { - chal = pickChallenge(challengeTypes[nextTyp], authz.Challenges) - nextTyp++ - } - if chal == nil { - errorMsg := fmt.Sprintf("acme/autocert: unable to authorize %q", domain) - for chal, err := range errs { - errorMsg += fmt.Sprintf("; challenge %q failed with error: %v", chal.Type, err) + // Satisfy all pending authorizations. + for _, zurl := range o.AuthzURLs { + z, err := client.GetAuthorization(ctx, zurl) + if err != nil { + return nil, err + } + if z.Status != acme.StatusPending { + // We are interested only in pending authorizations. + continue + } + // Pick the next preferred challenge. + var chal *acme.Challenge + for chal == nil && nextTyp < len(challengeTypes) { + chal = pickChallenge(challengeTypes[nextTyp], z.Challenges) + nextTyp++ + } + if chal == nil { + return nil, fmt.Errorf("acme/autocert: unable to satisfy %q for domain %q: no viable challenge type found", z.URI, domain) + } + // Respond to the challenge and wait for validation result. + cleanup, err := m.fulfill(ctx, client, chal, domain) + if err != nil { + continue AuthorizeOrderLoop + } + defer cleanup() + if _, err := client.Accept(ctx, chal); err != nil { + continue AuthorizeOrderLoop + } + if _, err := client.WaitAuthorization(ctx, z.URI); err != nil { + continue AuthorizeOrderLoop } - return errors.New(errorMsg) } - cleanup, err := m.fulfill(ctx, client, chal, domain) + + // All authorizations are satisfied. + // Wait for the CA to update the order status. + o, err = client.WaitOrder(ctx, o.URI) if err != nil { - errs[chal] = err - continue + continue AuthorizeOrderLoop } - defer cleanup() - if _, err := client.Accept(ctx, chal); err != nil { - errs[chal] = err - continue + return o, nil + } +} + +func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { + for _, c := range chal { + if c.Type == typ { + return c } + } + return nil +} - // A challenge is fulfilled and accepted: wait for the CA to validate. - if _, err := client.WaitAuthorization(ctx, authz.URI); err != nil { - errs[chal] = err - continue +func (m *Manager) supportedChallengeTypes() []string { + m.challengeMu.RLock() + defer m.challengeMu.RUnlock() + typ := []string{"tls-alpn-01"} + if m.tryHTTP01 { + typ = append(typ, "http-01") + } + return typ +} + +// deactivatePendingAuthz relinquishes all authorizations identified by the elements +// of the provided uri slice which are in "pending" state. +// It ignores revocation errors. +// +// deactivatePendingAuthz takes no context argument and instead runs with its own +// "detached" context because deactivations are done in a goroutine separate from +// that of the main issuance or renewal flow. +func (m *Manager) deactivatePendingAuthz(uri []string) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + client, err := m.acmeClient(ctx) + if err != nil { + return + } + for _, u := range uri { + z, err := client.GetAuthorization(ctx, u) + if err == nil && z.Status == acme.StatusPending { + client.RevokeAuthorization(ctx, u) } - delete(pendingAuthzs, authz.URI) - return nil } } @@ -780,20 +826,11 @@ func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.C return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type) } -func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { - for _, c := range chal { - if c.Type == typ { - return c - } - } - return nil -} - // putCertToken stores the token certificate with the specified name // in both m.certTokens map and m.Cache. func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { - m.tokensMu.Lock() - defer m.tokensMu.Unlock() + m.challengeMu.Lock() + defer m.challengeMu.Unlock() if m.certTokens == nil { m.certTokens = make(map[string]*tls.Certificate) } @@ -804,8 +841,8 @@ func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certi // deleteCertToken removes the token certificate with the specified name // from both m.certTokens map and m.Cache. func (m *Manager) deleteCertToken(name string) { - m.tokensMu.Lock() - defer m.tokensMu.Unlock() + m.challengeMu.Lock() + defer m.challengeMu.Unlock() delete(m.certTokens, name) if m.Cache != nil { ck := certKey{domain: name, isToken: true} @@ -816,8 +853,8 @@ func (m *Manager) deleteCertToken(name string) { // httpToken retrieves an existing http-01 token value from an in-memory map // or the optional cache. func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) { - m.tokensMu.RLock() - defer m.tokensMu.RUnlock() + m.challengeMu.RLock() + defer m.challengeMu.RUnlock() if v, ok := m.httpTokens[tokenPath]; ok { return v, nil } @@ -832,8 +869,8 @@ func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, erro // // It ignores any error returned from Cache.Put. func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) { - m.tokensMu.Lock() - defer m.tokensMu.Unlock() + m.challengeMu.Lock() + defer m.challengeMu.Unlock() if m.httpTokens == nil { m.httpTokens = make(map[string][]byte) } @@ -849,8 +886,8 @@ func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) { // // If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout. func (m *Manager) deleteHTTPToken(tokenPath string) { - m.tokensMu.Lock() - defer m.tokensMu.Unlock() + m.challengeMu.Lock() + defer m.challengeMu.Unlock() delete(m.httpTokens, tokenPath) if m.Cache != nil { m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath)) @@ -863,7 +900,7 @@ func httpTokenCacheKey(tokenPath string) string { return path.Base(tokenPath) + "+http-01" } -// renew starts a cert renewal timer loop, one per domain. +// startRenew starts a cert renewal timer loop, one per domain. // // The loop is scheduled in two cases: // - a cert was fetched from cache for the first time (wasn't in m.state) @@ -871,7 +908,7 @@ func httpTokenCacheKey(tokenPath string) string { // // The key argument is a certificate private key. // The exp argument is the cert expiration time (NotAfter). -func (m *Manager) renew(ck certKey, key crypto.Signer, exp time.Time) { +func (m *Manager) startRenew(ck certKey, key crypto.Signer, exp time.Time) { m.renewalMu.Lock() defer m.renewalMu.Unlock() if m.renewal[ck] != nil { @@ -949,7 +986,7 @@ func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) { client := m.Client if client == nil { - client = &acme.Client{DirectoryURL: acme.LetsEncryptURL} + client = &acme.Client{DirectoryURL: DefaultACMEDirectory} } if client.Key == nil { var err error @@ -965,16 +1002,25 @@ func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) { if m.Email != "" { contact = []string{"mailto:" + m.Email} } - a := &acme.Account{Contact: contact} + a := &acme.Account{Contact: contact, ExternalAccountBinding: m.ExternalAccountBinding} _, err := client.Register(ctx, a, m.Prompt) - if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict { - // conflict indicates the key is already registered + if err == nil || isAccountAlreadyExist(err) { m.client = client err = nil } return m.client, err } +// isAccountAlreadyExist reports whether the err, as returned from acme.Client.Register, +// indicates the account has already been registered. +func isAccountAlreadyExist(err error) bool { + if err == acme.ErrAccountAlreadyExists { + return true + } + ae, ok := err.(*acme.Error) + return ok && ae.StatusCode == http.StatusConflict +} + func (m *Manager) hostPolicy() HostPolicy { if m.HostPolicy != nil { return m.HostPolicy @@ -1021,11 +1067,11 @@ func (s *certState) tlscert() (*tls.Certificate, error) { }, nil } -// certRequest generates a CSR for the given common name cn and optional SANs. -func certRequest(key crypto.Signer, cn string, ext []pkix.Extension, san ...string) ([]byte, error) { +// certRequest generates a CSR for the given common name. +func certRequest(key crypto.Signer, name string, ext []pkix.Extension) ([]byte, error) { req := &x509.CertificateRequest{ - Subject: pkix.Name{CommonName: cn}, - DNSNames: san, + Subject: pkix.Name{CommonName: name}, + DNSNames: []string{name}, ExtraExtensions: ext, } return x509.CreateCertificateRequest(rand.Reader, req, key) @@ -1088,6 +1134,10 @@ func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf if err := leaf.VerifyHostname(ck.domain); err != nil { return nil, err } + // renew certificates revoked by Let's Encrypt in January 2022 + if isRevokedLetsEncrypt(leaf) { + return nil, errors.New("acme/autocert: certificate was probably revoked by Let's Encrypt") + } // ensure the leaf corresponds to the private key and matches the certKey type switch pub := leaf.PublicKey.(type) { case *rsa.PublicKey: @@ -1118,6 +1168,18 @@ func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf return leaf, nil } +// https://community.letsencrypt.org/t/2022-01-25-issue-with-tls-alpn-01-validation-method/170450 +var letsEncryptFixDeployTime = time.Date(2022, time.January, 26, 00, 48, 0, 0, time.UTC) + +// isRevokedLetsEncrypt returns whether the certificate is likely to be part of +// a batch of certificates revoked by Let's Encrypt in January 2022. This check +// can be safely removed from May 2022. +func isRevokedLetsEncrypt(cert *x509.Certificate) bool { + O := cert.Issuer.Organization + return len(O) == 1 && O[0] == "Let's Encrypt" && + cert.NotBefore.Before(letsEncryptFixDeployTime) +} + type lockedMathRand struct { sync.Mutex rnd *mathrand.Rand diff --git a/acme/autocert/autocert_test.go b/acme/autocert/autocert_test.go index 6020e55ae6..8ca8e2b3a7 100644 --- a/acme/autocert/autocert_test.go +++ b/acme/autocert/autocert_test.go @@ -16,12 +16,8 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/asn1" - "encoding/base64" - "encoding/json" "fmt" - "html/template" "io" - "io/ioutil" "math/big" "net/http" "net/http/httptest" @@ -41,33 +37,6 @@ var ( exampleCertKeyRSA = certKey{domain: exampleDomain, isRSA: true} ) -var discoTmpl = template.Must(template.New("disco").Parse(`{ - "new-reg": "{{.}}/new-reg", - "new-authz": "{{.}}/new-authz", - "new-cert": "{{.}}/new-cert" -}`)) - -var authzTmpl = template.Must(template.New("authz").Parse(`{ - "status": "pending", - "challenges": [ - { - "uri": "{{.}}/challenge/tls-alpn-01", - "type": "tls-alpn-01", - "token": "token-alpn" - }, - { - "uri": "{{.}}/challenge/dns-01", - "type": "dns-01", - "token": "token-dns-01" - }, - { - "uri": "{{.}}/challenge/http-01", - "type": "http-01", - "token": "token-http-01" - } - ] -}`)) - type memCache struct { t *testing.T mu sync.Mutex @@ -154,7 +123,7 @@ func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte return nil, err } t := &x509.Certificate{ - SerialNumber: big.NewInt(1), + SerialNumber: randomSerial(), NotBefore: start, NotAfter: end, BasicConstraintsValid: true, @@ -167,16 +136,12 @@ func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte return x509.CreateCertificate(rand.Reader, t, t, pub, key) } -func decodePayload(v interface{}, r io.Reader) error { - var req struct{ Payload string } - if err := json.NewDecoder(r).Decode(&req); err != nil { - return err - } - payload, err := base64.RawURLEncoding.DecodeString(req.Payload) +func randomSerial() *big.Int { + serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 32)) if err != nil { - return err + panic(err) } - return json.Unmarshal(payload, v) + return serial } type algorithmSupport int @@ -197,115 +162,314 @@ func clientHelloInfo(sni string, alg algorithmSupport) *tls.ClientHelloInfo { return hello } -// tokenCertFn returns a function suitable for startACMEServerStub. -// The returned function simulates a TLS hello request from a CA -// during validation of a tls-alpn-01 challenge. -func tokenCertFn(man *Manager, alg algorithmSupport) getCertificateFunc { - return func(sni string) (*tls.Certificate, error) { - hello := clientHelloInfo(sni, alg) - hello.SupportedProtos = []string{acme.ALPNProto} - return man.GetCertificate(hello) +func testManager(t *testing.T) *Manager { + man := &Manager{ + Prompt: AcceptTOS, + Cache: newMemCache(t), } + t.Cleanup(man.stopRenew) + return man } func TestGetCertificate(t *testing.T) { - man := &Manager{Prompt: AcceptTOS} - defer man.stopRenew() - hello := clientHelloInfo("example.org", algECDSA) - testGetCertificate(t, man, "example.org", hello) -} - -func TestGetCertificate_trailingDot(t *testing.T) { - man := &Manager{Prompt: AcceptTOS} - defer man.stopRenew() - hello := clientHelloInfo("example.org.", algECDSA) - testGetCertificate(t, man, "example.org", hello) -} - -func TestGetCertificate_unicodeIDN(t *testing.T) { - man := &Manager{Prompt: AcceptTOS} - defer man.stopRenew() - - hello := clientHelloInfo("σσσ.com", algECDSA) - testGetCertificate(t, man, "xn--4xaaa.com", hello) - - hello = clientHelloInfo("σςΣ.com", algECDSA) - testGetCertificate(t, man, "xn--4xaaa.com", hello) -} - -func TestGetCertificate_mixedcase(t *testing.T) { - man := &Manager{Prompt: AcceptTOS} - defer man.stopRenew() + tests := []struct { + name string + hello *tls.ClientHelloInfo + domain string + expectError string + prepare func(t *testing.T, man *Manager, s *acmetest.CAServer) + verify func(t *testing.T, man *Manager, leaf *x509.Certificate) + disableALPN bool + disableHTTP bool + }{ + { + name: "ALPN", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + disableHTTP: true, + }, + { + name: "HTTP", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + disableALPN: true, + }, + { + name: "nilPrompt", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + man.Prompt = nil + }, + expectError: "Manager.Prompt not set", + }, + { + name: "trailingDot", + hello: clientHelloInfo("example.org.", algECDSA), + domain: "example.org", + }, + { + name: "unicodeIDN", + hello: clientHelloInfo("éé.com", algECDSA), + domain: "xn--9caa.com", + }, + { + name: "unicodeIDN/mixedCase", + hello: clientHelloInfo("éÉ.com", algECDSA), + domain: "xn--9caa.com", + }, + { + name: "upperCase", + hello: clientHelloInfo("EXAMPLE.ORG", algECDSA), + domain: "example.org", + }, + { + name: "goodCache", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + // Make a valid cert and cache it. + c := s.Start().LeafCert(exampleDomain, "ECDSA", + // Use a time before the Let's Encrypt revocation cutoff to also test + // that non-Let's Encrypt certificates are not renewed. + time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), + time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), + ) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + }, + // Break the server to check that the cache is used. + disableALPN: true, disableHTTP: true, + }, + { + name: "expiredCache", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + // Make an expired cert and cache it. + c := s.Start().LeafCert(exampleDomain, "ECDSA", time.Now().Add(-10*time.Minute), time.Now().Add(-5*time.Minute)) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + }, + }, + { + name: "forceRSA", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + man.ForceRSA = true + }, + verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { + if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { + t.Errorf("leaf.PublicKey is %T; want *ecdsa.PublicKey", leaf.PublicKey) + } + }, + }, + { + name: "goodLetsEncrypt", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + // Make a valid certificate issued after the TLS-ALPN-01 + // revocation window and cache it. + s.IssuerName(pkix.Name{Country: []string{"US"}, + Organization: []string{"Let's Encrypt"}, CommonName: "R3"}) + c := s.Start().LeafCert(exampleDomain, "ECDSA", + time.Date(2022, time.January, 26, 12, 0, 0, 0, time.UTC), + time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), + ) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + }, + // Break the server to check that the cache is used. + disableALPN: true, disableHTTP: true, + }, + { + name: "revokedLetsEncrypt", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + // Make a certificate issued during the TLS-ALPN-01 + // revocation window and cache it. + s.IssuerName(pkix.Name{Country: []string{"US"}, + Organization: []string{"Let's Encrypt"}, CommonName: "R3"}) + c := s.Start().LeafCert(exampleDomain, "ECDSA", + time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), + time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), + ) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + }, + verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { + if leaf.NotBefore.Before(time.Now().Add(-10 * time.Minute)) { + t.Error("certificate was not reissued") + } + }, + }, + { + // TestGetCertificate/tokenCache tests the fallback of token + // certificate fetches to cache when Manager.certTokens misses. + name: "tokenCacheALPN", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + // Make a separate manager with a shared cache, simulating + // separate nodes that serve requests for the same domain. + man2 := testManager(t) + man2.Cache = man.Cache + // Redirect the verification request to man2, although the + // client request will hit man, testing that they can complete a + // verification by communicating through the cache. + s.ResolveGetCertificate("example.org", man2.GetCertificate) + }, + // Drop the default verification paths. + disableALPN: true, + }, + { + name: "tokenCacheHTTP", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + man2 := testManager(t) + man2.Cache = man.Cache + s.ResolveHandler("example.org", man2.HTTPHandler(nil)) + }, + disableHTTP: true, + }, + { + name: "ecdsa", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { + if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { + t.Error("an ECDSA client was served a non-ECDSA certificate") + } + }, + }, + { + name: "rsa", + hello: clientHelloInfo("example.org", algRSA), + domain: "example.org", + verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { + if _, ok := leaf.PublicKey.(*rsa.PublicKey); !ok { + t.Error("an RSA client was served a non-RSA certificate") + } + }, + }, + { + name: "wrongCacheKeyType", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + // Make an RSA cert and cache it without suffix. + c := s.Start().LeafCert(exampleDomain, "RSA", time.Now(), time.Now().Add(90*24*time.Hour)) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + }, + verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { + // The RSA cached cert should be silently ignored and replaced. + if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { + t.Error("an ECDSA client was served a non-ECDSA certificate") + } + if numCerts := man.Cache.(*memCache).numCerts(); numCerts != 1 { + t.Errorf("found %d certificates in cache; want %d", numCerts, 1) + } + }, + }, + { + name: "almostExpiredCache", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + man.RenewBefore = 24 * time.Hour + // Cache an almost expired cert. + c := s.Start().LeafCert(exampleDomain, "ECDSA", time.Now(), time.Now().Add(10*time.Minute)) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + }, + }, + { + name: "provideExternalAuth", + hello: clientHelloInfo("example.org", algECDSA), + domain: "example.org", + prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { + s.ExternalAccountRequired() + + man.ExternalAccountBinding = &acme.ExternalAccountBinding{ + KID: "test-key", + Key: make([]byte, 32), + } + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + man := testManager(t) + s := acmetest.NewCAServer(t) + if !tt.disableALPN { + s.ResolveGetCertificate(tt.domain, man.GetCertificate) + } + if !tt.disableHTTP { + s.ResolveHandler(tt.domain, man.HTTPHandler(nil)) + } - hello := clientHelloInfo("example.org", algECDSA) - testGetCertificate(t, man, "example.org", hello) + if tt.prepare != nil { + tt.prepare(t, man, s) + } - hello = clientHelloInfo("EXAMPLE.ORG", algECDSA) - testGetCertificate(t, man, "example.org", hello) -} + s.Start() -func TestGetCertificate_ForceRSA(t *testing.T) { - man := &Manager{ - Prompt: AcceptTOS, - Cache: newMemCache(t), - ForceRSA: true, - } - defer man.stopRenew() - hello := clientHelloInfo(exampleDomain, algECDSA) - testGetCertificate(t, man, exampleDomain, hello) + man.Client = &acme.Client{DirectoryURL: s.URL()} - // ForceRSA was deprecated and is now ignored. - cert, err := man.cacheGet(context.Background(), exampleCertKey) - if err != nil { - t.Fatalf("man.cacheGet: %v", err) - } - if _, ok := cert.PrivateKey.(*ecdsa.PrivateKey); !ok { - t.Errorf("cert.PrivateKey is %T; want *ecdsa.PrivateKey", cert.PrivateKey) - } -} + tlscert, err := man.GetCertificate(tt.hello) + if tt.expectError != "" { + if err == nil { + t.Fatal("expected error, got certificate") + } + if !strings.Contains(err.Error(), tt.expectError) { + t.Errorf("got %q, expected %q", err, tt.expectError) + } + return + } + if err != nil { + t.Fatalf("man.GetCertificate: %v", err) + } -func TestGetCertificate_nilPrompt(t *testing.T) { - man := &Manager{} - defer man.stopRenew() - url, finish := startACMEServerStub(t, tokenCertFn(man, algECDSA), "example.org") - defer finish() - man.Client = &acme.Client{DirectoryURL: url} - hello := clientHelloInfo("example.org", algECDSA) - if _, err := man.GetCertificate(hello); err == nil { - t.Error("got certificate for example.org; wanted error") - } -} + leaf, err := x509.ParseCertificate(tlscert.Certificate[0]) + if err != nil { + t.Fatal(err) + } + opts := x509.VerifyOptions{ + DNSName: tt.domain, + Intermediates: x509.NewCertPool(), + Roots: s.Roots(), + } + for _, cert := range tlscert.Certificate[1:] { + c, err := x509.ParseCertificate(cert) + if err != nil { + t.Fatal(err) + } + opts.Intermediates.AddCert(c) + } + if _, err := leaf.Verify(opts); err != nil { + t.Error(err) + } -func TestGetCertificate_expiredCache(t *testing.T) { - // Make an expired cert and cache it. - pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } - tmpl := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{CommonName: exampleDomain}, - NotAfter: time.Now(), - } - pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk) - if err != nil { - t.Fatal(err) - } - tlscert := &tls.Certificate{ - Certificate: [][]byte{pub}, - PrivateKey: pk, - } + if san := leaf.DNSNames[0]; san != tt.domain { + t.Errorf("got SAN %q, expected %q", san, tt.domain) + } - man := &Manager{Prompt: AcceptTOS, Cache: newMemCache(t)} - defer man.stopRenew() - if err := man.cachePut(context.Background(), exampleCertKey, tlscert); err != nil { - t.Fatalf("man.cachePut: %v", err) + if tt.verify != nil { + tt.verify(t, man, leaf) + } + }) } - - // The expired cached cert should trigger a new cert issuance - // and return without an error. - hello := clientHelloInfo(exampleDomain, algECDSA) - testGetCertificate(t, man, exampleDomain, hello) } func TestGetCertificate_failedAttempt(t *testing.T) { @@ -340,499 +504,47 @@ func TestGetCertificate_failedAttempt(t *testing.T) { if _, err := man.GetCertificate(hello); err == nil { t.Error("GetCertificate: err is nil") } - select { - case <-time.After(5 * time.Second): - t.Errorf("took too long to remove the %q state", exampleCertKey) - case <-done: - man.stateMu.Lock() - defer man.stateMu.Unlock() - if v, exist := man.state[exampleCertKey]; exist { - t.Errorf("state exists for %v: %+v", exampleCertKey, v) - } - } -} - -// testGetCertificate_tokenCache tests the fallback of token certificate fetches -// to cache when Manager.certTokens misses. -// algorithmSupport refers to the CA when verifying the certificate token. -func testGetCertificate_tokenCache(t *testing.T, tokenAlg algorithmSupport) { - man1 := &Manager{ - Cache: newMemCache(t), - Prompt: AcceptTOS, - } - defer man1.stopRenew() - man2 := &Manager{ - Cache: man1.Cache, - Prompt: AcceptTOS, - } - defer man2.stopRenew() - // Send the verification request to a different Manager from the one that - // initiated the authorization, when they share caches. - url, finish := startACMEServerStub(t, tokenCertFn(man2, tokenAlg), "example.org") - defer finish() - man1.Client = &acme.Client{DirectoryURL: url} - hello := clientHelloInfo("example.org", algECDSA) - if _, err := man1.GetCertificate(hello); err != nil { - t.Error(err) + <-done + man.stateMu.Lock() + defer man.stateMu.Unlock() + if v, exist := man.state[exampleCertKey]; exist { + t.Errorf("state exists for %v: %+v", exampleCertKey, v) } - if _, err := man2.GetCertificate(hello); err != nil { - t.Error(err) - } -} - -func TestGetCertificate_tokenCache(t *testing.T) { - t.Run("ecdsaSupport=true", func(t *testing.T) { - testGetCertificate_tokenCache(t, algECDSA) - }) - t.Run("ecdsaSupport=false", func(t *testing.T) { - testGetCertificate_tokenCache(t, algRSA) - }) } -func TestGetCertificate_ecdsaVsRSA(t *testing.T) { - cache := newMemCache(t) - man := &Manager{Prompt: AcceptTOS, Cache: cache} - defer man.stopRenew() - url, finish := startACMEServerStub(t, tokenCertFn(man, algECDSA), "example.org") - defer finish() - man.Client = &acme.Client{DirectoryURL: url} - - cert, err := man.GetCertificate(clientHelloInfo("example.org", algECDSA)) - if err != nil { - t.Error(err) - } - if _, ok := cert.Leaf.PublicKey.(*ecdsa.PublicKey); !ok { - t.Error("an ECDSA client was served a non-ECDSA certificate") - } - - cert, err = man.GetCertificate(clientHelloInfo("example.org", algRSA)) - if err != nil { - t.Error(err) - } - if _, ok := cert.Leaf.PublicKey.(*rsa.PublicKey); !ok { - t.Error("a RSA client was served a non-RSA certificate") - } - - if _, err := man.GetCertificate(clientHelloInfo("example.org", algECDSA)); err != nil { - t.Error(err) - } - if _, err := man.GetCertificate(clientHelloInfo("example.org", algRSA)); err != nil { - t.Error(err) - } - if numCerts := cache.numCerts(); numCerts != 2 { - t.Errorf("found %d certificates in cache; want %d", numCerts, 2) - } -} - -func TestGetCertificate_wrongCacheKeyType(t *testing.T) { - cache := newMemCache(t) - man := &Manager{Prompt: AcceptTOS, Cache: cache} - defer man.stopRenew() - url, finish := startACMEServerStub(t, tokenCertFn(man, algECDSA), exampleDomain) - defer finish() - man.Client = &acme.Client{DirectoryURL: url} +func TestRevokeFailedAuthz(t *testing.T) { + ca := acmetest.NewCAServer(t) + // Make the authz unfulfillable on the client side, so it will be left + // pending at the end of the verification attempt. + ca.ChallengeTypes("fake-01", "fake-02") + ca.Start() - // Make an RSA cert and cache it without suffix. - pk, err := rsa.GenerateKey(rand.Reader, 512) - if err != nil { - t.Fatal(err) - } - tmpl := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{CommonName: exampleDomain}, - NotAfter: time.Now().Add(90 * 24 * time.Hour), - } - pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk) - if err != nil { - t.Fatal(err) - } - rsaCert := &tls.Certificate{ - Certificate: [][]byte{pub}, - PrivateKey: pk, - } - if err := man.cachePut(context.Background(), exampleCertKey, rsaCert); err != nil { - t.Fatalf("man.cachePut: %v", err) - } + m := testManager(t) + m.Client = &acme.Client{DirectoryURL: ca.URL()} - // The RSA cached cert should be silently ignored and replaced. - cert, err := man.GetCertificate(clientHelloInfo(exampleDomain, algECDSA)) - if err != nil { - t.Error(err) - } - if _, ok := cert.Leaf.PublicKey.(*ecdsa.PublicKey); !ok { - t.Error("an ECDSA client was served a non-ECDSA certificate") - } - if numCerts := cache.numCerts(); numCerts != 1 { - t.Errorf("found %d certificates in cache; want %d", numCerts, 1) + _, err := m.GetCertificate(clientHelloInfo("example.org", algECDSA)) + if err == nil { + t.Fatal("expected GetCertificate to fail") } -} - -type getCertificateFunc func(domain string) (*tls.Certificate, error) -// startACMEServerStub runs an ACME server -// The domain argument is the expected domain name of a certificate request. -// TODO: Drop this in favour of x/crypto/acme/autocert/internal/acmetest. -func startACMEServerStub(t *testing.T, tokenCert getCertificateFunc, domain string) (url string, finish func()) { - verifyTokenCert := func() { - tlscert, err := tokenCert(domain) + logTicker := time.NewTicker(3 * time.Second) + defer logTicker.Stop() + for { + authz, err := m.Client.GetAuthorization(context.Background(), ca.URL()+"/authz/0") if err != nil { - t.Errorf("verifyTokenCert: tokenCert(%q): %v", domain, err) - return - } - crt, err := x509.ParseCertificate(tlscert.Certificate[0]) - if err != nil { - t.Errorf("verifyTokenCert: x509.ParseCertificate: %v", err) - } - if err := crt.VerifyHostname(domain); err != nil { - t.Errorf("verifyTokenCert: %v", err) + t.Fatal(err) } - // TODO: Update OID to the latest value 1.3.6.1.5.5.7.1.31 - // See https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1 - oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1} - for _, x := range crt.Extensions { - if x.Id.Equal(oid) { - // No need to check the extension value here. - // This is done in acme package tests. - return - } - } - t.Error("verifyTokenCert: no id-pe-acmeIdentifier extension found") - } - - // ACME CA server stub - var ca *httptest.Server - ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Replay-Nonce", "nonce") - if r.Method == "HEAD" { - // a nonce request + if authz.Status == acme.StatusDeactivated { return } - switch r.URL.Path { - // discovery - case "/": - if err := discoTmpl.Execute(w, ca.URL); err != nil { - t.Errorf("discoTmpl: %v", err) - } - // client key registration - case "/new-reg": - w.Write([]byte("{}")) - // domain authorization - case "/new-authz": - w.Header().Set("Location", ca.URL+"/authz/1") - w.WriteHeader(http.StatusCreated) - if err := authzTmpl.Execute(w, ca.URL); err != nil { - t.Errorf("authzTmpl: %v", err) - } - // accept tls-alpn-01 challenge - case "/challenge/tls-alpn-01": - verifyTokenCert() - w.Write([]byte("{}")) - // authorization status - case "/authz/1": - w.Write([]byte(`{"status": "valid"}`)) - // cert request - case "/new-cert": - var req struct { - CSR string `json:"csr"` - } - decodePayload(&req, r.Body) - b, _ := base64.RawURLEncoding.DecodeString(req.CSR) - csr, err := x509.ParseCertificateRequest(b) - if err != nil { - t.Errorf("new-cert: CSR: %v", err) - } - if csr.Subject.CommonName != domain { - t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain) - } - der, err := dummyCert(csr.PublicKey, domain) - if err != nil { - t.Errorf("new-cert: dummyCert: %v", err) - } - chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL) - w.Header().Set("Link", chainUp) - w.WriteHeader(http.StatusCreated) - w.Write(der) - // CA chain cert - case "/ca-cert": - der, err := dummyCert(nil, "ca") - if err != nil { - t.Errorf("ca-cert: dummyCert: %v", err) - } - w.Write(der) - default: - t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) - } - })) - finish = func() { - ca.Close() - - // make sure token cert was removed - cancel := make(chan struct{}) - done := make(chan struct{}) - go func() { - defer close(done) - tick := time.NewTicker(100 * time.Millisecond) - defer tick.Stop() - for { - if _, err := tokenCert(domain); err != nil { - return - } - select { - case <-tick.C: - case <-cancel: - return - } - } - }() select { - case <-done: - case <-time.After(5 * time.Second): - close(cancel) - t.Error("token cert was not removed") - <-done - } - } - return ca.URL, finish -} - -// tests man.GetCertificate flow using the provided hello argument. -// The domain argument is the expected domain name of a certificate request. -func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) { - url, finish := startACMEServerStub(t, tokenCertFn(man, algECDSA), domain) - defer finish() - man.Client = &acme.Client{DirectoryURL: url} - - // simulate tls.Config.GetCertificate - var tlscert *tls.Certificate - var err error - done := make(chan struct{}) - go func() { - tlscert, err = man.GetCertificate(hello) - close(done) - }() - select { - case <-time.After(time.Minute): - t.Fatal("man.GetCertificate took too long to return") - case <-done: - } - if err != nil { - t.Fatalf("man.GetCertificate: %v", err) - } - - // verify the tlscert is the same we responded with from the CA stub - if len(tlscert.Certificate) == 0 { - t.Fatal("len(tlscert.Certificate) is 0") - } - cert, err := x509.ParseCertificate(tlscert.Certificate[0]) - if err != nil { - t.Fatalf("x509.ParseCertificate: %v", err) - } - if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain { - t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain) - } - -} - -func TestVerifyHTTP01(t *testing.T) { - var ( - http01 http.Handler - - authzCount int // num. of created authorizations - didAcceptHTTP01 bool - ) - - verifyHTTPToken := func() { - r := httptest.NewRequest("GET", "/.well-known/acme-challenge/token-http-01", nil) - w := httptest.NewRecorder() - http01.ServeHTTP(w, r) - if w.Code != http.StatusOK { - t.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) - } - if v := w.Body.String(); !strings.HasPrefix(v, "token-http-01.") { - t.Errorf("http token value = %q; want 'token-http-01.' prefix", v) - } - } - - // ACME CA server stub, only the needed bits. - // TODO: Replace this with x/crypto/acme/autocert/internal/acmetest. - var ca *httptest.Server - ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Replay-Nonce", "nonce") - if r.Method == "HEAD" { - // a nonce request - return - } - - switch r.URL.Path { - // Discovery. - case "/": - if err := discoTmpl.Execute(w, ca.URL); err != nil { - t.Errorf("discoTmpl: %v", err) - } - // Client key registration. - case "/new-reg": - w.Write([]byte("{}")) - // New domain authorization. - case "/new-authz": - authzCount++ - w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount)) - w.WriteHeader(http.StatusCreated) - if err := authzTmpl.Execute(w, ca.URL); err != nil { - t.Errorf("authzTmpl: %v", err) - } - // Reject tls-alpn-01. - case "/challenge/tls-alpn-01": - http.Error(w, "won't accept tls-sni-01", http.StatusBadRequest) - // Should not accept dns-01. - case "/challenge/dns-01": - t.Errorf("dns-01 challenge was accepted") - http.Error(w, "won't accept dns-01", http.StatusBadRequest) - // Accept http-01. - case "/challenge/http-01": - didAcceptHTTP01 = true - verifyHTTPToken() - w.Write([]byte("{}")) - // Authorization statuses. - case "/authz/1": // tls-alpn-01 - w.Write([]byte(`{"status": "invalid"}`)) - case "/authz/2": // http-01 - w.Write([]byte(`{"status": "valid"}`)) - default: - http.NotFound(w, r) - t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) - } - })) - defer ca.Close() - - m := &Manager{ - Client: &acme.Client{ - DirectoryURL: ca.URL, - }, - } - http01 = m.HTTPHandler(nil) - ctx := context.Background() - client, err := m.acmeClient(ctx) - if err != nil { - t.Fatalf("m.acmeClient: %v", err) - } - if err := m.verify(ctx, client, "example.org"); err != nil { - t.Errorf("m.verify: %v", err) - } - // Only tls-alpn-01 and http-01 must be accepted. - // The dns-01 challenge is unsupported. - if authzCount != 2 { - t.Errorf("authzCount = %d; want 2", authzCount) - } - if !didAcceptHTTP01 { - t.Error("did not accept http-01 challenge") - } -} - -func TestRevokeFailedAuthz(t *testing.T) { - // Prefill authorization URIs expected to be revoked. - // The challenges are selected in a specific order, - // each tried within a newly created authorization. - // This means each authorization URI corresponds to a different challenge type. - revokedAuthz := map[string]bool{ - "/authz/0": false, // tls-alpn-01 - "/authz/1": false, // http-01 - "/authz/2": false, // no viable challenge, but authz is created - } - - var authzCount int // num. of created authorizations - var revokeCount int // num. of revoked authorizations - done := make(chan struct{}) // closed when revokeCount is 3 - - // ACME CA server stub, only the needed bits. - // TODO: Replace this with x/crypto/acme/autocert/internal/acmetest. - var ca *httptest.Server - ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Replay-Nonce", "nonce") - if r.Method == "HEAD" { - // a nonce request - return - } - - switch r.URL.Path { - // Discovery. - case "/": - if err := discoTmpl.Execute(w, ca.URL); err != nil { - t.Errorf("discoTmpl: %v", err) - } - // Client key registration. - case "/new-reg": - w.Write([]byte("{}")) - // New domain authorization. - case "/new-authz": - w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount)) - w.WriteHeader(http.StatusCreated) - if err := authzTmpl.Execute(w, ca.URL); err != nil { - t.Errorf("authzTmpl: %v", err) - } - authzCount++ - // tls-alpn-01 challenge "accept" request. - case "/challenge/tls-alpn-01": - // Refuse. - http.Error(w, "won't accept tls-alpn-01 challenge", http.StatusBadRequest) - // http-01 challenge "accept" request. - case "/challenge/http-01": - // Accept but the authorization will be "expired". - w.Write([]byte("{}")) - // Authorization requests. - case "/authz/0", "/authz/1", "/authz/2": - // Revocation requests. - if r.Method == "POST" { - var req struct{ Status string } - if err := decodePayload(&req, r.Body); err != nil { - t.Errorf("%s: decodePayload: %v", r.URL, err) - } - switch req.Status { - case "deactivated": - revokedAuthz[r.URL.Path] = true - revokeCount++ - if revokeCount >= 3 { - // Last authorization is revoked. - defer close(done) - } - default: - t.Errorf("%s: req.Status = %q; want 'deactivated'", r.URL, req.Status) - } - w.Write([]byte(`{"status": "invalid"}`)) - return - } - // Authorization status requests. - // Simulate abandoned authorization, deleted by the CA. - w.WriteHeader(http.StatusNotFound) + case <-logTicker.C: + t.Logf("still waiting on revocations") default: - http.NotFound(w, r) - t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) - } - })) - defer ca.Close() - - m := &Manager{ - Client: &acme.Client{DirectoryURL: ca.URL}, - } - m.HTTPHandler(nil) // enable http-01 challenge type - // Should fail and revoke 3 authorizations. - // The first 2 are tls-alpn-01 and http-01 challenges. - // The third time an authorization is created but no viable challenge is found. - // See revokedAuthz above for more explanation. - if _, err := m.createCert(context.Background(), exampleCertKey); err == nil { - t.Errorf("m.createCert returned nil error") - } - select { - case <-time.After(3 * time.Second): - t.Error("revocations took too long") - case <-done: - // revokeCount is at least 3. - } - for uri, ok := range revokedAuthz { - if !ok { - t.Errorf("%q authorization was not revoked", uri) } + time.Sleep(50 * time.Millisecond) } } @@ -849,9 +561,9 @@ func TestHTTPHandlerDefaultFallback(t *testing.T) { {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, {"GET", "http://example.org/foo%20bar", 302, "https://example.org/foo%20bar"}, - {"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"}, - {"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"}, - {"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"}, + {"GET", "http://[2602:d1:abcd::c60a]:1234/", 302, "https://[2602:d1:abcd::c60a]/"}, + {"GET", "http://[2602:d1:abcd::c60a]/", 302, "https://[2602:d1:abcd::c60a]/"}, + {"GET", "http://[2602:d1:abcd::c60a]/foo?a=b", 302, "https://[2602:d1:abcd::c60a]/foo?a=b"}, {"HEAD", "http://example.org/", 302, "https://example.org/"}, {"HEAD", "http://example.org/foo", 302, "https://example.org/foo"}, {"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, @@ -907,7 +619,7 @@ func TestCache(t *testing.T) { PrivateKey: ecdsaKey, } - rsaKey, err := rsa.GenerateKey(rand.Reader, 512) + rsaKey, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { t.Fatal(err) } @@ -949,14 +661,14 @@ func TestCache(t *testing.T) { } func TestHostWhitelist(t *testing.T) { - policy := HostWhitelist("example.com", "EXAMPLE.ORG", "*.example.net", "σςΣ.com") + policy := HostWhitelist("example.com", "EXAMPLE.ORG", "*.example.net", "éÉ.com") tt := []struct { host string allow bool }{ {"example.com", true}, {"example.org", true}, - {"xn--4xaaa.com", true}, + {"xn--9caa.com", true}, // éé.com {"one.example.com", false}, {"two.example.org", false}, {"three.example.net", false}, @@ -982,7 +694,7 @@ func TestValidCert(t *testing.T) { if err != nil { t.Fatal(err) } - key3, err := rsa.GenerateKey(rand.Reader, 512) + key3, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { t.Fatal(err) } @@ -1097,7 +809,7 @@ func TestCertRequest(t *testing.T) { Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1}, Value: []byte("dummy"), } - b, err := certRequest(key, "example.org", []pkix.Extension{ext}, "san.example.org") + b, err := certRequest(key, "example.org", []pkix.Extension{ext}) if err != nil { t.Fatalf("certRequest: %v", err) } @@ -1176,18 +888,16 @@ func TestSupportsECDSA(t *testing.T) { } } -// TODO: add same end-to-end for http-01 challenge type. -func TestEndToEnd(t *testing.T) { +func TestEndToEndALPN(t *testing.T) { const domain = "example.org" // ACME CA server - ca := acmetest.NewCAServer([]string{"tls-alpn-01"}, []string{domain}) - defer ca.Close() + ca := acmetest.NewCAServer(t).Start() - // User dummy server. + // User HTTPS server. m := &Manager{ Prompt: AcceptTOS, - Client: &acme.Client{DirectoryURL: ca.URL}, + Client: &acme.Client{DirectoryURL: ca.URL()}, } us := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) @@ -1209,21 +919,74 @@ func TestEndToEnd(t *testing.T) { // where to dial to instead. ca.Resolve(domain, strings.TrimPrefix(us.URL, "https://")) - // A client visiting user dummy server. + // A client visiting user's HTTPS server. tr := &http.Transport{ TLSClientConfig: &tls.Config{ - RootCAs: ca.Roots, + RootCAs: ca.Roots(), ServerName: domain, }, } client := &http.Client{Transport: tr} res, err := client.Get(us.URL) if err != nil { - t.Logf("CA errors: %v", ca.Errors()) t.Fatal(err) } defer res.Body.Close() - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if v := string(b); v != "OK" { + t.Errorf("user server response: %q; want 'OK'", v) + } +} + +func TestEndToEndHTTP(t *testing.T) { + const domain = "example.org" + + // ACME CA server. + ca := acmetest.NewCAServer(t).ChallengeTypes("http-01").Start() + + // User HTTP server for the ACME challenge. + m := testManager(t) + m.Client = &acme.Client{DirectoryURL: ca.URL()} + s := httptest.NewServer(m.HTTPHandler(nil)) + defer s.Close() + + // User HTTPS server. + ss := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("OK")) + })) + ss.TLS = &tls.Config{ + NextProtos: []string{"http/1.1", acme.ALPNProto}, + GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + cert, err := m.GetCertificate(hello) + if err != nil { + t.Errorf("m.GetCertificate: %v", err) + } + return cert, err + }, + } + ss.StartTLS() + defer ss.Close() + + // Redirect the CA requests to the HTTP server. + ca.Resolve(domain, strings.TrimPrefix(s.URL, "http://")) + + // A client visiting user's HTTPS server. + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: ca.Roots(), + ServerName: domain, + }, + } + client := &http.Client{Transport: tr} + res, err := client.Get(ss.URL) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + b, err := io.ReadAll(res.Body) if err != nil { t.Fatal(err) } diff --git a/acme/autocert/cache.go b/acme/autocert/cache.go index 03f63022fa..758ab12cb2 100644 --- a/acme/autocert/cache.go +++ b/acme/autocert/cache.go @@ -7,7 +7,6 @@ package autocert import ( "context" "errors" - "io/ioutil" "os" "path/filepath" ) @@ -41,14 +40,14 @@ type DirCache string // Get reads a certificate data from the specified file name. func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { - name = filepath.Join(string(d), name) + name = filepath.Join(string(d), filepath.Clean("/"+name)) var ( data []byte err error done = make(chan struct{}) ) go func() { - data, err = ioutil.ReadFile(name) + data, err = os.ReadFile(name) close(done) }() select { @@ -82,7 +81,7 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error { case <-ctx.Done(): // Don't overwrite the file if the context was canceled. default: - newName := filepath.Join(string(d), name) + newName := filepath.Join(string(d), filepath.Clean("/"+name)) err = os.Rename(tmp, newName) } }() @@ -96,7 +95,7 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error { // Delete removes the specified file name. func (d DirCache) Delete(ctx context.Context, name string) error { - name = filepath.Join(string(d), name) + name = filepath.Join(string(d), filepath.Clean("/"+name)) var ( err error done = make(chan struct{}) @@ -119,7 +118,7 @@ func (d DirCache) Delete(ctx context.Context, name string) error { // writeTempFile writes b to a temporary file, closes the file and returns its path. func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) { // TempFile uses 0600 permissions - f, err := ioutil.TempFile(string(d), prefix) + f, err := os.CreateTemp(string(d), prefix) if err != nil { return "", err } diff --git a/acme/autocert/cache_test.go b/acme/autocert/cache_test.go index 4d0b16270c..582e6b0580 100644 --- a/acme/autocert/cache_test.go +++ b/acme/autocert/cache_test.go @@ -6,7 +6,6 @@ package autocert import ( "context" - "io/ioutil" "os" "path/filepath" "reflect" @@ -17,7 +16,7 @@ import ( var _ Cache = DirCache("/") func TestDirCache(t *testing.T) { - dir, err := ioutil.TempDir("", "autocert") + dir, err := os.MkdirTemp("", "autocert") if err != nil { t.Fatal(err) } diff --git a/acme/autocert/example_test.go b/acme/autocert/example_test.go index d4225e5c76..6c7458b0d5 100644 --- a/acme/autocert/example_test.go +++ b/acme/autocert/example_test.go @@ -24,6 +24,7 @@ func ExampleManager() { m := &autocert.Manager{ Cache: autocert.DirCache("secret-dir"), Prompt: autocert.AcceptTOS, + Email: "example@example.org", HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"), } s := &http.Server{ diff --git a/acme/autocert/internal/acmetest/ca.go b/acme/autocert/internal/acmetest/ca.go index acc486af5c..c7ddd3dbfb 100644 --- a/acme/autocert/internal/acmetest/ca.go +++ b/acme/autocert/internal/acmetest/ca.go @@ -8,82 +8,101 @@ package acmetest import ( + "context" "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "crypto/rsa" "crypto/tls" "crypto/x509" "crypto/x509/pkix" + "encoding/asn1" "encoding/base64" "encoding/json" + "encoding/pem" "fmt" "io" "math/big" + "net" "net/http" "net/http/httptest" - "sort" + "path" + "strconv" "strings" "sync" + "testing" "time" + + "golang.org/x/crypto/acme" ) // CAServer is a simple test server which implements ACME spec bits needed for testing. type CAServer struct { - URL string // server URL after it has been started - Roots *x509.CertPool // CA root certificates; initialized in NewCAServer - rootKey crypto.Signer rootCert []byte // DER encoding rootTemplate *x509.Certificate - server *httptest.Server - challengeTypes []string // supported challenge types - domainsWhitelist []string // only these domains are valid for issuing, unless empty + t *testing.T + server *httptest.Server + issuer pkix.Name + challengeTypes []string + url string + roots *x509.CertPool + eabRequired bool mu sync.Mutex - certCount int // number of issued certs - domainAddr map[string]string // domain name to addr:port resolution - authorizations map[string]*authorization // keyed by domain name - errors []error // encountered client errors + certCount int // number of issued certs + acctRegistered bool // set once an account has been registered + domainAddr map[string]string // domain name to addr:port resolution + domainGetCert map[string]getCertificateFunc // domain name to GetCertificate function + domainHandler map[string]http.Handler // domain name to Handle function + validAuthz map[string]*authorization // valid authz, keyed by domain name + authorizations []*authorization // all authz, index is used as ID + orders []*order // index is used as order ID + errors []error // encountered client errors } -// NewCAServer creates a new ACME test server and starts serving requests. -// The returned CAServer issues certs signed with the CA roots -// available in the Roots field. -// -// The challengeTypes argument defines the supported ACME challenge types -// sent to a client in a response for a domain authorization. -// If domainsWhitelist is non-empty, the certs will be issued only for the specified -// list of domains. Otherwise, any domain name is allowed. -func NewCAServer(challengeTypes []string, domainsWhitelist []string) *CAServer { - var whitelist []string - for _, name := range domainsWhitelist { - whitelist = append(whitelist, name) - } - sort.Strings(whitelist) - ca := &CAServer{ - challengeTypes: challengeTypes, - domainsWhitelist: whitelist, - domainAddr: make(map[string]string), - authorizations: make(map[string]*authorization), +type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) + +// NewCAServer creates a new ACME test server. The returned CAServer issues +// certs signed with the CA roots available in the Roots field. +func NewCAServer(t *testing.T) *CAServer { + ca := &CAServer{t: t, + challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"}, + domainAddr: make(map[string]string), + domainGetCert: make(map[string]getCertificateFunc), + domainHandler: make(map[string]http.Handler), + validAuthz: make(map[string]*authorization), + } + + ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle)) + + r, err := rand.Int(rand.Reader, big.NewInt(1000000)) + if err != nil { + panic(fmt.Sprintf("rand.Int: %v", err)) } + ca.issuer = pkix.Name{ + Organization: []string{"Test Acme Co"}, + CommonName: "Root CA " + r.String(), + } + + return ca +} +func (ca *CAServer) generateRoot() { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err)) } tmpl := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - Organization: []string{"Test Acme Co"}, - CommonName: "Root CA", - }, + SerialNumber: big.NewInt(1), + Subject: ca.issuer, NotBefore: time.Now(), NotAfter: time.Now().Add(365 * 24 * time.Hour), KeyUsage: x509.KeyUsageCertSign, BasicConstraintsValid: true, - IsCA: true, + IsCA: true, } der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) if err != nil { @@ -93,28 +112,97 @@ func NewCAServer(challengeTypes []string, domainsWhitelist []string) *CAServer { if err != nil { panic(fmt.Sprintf("x509.ParseCertificate: %v", err)) } - ca.Roots = x509.NewCertPool() - ca.Roots.AddCert(cert) + ca.roots = x509.NewCertPool() + ca.roots.AddCert(cert) ca.rootKey = key ca.rootCert = der ca.rootTemplate = tmpl +} + +// IssuerName sets the name of the issuing CA. +func (ca *CAServer) IssuerName(name pkix.Name) *CAServer { + if ca.url != "" { + panic("IssuerName must be called before Start") + } + ca.issuer = name + return ca +} + +// ChallengeTypes sets the supported challenge types. +func (ca *CAServer) ChallengeTypes(types ...string) *CAServer { + if ca.url != "" { + panic("ChallengeTypes must be called before Start") + } + ca.challengeTypes = types + return ca +} + +// URL returns the server address, after Start has been called. +func (ca *CAServer) URL() string { + if ca.url == "" { + panic("URL called before Start") + } + return ca.url +} + +// Roots returns a pool containing the CA root. +func (ca *CAServer) Roots() *x509.CertPool { + if ca.url == "" { + panic("Roots called before Start") + } + return ca.roots +} + +// ExternalAccountRequired makes an EAB JWS required for account registration. +func (ca *CAServer) ExternalAccountRequired() *CAServer { + if ca.url != "" { + panic("ExternalAccountRequired must be called before Start") + } + ca.eabRequired = true + return ca +} - ca.server = httptest.NewServer(http.HandlerFunc(ca.handle)) - ca.URL = ca.server.URL +// Start starts serving requests. The server address becomes available in the +// URL field. +func (ca *CAServer) Start() *CAServer { + if ca.url == "" { + ca.generateRoot() + ca.server.Start() + ca.t.Cleanup(ca.server.Close) + ca.url = ca.server.URL + } return ca } -// Close shuts down the server and blocks until all outstanding -// requests on this server have completed. -func (ca *CAServer) Close() { - ca.server.Close() +func (ca *CAServer) serverURL(format string, arg ...interface{}) string { + return ca.server.URL + fmt.Sprintf(format, arg...) +} + +func (ca *CAServer) addr(domain string) (string, bool) { + ca.mu.Lock() + defer ca.mu.Unlock() + addr, ok := ca.domainAddr[domain] + return addr, ok +} + +func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) { + ca.mu.Lock() + defer ca.mu.Unlock() + f, ok := ca.domainGetCert[domain] + return f, ok } -// Errors returns all client errors. -func (ca *CAServer) Errors() []error { +func (ca *CAServer) getHandler(domain string) (http.Handler, bool) { ca.mu.Lock() defer ca.mu.Unlock() - return ca.errors + h, ok := ca.domainHandler[domain] + return h, ok +} + +func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) { + s := fmt.Sprintf(format, a...) + ca.t.Errorf(format, a...) + http.Error(w, s, code) } // Resolve adds a domain to address resolution for the ca to dial to @@ -125,10 +213,33 @@ func (ca *CAServer) Resolve(domain, addr string) { ca.domainAddr[domain] = addr } +// ResolveGetCertificate redirects TLS connections for domain to f when +// validating challenges for the domain authorization. +func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.domainGetCert[domain] = f +} + +// ResolveHandler redirects HTTP requests for domain to f when +// validating challenges for the domain authorization. +func (ca *CAServer) ResolveHandler(domain string, h http.Handler) { + ca.mu.Lock() + defer ca.mu.Unlock() + ca.domainHandler[domain] = h +} + type discovery struct { - NewReg string `json:"new-reg"` - NewAuthz string `json:"new-authz"` - NewCert string `json:"new-cert"` + NewNonce string `json:"newNonce"` + NewAccount string `json:"newAccount"` + NewOrder string `json:"newOrder"` + NewAuthz string `json:"newAuthz"` + + Meta discoveryMeta `json:"meta,omitempty"` +} + +type discoveryMeta struct { + ExternalAccountRequired bool `json:"externalAccountRequired,omitempty"` } type challenge struct { @@ -141,116 +252,174 @@ type authorization struct { Status string `json:"status"` Challenges []challenge `json:"challenges"` - id int domain string + id int +} + +type order struct { + Status string `json:"status"` + AuthzURLs []string `json:"authorizations"` + FinalizeURL string `json:"finalize"` // CSR submit URL + CertURL string `json:"certificate"` // already issued cert + + leaf []byte // issued cert in DER format } func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { + ca.t.Logf("%s %s", r.Method, r.URL) w.Header().Set("Replay-Nonce", "nonce") - if r.Method == "HEAD" { - // a nonce request - return - } - // TODO: Verify nonce header for all POST requests. switch { default: - err := fmt.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) - ca.addError(err) - http.Error(w, err.Error(), http.StatusBadRequest) + ca.httpErrorf(w, http.StatusBadRequest, "unrecognized r.URL.Path: %s", r.URL.Path) // Discovery request. case r.URL.Path == "/": resp := &discovery{ - NewReg: ca.serverURL("/new-reg"), - NewAuthz: ca.serverURL("/new-authz"), - NewCert: ca.serverURL("/new-cert"), + NewNonce: ca.serverURL("/new-nonce"), + NewAccount: ca.serverURL("/new-account"), + NewOrder: ca.serverURL("/new-order"), + Meta: discoveryMeta{ + ExternalAccountRequired: ca.eabRequired, + }, } if err := json.NewEncoder(w).Encode(resp); err != nil { panic(fmt.Sprintf("discovery response: %v", err)) } + // Nonce requests. + case r.URL.Path == "/new-nonce": + // Nonce values are always set. Nothing else to do. + return + // Client key registration request. - case r.URL.Path == "/new-reg": + case r.URL.Path == "/new-account": + ca.mu.Lock() + defer ca.mu.Unlock() + if ca.acctRegistered { + ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented") + return + } + ca.acctRegistered = true + + var req struct { + ExternalAccountBinding json.RawMessage + } + + if err := decodePayload(&req, r.Body); err != nil { + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) + return + } + + if ca.eabRequired && len(req.ExternalAccountBinding) == 0 { + ca.httpErrorf(w, http.StatusBadRequest, "registration failed: no JWS for EAB") + return + } + // TODO: Check the user account key against a ca.accountKeys? + w.Header().Set("Location", ca.serverURL("/accounts/1")) + w.WriteHeader(http.StatusCreated) w.Write([]byte("{}")) - // Domain authorization request. - case r.URL.Path == "/new-authz": + // New order request. + case r.URL.Path == "/new-order": var req struct { - Identifier struct{ Value string } + Identifiers []struct{ Value string } } if err := decodePayload(&req, r.Body); err != nil { - ca.addError(err) - http.Error(w, err.Error(), http.StatusBadRequest) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } ca.mu.Lock() defer ca.mu.Unlock() - authz, ok := ca.authorizations[req.Identifier.Value] - if !ok { - authz = &authorization{ - domain: req.Identifier.Value, - Status: "pending", - } - for _, typ := range ca.challengeTypes { - authz.Challenges = append(authz.Challenges, challenge{ - Type: typ, - URI: ca.serverURL("/challenge/%s/%s", typ, authz.domain), - Token: challengeToken(authz.domain, typ), - }) - } - ca.authorizations[authz.domain] = authz + o := &order{Status: acme.StatusPending} + for _, id := range req.Identifiers { + z := ca.authz(id.Value) + o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id)) } - w.Header().Set("Location", ca.serverURL("/authz/%s", authz.domain)) + orderID := len(ca.orders) + ca.orders = append(ca.orders, o) + w.Header().Set("Location", ca.serverURL("/orders/%d", orderID)) w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(authz); err != nil { - panic(fmt.Sprintf("new authz response: %v", err)) + if err := json.NewEncoder(w).Encode(o); err != nil { + panic(err) } - // Accept tls-alpn-01 challenge type requests. - // TODO: Add http-01 and dns-01 handlers. - case strings.HasPrefix(r.URL.Path, "/challenge/tls-alpn-01/"): - domain := strings.TrimPrefix(r.URL.Path, "/challenge/tls-alpn-01/") + // Existing order status requests. + case strings.HasPrefix(r.URL.Path, "/orders/"): ca.mu.Lock() defer ca.mu.Unlock() - if _, ok := ca.authorizations[domain]; !ok { - err := fmt.Errorf("challenge accept: no authz for %q", domain) - ca.addError(err) - http.Error(w, err.Error(), http.StatusNotFound) + o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/")) + if err != nil { + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } - go func(domain string) { - err := ca.verifyALPNChallenge(domain) - ca.mu.Lock() - defer ca.mu.Unlock() - authz := ca.authorizations[domain] - if err != nil { - authz.Status = "invalid" - return - } - authz.Status = "valid" + if err := json.NewEncoder(w).Encode(o); err != nil { + panic(err) + } - }(domain) + // Accept challenge requests. + case strings.HasPrefix(r.URL.Path, "/challenge/"): + parts := strings.Split(r.URL.Path, "/") + typ, id := parts[len(parts)-2], parts[len(parts)-1] + ca.mu.Lock() + supported := false + for _, suppTyp := range ca.challengeTypes { + if suppTyp == typ { + supported = true + } + } + a, err := ca.storedAuthz(id) + ca.mu.Unlock() + if !supported { + ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ) + return + } + if err != nil { + ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err) + return + } + ca.validateChallenge(a, typ) w.Write([]byte("{}")) // Get authorization status requests. case strings.HasPrefix(r.URL.Path, "/authz/"): - domain := strings.TrimPrefix(r.URL.Path, "/authz/") + var req struct{ Status string } + decodePayload(&req, r.Body) + deactivate := req.Status == "deactivated" ca.mu.Lock() defer ca.mu.Unlock() - authz, ok := ca.authorizations[domain] - if !ok { - http.Error(w, fmt.Sprintf("no authz for %q", domain), http.StatusNotFound) + authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/")) + if err != nil { + ca.httpErrorf(w, http.StatusNotFound, "%v", err) return } + if deactivate { + // Note we don't invalidate authorized orders as we should. + authz.Status = "deactivated" + ca.t.Logf("authz %d is now %s", authz.id, authz.Status) + ca.updatePendingOrders() + } if err := json.NewEncoder(w).Encode(authz); err != nil { - panic(fmt.Sprintf("get authz for %q response: %v", domain, err)) + panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err)) } - // Cert issuance request. - case r.URL.Path == "/new-cert": + // Certificate issuance request. + case strings.HasPrefix(r.URL.Path, "/new-cert/"): + ca.mu.Lock() + defer ca.mu.Unlock() + orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/") + o, err := ca.storedOrder(orderID) + if err != nil { + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) + return + } + if o.Status != acme.StatusReady { + ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) + return + } + // Validate CSR request. var req struct { CSR string `json:"csr"` } @@ -258,83 +427,101 @@ func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { b, _ := base64.RawURLEncoding.DecodeString(req.CSR) csr, err := x509.ParseCertificateRequest(b) if err != nil { - ca.addError(err) - http.Error(w, err.Error(), http.StatusBadRequest) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) return } - names := unique(append(csr.DNSNames, csr.Subject.CommonName)) - if err := ca.matchWhitelist(names); err != nil { - ca.addError(err) - http.Error(w, err.Error(), http.StatusUnauthorized) + // Issue the certificate. + der, err := ca.leafCert(csr) + if err != nil { + ca.httpErrorf(w, http.StatusBadRequest, "new-cert response: ca.leafCert: %v", err) return } - if err := ca.authorized(names); err != nil { - ca.addError(err) - http.Error(w, err.Error(), http.StatusUnauthorized) - return + o.leaf = der + o.CertURL = ca.serverURL("/issued-cert/%s", orderID) + o.Status = acme.StatusValid + if err := json.NewEncoder(w).Encode(o); err != nil { + panic(err) } - der, err := ca.leafCert(csr) + + // Already issued cert download requests. + case strings.HasPrefix(r.URL.Path, "/issued-cert/"): + ca.mu.Lock() + defer ca.mu.Unlock() + o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/")) if err != nil { - err = fmt.Errorf("new-cert response: ca.leafCert: %v", err) - ca.addError(err) - http.Error(w, err.Error(), http.StatusBadRequest) + ca.httpErrorf(w, http.StatusBadRequest, "%v", err) + return } - w.Header().Set("Link", fmt.Sprintf("<%s>; rel=up", ca.serverURL("/ca-cert"))) - w.WriteHeader(http.StatusCreated) - w.Write(der) - - // CA chain cert request. - case r.URL.Path == "/ca-cert": - w.Write(ca.rootCert) + if o.Status != acme.StatusValid { + ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) + return + } + w.Header().Set("Content-Type", "application/pem-certificate-chain") + pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: o.leaf}) + pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: ca.rootCert}) } } -func (ca *CAServer) addError(err error) { - ca.mu.Lock() - defer ca.mu.Unlock() - ca.errors = append(ca.errors, err) -} +// storedOrder retrieves a previously created order at index i. +// It requires ca.mu to be locked. +func (ca *CAServer) storedOrder(i string) (*order, error) { + idx, err := strconv.Atoi(i) + if err != nil { + return nil, fmt.Errorf("storedOrder: %v", err) + } + if idx < 0 { + return nil, fmt.Errorf("storedOrder: invalid order index %d", idx) + } + if idx > len(ca.orders)-1 { + return nil, fmt.Errorf("storedOrder: no such order %d", idx) + } -func (ca *CAServer) serverURL(format string, arg ...interface{}) string { - return ca.server.URL + fmt.Sprintf(format, arg...) + ca.updatePendingOrders() + return ca.orders[idx], nil } -func (ca *CAServer) matchWhitelist(dnsNames []string) error { - if len(ca.domainsWhitelist) == 0 { - return nil +// storedAuthz retrieves a previously created authz at index i. +// It requires ca.mu to be locked. +func (ca *CAServer) storedAuthz(i string) (*authorization, error) { + idx, err := strconv.Atoi(i) + if err != nil { + return nil, fmt.Errorf("storedAuthz: %v", err) } - var nomatch []string - for _, name := range dnsNames { - i := sort.SearchStrings(ca.domainsWhitelist, name) - if i == len(ca.domainsWhitelist) || ca.domainsWhitelist[i] != name { - nomatch = append(nomatch, name) - } + if idx < 0 { + return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx) } - if len(nomatch) > 0 { - return fmt.Errorf("matchWhitelist: some domains don't match: %q", nomatch) + if idx > len(ca.authorizations)-1 { + return nil, fmt.Errorf("storedAuthz: no such authz %d", idx) } - return nil + return ca.authorizations[idx], nil } -func (ca *CAServer) authorized(dnsNames []string) error { - ca.mu.Lock() - defer ca.mu.Unlock() - var noauthz []string - for _, name := range dnsNames { - authz, ok := ca.authorizations[name] - if !ok || authz.Status != "valid" { - noauthz = append(noauthz, name) +// authz returns an existing valid authorization for the identifier or creates a +// new one. It requires ca.mu to be locked. +func (ca *CAServer) authz(identifier string) *authorization { + authz, ok := ca.validAuthz[identifier] + if !ok { + authzId := len(ca.authorizations) + authz = &authorization{ + id: authzId, + domain: identifier, + Status: acme.StatusPending, } + for _, typ := range ca.challengeTypes { + authz.Challenges = append(authz.Challenges, challenge{ + Type: typ, + URI: ca.serverURL("/challenge/%s/%d", typ, authzId), + Token: challengeToken(authz.domain, typ, authzId), + }) + } + ca.authorizations = append(ca.authorizations, authz) } - if len(noauthz) > 0 { - return fmt.Errorf("CAServer: no authz for %q", noauthz) - } - return nil + return authz } +// leafCert issues a new certificate. +// It requires ca.mu to be locked. func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) { - ca.mu.Lock() - defer ca.mu.Unlock() ca.certCount++ // next leaf cert serial number leaf := &x509.Certificate{ SerialNumber: big.NewInt(int64(ca.certCount)), @@ -352,38 +539,231 @@ func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err erro return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey) } -func (ca *CAServer) addr(domain string) (string, error) { +// LeafCert issues a leaf certificate. +func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate { + if ca.url == "" { + panic("LeafCert called before Start") + } + ca.mu.Lock() defer ca.mu.Unlock() - addr, ok := ca.domainAddr[domain] - if !ok { - return "", fmt.Errorf("CAServer: no addr resolution for %q", domain) + var pk crypto.Signer + switch keyType { + case "RSA": + var err error + pk, err = rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + ca.t.Fatal(err) + } + case "ECDSA": + var err error + pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + ca.t.Fatal(err) + } + default: + panic("LeafCert: unknown key type") + } + ca.certCount++ // next leaf cert serial number + leaf := &x509.Certificate{ + SerialNumber: big.NewInt(int64(ca.certCount)), + Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + DNSNames: []string{name}, + BasicConstraintsValid: true, + } + der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey) + if err != nil { + ca.t.Fatal(err) + } + return &tls.Certificate{ + Certificate: [][]byte{der}, + PrivateKey: pk, + } +} + +func (ca *CAServer) validateChallenge(authz *authorization, typ string) { + var err error + switch typ { + case "tls-alpn-01": + err = ca.verifyALPNChallenge(authz) + case "http-01": + err = ca.verifyHTTPChallenge(authz) + default: + panic(fmt.Sprintf("validation of %q is not implemented", typ)) + } + ca.mu.Lock() + defer ca.mu.Unlock() + if err != nil { + authz.Status = "invalid" + } else { + authz.Status = "valid" + ca.validAuthz[authz.domain] = authz + } + ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err) + ca.t.Logf("authz %d is now %s", authz.id, authz.Status) + + ca.updatePendingOrders() +} + +func (ca *CAServer) updatePendingOrders() { + // Update all pending orders. + // An order becomes "ready" if all authorizations are "valid". + // An order becomes "invalid" if any authorization is "invalid". + // Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6 + for i, o := range ca.orders { + if o.Status != acme.StatusPending { + continue + } + + countValid, countInvalid := ca.validateAuthzURLs(o.AuthzURLs, i) + if countInvalid > 0 { + o.Status = acme.StatusInvalid + ca.t.Logf("order %d is now invalid", i) + continue + } + if countValid == len(o.AuthzURLs) { + o.Status = acme.StatusReady + o.FinalizeURL = ca.serverURL("/new-cert/%d", i) + ca.t.Logf("order %d is now ready", i) + } + } +} + +func (ca *CAServer) validateAuthzURLs(urls []string, orderNum int) (countValid, countInvalid int) { + for _, zurl := range urls { + z, err := ca.storedAuthz(path.Base(zurl)) + if err != nil { + ca.t.Logf("no authz %q for order %d", zurl, orderNum) + continue + } + if z.Status == acme.StatusInvalid { + countInvalid++ + } + if z.Status == acme.StatusValid { + countValid++ + } } - return addr, nil + return countValid, countInvalid } -func (ca *CAServer) verifyALPNChallenge(domain string) error { +func (ca *CAServer) verifyALPNChallenge(a *authorization) error { const acmeALPNProto = "acme-tls/1" - addr, err := ca.addr(domain) - if err != nil { - return err + addr, haveAddr := ca.addr(a.domain) + getCert, haveGetCert := ca.getCert(a.domain) + if !haveAddr && !haveGetCert { + return fmt.Errorf("no resolution information for %q", a.domain) } - conn, err := tls.Dial("tcp", addr, &tls.Config{ - ServerName: domain, - InsecureSkipVerify: true, - NextProtos: []string{acmeALPNProto}, - }) - if err != nil { - return err + if haveAddr && haveGetCert { + return fmt.Errorf("overlapping resolution information for %q", a.domain) } - if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { - return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) + + var crt *x509.Certificate + switch { + case haveAddr: + conn, err := tls.Dial("tcp", addr, &tls.Config{ + ServerName: a.domain, + InsecureSkipVerify: true, + NextProtos: []string{acmeALPNProto}, + MinVersion: tls.VersionTLS12, + }) + if err != nil { + return err + } + if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { + return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) + } + if n := len(conn.ConnectionState().PeerCertificates); n != 1 { + return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) + } + crt = conn.ConnectionState().PeerCertificates[0] + case haveGetCert: + hello := &tls.ClientHelloInfo{ + ServerName: a.domain, + // TODO: support selecting ECDSA. + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, + SupportedProtos: []string{acme.ALPNProto}, + SupportedVersions: []uint16{tls.VersionTLS12}, + } + c, err := getCert(hello) + if err != nil { + return err + } + crt, err = x509.ParseCertificate(c.Certificate[0]) + if err != nil { + return err + } + } + + if err := crt.VerifyHostname(a.domain); err != nil { + return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err) + } + // See RFC 8737, Section 6.1. + oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} + for _, x := range crt.Extensions { + if x.Id.Equal(oid) { + // TODO: check the token. + return nil + } + } + return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found") +} + +func (ca *CAServer) verifyHTTPChallenge(a *authorization) error { + addr, haveAddr := ca.addr(a.domain) + handler, haveHandler := ca.getHandler(a.domain) + if !haveAddr && !haveHandler { + return fmt.Errorf("no resolution information for %q", a.domain) } - if n := len(conn.ConnectionState().PeerCertificates); n != 1 { - return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) + if haveAddr && haveHandler { + return fmt.Errorf("overlapping resolution information for %q", a.domain) + } + + token := challengeToken(a.domain, "http-01", a.id) + path := "/.well-known/acme-challenge/" + token + + var body string + switch { + case haveAddr: + t := &http.Transport{ + DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, addr) + }, + } + req, err := http.NewRequest("GET", "http://"+a.domain+path, nil) + if err != nil { + return err + } + res, err := t.RoundTrip(req) + if err != nil { + return err + } + if res.StatusCode != http.StatusOK { + return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK) + } + b, err := io.ReadAll(res.Body) + if err != nil { + return err + } + body = string(b) + case haveHandler: + r := httptest.NewRequest("GET", path, nil) + r.Host = a.domain + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusOK { + return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) + } + body = w.Body.String() + } + + if !strings.HasPrefix(body, token) { + return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body) } - // TODO: verify conn.ConnectionState().PeerCertificates[0] return nil } @@ -399,18 +779,6 @@ func decodePayload(v interface{}, r io.Reader) error { return json.Unmarshal(payload, v) } -func challengeToken(domain, challType string) string { - return fmt.Sprintf("token-%s-%s", domain, challType) -} - -func unique(a []string) []string { - seen := make(map[string]bool) - var res []string - for _, s := range a { - if s != "" && !seen[s] { - seen[s] = true - res = append(res, s) - } - } - return res +func challengeToken(domain, challType string, authzID int) string { + return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID) } diff --git a/acme/autocert/listener.go b/acme/autocert/listener.go index 1e069818a5..460133e0cc 100644 --- a/acme/autocert/listener.go +++ b/acme/autocert/listener.go @@ -10,7 +10,6 @@ import ( "net" "os" "path/filepath" - "runtime" "time" ) @@ -20,7 +19,7 @@ import ( // // It enables one-line HTTPS servers: // -// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) +// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) // // NewListener is a convenience function for a common configuration. // More complex or custom configurations can use the autocert.Manager @@ -72,7 +71,6 @@ func NewListener(domains ...string) net.Listener { // the Manager m's Prompt, Cache, HostPolicy, and other desired options. func (m *Manager) Listener() net.Listener { ln := &listener{ - m: m, conf: m.TLSConfig(), } ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") @@ -80,7 +78,6 @@ func (m *Manager) Listener() net.Listener { } type listener struct { - m *Manager conf *tls.Config tcpListener net.Listener @@ -126,32 +123,13 @@ func (ln *listener) Close() error { return ln.tcpListener.Close() } -func homeDir() string { - if runtime.GOOS == "windows" { - return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") - } - if h := os.Getenv("HOME"); h != "" { - return h - } - return "/" -} - func cacheDir() string { const base = "golang-autocert" - switch runtime.GOOS { - case "darwin": - return filepath.Join(homeDir(), "Library", "Caches", base) - case "windows": - for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} { - if v := os.Getenv(ev); v != "" { - return filepath.Join(v, base) - } - } - // Worst case: - return filepath.Join(homeDir(), base) - } - if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" { - return filepath.Join(xdg, base) + cache, err := os.UserCacheDir() + if err != nil { + // Fall back to the root directory. + cache = "/.cache" } - return filepath.Join(homeDir(), ".cache", base) + + return filepath.Join(cache, base) } diff --git a/acme/autocert/renewal.go b/acme/autocert/renewal.go index 665f870dcd..0df7da78a6 100644 --- a/acme/autocert/renewal.go +++ b/acme/autocert/renewal.go @@ -21,8 +21,9 @@ type domainRenewal struct { ck certKey key crypto.Signer - timerMu sync.Mutex - timer *time.Timer + timerMu sync.Mutex + timer *time.Timer + timerClose chan struct{} // if non-nil, renew closes this channel (and nils out the timer fields) instead of running } // start starts a cert renewal timer at the time @@ -38,16 +39,28 @@ func (dr *domainRenewal) start(exp time.Time) { dr.timer = time.AfterFunc(dr.next(exp), dr.renew) } -// stop stops the cert renewal timer. -// If the timer is already stopped, calling stop is a noop. +// stop stops the cert renewal timer and waits for any in-flight calls to renew +// to complete. If the timer is already stopped, calling stop is a noop. func (dr *domainRenewal) stop() { dr.timerMu.Lock() defer dr.timerMu.Unlock() - if dr.timer == nil { - return + for { + if dr.timer == nil { + return + } + if dr.timer.Stop() { + dr.timer = nil + return + } else { + // dr.timer fired, and we acquired dr.timerMu before the renew callback did. + // (We know this because otherwise the renew callback would have reset dr.timer!) + timerClose := make(chan struct{}) + dr.timerClose = timerClose + dr.timerMu.Unlock() + <-timerClose + dr.timerMu.Lock() + } } - dr.timer.Stop() - dr.timer = nil } // renew is called periodically by a timer. @@ -55,7 +68,9 @@ func (dr *domainRenewal) stop() { func (dr *domainRenewal) renew() { dr.timerMu.Lock() defer dr.timerMu.Unlock() - if dr.timer == nil { + if dr.timerClose != nil { + close(dr.timerClose) + dr.timer, dr.timerClose = nil, nil return } @@ -67,8 +82,8 @@ func (dr *domainRenewal) renew() { next = renewJitter / 2 next += time.Duration(pseudoRand.int63n(int64(next))) } - dr.timer = time.AfterFunc(next, dr.renew) testDidRenewLoop(next, err) + dr.timer = time.AfterFunc(next, dr.renew) } // updateState locks and replaces the relevant Manager.state item with the given diff --git a/acme/autocert/renewal_test.go b/acme/autocert/renewal_test.go index 294f902643..ffe4af2a5c 100644 --- a/acme/autocert/renewal_test.go +++ b/acme/autocert/renewal_test.go @@ -6,19 +6,13 @@ package autocert import ( "context" + "crypto" "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/tls" - "crypto/x509" - "encoding/base64" - "fmt" - "net/http" - "net/http/httptest" "testing" "time" "golang.org/x/crypto/acme" + "golang.org/x/crypto/acme/autocert/internal/acmetest" ) func TestRenewalNext(t *testing.T) { @@ -48,98 +42,47 @@ func TestRenewalNext(t *testing.T) { } func TestRenewFromCache(t *testing.T) { - // ACME CA server stub - var ca *httptest.Server - ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Replay-Nonce", "nonce") - if r.Method == "HEAD" { - // a nonce request - return - } + man := testManager(t) + man.RenewBefore = 24 * time.Hour - switch r.URL.Path { - // discovery - case "/": - if err := discoTmpl.Execute(w, ca.URL); err != nil { - t.Fatalf("discoTmpl: %v", err) - } - // client key registration - case "/new-reg": - w.Write([]byte("{}")) - // domain authorization - case "/new-authz": - w.Header().Set("Location", ca.URL+"/authz/1") - w.WriteHeader(http.StatusCreated) - w.Write([]byte(`{"status": "valid"}`)) - // cert request - case "/new-cert": - var req struct { - CSR string `json:"csr"` - } - decodePayload(&req, r.Body) - b, _ := base64.RawURLEncoding.DecodeString(req.CSR) - csr, err := x509.ParseCertificateRequest(b) - if err != nil { - t.Fatalf("new-cert: CSR: %v", err) - } - der, err := dummyCert(csr.PublicKey, exampleDomain) - if err != nil { - t.Fatalf("new-cert: dummyCert: %v", err) - } - chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL) - w.Header().Set("Link", chainUp) - w.WriteHeader(http.StatusCreated) - w.Write(der) - // CA chain cert - case "/ca-cert": - der, err := dummyCert(nil, "ca") - if err != nil { - t.Fatalf("ca-cert: dummyCert: %v", err) - } - w.Write(der) - default: - t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) - } - })) - defer ca.Close() + ca := acmetest.NewCAServer(t).Start() + ca.ResolveGetCertificate(exampleDomain, man.GetCertificate) - man := &Manager{ - Prompt: AcceptTOS, - Cache: newMemCache(t), - RenewBefore: 24 * time.Hour, - Client: &acme.Client{ - DirectoryURL: ca.URL, - }, + man.Client = &acme.Client{ + DirectoryURL: ca.URL(), } - defer man.stopRenew() // cache an almost expired cert - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } now := time.Now() - cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), exampleDomain) - if err != nil { - t.Fatal(err) - } - tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}} - if err := man.cachePut(context.Background(), exampleCertKey, tlscert); err != nil { + c := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Minute)) + if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { t.Fatal(err) } - // veriy the renewal happened + // verify the renewal happened defer func() { + // Stop the timers that read and execute testDidRenewLoop before restoring it. + // Otherwise the timer callback may race with the deferred write. + man.stopRenew() testDidRenewLoop = func(next time.Duration, err error) {} }() - done := make(chan struct{}) + renewed := make(chan bool, 1) testDidRenewLoop = func(next time.Duration, err error) { - defer close(done) + defer func() { + select { + case renewed <- true: + default: + // The renewal timer uses a random backoff. If the first renewal fails for + // some reason, we could end up with multiple calls here before the test + // stops the timer. + } + }() + if err != nil { t.Errorf("testDidRenewLoop: %v", err) } // Next should be about 90 days: - // dummyCert creates 90days expiry + account for man.RenewBefore. + // CaServer creates 90days expiry + account for man.RenewBefore. // Previous expiration was within 1 min. future := 88 * 24 * time.Hour if next < future { @@ -150,7 +93,8 @@ func TestRenewFromCache(t *testing.T) { after := time.Now().Add(future) tlscert, err := man.cacheGet(context.Background(), exampleCertKey) if err != nil { - t.Fatalf("man.cacheGet: %v", err) + t.Errorf("man.cacheGet: %v", err) + return } if !tlscert.Leaf.NotAfter.After(after) { t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) @@ -161,11 +105,13 @@ func TestRenewFromCache(t *testing.T) { defer man.stateMu.Unlock() s := man.state[exampleCertKey] if s == nil { - t.Fatalf("m.state[%q] is nil", exampleCertKey) + t.Errorf("m.state[%q] is nil", exampleCertKey) + return } tlscert, err = s.tlscert() if err != nil { - t.Fatalf("s.tlscert: %v", err) + t.Errorf("s.tlscert: %v", err) + return } if !tlscert.Leaf.NotAfter.After(after) { t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) @@ -177,55 +123,34 @@ func TestRenewFromCache(t *testing.T) { if _, err := man.GetCertificate(hello); err != nil { t.Fatal(err) } - - // wait for renew loop - select { - case <-time.After(10 * time.Second): - t.Fatal("renew took too long to occur") - case <-done: - } + <-renewed } func TestRenewFromCacheAlreadyRenewed(t *testing.T) { - man := &Manager{ - Prompt: AcceptTOS, - Cache: newMemCache(t), - RenewBefore: 24 * time.Hour, - Client: &acme.Client{ - DirectoryURL: "invalid", - }, + ca := acmetest.NewCAServer(t).Start() + man := testManager(t) + man.RenewBefore = 24 * time.Hour + man.Client = &acme.Client{ + DirectoryURL: "invalid", } - defer man.stopRenew() // cache a recently renewed cert with a different private key - newKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } now := time.Now() - newCert, err := dateDummyCert(newKey.Public(), now.Add(-2*time.Hour), now.Add(time.Hour*24*90), exampleDomain) - if err != nil { + newCert := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Hour*24*90)) + if err := man.cachePut(context.Background(), exampleCertKey, newCert); err != nil { t.Fatal(err) } - newLeaf, err := validCert(exampleCertKey, [][]byte{newCert}, newKey, now) + newLeaf, err := validCert(exampleCertKey, newCert.Certificate, newCert.PrivateKey.(crypto.Signer), now) if err != nil { t.Fatal(err) } - newTLSCert := &tls.Certificate{PrivateKey: newKey, Certificate: [][]byte{newCert}, Leaf: newLeaf} - if err := man.cachePut(context.Background(), exampleCertKey, newTLSCert); err != nil { - t.Fatal(err) - } // set internal state to an almost expired cert - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } - oldCert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), exampleDomain) + oldCert := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Minute)) if err != nil { t.Fatal(err) } - oldLeaf, err := validCert(exampleCertKey, [][]byte{oldCert}, key, now) + oldLeaf, err := validCert(exampleCertKey, oldCert.Certificate, oldCert.PrivateKey.(crypto.Signer), now) if err != nil { t.Fatal(err) } @@ -234,20 +159,32 @@ func TestRenewFromCacheAlreadyRenewed(t *testing.T) { man.state = make(map[certKey]*certState) } s := &certState{ - key: key, - cert: [][]byte{oldCert}, + key: oldCert.PrivateKey.(crypto.Signer), + cert: oldCert.Certificate, leaf: oldLeaf, } man.state[exampleCertKey] = s man.stateMu.Unlock() - // veriy the renewal accepted the newer cached cert + // verify the renewal accepted the newer cached cert defer func() { + // Stop the timers that read and execute testDidRenewLoop before restoring it. + // Otherwise the timer callback may race with the deferred write. + man.stopRenew() testDidRenewLoop = func(next time.Duration, err error) {} }() - done := make(chan struct{}) + renewed := make(chan bool, 1) testDidRenewLoop = func(next time.Duration, err error) { - defer close(done) + defer func() { + select { + case renewed <- true: + default: + // The renewal timer uses a random backoff. If the first renewal fails for + // some reason, we could end up with multiple calls here before the test + // stops the timer. + } + }() + if err != nil { t.Errorf("testDidRenewLoop: %v", err) } @@ -261,7 +198,8 @@ func TestRenewFromCacheAlreadyRenewed(t *testing.T) { // ensure the cached cert was not modified tlscert, err := man.cacheGet(context.Background(), exampleCertKey) if err != nil { - t.Fatalf("man.cacheGet: %v", err) + t.Errorf("man.cacheGet: %v", err) + return } if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { t.Errorf("cache leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) @@ -272,30 +210,22 @@ func TestRenewFromCacheAlreadyRenewed(t *testing.T) { defer man.stateMu.Unlock() s := man.state[exampleCertKey] if s == nil { - t.Fatalf("m.state[%q] is nil", exampleCertKey) + t.Errorf("m.state[%q] is nil", exampleCertKey) + return } stateKey := s.key.Public().(*ecdsa.PublicKey) - if stateKey.X.Cmp(newKey.X) != 0 || stateKey.Y.Cmp(newKey.Y) != 0 { - t.Fatalf("state key was not updated from cache x: %v y: %v; want x: %v y: %v", stateKey.X, stateKey.Y, newKey.X, newKey.Y) + if !stateKey.Equal(newLeaf.PublicKey) { + t.Error("state key was not updated from cache") + return } tlscert, err = s.tlscert() if err != nil { - t.Fatalf("s.tlscert: %v", err) + t.Errorf("s.tlscert: %v", err) + return } if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) } - - // verify the private key is replaced in the renewal state - r := man.renewal[exampleCertKey] - if r == nil { - t.Fatalf("m.renewal[%q] is nil", exampleCertKey) - } - renewalKey := r.key.Public().(*ecdsa.PublicKey) - if renewalKey.X.Cmp(newKey.X) != 0 || renewalKey.Y.Cmp(newKey.Y) != 0 { - t.Fatalf("renewal private key was not updated from cache x: %v y: %v; want x: %v y: %v", renewalKey.X, renewalKey.Y, newKey.X, newKey.Y) - } - } // assert the expiring cert is returned from state @@ -309,21 +239,31 @@ func TestRenewFromCacheAlreadyRenewed(t *testing.T) { } // trigger renew - go man.renew(exampleCertKey, s.key, s.leaf.NotAfter) + man.startRenew(exampleCertKey, s.key, s.leaf.NotAfter) + <-renewed + func() { + man.renewalMu.Lock() + defer man.renewalMu.Unlock() - // wait for renew loop - select { - case <-time.After(10 * time.Second): - t.Fatal("renew took too long to occur") - case <-done: - // assert the new cert is returned from state after renew - hello := clientHelloInfo(exampleDomain, algECDSA) - tlscert, err := man.GetCertificate(hello) - if err != nil { - t.Fatal(err) + // verify the private key is replaced in the renewal state + r := man.renewal[exampleCertKey] + if r == nil { + t.Errorf("m.renewal[%q] is nil", exampleCertKey) + return } - if !newTLSCert.Leaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { - t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newTLSCert.Leaf.NotAfter) + renewalKey := r.key.Public().(*ecdsa.PublicKey) + if !renewalKey.Equal(newLeaf.PublicKey) { + t.Error("renewal private key was not updated from cache") } + }() + + // assert the new cert is returned from state after renew + hello = clientHelloInfo(exampleDomain, algECDSA) + tlscert, err = man.GetCertificate(hello) + if err != nil { + t.Fatal(err) + } + if !newLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { + t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) } } diff --git a/acme/http.go b/acme/http.go index 600d5798b8..8f29df56ee 100644 --- a/acme/http.go +++ b/acme/http.go @@ -10,10 +10,12 @@ import ( "crypto" "crypto/rand" "encoding/json" + "errors" "fmt" - "io/ioutil" + "io" "math/big" "net/http" + "runtime/debug" "strconv" "strings" "time" @@ -64,7 +66,7 @@ func (c *Client) retryTimer() *retryTimer { // 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 + const maxVal = 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 @@ -84,10 +86,7 @@ func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration { n = 30 } d := time.Duration(1< max { - return max - } - return d + return min(d, maxVal) } // retryAfter parses a Retry-After HTTP header value, @@ -155,8 +154,16 @@ func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Respons } } +// postAsGet is POST-as-GET, a replacement for GET in RFC 8555 +// as described in https://tools.ietf.org/html/rfc8555#section-6.3. +// It makes a POST request in KID form with zero JWS payload. +// See nopayload doc comments in jws.go. +func (c *Client) postAsGet(ctx context.Context, url string, ok resOkay) (*http.Response, error) { + return c.post(ctx, nil, url, noPayload, ok) +} + // post issues a signed POST request in JWS format using the provided key -// to the specified URL. +// to the specified URL. If key is nil, c.Key is used instead. // It returns a non-error value only when ok reports true. // // post retries unsuccessful attempts according to c.RetryBackoff @@ -193,14 +200,31 @@ func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body i } // 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. +// The body argument must be JSON-serializable. +// +// If key argument is nil, c.Key is used to sign the request. +// If key argument is nil and c.accountKID returns a non-zero keyID, +// the request is sent in KID form. Otherwise, JWK form is used. +// +// In practice, when interfacing with RFC-compliant CAs most requests are sent in KID form +// and JWK is used only when KID is unavailable: new account endpoint and certificate +// revocation requests authenticated by a cert key. +// See jwsEncodeJSON for other details. func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) { + kid := noKeyID + if key == nil { + if c.Key == nil { + return nil, nil, errors.New("acme: Client.Key must be populated to make POST requests") + } + key = c.Key + kid = c.accountKID(ctx) + } nonce, err := c.popNonce(ctx, url) if err != nil { return nil, nil, err } - b, err := jwsEncodeJSON(body, key, nonce) + b, err := jwsEncodeJSON(body, key, kid, nonce, url) if err != nil { return nil, nil, err } @@ -245,9 +269,27 @@ func (c *Client) httpClient() *http.Client { } // packageVersion is the version of the module that contains this package, for -// sending as part of the User-Agent header. It's set in version_go112.go. +// sending as part of the User-Agent header. var packageVersion string +func init() { + // Set packageVersion if the binary was built in modules mode and x/crypto + // was not replaced with a different module. + info, ok := debug.ReadBuildInfo() + if !ok { + return + } + for _, m := range info.Deps { + if m.Path != "golang.org/x/crypto" { + continue + } + if m.Replace == nil { + packageVersion = m.Version + } + break + } +} + // userAgent returns the User-Agent header value. It includes the package name, // the module version (if available), and the c.UserAgent value (if set). func (c *Client) userAgent() string { @@ -284,7 +326,7 @@ func isRetriable(code int) bool { 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) + b, _ := io.ReadAll(resp.Body) e := &wireError{Status: resp.StatusCode} if err := json.Unmarshal(b, e); err != nil { // this is not a regular error response: diff --git a/acme/http_test.go b/acme/http_test.go index a5dc35fe60..d124e4e219 100644 --- a/acme/http_test.go +++ b/acme/http_test.go @@ -7,7 +7,7 @@ package acme import ( "context" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "reflect" @@ -54,7 +54,7 @@ func TestErrorResponse(t *testing.T) { res := &http.Response{ StatusCode: 400, Status: "400 Bad Request", - Body: ioutil.NopCloser(strings.NewReader(s)), + Body: io.NopCloser(strings.NewReader(s)), Header: http.Header{"X-Foo": {"bar"}}, } err := responseError(res) @@ -87,7 +87,7 @@ func TestPostWithRetries(t *testing.T) { return } - head, err := decodeJWSHead(r) + head, err := decodeJWSHead(r.Body) switch { case err != nil: t.Errorf("decodeJWSHead: %v", err) @@ -115,8 +115,8 @@ func TestPostWithRetries(t *testing.T) { if _, err := client.Authorize(context.Background(), "example.com"); err != nil { t.Errorf("client.Authorize 1: %v", err) } - if count != 4 { - t.Errorf("total requests count: %d; want 4", count) + if count != 3 { + t.Errorf("total requests count: %d; want 3", count) } } @@ -224,7 +224,7 @@ func TestUserAgent(t *testing.T) { } w.WriteHeader(http.StatusOK) - w.Write([]byte(`{}`)) + w.Write([]byte(`{"newOrder": "sure"}`)) })) defer ts.Close() @@ -238,3 +238,18 @@ func TestUserAgent(t *testing.T) { } } } + +func TestAccountKidLoop(t *testing.T) { + // if Client.postNoRetry is called with a nil key argument + // then Client.Key must be set, otherwise we fall into an + // infinite loop (which also causes a deadlock). + client := &Client{dir: &Directory{OrderURL: ":)"}} + _, _, err := client.postNoRetry(context.Background(), nil, "", nil) + if err == nil { + t.Fatal("Client.postNoRetry didn't fail with a nil key") + } + expected := "acme: Client.Key must be populated to make POST requests" + if err.Error() != expected { + t.Fatalf("Unexpected error returned: wanted %q, got %q", expected, err.Error()) + } +} diff --git a/acme/internal/acmeprobe/prober.go b/acme/internal/acmeprobe/prober.go new file mode 100644 index 0000000000..25dba0c50e --- /dev/null +++ b/acme/internal/acmeprobe/prober.go @@ -0,0 +1,433 @@ +// Copyright 2019 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. + +// The acmeprober program runs against an actual ACME CA implementation. +// It spins up an HTTP server to fulfill authorization challenges +// or execute a DNS script to provision a response to dns-01 challenge. +// +// For http-01 and tls-alpn-01 challenge types this requires the ACME CA +// to be able to reach the HTTP server. +// +// A usage example: +// +// go run prober.go \ +// -d https://acme-staging-v02.api.letsencrypt.org/directory \ +// -f order \ +// -t http-01 \ +// -a :8080 \ +// -domain some.example.org +// +// The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 +// in order for the test to be able to fulfill http-01 challenge. +// To test tls-alpn-01 challenge, 443 port would need to be tunneled +// to 0.0.0.0:8080. +// When running with dns-01 challenge type, use -s argument instead of -a. +package main + +import ( + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "errors" + "flag" + "fmt" + "log" + "net" + "net/http" + "os" + "os/exec" + "strings" + "time" + + "golang.org/x/crypto/acme" +) + +var ( + // ACME CA directory URL. + // Let's Encrypt v2 prod: https://acme-v02.api.letsencrypt.org/directory + // Let's Encrypt v2 staging: https://acme-staging-v02.api.letsencrypt.org/directory + // See the following for more CAs implementing ACME protocol: + // https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment#CAs_&_PKIs_that_offer_ACME_certificates + directory = flag.String("d", "", "ACME directory URL.") + reginfo = flag.String("r", "", "ACME account registration info.") + flow = flag.String("f", "", `Flow to run: "order" or "preauthz" (RFC8555).`) + chaltyp = flag.String("t", "", "Challenge type: tls-alpn-01, http-01 or dns-01.") + addr = flag.String("a", "", "Local server address for tls-alpn-01 and http-01.") + dnsscript = flag.String("s", "", "Script to run for provisioning dns-01 challenges.") + domain = flag.String("domain", "", "Space separate domain identifiers.") + ipaddr = flag.String("ip", "", "Space separate IP address identifiers.") +) + +func main() { + flag.Usage = func() { + fmt.Fprintln(flag.CommandLine.Output(), ` +The prober program runs against an actual ACME CA implementation. +It spins up an HTTP server to fulfill authorization challenges +or execute a DNS script to provision a response to dns-01 challenge. + +For http-01 and tls-alpn-01 challenge types this requires the ACME CA +to be able to reach the HTTP server. + +A usage example: + + go run prober.go \ + -d https://acme-staging-v02.api.letsencrypt.org/directory \ + -f order \ + -t http-01 \ + -a :8080 \ + -domain some.example.org + +The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 +in order for the test to be able to fulfill http-01 challenge. +To test tls-alpn-01 challenge, 443 port would need to be tunneled +to 0.0.0.0:8080. +When running with dns-01 challenge type, use -s argument instead of -a. + `) + flag.PrintDefaults() + } + flag.Parse() + + identifiers := acme.DomainIDs(strings.Fields(*domain)...) + identifiers = append(identifiers, acme.IPIDs(strings.Fields(*ipaddr)...)...) + if len(identifiers) == 0 { + log.Fatal("at least one domain or IP addr identifier is required") + } + + // Duration of the whole run. + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + + // Create and register a new account. + akey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + log.Fatal(err) + } + cl := &acme.Client{Key: akey, DirectoryURL: *directory} + a := &acme.Account{Contact: strings.Fields(*reginfo)} + if _, err := cl.Register(ctx, a, acme.AcceptTOS); err != nil { + log.Fatalf("Register: %v", err) + } + + // Run the desired flow test. + p := &prober{ + client: cl, + chalType: *chaltyp, + localAddr: *addr, + dnsScript: *dnsscript, + } + switch *flow { + case "order": + p.runOrder(ctx, identifiers) + case "preauthz": + p.runPreauthz(ctx, identifiers) + default: + log.Fatalf("unknown flow: %q", *flow) + } + if len(p.errors) > 0 { + os.Exit(1) + } +} + +type prober struct { + client *acme.Client + chalType string + localAddr string + dnsScript string + + errors []error +} + +func (p *prober) errorf(format string, a ...interface{}) { + err := fmt.Errorf(format, a...) + log.Print(err) + p.errors = append(p.errors, err) +} + +func (p *prober) runOrder(ctx context.Context, identifiers []acme.AuthzID) { + // Create a new order and pick a challenge. + // Note that Let's Encrypt will reply with 400 error:malformed + // "NotBefore and NotAfter are not supported" when providing a NotAfter + // value like WithOrderNotAfter(time.Now().Add(24 * time.Hour)). + o, err := p.client.AuthorizeOrder(ctx, identifiers) + if err != nil { + log.Fatalf("AuthorizeOrder: %v", err) + } + + var zurls []string + for _, u := range o.AuthzURLs { + z, err := p.client.GetAuthorization(ctx, u) + if err != nil { + log.Fatalf("GetAuthorization(%q): %v", u, err) + } + log.Printf("%+v", z) + if z.Status != acme.StatusPending { + log.Printf("authz status is %q; skipping", z.Status) + continue + } + if err := p.fulfill(ctx, z); err != nil { + log.Fatalf("fulfill(%s): %v", z.URI, err) + } + zurls = append(zurls, z.URI) + log.Printf("authorized for %+v", z.Identifier) + } + + log.Print("all challenges are done") + if _, err := p.client.WaitOrder(ctx, o.URI); err != nil { + log.Fatalf("WaitOrder(%q): %v", o.URI, err) + } + csr, certkey := newCSR(identifiers) + der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) + if err != nil { + log.Fatalf("CreateOrderCert: %v", err) + } + log.Printf("cert URL: %s", curl) + if err := checkCert(der, identifiers); err != nil { + p.errorf("invalid cert: %v", err) + } + + // Deactivate all authorizations we satisfied earlier. + for _, v := range zurls { + if err := p.client.RevokeAuthorization(ctx, v); err != nil { + p.errorf("RevokAuthorization(%q): %v", v, err) + continue + } + } + // Deactivate the account. We don't need it for any further calls. + if err := p.client.DeactivateReg(ctx); err != nil { + p.errorf("DeactivateReg: %v", err) + } + // Try revoking the issued cert using its private key. + if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { + p.errorf("RevokeCert: %v", err) + } +} + +func (p *prober) runPreauthz(ctx context.Context, identifiers []acme.AuthzID) { + dir, err := p.client.Discover(ctx) + if err != nil { + log.Fatalf("Discover: %v", err) + } + if dir.AuthzURL == "" { + log.Fatal("CA does not support pre-authorization") + } + + var zurls []string + for _, id := range identifiers { + z, err := authorize(ctx, p.client, id) + if err != nil { + log.Fatalf("AuthorizeID(%+v): %v", z, err) + } + if z.Status == acme.StatusValid { + log.Printf("authz %s is valid; skipping", z.URI) + continue + } + if err := p.fulfill(ctx, z); err != nil { + log.Fatalf("fulfill(%s): %v", z.URI, err) + } + zurls = append(zurls, z.URI) + log.Printf("authorized for %+v", id) + } + + // We should be all set now. + // Expect all authorizations to be satisfied. + log.Print("all challenges are done") + o, err := p.client.AuthorizeOrder(ctx, identifiers) + if err != nil { + log.Fatalf("AuthorizeOrder: %v", err) + } + waitCtx, cancel := context.WithTimeout(ctx, time.Minute) + defer cancel() + if _, err := p.client.WaitOrder(waitCtx, o.URI); err != nil { + log.Fatalf("WaitOrder(%q): %v", o.URI, err) + } + csr, certkey := newCSR(identifiers) + der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) + if err != nil { + log.Fatalf("CreateOrderCert: %v", err) + } + log.Printf("cert URL: %s", curl) + if err := checkCert(der, identifiers); err != nil { + p.errorf("invalid cert: %v", err) + } + + // Deactivate all authorizations we satisfied earlier. + for _, v := range zurls { + if err := p.client.RevokeAuthorization(ctx, v); err != nil { + p.errorf("RevokeAuthorization(%q): %v", v, err) + continue + } + } + // Deactivate the account. We don't need it for any further calls. + if err := p.client.DeactivateReg(ctx); err != nil { + p.errorf("DeactivateReg: %v", err) + } + // Try revoking the issued cert using its private key. + if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { + p.errorf("RevokeCert: %v", err) + } +} + +func (p *prober) fulfill(ctx context.Context, z *acme.Authorization) error { + var chal *acme.Challenge + for i, c := range z.Challenges { + log.Printf("challenge %d: %+v", i, c) + if c.Type == p.chalType { + log.Printf("picked %s for authz %s", c.URI, z.URI) + chal = c + } + } + if chal == nil { + return fmt.Errorf("challenge type %q wasn't offered for authz %s", p.chalType, z.URI) + } + + switch chal.Type { + case "tls-alpn-01": + return p.runTLSALPN01(ctx, z, chal) + case "http-01": + return p.runHTTP01(ctx, z, chal) + case "dns-01": + return p.runDNS01(ctx, z, chal) + default: + return fmt.Errorf("unknown challenge type %q", chal.Type) + } +} + +func (p *prober) runTLSALPN01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { + tokenCert, err := p.client.TLSALPN01ChallengeCert(chal.Token, z.Identifier.Value) + if err != nil { + return fmt.Errorf("TLSALPN01ChallengeCert: %v", err) + } + s := &http.Server{ + Addr: p.localAddr, + TLSConfig: &tls.Config{ + NextProtos: []string{acme.ALPNProto}, + GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + log.Printf("hello: %+v", hello) + return &tokenCert, nil + }, + }, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Printf("%s %s", r.Method, r.URL) + w.WriteHeader(http.StatusNotFound) + }), + } + go s.ListenAndServeTLS("", "") + defer s.Close() + + if _, err := p.client.Accept(ctx, chal); err != nil { + return fmt.Errorf("Accept(%q): %v", chal.URI, err) + } + _, zerr := p.client.WaitAuthorization(ctx, z.URI) + return zerr +} + +func (p *prober) runHTTP01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { + body, err := p.client.HTTP01ChallengeResponse(chal.Token) + if err != nil { + return fmt.Errorf("HTTP01ChallengeResponse: %v", err) + } + s := &http.Server{ + Addr: p.localAddr, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Printf("%s %s", r.Method, r.URL) + if r.URL.Path != p.client.HTTP01ChallengePath(chal.Token) { + w.WriteHeader(http.StatusNotFound) + return + } + w.Write([]byte(body)) + }), + } + go s.ListenAndServe() + defer s.Close() + + if _, err := p.client.Accept(ctx, chal); err != nil { + return fmt.Errorf("Accept(%q): %v", chal.URI, err) + } + _, zerr := p.client.WaitAuthorization(ctx, z.URI) + return zerr +} + +func (p *prober) runDNS01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { + token, err := p.client.DNS01ChallengeRecord(chal.Token) + if err != nil { + return fmt.Errorf("DNS01ChallengeRecord: %v", err) + } + + name := fmt.Sprintf("_acme-challenge.%s", z.Identifier.Value) + cmd := exec.CommandContext(ctx, p.dnsScript, name, token) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("%s: %v", p.dnsScript, err) + } + + if _, err := p.client.Accept(ctx, chal); err != nil { + return fmt.Errorf("Accept(%q): %v", chal.URI, err) + } + _, zerr := p.client.WaitAuthorization(ctx, z.URI) + return zerr +} + +func authorize(ctx context.Context, client *acme.Client, id acme.AuthzID) (*acme.Authorization, error) { + if id.Type == "ip" { + return client.AuthorizeIP(ctx, id.Value) + } + return client.Authorize(ctx, id.Value) +} + +func checkCert(derChain [][]byte, id []acme.AuthzID) error { + if len(derChain) == 0 { + return errors.New("cert chain is zero bytes") + } + for i, b := range derChain { + crt, err := x509.ParseCertificate(b) + if err != nil { + return fmt.Errorf("%d: ParseCertificate: %v", i, err) + } + log.Printf("%d: serial: 0x%s", i, crt.SerialNumber) + log.Printf("%d: subject: %s", i, crt.Subject) + log.Printf("%d: issuer: %s", i, crt.Issuer) + log.Printf("%d: expires in %.1f day(s)", i, time.Until(crt.NotAfter).Hours()/24) + if i > 0 { // not a leaf cert + continue + } + p := &pem.Block{Type: "CERTIFICATE", Bytes: b} + log.Printf("%d: leaf:\n%s", i, pem.EncodeToMemory(p)) + for _, v := range id { + if err := crt.VerifyHostname(v.Value); err != nil { + return err + } + } + } + return nil +} + +func newCSR(identifiers []acme.AuthzID) ([]byte, crypto.Signer) { + var csr x509.CertificateRequest + for _, id := range identifiers { + switch id.Type { + case "dns": + csr.DNSNames = append(csr.DNSNames, id.Value) + case "ip": + csr.IPAddresses = append(csr.IPAddresses, net.ParseIP(id.Value)) + default: + panic(fmt.Sprintf("newCSR: unknown identifier type %q", id.Type)) + } + } + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(fmt.Sprintf("newCSR: ecdsa.GenerateKey for a cert: %v", err)) + } + b, err := x509.CreateCertificateRequest(rand.Reader, &csr, k) + if err != nil { + panic(fmt.Sprintf("newCSR: x509.CreateCertificateRequest: %v", err)) + } + return b, k +} diff --git a/acme/jws.go b/acme/jws.go index 1093b50390..6850275665 100644 --- a/acme/jws.go +++ b/acme/jws.go @@ -7,47 +7,109 @@ package acme import ( "crypto" "crypto/ecdsa" + "crypto/hmac" "crypto/rand" "crypto/rsa" "crypto/sha256" _ "crypto/sha512" // need for EC keys + "encoding/asn1" "encoding/base64" "encoding/json" + "errors" "fmt" "math/big" ) +// KeyID is the account key identity provided by a CA during registration. +type KeyID string + +// noKeyID indicates that jwsEncodeJSON should compute and use JWK instead of a KID. +// See jwsEncodeJSON for details. +const noKeyID = KeyID("") + +// noPayload indicates jwsEncodeJSON will encode zero-length octet string +// in a JWS request. This is called POST-as-GET in RFC 8555 and is used to make +// authenticated GET requests via POSTing with an empty payload. +// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details. +const noPayload = "" + +// noNonce indicates that the nonce should be omitted from the protected header. +// See jwsEncodeJSON for details. +const noNonce = "" + +// jsonWebSignature can be easily serialized into a JWS following +// https://tools.ietf.org/html/rfc7515#section-3.2. +type jsonWebSignature struct { + Protected string `json:"protected"` + Payload string `json:"payload"` + Sig string `json:"signature"` +} + // jwsEncodeJSON signs claimset using provided key and a nonce. -// The result is serialized in JSON format. +// The result is serialized in JSON format containing either kid or jwk +// fields based on the provided KeyID value. +// +// The claimset is marshalled using json.Marshal unless it is a string. +// In which case it is inserted directly into the message. +// +// If kid is non-empty, its quoted value is inserted in the protected header +// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted +// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive. +// +// If nonce is non-empty, its quoted value is inserted in the protected header. +// // See https://tools.ietf.org/html/rfc7515#section-7. -func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) { - jwk, err := jwkEncode(key.Public()) - if err != nil { - return nil, err +func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) { + if key == nil { + return nil, errors.New("nil key") } alg, sha := jwsHasher(key.Public()) if alg == "" || !sha.Available() { return nil, ErrUnsupportedKey } - phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce) - phead = base64.RawURLEncoding.EncodeToString([]byte(phead)) - cs, err := json.Marshal(claimset) + headers := struct { + Alg string `json:"alg"` + KID string `json:"kid,omitempty"` + JWK json.RawMessage `json:"jwk,omitempty"` + Nonce string `json:"nonce,omitempty"` + URL string `json:"url"` + }{ + Alg: alg, + Nonce: nonce, + URL: url, + } + switch kid { + case noKeyID: + jwk, err := jwkEncode(key.Public()) + if err != nil { + return nil, err + } + headers.JWK = json.RawMessage(jwk) + default: + headers.KID = string(kid) + } + phJSON, err := json.Marshal(headers) if err != nil { return nil, err } - payload := base64.RawURLEncoding.EncodeToString(cs) + phead := base64.RawURLEncoding.EncodeToString(phJSON) + var payload string + if val, ok := claimset.(string); ok { + payload = val + } else { + cs, err := json.Marshal(claimset) + if err != nil { + return nil, err + } + payload = base64.RawURLEncoding.EncodeToString(cs) + } hash := sha.New() hash.Write([]byte(phead + "." + payload)) sig, err := jwsSign(key, sha, hash.Sum(nil)) if err != nil { return nil, err } - - enc := struct { - Protected string `json:"protected"` - Payload string `json:"payload"` - Sig string `json:"signature"` - }{ + enc := jsonWebSignature{ Protected: phead, Payload: payload, Sig: base64.RawURLEncoding.EncodeToString(sig), @@ -55,6 +117,43 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byt return json.Marshal(&enc) } +// jwsWithMAC creates and signs a JWS using the given key and the HS256 +// algorithm. kid and url are included in the protected header. rawPayload +// should not be base64-URL-encoded. +func jwsWithMAC(key []byte, kid, url string, rawPayload []byte) (*jsonWebSignature, error) { + if len(key) == 0 { + return nil, errors.New("acme: cannot sign JWS with an empty MAC key") + } + header := struct { + Algorithm string `json:"alg"` + KID string `json:"kid"` + URL string `json:"url,omitempty"` + }{ + // Only HMAC-SHA256 is supported. + Algorithm: "HS256", + KID: kid, + URL: url, + } + rawProtected, err := json.Marshal(header) + if err != nil { + return nil, err + } + protected := base64.RawURLEncoding.EncodeToString(rawProtected) + payload := base64.RawURLEncoding.EncodeToString(rawPayload) + + h := hmac.New(sha256.New, key) + if _, err := h.Write([]byte(protected + "." + payload)); err != nil { + return nil, err + } + mac := h.Sum(nil) + + return &jsonWebSignature{ + Protected: protected, + Payload: payload, + Sig: base64.RawURLEncoding.EncodeToString(mac), + }, nil +} + // jwkEncode encodes public part of an RSA or ECDSA key into a JWK. // The result is also suitable for creating a JWK thumbprint. // https://tools.ietf.org/html/rfc7517 @@ -98,21 +197,23 @@ func jwkEncode(pub crypto.PublicKey) (string, error) { // jwsSign signs the digest using the given key. // The hash is unused for ECDSA keys. -// -// Note: non-stdlib crypto.Signer implementations are expected to return -// the signature in the format as specified in RFC7518. -// See https://tools.ietf.org/html/rfc7518 for more details. func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) { - if key, ok := key.(*ecdsa.PrivateKey); ok { - // The key.Sign method of ecdsa returns ASN1-encoded signature. - // So, we use the package Sign function instead - // to get R and S values directly and format the result accordingly. - r, s, err := ecdsa.Sign(rand.Reader, key, digest) + switch pub := key.Public().(type) { + case *rsa.PublicKey: + return key.Sign(rand.Reader, digest, hash) + case *ecdsa.PublicKey: + sigASN1, err := key.Sign(rand.Reader, digest, hash) if err != nil { return nil, err } - rb, sb := r.Bytes(), s.Bytes() - size := key.Params().BitSize / 8 + + var rs struct{ R, S *big.Int } + if _, err := asn1.Unmarshal(sigASN1, &rs); err != nil { + return nil, err + } + + rb, sb := rs.R.Bytes(), rs.S.Bytes() + size := pub.Params().BitSize / 8 if size%8 > 0 { size++ } @@ -121,7 +222,7 @@ func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) copy(sig[size*2-len(sb):], sb) return sig, nil } - return key.Sign(rand.Reader, digest, hash) + return nil, ErrUnsupportedKey } // jwsHasher indicates suitable JWS algorithm name and a hash function diff --git a/acme/jws_test.go b/acme/jws_test.go index ee30b1e1e4..d5f00ba2d3 100644 --- a/acme/jws_test.go +++ b/acme/jws_test.go @@ -9,6 +9,7 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" + "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/json" @@ -19,7 +20,18 @@ import ( "testing" ) +// The following shell command alias is used in the comments +// throughout this file: +// alias b64raw="base64 -w0 | tr -d '=' | tr '/+' '_-'" + const ( + // Modulus in raw base64: + // 4xgZ3eRPkwoRvy7qeRUbmMDe0V-xH9eWLdu0iheeLlrmD2mqWXfP9IeSKApbn34 + // g8TuAS9g5zhq8ELQ3kmjr-KV86GAMgI6VAcGlq3QrzpTCf_30Ab7-zawrfRaFON + // a1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosqEXeaIkVYBEhbh + // Nu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZfoyFyek380mHg + // JAumQ_I2fjj98_97mk3ihOY4AgVdCDj1z_GCoZkG5Rq7nbCGyosyKWyDX00Zs-n + // NqVhoLeIvXC4nnWdJMZ6rogxyQQ testKeyPEM = ` -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq @@ -82,7 +94,7 @@ GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ== ` // 1. openssl ec -in key.pem -noout -text // 2. remove first byte, 04 (the header); the rest is X and Y - // 3. convert each with: echo | xxd -r -p | base64 -w 100 | tr -d '=' | tr '/+' '_-' + // 3. convert each with: echo | xxd -r -p | b64raw testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ" testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk" testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt" @@ -91,7 +103,7 @@ GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ== testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax" // echo -n '{"crv":"P-256","kty":"EC","x":"","y":""}' | \ - // openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-' + // openssl dgst -binary -sha256 | b64raw testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU" ) @@ -140,7 +152,7 @@ func TestJWSEncodeJSON(t *testing.T) { // JWS signed with testKey and "nonce" as the nonce value // JSON-serialized JWS fields are split for easier testing const ( - // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"} + // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce","url":"url"} protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + @@ -151,19 +163,20 @@ func TestJWSEncodeJSON(t *testing.T) { "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + - "UVEifSwibm9uY2UiOiJub25jZSJ9" + "UVEifSwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" // {"Msg":"Hello JWS"} - payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" - signature = "eAGUikStX_UxyiFhxSLMyuyBcIB80GeBkFROCpap2sW3EmkU_ggF" + - "knaQzxrTfItICSAXsCLIquZ5BbrSWA_4vdEYrwWtdUj7NqFKjHRa" + - "zpLHcoR7r1rEHvkoP1xj49lS5fc3Wjjq8JUhffkhGbWZ8ZVkgPdC" + - "4tMBWiQDoth-x8jELP_3LYOB_ScUXi2mETBawLgOT2K8rA0Vbbmx" + - "hWNlOWuUf-8hL5YX4IOEwsS8JK_TrTq5Zc9My0zHJmaieqDV0UlP" + - "k0onFjPFkGm7MrPSgd0MqRG-4vSAg2O4hDo7rKv4n8POjjXlNQvM" + - "9IPLr8qZ7usYBKhEGwX3yq_eicAwBw" + payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" + // printf '.' | openssl dgst -binary -sha256 -sign testKey | b64raw + signature = "YFyl_xz1E7TR-3E1bIuASTr424EgCvBHjt25WUFC2VaDjXYV0Rj_" + + "Hd3dJ_2IRqBrXDZZ2n4ZeA_4mm3QFwmwyeDwe2sWElhb82lCZ8iX" + + "uFnjeOmSOjx-nWwPa5ibCXzLq13zZ-OBV1Z4oN_TuailQeRoSfA3" + + "nO8gG52mv1x2OMQ5MAFtt8jcngBLzts4AyhI6mBJ2w7Yaj3ZCriq" + + "DWA3GLFvvHdW1Ba9Z01wtGT2CuZI7DUk_6Qj1b3BkBGcoKur5C9i" + + "bUJtCkABwBMvBQNyD3MmXsrRFRTgvVlyU_yMaucYm7nmzEr_2PaQ" + + "50rFt_9qOfJ4sfbLtG1Wwae57BQx1g" ) - b, err := jwsEncodeJSON(claims, testKey, "nonce") + b, err := jwsEncodeJSON(claims, testKey, noKeyID, "nonce", "url") if err != nil { t.Fatal(err) } @@ -182,6 +195,84 @@ func TestJWSEncodeJSON(t *testing.T) { } } +func TestJWSEncodeNoNonce(t *testing.T) { + kid := KeyID("https://example.org/account/1") + claims := "RawString" + const ( + // {"alg":"ES256","kid":"https://example.org/account/1","nonce":"nonce","url":"url"} + protected = "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYWNjb3VudC8xIiwidXJsIjoidXJsIn0" + // "Raw String" + payload = "RawString" + ) + + b, err := jwsEncodeJSON(claims, testKeyEC, kid, "", "url") + if err != nil { + t.Fatal(err) + } + var jws struct{ Protected, Payload, Signature string } + if err := json.Unmarshal(b, &jws); err != nil { + t.Fatal(err) + } + if jws.Protected != protected { + t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) + } + if jws.Payload != payload { + t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) + } + + sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) + if err != nil { + t.Fatalf("jws.Signature: %v", err) + } + r, s := big.NewInt(0), big.NewInt(0) + r.SetBytes(sig[:len(sig)/2]) + s.SetBytes(sig[len(sig)/2:]) + h := sha256.Sum256([]byte(protected + "." + payload)) + if !ecdsa.Verify(testKeyEC.Public().(*ecdsa.PublicKey), h[:], r, s) { + t.Error("invalid signature") + } +} + +func TestJWSEncodeKID(t *testing.T) { + kid := KeyID("https://example.org/account/1") + claims := struct{ Msg string }{"Hello JWS"} + // JWS signed with testKeyEC + const ( + // {"alg":"ES256","kid":"https://example.org/account/1","nonce":"nonce","url":"url"} + protected = "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5" + + "vcmcvYWNjb3VudC8xIiwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" + // {"Msg":"Hello JWS"} + payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" + ) + + b, err := jwsEncodeJSON(claims, testKeyEC, kid, "nonce", "url") + if err != nil { + t.Fatal(err) + } + var jws struct{ Protected, Payload, Signature string } + if err := json.Unmarshal(b, &jws); err != nil { + t.Fatal(err) + } + if jws.Protected != protected { + t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) + } + if jws.Payload != payload { + t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) + } + + sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) + if err != nil { + t.Fatalf("jws.Signature: %v", err) + } + r, s := big.NewInt(0), big.NewInt(0) + r.SetBytes(sig[:len(sig)/2]) + s.SetBytes(sig[len(sig)/2:]) + h := sha256.Sum256([]byte(protected + "." + payload)) + if !ecdsa.Verify(testKeyEC.Public().(*ecdsa.PublicKey), h[:], r, s) { + t.Error("invalid signature") + } +} + func TestJWSEncodeJSONEC(t *testing.T) { tt := []struct { key *ecdsa.PrivateKey @@ -194,7 +285,7 @@ func TestJWSEncodeJSONEC(t *testing.T) { } for i, test := range tt { claims := struct{ Msg string }{"Hello JWS"} - b, err := jwsEncodeJSON(claims, test.key, "nonce") + b, err := jwsEncodeJSON(claims, test.key, noKeyID, "nonce", "url") if err != nil { t.Errorf("%d: %v", i, err) continue @@ -212,6 +303,8 @@ func TestJWSEncodeJSONEC(t *testing.T) { var head struct { Alg string Nonce string + URL string `json:"url"` + KID string `json:"kid"` JWK struct { Crv string Kty string @@ -228,6 +321,13 @@ func TestJWSEncodeJSONEC(t *testing.T) { if head.Nonce != "nonce" { t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce) } + if head.URL != "url" { + t.Errorf("%d: head.URL = %q; want 'url'", i, head.URL) + } + if head.KID != "" { + // We used noKeyID in jwsEncodeJSON: expect no kid value. + t.Errorf("%d: head.KID = %q; want empty", i, head.KID) + } if head.JWK.Crv != test.crv { t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv) } @@ -256,18 +356,27 @@ func (s *customTestSigner) Sign(io.Reader, []byte, crypto.SignerOpts) ([]byte, e func TestJWSEncodeJSONCustom(t *testing.T) { claims := struct{ Msg string }{"hello"} const ( - // printf '{"Msg":"hello"}' | base64 | tr -d '=' | tr '/+' '_-' + // printf '{"Msg":"hello"}' | b64raw payload = "eyJNc2ciOiJoZWxsbyJ9" - // printf 'testsig' | base64 | tr -d '=' + // printf 'testsig' | b64raw testsig = "dGVzdHNpZw" - // printf '{"alg":"ES256","jwk":{"crv":"P-256","kty":"EC","x":,"y":,"nonce":"nonce"}' | \ - // base64 | tr -d '=' | tr '/+' '_-' - es256phead = "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjVsaEV1" + - "ZzV4SzR4QkRaMm5BYmF4THRhTGl2ODVieEo3ZVBkMWRrTzIzSFEiLCJ5IjoiNGFpSzcyc0JlVUFH" + - "a3YwVGFMc213b2tZVVl5TnhHc1M1RU1JS3dzTklLayJ9LCJub25jZSI6Im5vbmNlIn0" + // the example P256 curve point from https://tools.ietf.org/html/rfc7515#appendix-A.3.1 + // encoded as ASN.1… + es256stdsig = "MEUCIA7RIVN5Y2xIPC9/FVgH1AKjsigDOvl8fheBmsMWnqZlAiEA" + + "xQoH04w8cOXY8S2vCEpUgKZlkMXyk1Cajz9/ioOjVNU" + // …and RFC7518 (https://tools.ietf.org/html/rfc7518#section-3.4) + es256jwsig = "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw" + + "5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" + + // printf '{"alg":"ES256","jwk":{"crv":"P-256","kty":"EC","x":,"y":},"nonce":"nonce","url":"url"}' | b64raw + es256phead = "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0" + + "eSI6IkVDIiwieCI6IjVsaEV1ZzV4SzR4QkRaMm5BYmF4THRhTGl2" + + "ODVieEo3ZVBkMWRrTzIzSFEiLCJ5IjoiNGFpSzcyc0JlVUFHa3Yw" + + "VGFMc213b2tZVVl5TnhHc1M1RU1JS3dzTklLayJ9LCJub25jZSI6" + + "Im5vbmNlIiwidXJsIjoidXJsIn0" - // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"} + // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce","url":"url"} rs256phead = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + @@ -278,28 +387,34 @@ func TestJWSEncodeJSONCustom(t *testing.T) { "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + - "UVEifSwibm9uY2UiOiJub25jZSJ9" + "UVEifSwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" ) tt := []struct { - alg, phead string - pub crypto.PublicKey + alg, phead string + pub crypto.PublicKey + stdsig, jwsig string }{ - {"RS256", rs256phead, testKey.Public()}, - {"ES256", es256phead, testKeyEC.Public()}, + {"ES256", es256phead, testKeyEC.Public(), es256stdsig, es256jwsig}, + {"RS256", rs256phead, testKey.Public(), testsig, testsig}, } for _, tc := range tt { tc := tc t.Run(tc.alg, func(t *testing.T) { + stdsig, err := base64.RawStdEncoding.DecodeString(tc.stdsig) + if err != nil { + t.Errorf("couldn't decode test vector: %v", err) + } signer := &customTestSigner{ - sig: []byte("testsig"), + sig: stdsig, pub: tc.pub, } - b, err := jwsEncodeJSON(claims, signer, "nonce") + + b, err := jwsEncodeJSON(claims, signer, noKeyID, "nonce", "url") if err != nil { t.Fatal(err) } - var j struct{ Protected, Payload, Signature string } + var j jsonWebSignature if err := json.Unmarshal(b, &j); err != nil { t.Fatal(err) } @@ -309,13 +424,56 @@ func TestJWSEncodeJSONCustom(t *testing.T) { if j.Payload != payload { t.Errorf("j.Payload = %q\nwant %q", j.Payload, payload) } - if j.Signature != testsig { - t.Errorf("j.Signature = %q\nwant %q", j.Signature, testsig) + if j.Sig != tc.jwsig { + t.Errorf("j.Sig = %q\nwant %q", j.Sig, tc.jwsig) } }) } } +func TestJWSWithMAC(t *testing.T) { + // Example from RFC 7520 Section 4.4.3. + // https://tools.ietf.org/html/rfc7520#section-4.4.3 + b64Key := "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg" + rawPayload := []byte("It\xe2\x80\x99s a dangerous business, Frodo, going out your " + + "door. You step onto the road, and if you don't keep your feet, " + + "there\xe2\x80\x99s no knowing where you might be swept off " + + "to.") + protected := "eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LW" + + "VlZjMxNGJjNzAzNyJ9" + payload := "SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywg" + + "Z29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9h" + + "ZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXi" + + "gJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9m" + + "ZiB0by4" + sig := "s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0" + + key, err := base64.RawURLEncoding.DecodeString(b64Key) + if err != nil { + t.Fatalf("unable to decode key: %q", b64Key) + } + got, err := jwsWithMAC(key, "018c0ae5-4d9b-471b-bfd6-eef314bc7037", "", rawPayload) + if err != nil { + t.Fatalf("jwsWithMAC() = %q", err) + } + if got.Protected != protected { + t.Errorf("got.Protected = %q\nwant %q", got.Protected, protected) + } + if got.Payload != payload { + t.Errorf("got.Payload = %q\nwant %q", got.Payload, payload) + } + if got.Sig != sig { + t.Errorf("got.Signature = %q\nwant %q", got.Sig, sig) + } +} + +func TestJWSWithMACError(t *testing.T) { + p := "{}" + if _, err := jwsWithMAC(nil, "", "", []byte(p)); err == nil { + t.Errorf("jwsWithMAC(nil, ...) = success; want err") + } +} + func TestJWKThumbprintRSA(t *testing.T) { // Key example from RFC 7638 const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" + @@ -352,10 +510,8 @@ func TestJWKThumbprintRSA(t *testing.T) { func TestJWKThumbprintEC(t *testing.T) { // Key example from RFC 7520 // expected was computed with - // echo -n '{"crv":"P-521","kty":"EC","x":"","y":""}' | \ - // openssl dgst -binary -sha256 | \ - // base64 | \ - // tr -d '=' | tr '/+' '_-' + // printf '{"crv":"P-521","kty":"EC","x":"","y":""}' | \ + // openssl dgst -binary -sha256 | b64raw const ( base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" + "KqjqvjyekWF-7ytDyRXYgCF5cj0Kt" diff --git a/acme/pebble_test.go b/acme/pebble_test.go new file mode 100644 index 0000000000..79051ac821 --- /dev/null +++ b/acme/pebble_test.go @@ -0,0 +1,809 @@ +// Copyright 2025 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_test + +import ( + "bytes" + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "encoding/json" + "encoding/pem" + "errors" + "flag" + "fmt" + "io" + "log" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + + "golang.org/x/crypto/acme" +) + +const ( + // pebbleModVersion is the module version used for Pebble and Pebble's + // challenge test server. It is ignored if `-pebble-local-dir` is provided. + pebbleModVersion = "v2.7.0" + // startingPort is the first port number used for binding interface + // addresses. Each call to takeNextPort() will increment a port number + // starting at this value. + startingPort = 5555 +) + +var ( + pebbleLocalDir = flag.String( + "pebble-local-dir", + "", + "Local Pebble to use, instead of fetching from source", + ) + nextPort atomic.Uint32 +) + +func init() { + nextPort.Store(startingPort) +} + +func TestWithPebble(t *testing.T) { + // We want to use process groups w/ syscall.Kill, and the acme package + // is very platform-agnostic, so skip on non-Linux. + if runtime.GOOS != "linux" { + t.Skip("skipping pebble tests on non-linux OS") + } + + if testing.Short() { + t.Skip("skipping pebble tests in short mode") + } + + tests := []struct { + name string + challSrv func(*environment) (challengeServer, string) + }{ + { + name: "TLSALPN01-Issuance", + challSrv: func(env *environment) (challengeServer, string) { + bindAddr := fmt.Sprintf(":%d", env.config.TLSPort) + return newChallTLSServer(bindAddr), bindAddr + }, + }, + + { + name: "HTTP01-Issuance", + challSrv: func(env *environment) (challengeServer, string) { + bindAddr := fmt.Sprintf(":%d", env.config.HTTPPort) + return newChallHTTPServer(bindAddr), bindAddr + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + env := startPebbleEnvironment(t, nil) + challSrv, challSrvAddr := tt.challSrv(&env) + challSrv.Run() + + t.Cleanup(func() { + challSrv.Shutdown() + }) + + waitForServer(t, challSrvAddr) + testIssuance(t, &env, challSrv) + }) + } +} + +// challengeServer abstracts over the details of running a challenge response +// server for some supported acme.Challenge type. Responses are provisioned +// during the test issuance process to be presented to the ACME server's +// validation authority. +type challengeServer interface { + Run() + Shutdown() error + Supported(chal *acme.Challenge) bool + Provision(client *acme.Client, ident acme.AuthzID, chal *acme.Challenge) error +} + +// challTLSServer is a simple challenge response server that listens for TLS +// connections on a specific port and if they are TLS-ALPN-01 challenge +// requests, completes the handshake using the configured challenge response +// certificate for the SNI value provided. +type challTLSServer struct { + *http.Server + // mu protects challCerts. + mu sync.RWMutex + // challCerts is a map from SNI domain name to challenge response certificate. + challCerts map[string]*tls.Certificate +} + +// https://datatracker.ietf.org/doc/html/rfc8737#section-4 +const acmeTLSAlpnProtocol = "acme-tls/1" + +func newChallTLSServer(address string) *challTLSServer { + challServer := &challTLSServer{Server: &http.Server{ + Addr: address, + ReadTimeout: 5 * time.Second, + WriteTimeout: 5 * time.Second, + }, challCerts: make(map[string]*tls.Certificate)} + + // Configure the server to support the TLS-ALPN-01 challenge protocol + // and to use a callback for selecting the handshake certificate. + challServer.Server.TLSConfig = &tls.Config{ + NextProtos: []string{acmeTLSAlpnProtocol}, + GetCertificate: challServer.getCertificate, + } + + return challServer +} + +func (c *challTLSServer) Shutdown() error { + log.Printf("challTLSServer: shutting down") + ctx, cancel := context.WithTimeout(context.Background(), 10) + defer cancel() + return c.Server.Shutdown(ctx) +} + +func (c *challTLSServer) Run() { + go func() { + // Note: certFile and keyFile are empty because our config uses a + // GetCertificate callback. + if err := c.Server.ListenAndServeTLS("", ""); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + log.Printf("challTLSServer error: %v", err) + } + } + }() +} + +func (c *challTLSServer) Supported(chal *acme.Challenge) bool { + return chal.Type == "tls-alpn-01" +} + +func (c *challTLSServer) Provision(client *acme.Client, ident acme.AuthzID, chal *acme.Challenge) error { + respCert, err := client.TLSALPN01ChallengeCert(chal.Token, ident.Value) + if err != nil { + return fmt.Errorf("challTLSServer: failed to generate challlenge response cert for %s: %w", + ident.Value, err) + } + + log.Printf("challTLSServer: setting challenge response certificate for %s", ident.Value) + c.mu.Lock() + defer c.mu.Unlock() + c.challCerts[ident.Value] = &respCert + + return nil +} + +func (c *challTLSServer) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { + // Verify the request looks like a TLS-ALPN-01 challenge request. + if len(clientHello.SupportedProtos) != 1 || clientHello.SupportedProtos[0] != acmeTLSAlpnProtocol { + return nil, fmt.Errorf( + "challTLSServer: non-TLS-ALPN-01 challenge request received with SupportedProtos: %s", + clientHello.SupportedProtos) + } + + serverName := clientHello.ServerName + + // TLS-ALPN-01 challenge requests for IP addresses are encoded in the SNI + // using the reverse-DNS notation. See RFC 8738 Section 6: + // https://www.rfc-editor.org/rfc/rfc8738.html#section-6 + if strings.HasSuffix(serverName, ".in-addr.arpa") { + serverName = strings.TrimSuffix(serverName, ".in-addr.arpa") + parts := strings.Split(serverName, ".") + for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 { + parts[i], parts[j] = parts[j], parts[i] + } + serverName = strings.Join(parts, ".") + } + + log.Printf("challTLSServer: selecting certificate for request from %s for %s", + clientHello.Conn.RemoteAddr(), serverName) + + c.mu.RLock() + defer c.mu.RUnlock() + cert := c.challCerts[serverName] + if cert == nil { + return nil, fmt.Errorf("challTLSServer: no challenge response certificate configured for %s", serverName) + } + + return cert, nil +} + +// challHTTPServer is a simple challenge response server that listens for HTTP +// connections on a specific port and if they are HTTP-01 challenge requests, +// serves the challenge response key authorization. +type challHTTPServer struct { + *http.Server + // mu protects challMap + mu sync.RWMutex + // challMap is a mapping from request path to response body. + challMap map[string]string +} + +func newChallHTTPServer(address string) *challHTTPServer { + challServer := &challHTTPServer{ + Server: &http.Server{ + Addr: address, + ReadTimeout: 5 * time.Second, + WriteTimeout: 5 * time.Second, + }, + challMap: make(map[string]string), + } + + challServer.Server.Handler = challServer + + return challServer +} + +func (c *challHTTPServer) Supported(chal *acme.Challenge) bool { + return chal.Type == "http-01" +} + +func (c *challHTTPServer) Provision(client *acme.Client, ident acme.AuthzID, chall *acme.Challenge) error { + path := client.HTTP01ChallengePath(chall.Token) + body, err := client.HTTP01ChallengeResponse(chall.Token) + if err != nil { + return fmt.Errorf("failed to generate HTTP-01 challenge response for %v challenge %s token %s: %w", + ident, chall.URI, chall.Token, err) + } + + c.mu.Lock() + defer c.mu.Unlock() + log.Printf("challHTTPServer: setting challenge response for %s", path) + c.challMap[path] = body + + return nil +} + +func (c *challHTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + log.Printf("challHTTPServer: handling %s to %s from %s", r.Method, r.URL.Path, r.RemoteAddr) + if r.Method != http.MethodGet { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + c.mu.RLock() + defer c.mu.RUnlock() + response, exists := c.challMap[r.URL.Path] + + if !exists { + http.NotFound(w, r) + return + } + + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte(response)) +} + +func (c *challHTTPServer) Shutdown() error { + log.Printf("challHTTPServer: shutting down") + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + return c.Server.Shutdown(ctx) +} + +func (c *challHTTPServer) Run() { + go func() { + if err := c.Server.ListenAndServe(); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + log.Printf("challHTTPServer error: %v", err) + } + } + }() +} + +func testIssuance(t *testing.T, env *environment, challSrv challengeServer) { + t.Helper() + + // Bound the total issuance process by a timeout of 60 seconds. + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + // Create a new ACME account. + client := env.client + acct, err := client.Register(ctx, &acme.Account{}, acme.AcceptTOS) + if err != nil { + t.Fatalf("failed to register account: %v", err) + } + if acct.Status != acme.StatusValid { + t.Fatalf("expected new account status to be valid, got %v", acct.Status) + } + log.Printf("registered account: %s", acct.URI) + + // Create a new order for some example identifiers + identifiers := []acme.AuthzID{ + { + Type: "dns", + Value: "example.com", + }, + { + Type: "dns", + Value: "www.example.com", + }, + { + Type: "ip", + Value: "127.0.0.1", + }, + } + order, err := client.AuthorizeOrder(ctx, identifiers) + if err != nil { + t.Fatalf("failed to create order for %v: %v", identifiers, err) + } + if order.Status != acme.StatusPending { + t.Fatalf("expected new order status to be pending, got %v", order.Status) + } + orderURL := order.URI + log.Printf("created order: %v", orderURL) + + // For each pending authz provision a supported challenge type's response + // with the test challenge server, and tell the ACME server to verify it. + for _, authzURL := range order.AuthzURLs { + authz, err := client.GetAuthorization(ctx, authzURL) + if err != nil { + t.Fatalf("failed to get order %s authorization %s: %v", + orderURL, authzURL, err) + } + + if authz.Status != acme.StatusPending { + continue + } + + for _, challenge := range authz.Challenges { + if challenge.Status != acme.StatusPending || !challSrv.Supported(challenge) { + continue + } + + if err := challSrv.Provision(client, authz.Identifier, challenge); err != nil { + t.Fatalf("failed to provision challenge %s: %v", challenge.URI, err) + } + + _, err = client.Accept(ctx, challenge) + if err != nil { + t.Fatalf("failed to accept order %s challenge %s: %v", + orderURL, challenge.URI, err) + } + } + } + + // Wait for the order to become ready for finalization. + order, err = client.WaitOrder(ctx, order.URI) + if err != nil { + var orderErr *acme.OrderError + if errors.Is(err, orderErr) { + t.Fatalf("failed to wait for order %s: %s: %s", orderURL, err, orderErr.Problem) + } else { + t.Fatalf("failed to wait for order %s: %s", orderURL, err) + } + } + if order.Status != acme.StatusReady { + t.Fatalf("expected order %s status to be ready, got %v", + orderURL, order.Status) + } + + // Generate a certificate keypair and a CSR for the order identifiers. + certKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("failed to generate certificate key: %v", err) + } + var dnsNames []string + var ipAddresses []net.IP + for _, ident := range identifiers { + switch ident.Type { + case "dns": + dnsNames = append(dnsNames, ident.Value) + case "ip": + ipAddresses = append(ipAddresses, net.ParseIP(ident.Value)) + default: + t.Fatalf("unsupported identifier type: %s", ident.Type) + } + } + csrDer, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{ + DNSNames: dnsNames, + IPAddresses: ipAddresses, + }, certKey) + if err != nil { + t.Fatalf("failed to create CSR: %v", err) + } + + // Finalize the order by creating a certificate with our CSR. + chain, _, err := client.CreateOrderCert(ctx, order.FinalizeURL, csrDer, true) + if err != nil { + t.Fatalf("failed to finalize order %s with finalize URL %s: %v", + orderURL, order.FinalizeURL, err) + } + + // Split the chain into the leaf and any intermediates. + leaf := chain[0] + intermediatesDER := chain[1:] + leafCert, err := x509.ParseCertificate(leaf) + if err != nil { + t.Fatalf("failed to parse order %s leaf certificate: %v", orderURL, err) + } + intermediates := x509.NewCertPool() + for i, intermediateDER := range intermediatesDER { + intermediate, err := x509.ParseCertificate(intermediateDER) + if err != nil { + t.Fatalf("failed to parse intermediate %d: %v", i, err) + } + intermediates.AddCert(intermediate) + } + + // Verify there is a valid path from the leaf certificate to Pebble's + // issuing root using the provided intermediate certificates. + roots, err := env.RootCert() + if err != nil { + t.Fatalf("failed to get Pebble issuer root certs: %v", err) + } + paths, err := leafCert.Verify(x509.VerifyOptions{ + Intermediates: intermediates, + Roots: roots, + }) + if err != nil { + t.Fatalf("failed to verify order %s leaf certificate: %v", orderURL, err) + } + log.Printf("verified %d path(s) from issued leaf certificate to Pebble root CA", len(paths)) + + // Also verify that the leaf cert is valid for each of the DNS names + // and IP addresses from our order's identifiers. + for _, name := range dnsNames { + if err := leafCert.VerifyHostname(name); err != nil { + t.Fatalf("failed to verify order %s leaf certificate for order DNS name %s: %v", + orderURL, name, err) + } + } + for _, ip := range ipAddresses { + if err := leafCert.VerifyHostname(ip.String()); err != nil { + t.Fatalf("failed to verify order %s leaf certificate for order IP address %s: %v", + orderURL, ip, err) + } + } +} + +type environment struct { + config *environmentConfig + client *acme.Client +} + +// RootCert returns the Pebble CA's primary issuing hierarchy root certificate. +// This is generated randomly at each startup and can be used to verify +// certificate chains issued by Pebble's ACME interface. Note that this +// is separate from the static root certificate used by the Pebble ACME +// HTTPS interface. +func (e *environment) RootCert() (*x509.CertPool, error) { + // NOTE: in the future we may want to consider the alternative chains + // returned as Link alternative headers. + rootURL := fmt.Sprintf("https://%s/roots/0", e.config.pebbleConfig.ManagementListenAddress) + resp, err := e.client.HTTPClient.Get(rootURL) + if err != nil || resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to GET Pebble root CA from %s: %v", rootURL, err) + } + + roots := x509.NewCertPool() + rootPEM, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to parse Pebble root CA PEM: %v", err) + } + rootDERBlock, _ := pem.Decode(rootPEM) + rootCA, err := x509.ParseCertificate(rootDERBlock.Bytes) + if err != nil { + return nil, fmt.Errorf("failed to parse Pebble root CA DER: %v", err) + } + roots.AddCert(rootCA) + + return roots, nil +} + +// environmentConfig describes the Pebble configuration, and configuration +// shared between pebble and pebble-challtestsrv. +type environmentConfig struct { + pebbleConfig + dnsPort uint32 +} + +// defaultConfig returns an environmentConfig populated with default values. +// The provided pebbleDir is used to specify certificate/private key paths +// for the HTTPS ACME interface. +func defaultConfig(pebbleDir string) environmentConfig { + return environmentConfig{ + pebbleConfig: pebbleConfig{ + ListenAddress: fmt.Sprintf("127.0.0.1:%d", takeNextPort()), + ManagementListenAddress: fmt.Sprintf("127.0.0.1:%d", takeNextPort()), + HTTPPort: takeNextPort(), + TLSPort: takeNextPort(), + Certificate: fmt.Sprintf("%s/test/certs/localhost/cert.pem", pebbleDir), + PrivateKey: fmt.Sprintf("%s/test/certs/localhost/key.pem", pebbleDir), + OCSPResponderURL: "", + ExternalAccountBindingRequired: false, + ExternalAccountMACKeys: make(map[string]string), + DomainBlocklist: []string{"blocked-domain.example"}, + Profiles: map[string]struct { + Description string + ValidityPeriod uint64 + }{ + "default": { + Description: "default profile", + ValidityPeriod: 3600, + }, + }, + RetryAfter: struct { + Authz int + Order int + }{ + 3, + 5, + }, + }, + dnsPort: takeNextPort(), + } +} + +// pebbleConfig matches the JSON structure of the Pebble configuration file. +type pebbleConfig struct { + ListenAddress string + ManagementListenAddress string + HTTPPort uint32 + TLSPort uint32 + Certificate string + PrivateKey string + OCSPResponderURL string + ExternalAccountBindingRequired bool + ExternalAccountMACKeys map[string]string + DomainBlocklist []string + Profiles map[string]struct { + Description string + ValidityPeriod uint64 + } + RetryAfter struct { + Authz int + Order int + } +} + +func takeNextPort() uint32 { + return nextPort.Add(1) - 1 +} + +// startPebbleEnvironment is a test helper that spawns Pebble and Pebble +// challenge test server processes based on the provided environmentConfig. The +// processes will be torn down when the test ends. +func startPebbleEnvironment(t *testing.T, config *environmentConfig) environment { + t.Helper() + + var pebbleDir string + if *pebbleLocalDir != "" { + pebbleDir = *pebbleLocalDir + } else { + pebbleDir = fetchModule(t, "github.com/letsencrypt/pebble/v2", pebbleModVersion) + } + + binDir := prepareBinaries(t, pebbleDir) + + if config == nil { + cfg := defaultConfig(pebbleDir) + config = &cfg + } + + marshalConfig := struct { + Pebble pebbleConfig + }{ + Pebble: config.pebbleConfig, + } + + configData, err := json.Marshal(marshalConfig) + if err != nil { + t.Fatalf("failed to marshal config: %v", err) + } + + configFile, err := os.CreateTemp("", "pebble-config-*.json") + if err != nil { + t.Fatalf("failed to create temp config file: %v", err) + } + t.Cleanup(func() { os.Remove(configFile.Name()) }) + + if _, err := configFile.Write(configData); err != nil { + t.Fatalf("failed to write config file: %v", err) + } + configFile.Close() + + log.Printf("pebble dir: %s", pebbleDir) + log.Printf("config file: %s", configFile.Name()) + + // Spawn the Pebble CA server. It answers ACME requests and performs + // outbound validations. We configure it to use a mock DNS server that + // always answers 127.0.0.1 for all A queries so that validation + // requests for any domain name will resolve to our local challenge + // server instances. + spawnServerProcess(t, binDir, "pebble", "-config", configFile.Name(), + "-dnsserver", fmt.Sprintf("127.0.0.1:%d", config.dnsPort), + "-strict") + + // Spawn the Pebble challenge test server. We'll use it to mock DNS + // responses but disable all the other interfaces. We want to stand + // up our own challenge response servers for TLS-ALPN-01, + // etc. + // Note: we specify -defaultIPv6 "" so that no AAAA records are served. + // The LUCI CI runners have issues with IPv6 connectivity on localhost. + spawnServerProcess(t, binDir, "pebble-challtestsrv", + "-dns01", fmt.Sprintf(":%d", config.dnsPort), + "-defaultIPv6", "", + "-management", fmt.Sprintf(":%d", takeNextPort()), + "-doh", "", + "-http01", "", + "-tlsalpn01", "", + "-https01", "") + + waitForServer(t, config.pebbleConfig.ListenAddress) + waitForServer(t, fmt.Sprintf("127.0.0.1:%d", config.dnsPort)) + + log.Printf("pebble environment ready") + + // Construct a cert pool that contains the CA certificate used by the ACME + // interface's certificate chain. This is separate from the issuing + // hierarchy and is used for the ACME client to interact with the ACME + // interface without cert verification error. + caCertPath := filepath.Join(pebbleDir, "test/certs/pebble.minica.pem") + caCert, err := os.ReadFile(caCertPath) + if err != nil { + t.Fatalf("failed to read CA certificate %s: %v", caCertPath, err) + } + caCertPool := x509.NewCertPool() + if !caCertPool.AppendCertsFromPEM(caCert) { + t.Fatalf("failed to parse CA certificate %s", caCertPath) + } + httpClient := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + }, + }, + } + + // Create an ACME account keypair/client and verify it can discover + // the Pebble server's ACME directory without error. + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("failed to generate account key: %v", err) + } + client := &acme.Client{ + Key: key, + HTTPClient: httpClient, + DirectoryURL: fmt.Sprintf("https://%s/dir", config.ListenAddress), + } + _, err = client.Discover(context.TODO()) + if err != nil { + t.Fatalf("failed to discover ACME directory: %v", err) + } + + return environment{ + config: config, + client: client, + } +} + +func waitForServer(t *testing.T, addr string) { + t.Helper() + + for i := 0; i < 20; i++ { + if conn, err := net.Dial("tcp", addr); err == nil { + conn.Close() + return + } + time.Sleep(time.Duration(i*100) * time.Millisecond) + } + t.Fatalf("failed to connect to %q after 20 tries", addr) +} + +// fetchModule fetches the module at the given version and returns the directory +// containing its source tree. It skips the test if fetching modules is not +// possible in this environment. +// +// Copied from the stdlib cryptotest.FetchModule and adapted to not rely on the +// stdlib internal testenv package. +func fetchModule(t *testing.T, module, version string) string { + // If the default GOMODCACHE doesn't exist, use a temporary directory + // instead. (For example, run.bash sets GOPATH=/nonexist-gopath.) + out, err := exec.Command("go", "env", "GOMODCACHE").Output() + if err != nil { + t.Errorf("go env GOMODCACHE: %v\n%s", err, out) + if ee, ok := err.(*exec.ExitError); ok { + t.Logf("%s", ee.Stderr) + } + t.FailNow() + } + modcacheOk := false + if gomodcache := string(bytes.TrimSpace(out)); gomodcache != "" { + if _, err := os.Stat(gomodcache); err == nil { + modcacheOk = true + } + } + if !modcacheOk { + t.Setenv("GOMODCACHE", t.TempDir()) + // Allow t.TempDir() to clean up subdirectories. + t.Setenv("GOFLAGS", os.Getenv("GOFLAGS")+" -modcacherw") + } + + t.Logf("fetching %s@%s\n", module, version) + + output, err := exec.Command("go", "mod", "download", "-json", module+"@"+version).CombinedOutput() + if err != nil { + t.Fatalf("failed to download %s@%s: %s\n%s\n", module, version, err, output) + } + var j struct { + Dir string + } + if err := json.Unmarshal(output, &j); err != nil { + t.Fatalf("failed to parse 'go mod download': %s\n%s\n", err, output) + } + + return j.Dir +} + +func prepareBinaries(t *testing.T, pebbleDir string) string { + t.Helper() + + // We don't want to build in the module cache dir, which might not be + // writable or to pollute the user's clone with binaries if pebbleLocalDir + // is used. + binDir := t.TempDir() + + build := func(cmd string) { + log.Printf("building %s", cmd) + buildCmd := exec.Command( + "go", + "build", "-o", filepath.Join(binDir, cmd), "-mod", "mod", "./cmd/"+cmd) + buildCmd.Dir = pebbleDir + output, err := buildCmd.CombinedOutput() + if err != nil { + t.Fatalf("failed to build %s: %s\n%s\n", cmd, err, output) + } + } + + build("pebble") + build("pebble-challtestsrv") + + return binDir +} + +func spawnServerProcess(t *testing.T, dir string, cmd string, args ...string) { + t.Helper() + + var stdout, stderr bytes.Buffer + + cmdInstance := exec.Command("./"+cmd, args...) + cmdInstance.Dir = dir + cmdInstance.Stdout = &stdout + cmdInstance.Stderr = &stderr + + if err := cmdInstance.Start(); err != nil { + t.Fatalf("failed to start %s: %v", cmd, err) + } + + t.Cleanup(func() { + cmdInstance.Process.Kill() + cmdInstance.Wait() + + if t.Failed() || testing.Verbose() { + t.Logf("=== %s output ===", cmd) + if stdout.Len() > 0 { + t.Logf("stdout:\n%s", strings.TrimSpace(stdout.String())) + } + if stderr.Len() > 0 { + t.Logf("stderr:\n%s", strings.TrimSpace(stderr.String())) + } + } + }) +} diff --git a/acme/rfc8555.go b/acme/rfc8555.go new file mode 100644 index 0000000000..976b27702a --- /dev/null +++ b/acme/rfc8555.go @@ -0,0 +1,476 @@ +// Copyright 2019 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 ( + "context" + "crypto" + "encoding/base64" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + "io" + "net/http" + "time" +) + +// DeactivateReg permanently disables an existing account associated with c.Key. +// A deactivated account can no longer request certificate issuance or access +// resources related to the account, such as orders or authorizations. +// +// It only works with CAs implementing RFC 8555. +func (c *Client) DeactivateReg(ctx context.Context) error { + if _, err := c.Discover(ctx); err != nil { // required by c.accountKID + return err + } + url := string(c.accountKID(ctx)) + if url == "" { + return ErrNoAccount + } + req := json.RawMessage(`{"status": "deactivated"}`) + res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) + if err != nil { + return err + } + res.Body.Close() + return nil +} + +// registerRFC is equivalent to c.Register but for CAs implementing RFC 8555. +// It expects c.Discover to have already been called. +func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { + c.cacheMu.Lock() // guard c.kid access + defer c.cacheMu.Unlock() + + req := struct { + TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"` + Contact []string `json:"contact,omitempty"` + ExternalAccountBinding *jsonWebSignature `json:"externalAccountBinding,omitempty"` + }{ + Contact: acct.Contact, + } + if c.dir.Terms != "" { + req.TermsAgreed = prompt(c.dir.Terms) + } + + // set 'externalAccountBinding' field if requested + if acct.ExternalAccountBinding != nil { + eabJWS, err := c.encodeExternalAccountBinding(acct.ExternalAccountBinding) + if err != nil { + return nil, fmt.Errorf("acme: failed to encode external account binding: %v", err) + } + req.ExternalAccountBinding = eabJWS + } + + res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus( + http.StatusOK, // account with this key already registered + http.StatusCreated, // new account created + )) + if err != nil { + return nil, err + } + + defer res.Body.Close() + a, err := responseAccount(res) + if err != nil { + return nil, err + } + // Cache Account URL even if we return an error to the caller. + // It is by all means a valid and usable "kid" value for future requests. + c.KID = KeyID(a.URI) + if res.StatusCode == http.StatusOK { + return nil, ErrAccountAlreadyExists + } + return a, nil +} + +// encodeExternalAccountBinding will encode an external account binding stanza +// as described in https://tools.ietf.org/html/rfc8555#section-7.3.4. +func (c *Client) encodeExternalAccountBinding(eab *ExternalAccountBinding) (*jsonWebSignature, error) { + jwk, err := jwkEncode(c.Key.Public()) + if err != nil { + return nil, err + } + return jwsWithMAC(eab.Key, eab.KID, c.dir.RegURL, []byte(jwk)) +} + +// updateRegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555. +// It expects c.Discover to have already been called. +func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) { + url := string(c.accountKID(ctx)) + if url == "" { + return nil, ErrNoAccount + } + req := struct { + Contact []string `json:"contact,omitempty"` + }{ + Contact: a.Contact, + } + res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) + if err != nil { + return nil, err + } + defer res.Body.Close() + return responseAccount(res) +} + +// getRegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555. +// It expects c.Discover to have already been called. +func (c *Client) getRegRFC(ctx context.Context) (*Account, error) { + req := json.RawMessage(`{"onlyReturnExisting": true}`) + res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK)) + if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" { + return nil, ErrNoAccount + } + if err != nil { + return nil, err + } + + defer res.Body.Close() + return responseAccount(res) +} + +func responseAccount(res *http.Response) (*Account, error) { + var v struct { + Status string + Contact []string + Orders string + } + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: invalid account response: %v", err) + } + return &Account{ + URI: res.Header.Get("Location"), + Status: v.Status, + Contact: v.Contact, + OrdersURL: v.Orders, + }, nil +} + +// accountKeyRollover attempts to perform account key rollover. +// On success it will change client.Key to the new key. +func (c *Client) accountKeyRollover(ctx context.Context, newKey crypto.Signer) error { + dir, err := c.Discover(ctx) // Also required by c.accountKID + if err != nil { + return err + } + kid := c.accountKID(ctx) + if kid == noKeyID { + return ErrNoAccount + } + oldKey, err := jwkEncode(c.Key.Public()) + if err != nil { + return err + } + payload := struct { + Account string `json:"account"` + OldKey json.RawMessage `json:"oldKey"` + }{ + Account: string(kid), + OldKey: json.RawMessage(oldKey), + } + inner, err := jwsEncodeJSON(payload, newKey, noKeyID, noNonce, dir.KeyChangeURL) + if err != nil { + return err + } + + res, err := c.post(ctx, nil, dir.KeyChangeURL, base64.RawURLEncoding.EncodeToString(inner), wantStatus(http.StatusOK)) + if err != nil { + return err + } + defer res.Body.Close() + c.Key = newKey + return nil +} + +// AuthorizeOrder initiates the order-based application for certificate issuance, +// as opposed to pre-authorization in Authorize. +// It is only supported by CAs implementing RFC 8555. +// +// The caller then needs to fetch each authorization with GetAuthorization, +// identify those with StatusPending status and fulfill a challenge using Accept. +// Once all authorizations are satisfied, the caller will typically want to poll +// order status using WaitOrder until it's in StatusReady state. +// To finalize the order and obtain a certificate, the caller submits a CSR with CreateOrderCert. +func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error) { + dir, err := c.Discover(ctx) + if err != nil { + return nil, err + } + + req := struct { + Identifiers []wireAuthzID `json:"identifiers"` + NotBefore string `json:"notBefore,omitempty"` + NotAfter string `json:"notAfter,omitempty"` + }{} + for _, v := range id { + req.Identifiers = append(req.Identifiers, wireAuthzID{ + Type: v.Type, + Value: v.Value, + }) + } + for _, o := range opt { + switch o := o.(type) { + case orderNotBeforeOpt: + req.NotBefore = time.Time(o).Format(time.RFC3339) + case orderNotAfterOpt: + req.NotAfter = time.Time(o).Format(time.RFC3339) + default: + // Package's fault if we let this happen. + panic(fmt.Sprintf("unsupported order option type %T", o)) + } + } + + res, err := c.post(ctx, nil, dir.OrderURL, req, wantStatus(http.StatusCreated)) + if err != nil { + return nil, err + } + defer res.Body.Close() + return responseOrder(res) +} + +// GetOrder retrieves an order identified by the given URL. +// For orders created with AuthorizeOrder, the url value is Order.URI. +// +// If a caller needs to poll an order until its status is final, +// see the WaitOrder method. +func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error) { + if _, err := c.Discover(ctx); err != nil { + return nil, err + } + + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) + if err != nil { + return nil, err + } + defer res.Body.Close() + return responseOrder(res) +} + +// WaitOrder polls an order from the given URL until it is in one of the final states, +// StatusReady, StatusValid or StatusInvalid, the CA responded with a non-retryable error +// or the context is done. +// +// It returns a non-nil Order only if its Status is StatusReady or StatusValid. +// In all other cases WaitOrder returns an error. +// If the Status is StatusInvalid, the returned error is of type *OrderError. +func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) { + if _, err := c.Discover(ctx); err != nil { + return nil, err + } + for { + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) + if err != nil { + return nil, err + } + o, err := responseOrder(res) + res.Body.Close() + switch { + case err != nil: + // Skip and retry. + case o.Status == StatusInvalid: + return nil, &OrderError{OrderURL: o.URI, Status: o.Status, Problem: o.Error} + case o.Status == StatusReady || o.Status == StatusValid: + return o, nil + } + + d := retryAfter(res.Header.Get("Retry-After")) + if d == 0 { + // Default retry-after. + // Same reasoning as in WaitAuthorization. + d = time.Second + } + t := time.NewTimer(d) + select { + case <-ctx.Done(): + t.Stop() + return nil, ctx.Err() + case <-t.C: + // Retry. + } + } +} + +func responseOrder(res *http.Response) (*Order, error) { + var v struct { + Status string + Expires time.Time + Identifiers []wireAuthzID + NotBefore time.Time + NotAfter time.Time + Error *wireError + Authorizations []string + Finalize string + Certificate string + } + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: error reading order: %v", err) + } + o := &Order{ + URI: res.Header.Get("Location"), + Status: v.Status, + Expires: v.Expires, + NotBefore: v.NotBefore, + NotAfter: v.NotAfter, + AuthzURLs: v.Authorizations, + FinalizeURL: v.Finalize, + CertURL: v.Certificate, + } + for _, id := range v.Identifiers { + o.Identifiers = append(o.Identifiers, AuthzID{Type: id.Type, Value: id.Value}) + } + if v.Error != nil { + o.Error = v.Error.error(nil /* headers */) + } + return o, nil +} + +// CreateOrderCert submits the CSR (Certificate Signing Request) to a CA at the specified URL. +// The URL is the FinalizeURL field of an Order created with AuthorizeOrder. +// +// If the bundle argument is true, the returned value also contain the CA (issuer) +// certificate chain. Otherwise, only a leaf certificate is returned. +// The returned URL can be used to re-fetch the certificate using FetchCert. +// +// This method is only supported by CAs implementing RFC 8555. See CreateCert for pre-RFC CAs. +// +// CreateOrderCert returns an error if the CA's response is unreasonably large. +// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features. +func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) { + if _, err := c.Discover(ctx); err != nil { // required by c.accountKID + return nil, "", err + } + + // RFC describes this as "finalize order" request. + req := struct { + CSR string `json:"csr"` + }{ + CSR: base64.RawURLEncoding.EncodeToString(csr), + } + res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) + if err != nil { + return nil, "", err + } + defer res.Body.Close() + o, err := responseOrder(res) + if err != nil { + return nil, "", err + } + + // Wait for CA to issue the cert if they haven't. + if o.Status != StatusValid { + o, err = c.WaitOrder(ctx, o.URI) + } + if err != nil { + return nil, "", err + } + // The only acceptable status post finalize and WaitOrder is "valid". + if o.Status != StatusValid { + return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status, Problem: o.Error} + } + crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle) + return crt, o.CertURL, err +} + +// fetchCertRFC downloads issued certificate from the given URL. +// It expects the CA to respond with PEM-encoded certificate chain. +// +// The URL argument is the CertURL field of Order. +func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][]byte, error) { + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) + if err != nil { + return nil, err + } + defer res.Body.Close() + + // Get all the bytes up to a sane maximum. + // Account very roughly for base64 overhead. + const max = maxCertChainSize + maxCertChainSize/33 + b, err := io.ReadAll(io.LimitReader(res.Body, max+1)) + if err != nil { + return nil, fmt.Errorf("acme: fetch cert response stream: %v", err) + } + if len(b) > max { + return nil, errors.New("acme: certificate chain is too big") + } + + // Decode PEM chain. + var chain [][]byte + for { + var p *pem.Block + p, b = pem.Decode(b) + if p == nil { + break + } + if p.Type != "CERTIFICATE" { + return nil, fmt.Errorf("acme: invalid PEM cert type %q", p.Type) + } + + chain = append(chain, p.Bytes) + if !bundle { + return chain, nil + } + if len(chain) > maxChainLen { + return nil, errors.New("acme: certificate chain is too long") + } + } + if len(chain) == 0 { + return nil, errors.New("acme: certificate chain is empty") + } + return chain, nil +} + +// sends a cert revocation request in either JWK form when key is non-nil or KID form otherwise. +func (c *Client) revokeCertRFC(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { + req := &struct { + Cert string `json:"certificate"` + Reason int `json:"reason"` + }{ + Cert: base64.RawURLEncoding.EncodeToString(cert), + Reason: int(reason), + } + res, err := c.post(ctx, key, c.dir.RevokeURL, req, wantStatus(http.StatusOK)) + if err != nil { + if isAlreadyRevoked(err) { + // Assume it is not an error to revoke an already revoked cert. + return nil + } + return err + } + defer res.Body.Close() + return nil +} + +func isAlreadyRevoked(err error) bool { + e, ok := err.(*Error) + return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked" +} + +// ListCertAlternates retrieves any alternate certificate chain URLs for the +// given certificate chain URL. These alternate URLs can be passed to FetchCert +// in order to retrieve the alternate certificate chains. +// +// If there are no alternate issuer certificate chains, a nil slice will be +// returned. +func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) { + if _, err := c.Discover(ctx); err != nil { // required by c.accountKID + return nil, err + } + + res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) + if err != nil { + return nil, err + } + defer res.Body.Close() + + // We don't need the body but we need to discard it so we don't end up + // preventing keep-alive + if _, err := io.Copy(io.Discard, res.Body); err != nil { + return nil, fmt.Errorf("acme: cert alternates response stream: %v", err) + } + alts := linkHeader(res.Header, "alternate") + return alts, nil +} diff --git a/acme/rfc8555_test.go b/acme/rfc8555_test.go new file mode 100644 index 0000000000..e9cedb5927 --- /dev/null +++ b/acme/rfc8555_test.go @@ -0,0 +1,1030 @@ +// Copyright 2019 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/hmac" + "crypto/rand" + "crypto/sha256" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + "io" + "math/big" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "sync" + "testing" + "time" +) + +// While contents of this file is pertinent only to RFC8555, +// it is complementary to the tests in the other _test.go files +// many of which are valid for both pre- and RFC8555. +// This will make it easier to clean up the tests once non-RFC compliant +// code is removed. + +func TestRFC_Discover(t *testing.T) { + const ( + nonce = "https://example.com/acme/new-nonce" + reg = "https://example.com/acme/new-acct" + order = "https://example.com/acme/new-order" + authz = "https://example.com/acme/new-authz" + revoke = "https://example.com/acme/revoke-cert" + keychange = "https://example.com/acme/key-change" + metaTerms = "https://example.com/acme/terms/2017-5-30" + metaWebsite = "https://www.example.com/" + metaCAA = "example.com" + ) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, `{ + "newNonce": %q, + "newAccount": %q, + "newOrder": %q, + "newAuthz": %q, + "revokeCert": %q, + "keyChange": %q, + "meta": { + "termsOfService": %q, + "website": %q, + "caaIdentities": [%q], + "externalAccountRequired": true + } + }`, nonce, reg, order, authz, revoke, keychange, metaTerms, metaWebsite, metaCAA) + })) + defer ts.Close() + c := &Client{DirectoryURL: ts.URL} + dir, err := c.Discover(context.Background()) + if err != nil { + t.Fatal(err) + } + if dir.NonceURL != nonce { + t.Errorf("dir.NonceURL = %q; want %q", dir.NonceURL, nonce) + } + if dir.RegURL != reg { + t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg) + } + if dir.OrderURL != order { + t.Errorf("dir.OrderURL = %q; want %q", dir.OrderURL, order) + } + if dir.AuthzURL != authz { + t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz) + } + if dir.RevokeURL != revoke { + t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke) + } + if dir.KeyChangeURL != keychange { + t.Errorf("dir.KeyChangeURL = %q; want %q", dir.KeyChangeURL, keychange) + } + if dir.Terms != metaTerms { + t.Errorf("dir.Terms = %q; want %q", dir.Terms, metaTerms) + } + if dir.Website != metaWebsite { + t.Errorf("dir.Website = %q; want %q", dir.Website, metaWebsite) + } + if len(dir.CAA) == 0 || dir.CAA[0] != metaCAA { + t.Errorf("dir.CAA = %q; want [%q]", dir.CAA, metaCAA) + } + if !dir.ExternalAccountRequired { + t.Error("dir.Meta.ExternalAccountRequired is false") + } +} + +func TestRFC_popNonce(t *testing.T) { + var count int + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // The Client uses only Directory.NonceURL when specified. + // Expect no other URL paths. + if r.URL.Path != "/new-nonce" { + t.Errorf("r.URL.Path = %q; want /new-nonce", r.URL.Path) + } + if count > 0 { + w.WriteHeader(http.StatusTooManyRequests) + return + } + count++ + w.Header().Set("Replay-Nonce", "second") + })) + cl := &Client{ + DirectoryURL: ts.URL, + dir: &Directory{NonceURL: ts.URL + "/new-nonce"}, + } + cl.addNonce(http.Header{"Replay-Nonce": {"first"}}) + + for i, nonce := range []string{"first", "second"} { + v, err := cl.popNonce(context.Background(), "") + if err != nil { + t.Errorf("%d: cl.popNonce: %v", i, err) + } + if v != nonce { + t.Errorf("%d: cl.popNonce = %q; want %q", i, v, nonce) + } + } + // No more nonces and server replies with an error past first nonce fetch. + // Expected to fail. + if _, err := cl.popNonce(context.Background(), ""); err == nil { + t.Error("last cl.popNonce returned nil error") + } +} + +func TestRFC_postKID(t *testing.T) { + var ts *httptest.Server + ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/new-nonce": + w.Header().Set("Replay-Nonce", "nonce") + case "/new-account": + w.Header().Set("Location", "/account-1") + w.Write([]byte(`{"status":"valid"}`)) + case "/post": + b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx + head, err := decodeJWSHead(bytes.NewReader(b)) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if head.KID != "/account-1" { + t.Errorf("head.KID = %q; want /account-1", head.KID) + } + if len(head.JWK) != 0 { + t.Errorf("head.JWK = %q; want zero map", head.JWK) + } + if v := ts.URL + "/post"; head.URL != v { + t.Errorf("head.URL = %q; want %q", head.URL, v) + } + + var payload struct{ Msg string } + decodeJWSRequest(t, &payload, bytes.NewReader(b)) + if payload.Msg != "ping" { + t.Errorf("payload.Msg = %q; want ping", payload.Msg) + } + w.Write([]byte("pong")) + default: + t.Errorf("unhandled %s %s", r.Method, r.URL) + w.WriteHeader(http.StatusBadRequest) + } + })) + defer ts.Close() + + ctx := context.Background() + cl := &Client{ + Key: testKey, + DirectoryURL: ts.URL, + dir: &Directory{ + NonceURL: ts.URL + "/new-nonce", + RegURL: ts.URL + "/new-account", + OrderURL: "/force-rfc-mode", + }, + } + req := json.RawMessage(`{"msg":"ping"}`) + res, err := cl.post(ctx, nil /* use kid */, ts.URL+"/post", req, wantStatus(http.StatusOK)) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + b, _ := io.ReadAll(res.Body) // don't care about err - just checking b + if string(b) != "pong" { + t.Errorf("res.Body = %q; want pong", b) + } +} + +// acmeServer simulates a subset of RFC 8555 compliant CA. +// +// TODO: We also have x/crypto/acme/autocert/acmetest and startACMEServerStub in autocert_test.go. +// It feels like this acmeServer is a sweet spot between usefulness and added complexity. +// Also, acmetest and startACMEServerStub were both written for draft-02, no RFC support. +// The goal is to consolidate all into one ACME test server. +type acmeServer struct { + ts *httptest.Server + handler map[string]http.HandlerFunc // keyed by r.URL.Path + + mu sync.Mutex + nnonce int +} + +func newACMEServer() *acmeServer { + return &acmeServer{handler: make(map[string]http.HandlerFunc)} +} + +func (s *acmeServer) handle(path string, f func(http.ResponseWriter, *http.Request)) { + s.handler[path] = http.HandlerFunc(f) +} + +func (s *acmeServer) start() { + s.ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + + // Directory request. + if r.URL.Path == "/" { + fmt.Fprintf(w, `{ + "newNonce": %q, + "newAccount": %q, + "newOrder": %q, + "newAuthz": %q, + "revokeCert": %q, + "keyChange": %q, + "meta": {"termsOfService": %q} + }`, + s.url("http://github.com/acme/new-nonce"), + s.url("http://github.com/acme/new-account"), + s.url("http://github.com/acme/new-order"), + s.url("http://github.com/acme/new-authz"), + s.url("http://github.com/acme/revoke-cert"), + s.url("http://github.com/acme/key-change"), + s.url("http://github.com/terms"), + ) + return + } + + // All other responses contain a nonce value unconditionally. + w.Header().Set("Replay-Nonce", s.nonce()) + if r.URL.Path == "/acme/new-nonce" { + return + } + + h := s.handler[r.URL.Path] + if h == nil { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Unhandled %s", r.URL.Path) + return + } + h.ServeHTTP(w, r) + })) +} + +func (s *acmeServer) close() { + s.ts.Close() +} + +func (s *acmeServer) url(http://github.com/path%20string) string { + return s.ts.URL + path +} + +func (s *acmeServer) nonce() string { + s.mu.Lock() + defer s.mu.Unlock() + s.nnonce++ + return fmt.Sprintf("nonce%d", s.nnonce) +} + +func (s *acmeServer) error(w http.ResponseWriter, e *wireError) { + w.WriteHeader(e.Status) + json.NewEncoder(w).Encode(e) +} + +func TestRFC_Register(t *testing.T) { + const email = "mailto:user@example.org" + + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusCreated) // 201 means new account created + fmt.Fprintf(w, `{ + "status": "valid", + "contact": [%q], + "orders": %q + }`, email, s.url("http://github.com/accounts/1/orders")) + + b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx + head, err := decodeJWSHead(bytes.NewReader(b)) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if len(head.JWK) == 0 { + t.Error("head.JWK is empty") + } + + var req struct{ Contact []string } + decodeJWSRequest(t, &req, bytes.NewReader(b)) + if len(req.Contact) != 1 || req.Contact[0] != email { + t.Errorf("req.Contact = %q; want [%q]", req.Contact, email) + } + }) + s.start() + defer s.close() + + ctx := context.Background() + cl := &Client{ + Key: testKeyEC, + DirectoryURL: s.url("http://github.com/"), + } + + var didPrompt bool + a := &Account{Contact: []string{email}} + acct, err := cl.Register(ctx, a, func(tos string) bool { + didPrompt = true + terms := s.url("http://github.com/terms") + if tos != terms { + t.Errorf("tos = %q; want %q", tos, terms) + } + return true + }) + if err != nil { + t.Fatal(err) + } + okAccount := &Account{ + URI: s.url("http://github.com/accounts/1"), + Status: StatusValid, + Contact: []string{email}, + OrdersURL: s.url("http://github.com/accounts/1/orders"), + } + if !reflect.DeepEqual(acct, okAccount) { + t.Errorf("acct = %+v; want %+v", acct, okAccount) + } + if !didPrompt { + t.Error("tos prompt wasn't called") + } + if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) { + t.Errorf("account kid = %q; want %q", v, okAccount.URI) + } +} + +func TestRFC_RegisterExternalAccountBinding(t *testing.T) { + eab := &ExternalAccountBinding{ + KID: "kid-1", + Key: []byte("secret"), + } + + type protected struct { + Algorithm string `json:"alg"` + KID string `json:"kid"` + URL string `json:"url"` + } + const email = "mailto:user@example.org" + + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Protected string + Contact []string + TermsOfServiceAgreed bool + ExternalaccountBinding struct { + Protected string + Payload string + Signature string + } + } + decodeJWSRequest(t, &j, r.Body) + protData, err := base64.RawURLEncoding.DecodeString(j.ExternalaccountBinding.Protected) + if err != nil { + t.Fatal(err) + } + + var prot protected + err = json.Unmarshal(protData, &prot) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(j.Contact, []string{email}) { + t.Errorf("j.Contact = %v; want %v", j.Contact, []string{email}) + } + if !j.TermsOfServiceAgreed { + t.Error("j.TermsOfServiceAgreed = false; want true") + } + + // Ensure same KID. + if prot.KID != eab.KID { + t.Errorf("j.ExternalAccountBinding.KID = %s; want %s", prot.KID, eab.KID) + } + // Ensure expected Algorithm. + if prot.Algorithm != "HS256" { + t.Errorf("j.ExternalAccountBinding.Alg = %s; want %s", + prot.Algorithm, "HS256") + } + + // Ensure same URL as outer JWS. + url := fmt.Sprintf("http://%s/acme/new-account", r.Host) + if prot.URL != url { + t.Errorf("j.ExternalAccountBinding.URL = %s; want %s", + prot.URL, url) + } + + // Ensure payload is base64URL encoded string of JWK in outer JWS + jwk, err := jwkEncode(testKeyEC.Public()) + if err != nil { + t.Fatal(err) + } + decodedPayload, err := base64.RawURLEncoding.DecodeString(j.ExternalaccountBinding.Payload) + if err != nil { + t.Fatal(err) + } + if jwk != string(decodedPayload) { + t.Errorf("j.ExternalAccountBinding.Payload = %s; want %s", decodedPayload, jwk) + } + + // Check signature on inner external account binding JWS + hmac := hmac.New(sha256.New, []byte("secret")) + _, err = hmac.Write([]byte(j.ExternalaccountBinding.Protected + "." + j.ExternalaccountBinding.Payload)) + if err != nil { + t.Fatal(err) + } + mac := hmac.Sum(nil) + encodedMAC := base64.RawURLEncoding.EncodeToString(mac) + + if !bytes.Equal([]byte(encodedMAC), []byte(j.ExternalaccountBinding.Signature)) { + t.Errorf("j.ExternalAccountBinding.Signature = %v; want %v", + []byte(j.ExternalaccountBinding.Signature), encodedMAC) + } + + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusCreated) + b, _ := json.Marshal([]string{email}) + fmt.Fprintf(w, `{"status":"valid","orders":"%s","contact":%s}`, s.url("http://github.com/accounts/1/orders"), b) + }) + s.start() + defer s.close() + + ctx := context.Background() + cl := &Client{ + Key: testKeyEC, + DirectoryURL: s.url("http://github.com/"), + } + + var didPrompt bool + a := &Account{Contact: []string{email}, ExternalAccountBinding: eab} + acct, err := cl.Register(ctx, a, func(tos string) bool { + didPrompt = true + terms := s.url("http://github.com/terms") + if tos != terms { + t.Errorf("tos = %q; want %q", tos, terms) + } + return true + }) + if err != nil { + t.Fatal(err) + } + okAccount := &Account{ + URI: s.url("http://github.com/accounts/1"), + Status: StatusValid, + Contact: []string{email}, + OrdersURL: s.url("http://github.com/accounts/1/orders"), + } + if !reflect.DeepEqual(acct, okAccount) { + t.Errorf("acct = %+v; want %+v", acct, okAccount) + } + if !didPrompt { + t.Error("tos prompt wasn't called") + } + if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) { + t.Errorf("account kid = %q; want %q", v, okAccount.URI) + } +} + +func TestRFC_RegisterExisting(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) // 200 means account already exists + w.Write([]byte(`{"status": "valid"}`)) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + _, err := cl.Register(context.Background(), &Account{}, AcceptTOS) + if err != ErrAccountAlreadyExists { + t.Errorf("err = %v; want %v", err, ErrAccountAlreadyExists) + } + kid := KeyID(s.url("http://github.com/accounts/1")) + if v := cl.accountKID(context.Background()); v != kid { + t.Errorf("account kid = %q; want %q", v, kid) + } +} + +func TestRFC_UpdateReg(t *testing.T) { + const email = "mailto:user@example.org" + + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + }) + var didUpdate bool + s.handle("/accounts/1", func(w http.ResponseWriter, r *http.Request) { + didUpdate = true + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + + b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx + head, err := decodeJWSHead(bytes.NewReader(b)) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if len(head.JWK) != 0 { + t.Error("head.JWK is non-zero") + } + kid := s.url("http://github.com/accounts/1") + if head.KID != kid { + t.Errorf("head.KID = %q; want %q", head.KID, kid) + } + + var req struct{ Contact []string } + decodeJWSRequest(t, &req, bytes.NewReader(b)) + if len(req.Contact) != 1 || req.Contact[0] != email { + t.Errorf("req.Contact = %q; want [%q]", req.Contact, email) + } + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + _, err := cl.UpdateReg(context.Background(), &Account{Contact: []string{email}}) + if err != nil { + t.Error(err) + } + if !didUpdate { + t.Error("UpdateReg didn't update the account") + } +} + +func TestRFC_GetReg(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + + head, err := decodeJWSHead(r.Body) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if len(head.JWK) == 0 { + t.Error("head.JWK is empty") + } + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + acct, err := cl.GetReg(context.Background(), "") + if err != nil { + t.Fatal(err) + } + okAccount := &Account{ + URI: s.url("http://github.com/accounts/1"), + Status: StatusValid, + } + if !reflect.DeepEqual(acct, okAccount) { + t.Errorf("acct = %+v; want %+v", acct, okAccount) + } +} + +func TestRFC_GetRegNoAccount(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + s.error(w, &wireError{ + Status: http.StatusBadRequest, + Type: "urn:ietf:params:acme:error:accountDoesNotExist", + }) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + if _, err := cl.GetReg(context.Background(), ""); err != ErrNoAccount { + t.Errorf("err = %v; want %v", err, ErrNoAccount) + } +} + +func TestRFC_GetRegOtherError(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + if _, err := cl.GetReg(context.Background(), ""); err == nil || err == ErrNoAccount { + t.Errorf("GetReg: %v; want any other non-nil err", err) + } +} + +func TestRFC_AccountKeyRollover(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + }) + s.handle("/acme/key-change", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + if err := cl.AccountKeyRollover(context.Background(), testKeyEC384); err != nil { + t.Errorf("AccountKeyRollover: %v, wanted no error", err) + } else if cl.Key != testKeyEC384 { + t.Error("AccountKeyRollover did not rotate the client key") + } +} + +func TestRFC_DeactivateReg(t *testing.T) { + const email = "mailto:user@example.org" + curStatus := StatusValid + + type account struct { + Status string `json:"status"` + Contact []string `json:"contact"` + AcceptTOS bool `json:"termsOfServiceAgreed"` + Orders string `json:"orders"` + } + + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) // 200 means existing account + json.NewEncoder(w).Encode(account{ + Status: curStatus, + Contact: []string{email}, + AcceptTOS: true, + Orders: s.url("http://github.com/accounts/1/orders"), + }) + + b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx + head, err := decodeJWSHead(bytes.NewReader(b)) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if len(head.JWK) == 0 { + t.Error("head.JWK is empty") + } + + var req struct { + Status string `json:"status"` + Contact []string `json:"contact"` + AcceptTOS bool `json:"termsOfServiceAgreed"` + OnlyExisting bool `json:"onlyReturnExisting"` + } + decodeJWSRequest(t, &req, bytes.NewReader(b)) + if !req.OnlyExisting { + t.Errorf("req.OnlyReturnExisting = %t; want = %t", req.OnlyExisting, true) + } + }) + s.handle("/accounts/1", func(w http.ResponseWriter, r *http.Request) { + if curStatus == StatusValid { + curStatus = StatusDeactivated + w.WriteHeader(http.StatusOK) + } else { + s.error(w, &wireError{ + Status: http.StatusUnauthorized, + Type: "urn:ietf:params:acme:error:unauthorized", + }) + } + var req account + b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx + head, err := decodeJWSHead(bytes.NewReader(b)) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if len(head.JWK) != 0 { + t.Error("head.JWK is not empty") + } + if !strings.HasSuffix(head.KID, "/accounts/1") { + t.Errorf("head.KID = %q; want suffix /accounts/1", head.KID) + } + + decodeJWSRequest(t, &req, bytes.NewReader(b)) + if req.Status != StatusDeactivated { + t.Errorf("req.Status = %q; want = %q", req.Status, StatusDeactivated) + } + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + if err := cl.DeactivateReg(context.Background()); err != nil { + t.Errorf("DeactivateReg: %v, wanted no error", err) + } + if err := cl.DeactivateReg(context.Background()); err == nil { + t.Errorf("DeactivateReg: %v, wanted error for unauthorized", err) + } +} + +func TestRF_DeactivateRegNoAccount(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + s.error(w, &wireError{ + Status: http.StatusBadRequest, + Type: "urn:ietf:params:acme:error:accountDoesNotExist", + }) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + if err := cl.DeactivateReg(context.Background()); !errors.Is(err, ErrNoAccount) { + t.Errorf("DeactivateReg: %v, wanted ErrNoAccount", err) + } +} + +func TestRFC_AuthorizeOrder(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + }) + s.handle("/acme/new-order", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/orders/1")) + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, `{ + "status": "pending", + "expires": "2019-09-01T00:00:00Z", + "notBefore": "2019-08-31T00:00:00Z", + "notAfter": "2019-09-02T00:00:00Z", + "identifiers": [{"type":"dns", "value":"example.org"}], + "authorizations": [%q] + }`, s.url("http://github.com/authz/1")) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + o, err := cl.AuthorizeOrder(context.Background(), DomainIDs("example.org"), + WithOrderNotBefore(time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC)), + WithOrderNotAfter(time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC)), + ) + if err != nil { + t.Fatal(err) + } + okOrder := &Order{ + URI: s.url("http://github.com/orders/1"), + Status: StatusPending, + Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC), + NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC), + NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC), + Identifiers: []AuthzID{AuthzID{Type: "dns", Value: "example.org"}}, + AuthzURLs: []string{s.url("http://github.com/authz/1")}, + } + if !reflect.DeepEqual(o, okOrder) { + t.Errorf("AuthorizeOrder = %+v; want %+v", o, okOrder) + } +} + +func TestRFC_GetOrder(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + }) + s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/orders/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{ + "status": "invalid", + "expires": "2019-09-01T00:00:00Z", + "notBefore": "2019-08-31T00:00:00Z", + "notAfter": "2019-09-02T00:00:00Z", + "identifiers": [{"type":"dns", "value":"example.org"}], + "authorizations": ["/authz/1"], + "finalize": "/orders/1/fin", + "certificate": "/orders/1/cert", + "error": {"type": "badRequest"} + }`)) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + o, err := cl.GetOrder(context.Background(), s.url("http://github.com/orders/1")) + if err != nil { + t.Fatal(err) + } + okOrder := &Order{ + URI: s.url("http://github.com/orders/1"), + Status: StatusInvalid, + Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC), + NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC), + NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC), + Identifiers: []AuthzID{AuthzID{Type: "dns", Value: "example.org"}}, + AuthzURLs: []string{"/authz/1"}, + FinalizeURL: "/orders/1/fin", + CertURL: "/orders/1/cert", + Error: &Error{ProblemType: "badRequest"}, + } + if !reflect.DeepEqual(o, okOrder) { + t.Errorf("GetOrder = %+v\nwant %+v", o, okOrder) + } +} + +func TestRFC_WaitOrder(t *testing.T) { + for _, st := range []string{StatusReady, StatusValid} { + t.Run(st, func(t *testing.T) { + testWaitOrderStatus(t, st) + }) + } +} + +func testWaitOrderStatus(t *testing.T, okStatus string) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + }) + var count int + s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/orders/1")) + w.WriteHeader(http.StatusOK) + s := StatusPending + if count > 0 { + s = okStatus + } + fmt.Fprintf(w, `{"status": %q}`, s) + count++ + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + order, err := cl.WaitOrder(context.Background(), s.url("http://github.com/orders/1")) + if err != nil { + t.Fatalf("WaitOrder: %v", err) + } + if order.Status != okStatus { + t.Errorf("order.Status = %q; want %q", order.Status, okStatus) + } +} + +func TestRFC_WaitOrderError(t *testing.T) { + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"status": "valid"}`)) + }) + var count int + s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/orders/1")) + w.WriteHeader(http.StatusOK) + if count > 0 { + // https://www.rfc-editor.org/rfc/rfc8555#section-7.3.3 + errorData := `{ + "type": "urn:ietf:params:acme:error:userActionRequired", + "detail": "Terms of service have changed", + "instance": "https://example.com/acme/agreement/?token=W8Ih3PswD-8" + }` + fmt.Fprintf(w, `{"status": %q, "error": %s}`, StatusInvalid, errorData) + } else { + fmt.Fprintf(w, `{"status": %q}`, StatusPending) + } + count++ + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + _, err := cl.WaitOrder(context.Background(), s.url("http://github.com/orders/1")) + if err == nil { + t.Fatal("WaitOrder returned nil error") + } + e, ok := err.(*OrderError) + if !ok { + t.Fatalf("err = %v (%T); want OrderError", err, err) + } + if e.OrderURL != s.url("http://github.com/orders/1") { + t.Errorf("e.OrderURL = %q; want %q", e.OrderURL, s.url("http://github.com/orders/1")) + } + if e.Status != StatusInvalid { + t.Errorf("e.Status = %q; want %q", e.Status, StatusInvalid) + } + if e.Problem == nil { + t.Errorf("e.Problem = nil") + } + expectedProbType := "urn:ietf:params:acme:error:userActionRequired" + if e.Problem.ProblemType != expectedProbType { + t.Errorf("e.Problem.ProblemType = %q; want %q", e.Problem.ProblemType, expectedProbType) + } +} + +func TestRFC_CreateOrderCert(t *testing.T) { + q := &x509.CertificateRequest{ + Subject: pkix.Name{CommonName: "example.org"}, + } + csr, err := x509.CreateCertificateRequest(rand.Reader, q, testKeyEC) + if err != nil { + t.Fatal(err) + } + + tmpl := &x509.Certificate{SerialNumber: big.NewInt(1)} + leaf, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testKeyEC.PublicKey, testKeyEC) + if err != nil { + t.Fatal(err) + } + + s := newACMEServer() + s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/accounts/1")) + w.Write([]byte(`{"status": "valid"}`)) + }) + var count int + s.handle("/pleaseissue", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Location", s.url("http://github.com/pleaseissue")) + st := StatusProcessing + if count > 0 { + st = StatusValid + } + fmt.Fprintf(w, `{"status":%q, "certificate":%q}`, st, s.url("http://github.com/crt")) + count++ + }) + s.handle("/crt", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/pem-certificate-chain") + pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: leaf}) + }) + s.start() + defer s.close() + ctx := context.Background() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + cert, curl, err := cl.CreateOrderCert(ctx, s.url("http://github.com/pleaseissue"), csr, true) + if err != nil { + t.Fatalf("CreateOrderCert: %v", err) + } + if _, err := x509.ParseCertificate(cert[0]); err != nil { + t.Errorf("ParseCertificate: %v", err) + } + if !reflect.DeepEqual(cert[0], leaf) { + t.Errorf("cert and leaf bytes don't match") + } + if u := s.url("http://github.com/crt"); curl != u { + t.Errorf("curl = %q; want %q", curl, u) + } +} + +func TestRFC_AlreadyRevokedCert(t *testing.T) { + s := newACMEServer() + s.handle("/acme/revoke-cert", func(w http.ResponseWriter, r *http.Request) { + s.error(w, &wireError{ + Status: http.StatusBadRequest, + Type: "urn:ietf:params:acme:error:alreadyRevoked", + }) + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + err := cl.RevokeCert(context.Background(), testKeyEC, []byte{0}, CRLReasonUnspecified) + if err != nil { + t.Fatalf("RevokeCert: %v", err) + } +} + +func TestRFC_ListCertAlternates(t *testing.T) { + s := newACMEServer() + s.handle("/crt", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/pem-certificate-chain") + w.Header().Add("Link", `;rel="alternate"`) + w.Header().Add("Link", `; rel="alternate"`) + w.Header().Add("Link", `; rel="index"`) + }) + s.handle("/crt2", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/pem-certificate-chain") + }) + s.start() + defer s.close() + + cl := &Client{Key: testKeyEC, DirectoryURL: s.url("http://github.com/")} + crts, err := cl.ListCertAlternates(context.Background(), s.url("http://github.com/crt")) + if err != nil { + t.Fatalf("ListCertAlternates: %v", err) + } + want := []string{"https://example.com/crt/2", "https://example.com/crt/3"} + if !reflect.DeepEqual(crts, want) { + t.Errorf("ListCertAlternates(/crt): %v; want %v", crts, want) + } + crts, err = cl.ListCertAlternates(context.Background(), s.url("http://github.com/crt2")) + if err != nil { + t.Fatalf("ListCertAlternates: %v", err) + } + if crts != nil { + t.Errorf("ListCertAlternates(/crt2): %v; want nil", crts) + } +} diff --git a/acme/types.go b/acme/types.go index 54792c0650..322640c453 100644 --- a/acme/types.go +++ b/acme/types.go @@ -7,6 +7,7 @@ package acme import ( "crypto" "crypto/x509" + "encoding/json" "errors" "fmt" "net/http" @@ -14,14 +15,18 @@ import ( "time" ) -// ACME server response statuses used to describe Authorization and Challenge states. +// ACME status values of Account, Order, Authorization and Challenge objects. +// See https://tools.ietf.org/html/rfc8555#section-7.1.6 for details. const ( - StatusUnknown = "unknown" - StatusPending = "pending" - StatusProcessing = "processing" - StatusValid = "valid" - StatusInvalid = "invalid" - StatusRevoked = "revoked" + StatusDeactivated = "deactivated" + StatusExpired = "expired" + StatusInvalid = "invalid" + StatusPending = "pending" + StatusProcessing = "processing" + StatusReady = "ready" + StatusRevoked = "revoked" + StatusUnknown = "unknown" + StatusValid = "valid" ) // CRLReasonCode identifies the reason for a certificate revocation. @@ -41,8 +46,47 @@ const ( CRLReasonAACompromise CRLReasonCode = 10 ) -// ErrUnsupportedKey is returned when an unsupported key type is encountered. -var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported") +var ( + // ErrUnsupportedKey is returned when an unsupported key type is encountered. + ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported") + + // ErrAccountAlreadyExists indicates that the Client's key has already been registered + // with the CA. It is returned by Register method. + ErrAccountAlreadyExists = errors.New("acme: account already exists") + + // ErrNoAccount indicates that the Client's key has not been registered with the CA. + ErrNoAccount = errors.New("acme: account does not exist") + + // errPreAuthorizationNotSupported indicates that the server does not + // support pre-authorization of identifiers. + errPreAuthorizationNotSupported = errors.New("acme: pre-authorization is not supported") +) + +// A Subproblem describes an ACME subproblem as reported in an Error. +type Subproblem struct { + // Type is a URI reference that identifies the problem type, + // typically in a "urn:acme:error:xxx" form. + Type string + // Detail is a human-readable explanation specific to this occurrence of the problem. + Detail string + // Instance indicates a URL that the client should direct a human user to visit + // in order for instructions on how to agree to the updated Terms of Service. + // In such an event CA sets StatusCode to 403, Type to + // "urn:ietf:params:acme:error:userActionRequired", and adds a Link header with relation + // "terms-of-service" containing the latest TOS URL. + Instance string + // Identifier may contain the ACME identifier that the error is for. + Identifier *AuthzID +} + +func (sp Subproblem) String() string { + str := fmt.Sprintf("%s: ", sp.Type) + if sp.Identifier != nil { + str += fmt.Sprintf("[%s: %s] ", sp.Identifier.Type, sp.Identifier.Value) + } + str += sp.Detail + return str +} // Error is an ACME error, defined in Problem Details for HTTP APIs doc // http://tools.ietf.org/html/draft-ietf-appsawg-http-problem. @@ -54,13 +98,30 @@ type Error struct { ProblemType string // Detail is a human-readable explanation specific to this occurrence of the problem. Detail string + // Instance indicates a URL that the client should direct a human user to visit + // in order for instructions on how to agree to the updated Terms of Service. + // In such an event CA sets StatusCode to 403, ProblemType to + // "urn:ietf:params:acme:error:userActionRequired" and a Link header with relation + // "terms-of-service" containing the latest TOS URL. + Instance string // Header is the original server error response headers. // It may be nil. Header http.Header + // Subproblems may contain more detailed information about the individual problems + // that caused the error. This field is only sent by RFC 8555 compatible ACME + // servers. Defined in RFC 8555 Section 6.7.1. + Subproblems []Subproblem } func (e *Error) Error() string { - return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail) + str := fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail) + if len(e.Subproblems) > 0 { + str += fmt.Sprintf("; subproblems:") + for _, sp := range e.Subproblems { + str += fmt.Sprintf("\n\t%s", sp) + } + } + return str } // AuthorizationError indicates that an authorization for an identifier @@ -83,7 +144,30 @@ func (a *AuthorizationError) Error() string { for i, err := range a.Errors { e[i] = err.Error() } - return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; ")) + + if a.Identifier != "" { + return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; ")) + } + + return fmt.Sprintf("acme: authorization error: %s", strings.Join(e, "; ")) +} + +// OrderError is returned from Client's order related methods. +// It indicates the order is unusable and the clients should start over with +// AuthorizeOrder. A Problem description may be provided with details on +// what caused the order to become unusable. +// +// The clients can still fetch the order object from CA using GetOrder +// to inspect its state. +type OrderError struct { + OrderURL string + Status string + // Problem is the error that occurred while processing the order. + Problem *Error +} + +func (oe *OrderError) Error() string { + return fmt.Sprintf("acme: order %s status: %s", oe.OrderURL, oe.Status) } // RateLimit reports whether err represents a rate limit error and @@ -108,50 +192,111 @@ func RateLimit(err error) (time.Duration, bool) { } // Account is a user account. It is associated with a private key. +// Non-RFC 8555 fields are empty when interfacing with a compliant CA. type Account struct { // URI is the account unique ID, which is also a URL used to retrieve // account data from the CA. + // When interfacing with RFC 8555-compliant CAs, URI is the "kid" field + // value in JWS signed requests. URI string // Contact is a slice of contact info used during registration. + // See https://tools.ietf.org/html/rfc8555#section-7.3 for supported + // formats. Contact []string + // Status indicates current account status as returned by the CA. + // Possible values are StatusValid, StatusDeactivated, and StatusRevoked. + Status string + + // OrdersURL is a URL from which a list of orders submitted by this account + // can be fetched. + OrdersURL string + // The terms user has agreed to. // A value not matching CurrentTerms indicates that the user hasn't agreed // to the actual Terms of Service of the CA. + // + // It is non-RFC 8555 compliant. Package users can store the ToS they agree to + // during Client's Register call in the prompt callback function. AgreedTerms string // Actual terms of a CA. + // + // It is non-RFC 8555 compliant. Use Directory's Terms field. + // When a CA updates their terms and requires an account agreement, + // a URL at which instructions to do so is available in Error's Instance field. CurrentTerms string // Authz is the authorization URL used to initiate a new authz flow. + // + // It is non-RFC 8555 compliant. Use Directory's AuthzURL or OrderURL. Authz string // Authorizations is a URI from which a list of authorizations // granted to this account can be fetched via a GET request. + // + // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. Authorizations string // Certificates is a URI from which a list of certificates // issued for this account can be fetched via a GET request. + // + // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. Certificates string + + // ExternalAccountBinding represents an arbitrary binding to an account of + // the CA which the ACME server is tied to. + // See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. + ExternalAccountBinding *ExternalAccountBinding +} + +// ExternalAccountBinding contains the data needed to form a request with +// an external account binding. +// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. +type ExternalAccountBinding struct { + // KID is the Key ID of the symmetric MAC key that the CA provides to + // identify an external account from ACME. + KID string + + // Key is the bytes of the symmetric key that the CA provides to identify + // the account. Key must correspond to the KID. + Key []byte +} + +func (e *ExternalAccountBinding) String() string { + return fmt.Sprintf("&{KID: %q, Key: redacted}", e.KID) } // Directory is ACME server discovery data. +// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details. type Directory struct { - // RegURL is an account endpoint URL, allowing for creating new - // and modifying existing accounts. + // NonceURL indicates an endpoint where to fetch fresh nonce values from. + NonceURL string + + // RegURL is an account endpoint URL, allowing for creating new accounts. + // Pre-RFC 8555 CAs also allow modifying existing accounts at this URL. RegURL string - // AuthzURL is used to initiate Identifier Authorization flow. + // OrderURL is used to initiate the certificate issuance flow + // as described in RFC 8555. + OrderURL string + + // AuthzURL is used to initiate identifier pre-authorization flow. + // Empty string indicates the flow is unsupported by the CA. AuthzURL string // CertURL is a new certificate issuance endpoint URL. + // It is non-RFC 8555 compliant and is obsoleted by OrderURL. CertURL string // RevokeURL is used to initiate a certificate revocation flow. RevokeURL string - // Term is a URI identifying the current terms of service. + // KeyChangeURL allows to perform account key rollover flow. + KeyChangeURL string + + // Terms is a URI identifying the current terms of service. Terms string // Website is an HTTP or HTTPS URL locating a website @@ -160,46 +305,120 @@ type Directory struct { // CAA consists of lowercase hostname elements, which the ACME server // recognises as referring to itself for the purposes of CAA record validation - // as defined in RFC6844. + // as defined in RFC 6844. CAA []string -} -// Challenge encodes a returned CA challenge. -// Its Error field may be non-nil if the challenge is part of an Authorization -// with StatusInvalid. -type Challenge struct { - // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01". - Type string + // ExternalAccountRequired indicates that the CA requires for all account-related + // requests to include external account binding information. + ExternalAccountRequired bool +} - // URI is where a challenge response can be posted to. +// Order represents a client's request for a certificate. +// It tracks the request flow progress through to issuance. +type Order struct { + // URI uniquely identifies an order. URI string - // Token is a random value that uniquely identifies the challenge. - Token string - - // Status identifies the status of this challenge. + // Status represents the current status of the order. + // It indicates which action the client should take. + // + // Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid. + // Pending means the CA does not believe that the client has fulfilled the requirements. + // Ready indicates that the client has fulfilled all the requirements and can submit a CSR + // to obtain a certificate. This is done with Client's CreateOrderCert. + // Processing means the certificate is being issued. + // Valid indicates the CA has issued the certificate. It can be downloaded + // from the Order's CertURL. This is done with Client's FetchCert. + // Invalid means the certificate will not be issued. Users should consider this order + // abandoned. Status string - // Error indicates the reason for an authorization failure - // when this challenge was used. - // The type of a non-nil value is *Error. - Error error + // Expires is the timestamp after which CA considers this order invalid. + Expires time.Time + + // Identifiers contains all identifier objects which the order pertains to. + Identifiers []AuthzID + + // NotBefore is the requested value of the notBefore field in the certificate. + NotBefore time.Time + + // NotAfter is the requested value of the notAfter field in the certificate. + NotAfter time.Time + + // AuthzURLs represents authorizations to complete before a certificate + // for identifiers specified in the order can be issued. + // It also contains unexpired authorizations that the client has completed + // in the past. + // + // Authorization objects can be fetched using Client's GetAuthorization method. + // + // The required authorizations are dictated by CA policies. + // There may not be a 1:1 relationship between the identifiers and required authorizations. + // Required authorizations can be identified by their StatusPending status. + // + // For orders in the StatusValid or StatusInvalid state these are the authorizations + // which were completed. + AuthzURLs []string + + // FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate + // once all the authorizations are satisfied. + FinalizeURL string + + // CertURL points to the certificate that has been issued in response to this order. + CertURL string + + // The error that occurred while processing the order as received from a CA, if any. + Error *Error +} + +// OrderOption allows customizing Client.AuthorizeOrder call. +type OrderOption interface { + privateOrderOpt() } +// WithOrderNotBefore sets order's NotBefore field. +func WithOrderNotBefore(t time.Time) OrderOption { + return orderNotBeforeOpt(t) +} + +// WithOrderNotAfter sets order's NotAfter field. +func WithOrderNotAfter(t time.Time) OrderOption { + return orderNotAfterOpt(t) +} + +type orderNotBeforeOpt time.Time + +func (orderNotBeforeOpt) privateOrderOpt() {} + +type orderNotAfterOpt time.Time + +func (orderNotAfterOpt) privateOrderOpt() {} + // Authorization encodes an authorization response. type Authorization struct { // URI uniquely identifies a authorization. URI string - // Status identifies the status of an authorization. + // Status is the current status of an authorization. + // Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated, + // StatusExpired and StatusRevoked. Status string // Identifier is what the account is authorized to represent. Identifier AuthzID + // The timestamp after which the CA considers the authorization invalid. + Expires time.Time + + // Wildcard is true for authorizations of a wildcard domain name. + Wildcard bool + // Challenges that the client needs to fulfill in order to prove possession // of the identifier (for pending authorizations). - // For final authorizations, the challenges that were used. + // For valid authorizations, the challenge that was validated. + // For invalid authorizations, the challenge that was attempted and failed. + // + // RFC 8555 compatible CAs require users to fuflfill only one of the challenges. Challenges []*Challenge // A collection of sets of challenges, each of which would be sufficient @@ -207,24 +426,52 @@ type Authorization struct { // Clients must complete a set of challenges that covers at least one set. // Challenges are identified by their indices in the challenges array. // If this field is empty, the client needs to complete all challenges. + // + // This field is unused in RFC 8555. Combinations [][]int } // AuthzID is an identifier that an account is authorized to represent. type AuthzID struct { - Type string // The type of identifier, e.g. "dns". + Type string // The type of identifier, "dns" or "ip". Value string // The identifier itself, e.g. "example.org". } +// DomainIDs creates a slice of AuthzID with "dns" identifier type. +func DomainIDs(names ...string) []AuthzID { + a := make([]AuthzID, len(names)) + for i, v := range names { + a[i] = AuthzID{Type: "dns", Value: v} + } + return a +} + +// IPIDs creates a slice of AuthzID with "ip" identifier type. +// Each element of addr is textual form of an address as defined +// in RFC 1123 Section 2.1 for IPv4 and in RFC 5952 Section 4 for IPv6. +func IPIDs(addr ...string) []AuthzID { + a := make([]AuthzID, len(addr)) + for i, v := range addr { + a[i] = AuthzID{Type: "ip", Value: v} + } + return a +} + +// wireAuthzID is ACME JSON representation of authorization identifier objects. +type wireAuthzID struct { + Type string `json:"type"` + Value string `json:"value"` +} + // wireAuthz is ACME JSON representation of Authorization objects. type wireAuthz struct { + Identifier wireAuthzID Status string + Expires time.Time + Wildcard bool Challenges []wireChallenge Combinations [][]int - Identifier struct { - Type string - Value string - } + Error *wireError } func (z *wireAuthz) authorization(uri string) *Authorization { @@ -232,8 +479,10 @@ func (z *wireAuthz) authorization(uri string) *Authorization { URI: uri, Status: z.Status, Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, - Combinations: z.Combinations, // shallow copy + Expires: z.Expires, + Wildcard: z.Wildcard, Challenges: make([]*Challenge, len(z.Challenges)), + Combinations: z.Combinations, // shallow copy } for i, v := range z.Challenges { a.Challenges[i] = v.challenge() @@ -246,30 +495,79 @@ func (z *wireAuthz) error(uri string) *AuthorizationError { URI: uri, Identifier: z.Identifier.Value, } + + if z.Error != nil { + err.Errors = append(err.Errors, z.Error.error(nil)) + } + for _, raw := range z.Challenges { if raw.Error != nil { err.Errors = append(err.Errors, raw.Error.error(nil)) } } + return err } +// Challenge encodes a returned CA challenge. +// Its Error field may be non-nil if the challenge is part of an Authorization +// with StatusInvalid. +type Challenge struct { + // Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01". + Type string + + // URI is where a challenge response can be posted to. + URI string + + // Token is a random value that uniquely identifies the challenge. + Token string + + // Status identifies the status of this challenge. + // In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid, + // and StatusInvalid. + Status string + + // Validated is the time at which the CA validated this challenge. + // Always zero value in pre-RFC 8555. + Validated time.Time + + // Error indicates the reason for an authorization failure + // when this challenge was used. + // The type of a non-nil value is *Error. + Error error + + // Payload is the JSON-formatted payload that the client sends + // to the server to indicate it is ready to respond to the challenge. + // When unset, it defaults to an empty JSON object: {}. + // For most challenges, the client must not set Payload, + // see https://tools.ietf.org/html/rfc8555#section-7.5.1. + // Payload is used only for newer challenges (such as "device-attest-01") + // where the client must send additional data for the server to validate + // the challenge. + Payload json.RawMessage +} + // wireChallenge is ACME JSON challenge representation. type wireChallenge struct { - URI string `json:"uri"` - Type string - Token string - Status string - Error *wireError + URL string `json:"url"` // RFC + URI string `json:"uri"` // pre-RFC + Type string + Token string + Status string + Validated time.Time + Error *wireError } func (c *wireChallenge) challenge() *Challenge { v := &Challenge{ - URI: c.URI, + URI: c.URL, Type: c.Type, Token: c.Token, Status: c.Status, } + if v.URI == "" { + v.URI = c.URI // c.URL was empty; use legacy + } if v.Status == "" { v.Status = StatusPending } @@ -282,18 +580,23 @@ func (c *wireChallenge) challenge() *Challenge { // wireError is a subset of fields of the Problem Details object // as described in https://tools.ietf.org/html/rfc7807#section-3.1. type wireError struct { - Status int - Type string - Detail string + Status int + Type string + Detail string + Instance string + Subproblems []Subproblem } func (e *wireError) error(h http.Header) *Error { - return &Error{ + err := &Error{ StatusCode: e.Status, ProblemType: e.Type, Detail: e.Detail, + Instance: e.Instance, Header: h, + Subproblems: e.Subproblems, } + return err } // CertOption is an optional argument type for the TLS ChallengeCert methods for @@ -319,7 +622,7 @@ func (*certOptKey) privateCertOpt() {} // // In TLS ChallengeCert methods, the template is also used as parent, // resulting in a self-signed certificate. -// The DNSNames field of t is always overwritten for tls-sni challenge certs. +// The DNSNames or IPAddresses fields of t are always overwritten for tls-alpn challenge certs. func WithTemplate(t *x509.Certificate) CertOption { return (*certOptTemplate)(t) } diff --git a/acme/types_test.go b/acme/types_test.go index a7553e6b70..59ce7e7602 100644 --- a/acme/types_test.go +++ b/acme/types_test.go @@ -7,10 +7,23 @@ package acme import ( "errors" "net/http" + "reflect" "testing" "time" ) +func TestExternalAccountBindingString(t *testing.T) { + eab := ExternalAccountBinding{ + KID: "kid", + Key: []byte("key"), + } + got := eab.String() + want := `&{KID: "kid", Key: redacted}` + if got != want { + t.Errorf("eab.String() = %q, want: %q", got, want) + } +} + func TestRateLimit(t *testing.T) { now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC) f := timeNow @@ -61,3 +74,146 @@ func TestRateLimit(t *testing.T) { } } } + +func TestAuthorizationError(t *testing.T) { + tests := []struct { + desc string + err *AuthorizationError + msg string + }{ + { + desc: "when auth error identifier is set", + err: &AuthorizationError{ + Identifier: "domain.com", + Errors: []error{ + (&wireError{ + Status: 403, + Type: "urn:ietf:params:acme:error:caa", + Detail: "CAA record for domain.com prevents issuance", + }).error(nil), + }, + }, + msg: "acme: authorization error for domain.com: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance", + }, + + { + desc: "when auth error identifier is unset", + err: &AuthorizationError{ + Errors: []error{ + (&wireError{ + Status: 403, + Type: "urn:ietf:params:acme:error:caa", + Detail: "CAA record for domain.com prevents issuance", + }).error(nil), + }, + }, + msg: "acme: authorization error: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance", + }, + } + + for _, tt := range tests { + if tt.err.Error() != tt.msg { + t.Errorf("got: %s\nwant: %s", tt.err, tt.msg) + } + } +} + +func TestSubproblems(t *testing.T) { + tests := []struct { + wire wireError + expectedOut Error + }{ + { + wire: wireError{ + Status: 1, + Type: "urn:error", + Detail: "it's an error", + }, + expectedOut: Error{ + StatusCode: 1, + ProblemType: "urn:error", + Detail: "it's an error", + }, + }, + { + wire: wireError{ + Status: 1, + Type: "urn:error", + Detail: "it's an error", + Subproblems: []Subproblem{ + { + Type: "urn:error:sub", + Detail: "it's a subproblem", + }, + }, + }, + expectedOut: Error{ + StatusCode: 1, + ProblemType: "urn:error", + Detail: "it's an error", + Subproblems: []Subproblem{ + { + Type: "urn:error:sub", + Detail: "it's a subproblem", + }, + }, + }, + }, + { + wire: wireError{ + Status: 1, + Type: "urn:error", + Detail: "it's an error", + Subproblems: []Subproblem{ + { + Type: "urn:error:sub", + Detail: "it's a subproblem", + Identifier: &AuthzID{Type: "dns", Value: "example"}, + }, + }, + }, + expectedOut: Error{ + StatusCode: 1, + ProblemType: "urn:error", + Detail: "it's an error", + Subproblems: []Subproblem{ + { + Type: "urn:error:sub", + Detail: "it's a subproblem", + Identifier: &AuthzID{Type: "dns", Value: "example"}, + }, + }, + }, + }, + } + + for _, tc := range tests { + out := tc.wire.error(nil) + if !reflect.DeepEqual(*out, tc.expectedOut) { + t.Errorf("Unexpected error: wanted %v, got %v", tc.expectedOut, *out) + } + } +} + +func TestErrorStringerWithSubproblems(t *testing.T) { + err := Error{ + StatusCode: 1, + ProblemType: "urn:error", + Detail: "it's an error", + Subproblems: []Subproblem{ + { + Type: "urn:error:sub", + Detail: "it's a subproblem", + }, + { + Type: "urn:error:sub", + Detail: "it's a subproblem", + Identifier: &AuthzID{Type: "dns", Value: "example"}, + }, + }, + } + expectedStr := "1 urn:error: it's an error; subproblems:\n\turn:error:sub: it's a subproblem\n\turn:error:sub: [dns: example] it's a subproblem" + if err.Error() != expectedStr { + t.Errorf("Unexpected error string: wanted %q, got %q", expectedStr, err.Error()) + } +} diff --git a/acme/version_go112.go b/acme/version_go112.go deleted file mode 100644 index b58f2456be..0000000000 --- a/acme/version_go112.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 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 go1.12 - -package acme - -import "runtime/debug" - -func init() { - // Set packageVersion if the binary was built in modules mode and x/crypto - // was not replaced with a different module. - info, ok := debug.ReadBuildInfo() - if !ok { - return - } - for _, m := range info.Deps { - if m.Path != "golang.org/x/crypto" { - continue - } - if m.Replace == nil { - packageVersion = m.Version - } - break - } -} diff --git a/argon2/_asm/blamka_amd64.go b/argon2/_asm/blamka_amd64.go new file mode 100644 index 0000000000..17a1e7629a --- /dev/null +++ b/argon2/_asm/blamka_amd64.go @@ -0,0 +1,287 @@ +// Copyright 2024 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 main + +import ( + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/argon2" +) + +//go:generate go run . -out ../blamka_amd64.s -pkg argon2 + +func main() { + Package("golang.org/x/crypto/argon2") + ConstraintExpr("amd64,gc,!purego") + + blamkaSSE4() + mixBlocksSSE2() + xorBlocksSSE2() + Generate() +} + +func blamkaSSE4() { + Implement("blamkaSSE4") + Attributes(NOSPLIT) + AllocLocal(0) + + Load(Param("b"), RAX) + + c40 := c40_DATA() + c48 := c48_DATA() + + MOVOU(c40, X10) + MOVOU(c48, X11) + + BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11) + + BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11) + RET() +} + +func mixBlocksSSE2() { + Implement("mixBlocksSSE2") + Attributes(NOSPLIT) + AllocLocal(0) + + Load(Param("out"), RDX) + Load(Param("a"), RAX) + Load(Param("b"), RBX) + Load(Param("c"), RCX) + MOVQ(U32(128), RDI) + + Label("loop") + MOVOU(Mem{Base: AX}.Offset(0), X0) + MOVOU(Mem{Base: BX}.Offset(0), X1) + MOVOU(Mem{Base: CX}.Offset(0), X2) + PXOR(X1, X0) + PXOR(X2, X0) + MOVOU(X0, Mem{Base: DX}.Offset(0)) + ADDQ(Imm(16), RAX) + ADDQ(Imm(16), RBX) + ADDQ(Imm(16), RCX) + ADDQ(Imm(16), RDX) + SUBQ(Imm(2), RDI) + JA(LabelRef("loop")) + RET() +} + +func xorBlocksSSE2() { + Implement("xorBlocksSSE2") + Attributes(NOSPLIT) + AllocLocal(0) + + Load(Param("out"), RDX) + Load(Param("a"), RAX) + Load(Param("b"), RBX) + Load(Param("c"), RCX) + MOVQ(U32(128), RDI) + + Label("loop") + MOVOU(Mem{Base: AX}.Offset(0), X0) + MOVOU(Mem{Base: BX}.Offset(0), X1) + MOVOU(Mem{Base: CX}.Offset(0), X2) + MOVOU(Mem{Base: DX}.Offset(0), X3) + PXOR(X1, X0) + PXOR(X2, X0) + PXOR(X3, X0) + MOVOU(X0, Mem{Base: DX}.Offset(0)) + ADDQ(Imm(16), RAX) + ADDQ(Imm(16), RBX) + ADDQ(Imm(16), RCX) + ADDQ(Imm(16), RDX) + SUBQ(Imm(2), RDI) + JA(LabelRef("loop")) + RET() +} + +func SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { + MOVO(v4, t1) + MOVO(v5, v4) + MOVO(t1, v5) + MOVO(v6, t1) + PUNPCKLQDQ(v6, t2) + PUNPCKHQDQ(v7, v6) + PUNPCKHQDQ(t2, v6) + PUNPCKLQDQ(v7, t2) + MOVO(t1, v7) + MOVO(v2, t1) + PUNPCKHQDQ(t2, v7) + PUNPCKLQDQ(v3, t2) + PUNPCKHQDQ(t2, v2) + PUNPCKLQDQ(t1, t2) + PUNPCKHQDQ(t2, v3) +} + +func SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { + MOVO(v4, t1) + MOVO(v5, v4) + MOVO(t1, v5) + MOVO(v2, t1) + PUNPCKLQDQ(v2, t2) + PUNPCKHQDQ(v3, v2) + PUNPCKHQDQ(t2, v2) + PUNPCKLQDQ(v3, t2) + MOVO(t1, v3) + MOVO(v6, t1) + PUNPCKHQDQ(t2, v3) + PUNPCKLQDQ(v7, t2) + PUNPCKHQDQ(t2, v6) + PUNPCKLQDQ(t1, t2) + PUNPCKHQDQ(t2, v7) +} + +func HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48 VecPhysical) { + MOVO(v0, t0) + PMULULQ(v2, t0) + PADDQ(v2, v0) + PADDQ(t0, v0) + PADDQ(t0, v0) + PXOR(v0, v6) + PSHUFD(Imm(0xB1), v6, v6) + MOVO(v4, t0) + PMULULQ(v6, t0) + PADDQ(v6, v4) + PADDQ(t0, v4) + PADDQ(t0, v4) + PXOR(v4, v2) + PSHUFB(c40, v2) + MOVO(v0, t0) + PMULULQ(v2, t0) + PADDQ(v2, v0) + PADDQ(t0, v0) + PADDQ(t0, v0) + PXOR(v0, v6) + PSHUFB(c48, v6) + MOVO(v4, t0) + PMULULQ(v6, t0) + PADDQ(v6, v4) + PADDQ(t0, v4) + PADDQ(t0, v4) + PXOR(v4, v2) + MOVO(v2, t0) + PADDQ(v2, t0) + PSRLQ(Imm(63), v2) + PXOR(t0, v2) + MOVO(v1, t0) + PMULULQ(v3, t0) + PADDQ(v3, v1) + PADDQ(t0, v1) + PADDQ(t0, v1) + PXOR(v1, v7) + PSHUFD(Imm(0xB1), v7, v7) + MOVO(v5, t0) + PMULULQ(v7, t0) + PADDQ(v7, v5) + PADDQ(t0, v5) + PADDQ(t0, v5) + PXOR(v5, v3) + PSHUFB(c40, v3) + MOVO(v1, t0) + PMULULQ(v3, t0) + PADDQ(v3, v1) + PADDQ(t0, v1) + PADDQ(t0, v1) + PXOR(v1, v7) + PSHUFB(c48, v7) + MOVO(v5, t0) + PMULULQ(v7, t0) + PADDQ(v7, v5) + PADDQ(t0, v5) + PADDQ(t0, v5) + PXOR(v5, v3) + MOVO(v3, t0) + PADDQ(v3, t0) + PSRLQ(Imm(63), v3) + PXOR(t0, v3) +} + +func LOAD_MSG_0(block GPPhysical, off int) { + var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} + for i, r := range registers { + MOVOU(Mem{Base: block}.Offset(8*(off+(i*2))), r) + } +} + +func STORE_MSG_0(block GPPhysical, off int) { + var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} + for i, r := range registers { + MOVOU(r, Mem{Base: block}.Offset(8*(off+(i*2)))) + } +} + +func LOAD_MSG_1(block GPPhysical, off int) { + var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} + for i, r := range registers { + MOVOU(Mem{Base: block}.Offset(8*off+i*16*8), r) + } +} + +func STORE_MSG_1(block GPPhysical, off int) { + var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} + for i, r := range registers { + MOVOU(r, Mem{Base: block}.Offset(8*off+i*16*8)) + } +} + +func BLAMKA_ROUND_0(block GPPhysical, off int, t0, t1, c40, c48 VecPhysical) { + LOAD_MSG_0(block, off) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48) + SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1) + STORE_MSG_0(block, off) +} + +func BLAMKA_ROUND_1(block GPPhysical, off int, t0, t1, c40, c48 VecPhysical) { + LOAD_MSG_1(block, off) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48) + SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1) + STORE_MSG_1(block, off) +} + +// ##------------------DATA SECTION-------------------## + +var c40_DATA_ptr, c48_DATA_ptr *Mem + +func c40_DATA() Mem { + if c40_DATA_ptr != nil { + return *c40_DATA_ptr + } + + c40_DATA := GLOBL("·c40", NOPTR|RODATA) + c40_DATA_ptr = &c40_DATA + DATA(0x00, U64(0x0201000706050403)) + DATA(0x08, U64(0x0a09080f0e0d0c0b)) + return c40_DATA +} +func c48_DATA() Mem { + if c48_DATA_ptr != nil { + return *c48_DATA_ptr + } + + c48_DATA := GLOBL("·c48", NOPTR|RODATA) + c48_DATA_ptr = &c48_DATA + DATA(0x00, U64(0x0100070605040302)) + DATA(0x08, U64(0x09080f0e0d0c0b0a)) + return c48_DATA +} diff --git a/argon2/_asm/go.mod b/argon2/_asm/go.mod new file mode 100644 index 0000000000..aa51840a9b --- /dev/null +++ b/argon2/_asm/go.mod @@ -0,0 +1,15 @@ +module argon2/_asm + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/argon2/_asm/go.sum b/argon2/_asm/go.sum new file mode 100644 index 0000000000..39dd154050 --- /dev/null +++ b/argon2/_asm/go.sum @@ -0,0 +1,12 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/argon2/argon2.go b/argon2/argon2.go index b423feaea9..2b65ec91ac 100644 --- a/argon2/argon2.go +++ b/argon2/argon2.go @@ -6,34 +6,32 @@ // Argon2 was selected as the winner of the Password Hashing Competition and can // be used to derive cryptographic keys from passwords. // -// For a detailed specification of Argon2 see [1]. +// For a detailed specification of Argon2 see [argon2-specs.pdf]. // // If you aren't sure which function you need, use Argon2id (IDKey) and // the parameter recommendations for your scenario. // -// -// Argon2i +// # Argon2i // // Argon2i (implemented by Key) is the side-channel resistant version of Argon2. // It uses data-independent memory access, which is preferred for password // hashing and password-based key derivation. Argon2i requires more passes over // memory than Argon2id to protect from trade-off attacks. The recommended -// parameters (taken from [2]) for non-interactive operations are time=3 and to +// parameters (taken from [RFC 9106 Section 7.3]) for non-interactive operations are time=3 and to // use the maximum available memory. // -// -// Argon2id +// # Argon2id // // Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining // Argon2i and Argon2d. It uses data-independent memory access for the first // half of the first iteration over the memory and data-dependent memory access // for the rest. Argon2id is side-channel resistant and provides better brute- // force cost savings due to time-memory tradeoffs than Argon2i. The recommended -// parameters for non-interactive operations (taken from [2]) are time=1 and to +// parameters for non-interactive operations (taken from [RFC 9106 Section 7.3]) are time=1 and to // use the maximum available memory. // -// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf -// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3 +// [argon2-specs.pdf]: https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3 package argon2 import ( @@ -59,9 +57,9 @@ const ( // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // -// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) +// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) // -// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number. +// [RFC 9106 Section 7.3] recommends time=3, and memory=32*1024 as a sensible number. // If using that amount of memory (32 MB) is not possible in some contexts then // the time parameter can be increased to compensate. // @@ -71,6 +69,8 @@ const ( // adjusted to the number of available CPUs. The cost parameters should be // increased as memory latency and CPU parallelism increases. Remember to get a // good random salt. +// +// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3 func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) } @@ -83,9 +83,9 @@ func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint3 // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // -// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) +// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) // -// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number. +// [RFC 9106 Section 7.3] recommends time=1, and memory=64*1024 as a sensible number. // If using that amount of memory (64 MB) is not possible in some contexts then // the time parameter can be increased to compensate. // @@ -95,6 +95,8 @@ func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint3 // adjusted to the numbers of available CPUs. The cost parameters should be // increased as memory latency and CPU parallelism increases. Remember to get a // good random salt. +// +// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3 func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) } diff --git a/argon2/blamka_amd64.go b/argon2/blamka_amd64.go index 2fc1ec0312..063e7784f8 100644 --- a/argon2/blamka_amd64.go +++ b/argon2/blamka_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego package argon2 diff --git a/argon2/blamka_amd64.s b/argon2/blamka_amd64.s index 74a6e7332a..c3895478ed 100644 --- a/argon2/blamka_amd64.s +++ b/argon2/blamka_amd64.s @@ -1,243 +1,2791 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run blamka_amd64.go -out ../blamka_amd64.s -pkg argon2. DO NOT EDIT. -// +build amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego #include "textflag.h" -DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 - -DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 - -#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ - MOVO v4, t1; \ - MOVO v5, v4; \ - MOVO t1, v5; \ - MOVO v6, t1; \ - PUNPCKLQDQ v6, t2; \ - PUNPCKHQDQ v7, v6; \ - PUNPCKHQDQ t2, v6; \ - PUNPCKLQDQ v7, t2; \ - MOVO t1, v7; \ - MOVO v2, t1; \ - PUNPCKHQDQ t2, v7; \ - PUNPCKLQDQ v3, t2; \ - PUNPCKHQDQ t2, v2; \ - PUNPCKLQDQ t1, t2; \ - PUNPCKHQDQ t2, v3 - -#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ - MOVO v4, t1; \ - MOVO v5, v4; \ - MOVO t1, v5; \ - MOVO v2, t1; \ - PUNPCKLQDQ v2, t2; \ - PUNPCKHQDQ v3, v2; \ - PUNPCKHQDQ t2, v2; \ - PUNPCKLQDQ v3, t2; \ - MOVO t1, v3; \ - MOVO v6, t1; \ - PUNPCKHQDQ t2, v3; \ - PUNPCKLQDQ v7, t2; \ - PUNPCKHQDQ t2, v6; \ - PUNPCKLQDQ t1, t2; \ - PUNPCKHQDQ t2, v7 - -#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \ - MOVO v0, t0; \ - PMULULQ v2, t0; \ - PADDQ v2, v0; \ - PADDQ t0, v0; \ - PADDQ t0, v0; \ - PXOR v0, v6; \ - PSHUFD $0xB1, v6, v6; \ - MOVO v4, t0; \ - PMULULQ v6, t0; \ - PADDQ v6, v4; \ - PADDQ t0, v4; \ - PADDQ t0, v4; \ - PXOR v4, v2; \ - PSHUFB c40, v2; \ - MOVO v0, t0; \ - PMULULQ v2, t0; \ - PADDQ v2, v0; \ - PADDQ t0, v0; \ - PADDQ t0, v0; \ - PXOR v0, v6; \ - PSHUFB c48, v6; \ - MOVO v4, t0; \ - PMULULQ v6, t0; \ - PADDQ v6, v4; \ - PADDQ t0, v4; \ - PADDQ t0, v4; \ - PXOR v4, v2; \ - MOVO v2, t0; \ - PADDQ v2, t0; \ - PSRLQ $63, v2; \ - PXOR t0, v2; \ - MOVO v1, t0; \ - PMULULQ v3, t0; \ - PADDQ v3, v1; \ - PADDQ t0, v1; \ - PADDQ t0, v1; \ - PXOR v1, v7; \ - PSHUFD $0xB1, v7, v7; \ - MOVO v5, t0; \ - PMULULQ v7, t0; \ - PADDQ v7, v5; \ - PADDQ t0, v5; \ - PADDQ t0, v5; \ - PXOR v5, v3; \ - PSHUFB c40, v3; \ - MOVO v1, t0; \ - PMULULQ v3, t0; \ - PADDQ v3, v1; \ - PADDQ t0, v1; \ - PADDQ t0, v1; \ - PXOR v1, v7; \ - PSHUFB c48, v7; \ - MOVO v5, t0; \ - PMULULQ v7, t0; \ - PADDQ v7, v5; \ - PADDQ t0, v5; \ - PADDQ t0, v5; \ - PXOR v5, v3; \ - MOVO v3, t0; \ - PADDQ v3, t0; \ - PSRLQ $63, v3; \ - PXOR t0, v3 - -#define LOAD_MSG_0(block, off) \ - MOVOU 8*(off+0)(block), X0; \ - MOVOU 8*(off+2)(block), X1; \ - MOVOU 8*(off+4)(block), X2; \ - MOVOU 8*(off+6)(block), X3; \ - MOVOU 8*(off+8)(block), X4; \ - MOVOU 8*(off+10)(block), X5; \ - MOVOU 8*(off+12)(block), X6; \ - MOVOU 8*(off+14)(block), X7 - -#define STORE_MSG_0(block, off) \ - MOVOU X0, 8*(off+0)(block); \ - MOVOU X1, 8*(off+2)(block); \ - MOVOU X2, 8*(off+4)(block); \ - MOVOU X3, 8*(off+6)(block); \ - MOVOU X4, 8*(off+8)(block); \ - MOVOU X5, 8*(off+10)(block); \ - MOVOU X6, 8*(off+12)(block); \ - MOVOU X7, 8*(off+14)(block) - -#define LOAD_MSG_1(block, off) \ - MOVOU 8*off+0*8(block), X0; \ - MOVOU 8*off+16*8(block), X1; \ - MOVOU 8*off+32*8(block), X2; \ - MOVOU 8*off+48*8(block), X3; \ - MOVOU 8*off+64*8(block), X4; \ - MOVOU 8*off+80*8(block), X5; \ - MOVOU 8*off+96*8(block), X6; \ - MOVOU 8*off+112*8(block), X7 - -#define STORE_MSG_1(block, off) \ - MOVOU X0, 8*off+0*8(block); \ - MOVOU X1, 8*off+16*8(block); \ - MOVOU X2, 8*off+32*8(block); \ - MOVOU X3, 8*off+48*8(block); \ - MOVOU X4, 8*off+64*8(block); \ - MOVOU X5, 8*off+80*8(block); \ - MOVOU X6, 8*off+96*8(block); \ - MOVOU X7, 8*off+112*8(block) - -#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \ - LOAD_MSG_0(block, off); \ - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ - SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ - STORE_MSG_0(block, off) - -#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \ - LOAD_MSG_1(block, off); \ - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ - SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ - STORE_MSG_1(block, off) - // func blamkaSSE4(b *block) -TEXT ·blamkaSSE4(SB), 4, $0-8 - MOVQ b+0(FP), AX - - MOVOU ·c40<>(SB), X10 - MOVOU ·c48<>(SB), X11 +// Requires: SSE2, SSSE3 +TEXT ·blamkaSSE4(SB), NOSPLIT, $0-8 + MOVQ b+0(FP), AX + MOVOU ·c40<>+0(SB), X10 + MOVOU ·c48<>+0(SB), X11 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU 64(AX), X4 + MOVOU 80(AX), X5 + MOVOU 96(AX), X6 + MOVOU 112(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, (AX) + MOVOU X1, 16(AX) + MOVOU X2, 32(AX) + MOVOU X3, 48(AX) + MOVOU X4, 64(AX) + MOVOU X5, 80(AX) + MOVOU X6, 96(AX) + MOVOU X7, 112(AX) + MOVOU 128(AX), X0 + MOVOU 144(AX), X1 + MOVOU 160(AX), X2 + MOVOU 176(AX), X3 + MOVOU 192(AX), X4 + MOVOU 208(AX), X5 + MOVOU 224(AX), X6 + MOVOU 240(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 128(AX) + MOVOU X1, 144(AX) + MOVOU X2, 160(AX) + MOVOU X3, 176(AX) + MOVOU X4, 192(AX) + MOVOU X5, 208(AX) + MOVOU X6, 224(AX) + MOVOU X7, 240(AX) + MOVOU 256(AX), X0 + MOVOU 272(AX), X1 + MOVOU 288(AX), X2 + MOVOU 304(AX), X3 + MOVOU 320(AX), X4 + MOVOU 336(AX), X5 + MOVOU 352(AX), X6 + MOVOU 368(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 256(AX) + MOVOU X1, 272(AX) + MOVOU X2, 288(AX) + MOVOU X3, 304(AX) + MOVOU X4, 320(AX) + MOVOU X5, 336(AX) + MOVOU X6, 352(AX) + MOVOU X7, 368(AX) + MOVOU 384(AX), X0 + MOVOU 400(AX), X1 + MOVOU 416(AX), X2 + MOVOU 432(AX), X3 + MOVOU 448(AX), X4 + MOVOU 464(AX), X5 + MOVOU 480(AX), X6 + MOVOU 496(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 384(AX) + MOVOU X1, 400(AX) + MOVOU X2, 416(AX) + MOVOU X3, 432(AX) + MOVOU X4, 448(AX) + MOVOU X5, 464(AX) + MOVOU X6, 480(AX) + MOVOU X7, 496(AX) + MOVOU 512(AX), X0 + MOVOU 528(AX), X1 + MOVOU 544(AX), X2 + MOVOU 560(AX), X3 + MOVOU 576(AX), X4 + MOVOU 592(AX), X5 + MOVOU 608(AX), X6 + MOVOU 624(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 512(AX) + MOVOU X1, 528(AX) + MOVOU X2, 544(AX) + MOVOU X3, 560(AX) + MOVOU X4, 576(AX) + MOVOU X5, 592(AX) + MOVOU X6, 608(AX) + MOVOU X7, 624(AX) + MOVOU 640(AX), X0 + MOVOU 656(AX), X1 + MOVOU 672(AX), X2 + MOVOU 688(AX), X3 + MOVOU 704(AX), X4 + MOVOU 720(AX), X5 + MOVOU 736(AX), X6 + MOVOU 752(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 640(AX) + MOVOU X1, 656(AX) + MOVOU X2, 672(AX) + MOVOU X3, 688(AX) + MOVOU X4, 704(AX) + MOVOU X5, 720(AX) + MOVOU X6, 736(AX) + MOVOU X7, 752(AX) + MOVOU 768(AX), X0 + MOVOU 784(AX), X1 + MOVOU 800(AX), X2 + MOVOU 816(AX), X3 + MOVOU 832(AX), X4 + MOVOU 848(AX), X5 + MOVOU 864(AX), X6 + MOVOU 880(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 768(AX) + MOVOU X1, 784(AX) + MOVOU X2, 800(AX) + MOVOU X3, 816(AX) + MOVOU X4, 832(AX) + MOVOU X5, 848(AX) + MOVOU X6, 864(AX) + MOVOU X7, 880(AX) + MOVOU 896(AX), X0 + MOVOU 912(AX), X1 + MOVOU 928(AX), X2 + MOVOU 944(AX), X3 + MOVOU 960(AX), X4 + MOVOU 976(AX), X5 + MOVOU 992(AX), X6 + MOVOU 1008(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 896(AX) + MOVOU X1, 912(AX) + MOVOU X2, 928(AX) + MOVOU X3, 944(AX) + MOVOU X4, 960(AX) + MOVOU X5, 976(AX) + MOVOU X6, 992(AX) + MOVOU X7, 1008(AX) + MOVOU (AX), X0 + MOVOU 128(AX), X1 + MOVOU 256(AX), X2 + MOVOU 384(AX), X3 + MOVOU 512(AX), X4 + MOVOU 640(AX), X5 + MOVOU 768(AX), X6 + MOVOU 896(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, (AX) + MOVOU X1, 128(AX) + MOVOU X2, 256(AX) + MOVOU X3, 384(AX) + MOVOU X4, 512(AX) + MOVOU X5, 640(AX) + MOVOU X6, 768(AX) + MOVOU X7, 896(AX) + MOVOU 16(AX), X0 + MOVOU 144(AX), X1 + MOVOU 272(AX), X2 + MOVOU 400(AX), X3 + MOVOU 528(AX), X4 + MOVOU 656(AX), X5 + MOVOU 784(AX), X6 + MOVOU 912(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 16(AX) + MOVOU X1, 144(AX) + MOVOU X2, 272(AX) + MOVOU X3, 400(AX) + MOVOU X4, 528(AX) + MOVOU X5, 656(AX) + MOVOU X6, 784(AX) + MOVOU X7, 912(AX) + MOVOU 32(AX), X0 + MOVOU 160(AX), X1 + MOVOU 288(AX), X2 + MOVOU 416(AX), X3 + MOVOU 544(AX), X4 + MOVOU 672(AX), X5 + MOVOU 800(AX), X6 + MOVOU 928(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 32(AX) + MOVOU X1, 160(AX) + MOVOU X2, 288(AX) + MOVOU X3, 416(AX) + MOVOU X4, 544(AX) + MOVOU X5, 672(AX) + MOVOU X6, 800(AX) + MOVOU X7, 928(AX) + MOVOU 48(AX), X0 + MOVOU 176(AX), X1 + MOVOU 304(AX), X2 + MOVOU 432(AX), X3 + MOVOU 560(AX), X4 + MOVOU 688(AX), X5 + MOVOU 816(AX), X6 + MOVOU 944(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 48(AX) + MOVOU X1, 176(AX) + MOVOU X2, 304(AX) + MOVOU X3, 432(AX) + MOVOU X4, 560(AX) + MOVOU X5, 688(AX) + MOVOU X6, 816(AX) + MOVOU X7, 944(AX) + MOVOU 64(AX), X0 + MOVOU 192(AX), X1 + MOVOU 320(AX), X2 + MOVOU 448(AX), X3 + MOVOU 576(AX), X4 + MOVOU 704(AX), X5 + MOVOU 832(AX), X6 + MOVOU 960(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 64(AX) + MOVOU X1, 192(AX) + MOVOU X2, 320(AX) + MOVOU X3, 448(AX) + MOVOU X4, 576(AX) + MOVOU X5, 704(AX) + MOVOU X6, 832(AX) + MOVOU X7, 960(AX) + MOVOU 80(AX), X0 + MOVOU 208(AX), X1 + MOVOU 336(AX), X2 + MOVOU 464(AX), X3 + MOVOU 592(AX), X4 + MOVOU 720(AX), X5 + MOVOU 848(AX), X6 + MOVOU 976(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 80(AX) + MOVOU X1, 208(AX) + MOVOU X2, 336(AX) + MOVOU X3, 464(AX) + MOVOU X4, 592(AX) + MOVOU X5, 720(AX) + MOVOU X6, 848(AX) + MOVOU X7, 976(AX) + MOVOU 96(AX), X0 + MOVOU 224(AX), X1 + MOVOU 352(AX), X2 + MOVOU 480(AX), X3 + MOVOU 608(AX), X4 + MOVOU 736(AX), X5 + MOVOU 864(AX), X6 + MOVOU 992(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 96(AX) + MOVOU X1, 224(AX) + MOVOU X2, 352(AX) + MOVOU X3, 480(AX) + MOVOU X4, 608(AX) + MOVOU X5, 736(AX) + MOVOU X6, 864(AX) + MOVOU X7, 992(AX) + MOVOU 112(AX), X0 + MOVOU 240(AX), X1 + MOVOU 368(AX), X2 + MOVOU 496(AX), X3 + MOVOU 624(AX), X4 + MOVOU 752(AX), X5 + MOVOU 880(AX), X6 + MOVOU 1008(AX), X7 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFD $0xb1, X6, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + PSHUFB X10, X2 + MOVO X0, X8 + PMULULQ X2, X8 + PADDQ X2, X0 + PADDQ X8, X0 + PADDQ X8, X0 + PXOR X0, X6 + PSHUFB X11, X6 + MOVO X4, X8 + PMULULQ X6, X8 + PADDQ X6, X4 + PADDQ X8, X4 + PADDQ X8, X4 + PXOR X4, X2 + MOVO X2, X8 + PADDQ X2, X8 + PSRLQ $0x3f, X2 + PXOR X8, X2 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFD $0xb1, X7, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + PSHUFB X10, X3 + MOVO X1, X8 + PMULULQ X3, X8 + PADDQ X3, X1 + PADDQ X8, X1 + PADDQ X8, X1 + PXOR X1, X7 + PSHUFB X11, X7 + MOVO X5, X8 + PMULULQ X7, X8 + PADDQ X7, X5 + PADDQ X8, X5 + PADDQ X8, X5 + PXOR X5, X3 + MOVO X3, X8 + PADDQ X3, X8 + PSRLQ $0x3f, X3 + PXOR X8, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU X0, 112(AX) + MOVOU X1, 240(AX) + MOVOU X2, 368(AX) + MOVOU X3, 496(AX) + MOVOU X4, 624(AX) + MOVOU X5, 752(AX) + MOVOU X6, 880(AX) + MOVOU X7, 1008(AX) + RET - BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11) - BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11) +DATA ·c40<>+0(SB)/8, $0x0201000706050403 +DATA ·c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), RODATA|NOPTR, $16 - BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11) - BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11) - RET +DATA ·c48<>+0(SB)/8, $0x0100070605040302 +DATA ·c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), RODATA|NOPTR, $16 -// func mixBlocksSSE2(out, a, b, c *block) -TEXT ·mixBlocksSSE2(SB), 4, $0-32 +// func mixBlocksSSE2(out *block, a *block, b *block, c *block) +// Requires: SSE2 +TEXT ·mixBlocksSSE2(SB), NOSPLIT, $0-32 MOVQ out+0(FP), DX MOVQ a+8(FP), AX MOVQ b+16(FP), BX - MOVQ a+24(FP), CX - MOVQ $128, BP + MOVQ c+24(FP), CX + MOVQ $0x00000080, DI loop: - MOVOU 0(AX), X0 - MOVOU 0(BX), X1 - MOVOU 0(CX), X2 + MOVOU (AX), X0 + MOVOU (BX), X1 + MOVOU (CX), X2 PXOR X1, X0 PXOR X2, X0 - MOVOU X0, 0(DX) - ADDQ $16, AX - ADDQ $16, BX - ADDQ $16, CX - ADDQ $16, DX - SUBQ $2, BP + MOVOU X0, (DX) + ADDQ $0x10, AX + ADDQ $0x10, BX + ADDQ $0x10, CX + ADDQ $0x10, DX + SUBQ $0x02, DI JA loop RET -// func xorBlocksSSE2(out, a, b, c *block) -TEXT ·xorBlocksSSE2(SB), 4, $0-32 +// func xorBlocksSSE2(out *block, a *block, b *block, c *block) +// Requires: SSE2 +TEXT ·xorBlocksSSE2(SB), NOSPLIT, $0-32 MOVQ out+0(FP), DX MOVQ a+8(FP), AX MOVQ b+16(FP), BX - MOVQ a+24(FP), CX - MOVQ $128, BP + MOVQ c+24(FP), CX + MOVQ $0x00000080, DI loop: - MOVOU 0(AX), X0 - MOVOU 0(BX), X1 - MOVOU 0(CX), X2 - MOVOU 0(DX), X3 + MOVOU (AX), X0 + MOVOU (BX), X1 + MOVOU (CX), X2 + MOVOU (DX), X3 PXOR X1, X0 PXOR X2, X0 PXOR X3, X0 - MOVOU X0, 0(DX) - ADDQ $16, AX - ADDQ $16, BX - ADDQ $16, CX - ADDQ $16, DX - SUBQ $2, BP + MOVOU X0, (DX) + ADDQ $0x10, AX + ADDQ $0x10, BX + ADDQ $0x10, CX + ADDQ $0x10, DX + SUBQ $0x02, DI JA loop RET diff --git a/argon2/blamka_ref.go b/argon2/blamka_ref.go index baf7b551da..16d58c650e 100644 --- a/argon2/blamka_ref.go +++ b/argon2/blamka_ref.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine gccgo +//go:build !amd64 || purego || !gc package argon2 diff --git a/bcrypt/bcrypt.go b/bcrypt/bcrypt.go index aeb73f81a1..3e7f8df871 100644 --- a/bcrypt/bcrypt.go +++ b/bcrypt/bcrypt.go @@ -4,7 +4,7 @@ // Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing // algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf -package bcrypt // import "golang.org/x/crypto/bcrypt" +package bcrypt // The code is a port of Provos and Mazières's C implementation. import ( @@ -50,7 +50,7 @@ func (ih InvalidHashPrefixError) Error() string { type InvalidCostError int func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed inclusive range %d..%d", int(ic), MinCost, MaxCost) } const ( @@ -82,11 +82,20 @@ type hashed struct { minor byte } +// ErrPasswordTooLong is returned when the password passed to +// GenerateFromPassword is too long (i.e. > 72 bytes). +var ErrPasswordTooLong = errors.New("bcrypt: password length exceeds 72 bytes") + // GenerateFromPassword returns the bcrypt hash of the password at the given // cost. If the cost given is less than MinCost, the cost will be set to // DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, // to compare the returned hashed password with its cleartext version. +// GenerateFromPassword does not accept passwords longer than 72 bytes, which +// is the longest password bcrypt will operate on. func GenerateFromPassword(password []byte, cost int) ([]byte, error) { + if len(password) > 72 { + return nil, ErrPasswordTooLong + } p, err := newFromPassword(password, cost) if err != nil { return nil, err diff --git a/bcrypt/bcrypt_test.go b/bcrypt/bcrypt_test.go index b7162d8217..8b589e3652 100644 --- a/bcrypt/bcrypt_test.go +++ b/bcrypt/bcrypt_test.go @@ -241,3 +241,10 @@ func TestNoSideEffectsFromCompare(t *testing.T) { t.Errorf("got=%q want=%q", got, want) } } + +func TestPasswordTooLong(t *testing.T) { + _, err := GenerateFromPassword(make([]byte, 73), 1) + if err != ErrPasswordTooLong { + t.Errorf("unexpected error: got %q, want %q", err, ErrPasswordTooLong) + } +} diff --git a/blake2b/_asm/AVX2/blake2bAVX2_amd64_asm.go b/blake2b/_asm/AVX2/blake2bAVX2_amd64_asm.go new file mode 100644 index 0000000000..c297c0ca63 --- /dev/null +++ b/blake2b/_asm/AVX2/blake2bAVX2_amd64_asm.go @@ -0,0 +1,1228 @@ +// Copyright 2024 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 main + +import ( + . "github.com/mmcloughlin/avo/build" + "github.com/mmcloughlin/avo/ir" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/blake2b" +) + +//go:generate go run . -out ../../blake2bAVX2_amd64.s -pkg blake2b + +const ThatPeskyUnicodeDot = "\u00b7" + +func main() { + Package("golang.org/x/crypto/blake2b") + ConstraintExpr("amd64,gc,!purego") + hashBlocksAVX2() + hashBlocksAVX() + Generate() +} + +// Utility function to emit a BYTE instruction +func BYTE(imm Op) { + Instruction(&ir.Instruction{Opcode: "BYTE", Operands: []Op{imm}}) +} + +func VPERMQ_0x39_Y1_Y1() { + BYTE(U8(0xc4)) + BYTE(U8(0xe3)) + BYTE(U8(0xfd)) + BYTE(U8(0x00)) + BYTE(U8(0xc9)) + BYTE(U8(0x39)) +} + +func VPERMQ_0x93_Y1_Y1() { + BYTE(U8(0xc4)) + BYTE(U8(0xe3)) + BYTE(U8(0xfd)) + BYTE(U8(0x00)) + BYTE(U8(0xc9)) + BYTE(U8(0x93)) +} + +func VPERMQ_0x4E_Y2_Y2() { + BYTE(U8(0xc4)) + BYTE(U8(0xe3)) + BYTE(U8(0xfd)) + BYTE(U8(0x00)) + BYTE(U8(0xd2)) + BYTE(U8(0x4e)) +} + +func VPERMQ_0x93_Y3_Y3() { + BYTE(U8(0xc4)) + BYTE(U8(0xe3)) + BYTE(U8(0xfd)) + BYTE(U8(0x00)) + BYTE(U8(0xdb)) + BYTE(U8(0x93)) +} + +func VPERMQ_0x39_Y3_Y3() { + BYTE(U8(0xc4)) + BYTE(U8(0xe3)) + BYTE(U8(0xfd)) + BYTE(U8(0x00)) + BYTE(U8(0xdb)) + BYTE(U8(0x39)) +} + +func ROUND_AVX2(m0, m1, m2, m3 Op, t, c40, c48 VecPhysical) { + VPADDQ(m0, Y0, Y0) + VPADDQ(Y1, Y0, Y0) + VPXOR(Y0, Y3, Y3) + VPSHUFD(I8(-79), Y3, Y3) + VPADDQ(Y3, Y2, Y2) + VPXOR(Y2, Y1, Y1) + VPSHUFB(c40, Y1, Y1) + VPADDQ(m1, Y0, Y0) + VPADDQ(Y1, Y0, Y0) + VPXOR(Y0, Y3, Y3) + VPSHUFB(c48, Y3, Y3) + VPADDQ(Y3, Y2, Y2) + VPXOR(Y2, Y1, Y1) + VPADDQ(Y1, Y1, t) + VPSRLQ(Imm(63), Y1, Y1) + VPXOR(t, Y1, Y1) + VPERMQ_0x39_Y1_Y1() + VPERMQ_0x4E_Y2_Y2() + VPERMQ_0x93_Y3_Y3() + VPADDQ(m2, Y0, Y0) + VPADDQ(Y1, Y0, Y0) + VPXOR(Y0, Y3, Y3) + VPSHUFD(I8(-79), Y3, Y3) + VPADDQ(Y3, Y2, Y2) + VPXOR(Y2, Y1, Y1) + VPSHUFB(c40, Y1, Y1) + VPADDQ(m3, Y0, Y0) + VPADDQ(Y1, Y0, Y0) + VPXOR(Y0, Y3, Y3) + VPSHUFB(c48, Y3, Y3) + VPADDQ(Y3, Y2, Y2) + VPXOR(Y2, Y1, Y1) + VPADDQ(Y1, Y1, t) + VPSRLQ(Imm(63), Y1, Y1) + VPXOR(t, Y1, Y1) + VPERMQ_0x39_Y3_Y3() + VPERMQ_0x4E_Y2_Y2() + VPERMQ_0x93_Y1_Y1() +} + +func VMOVQ_SI_X11_0() { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x1E)) +} + +func VMOVQ_SI_X12_0() { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x26)) +} + +func VMOVQ_SI_X13_0() { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x2E)) +} + +func VMOVQ_SI_X14_0() { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x36)) +} + +func VMOVQ_SI_X15_0() { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x3E)) +} + +func VMOVQ_SI_X11(n uint8) { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x5E)) + BYTE(U8(n)) +} + +func VMOVQ_SI_X12(n uint8) { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x66)) + BYTE(U8(n)) +} + +func VMOVQ_SI_X13(n uint8) { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x6E)) + BYTE(U8(n)) +} + +func VMOVQ_SI_X14(n uint8) { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x76)) + BYTE(U8(n)) +} + +func VMOVQ_SI_X15(n uint8) { + BYTE(U8(0xC5)) + BYTE(U8(0x7A)) + BYTE(U8(0x7E)) + BYTE(U8(0x7E)) + BYTE(U8(n)) +} + +func VPINSRQ_1_SI_X11_0() { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0xA1)) + BYTE(U8(0x22)) + BYTE(U8(0x1E)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X12_0() { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x99)) + BYTE(U8(0x22)) + BYTE(U8(0x26)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X13_0() { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x91)) + BYTE(U8(0x22)) + BYTE(U8(0x2E)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X14_0() { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x89)) + BYTE(U8(0x22)) + BYTE(U8(0x36)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X15_0() { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x81)) + BYTE(U8(0x22)) + BYTE(U8(0x3E)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X11(n uint8) { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0xA1)) + BYTE(U8(0x22)) + BYTE(U8(0x5E)) + BYTE(U8(n)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X12(n uint8) { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x99)) + BYTE(U8(0x22)) + BYTE(U8(0x66)) + BYTE(U8(n)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X13(n uint8) { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x91)) + BYTE(U8(0x22)) + BYTE(U8(0x6E)) + BYTE(U8(n)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X14(n uint8) { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x89)) + BYTE(U8(0x22)) + BYTE(U8(0x76)) + BYTE(U8(n)) + BYTE(U8(0x01)) +} + +func VPINSRQ_1_SI_X15(n uint8) { + BYTE(U8(0xC4)) + BYTE(U8(0x63)) + BYTE(U8(0x81)) + BYTE(U8(0x22)) + BYTE(U8(0x7E)) + BYTE(U8(n)) + BYTE(U8(0x01)) +} + +func VMOVQ_R8_X15() { + BYTE(U8(0xC4)) + BYTE(U8(0x41)) + BYTE(U8(0xF9)) + BYTE(U8(0x6E)) + BYTE(U8(0xF8)) +} + +func VPINSRQ_1_R9_X15() { + BYTE(U8(0xC4)) + BYTE(U8(0x43)) + BYTE(U8(0x81)) + BYTE(U8(0x22)) + BYTE(U8(0xF9)) + BYTE(U8(0x01)) +} + +// load msg: +// +// Y12 = (i0, i1, i2, i3) +// +// i0, i1, i2, i3 must not be 0 +func LOAD_MSG_AVX2_Y12(i0, i1, i2, i3 uint8) { + VMOVQ_SI_X12(i0 * 8) + VMOVQ_SI_X11(i2 * 8) + VPINSRQ_1_SI_X12(i1 * 8) + VPINSRQ_1_SI_X11(i3 * 8) + VINSERTI128(Imm(1), X11, Y12, Y12) +} + +// load msg: +// +// Y13 = (i0, i1, i2, i3) +// +// i0, i1, i2, i3 must not be 0 +func LOAD_MSG_AVX2_Y13(i0, i1, i2, i3 uint8) { + VMOVQ_SI_X13(i0 * 8) + VMOVQ_SI_X11(i2 * 8) + VPINSRQ_1_SI_X13(i1 * 8) + VPINSRQ_1_SI_X11(i3 * 8) + VINSERTI128(Imm(1), X11, Y13, Y13) +} + +// load msg: +// +// Y14 = (i0, i1, i2, i3) +// +// i0, i1, i2, i3 must not be 0 +func LOAD_MSG_AVX2_Y14(i0, i1, i2, i3 uint8) { + VMOVQ_SI_X14(i0 * 8) + VMOVQ_SI_X11(i2 * 8) + VPINSRQ_1_SI_X14(i1 * 8) + VPINSRQ_1_SI_X11(i3 * 8) + VINSERTI128(Imm(1), X11, Y14, Y14) +} + +// load msg: +// +// Y15 = (i0, i1, i2, i3) +// +// i0, i1, i2, i3 must not be 0 +func LOAD_MSG_AVX2_Y15(i0, i1, i2, i3 uint8) { + VMOVQ_SI_X15(i0 * 8) + VMOVQ_SI_X11(i2 * 8) + VPINSRQ_1_SI_X15(i1 * 8) + VPINSRQ_1_SI_X11(i3 * 8) + VINSERTI128(Imm(1), X11, Y15, Y15) +} + +func LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() { + VMOVQ_SI_X12_0() + VMOVQ_SI_X11(4 * 8) + VPINSRQ_1_SI_X12(2 * 8) + VPINSRQ_1_SI_X11(6 * 8) + VINSERTI128(Imm(1), X11, Y12, Y12) + LOAD_MSG_AVX2_Y13(1, 3, 5, 7) + LOAD_MSG_AVX2_Y14(8, 10, 12, 14) + LOAD_MSG_AVX2_Y15(9, 11, 13, 15) +} + +func LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() { + LOAD_MSG_AVX2_Y12(14, 4, 9, 13) + LOAD_MSG_AVX2_Y13(10, 8, 15, 6) + VMOVQ_SI_X11(11 * 8) + VPSHUFD(Imm(0x4E), Mem{Base: SI}.Offset(0*8), X14) + VPINSRQ_1_SI_X11(5 * 8) + VINSERTI128(Imm(1), X11, Y14, Y14) + LOAD_MSG_AVX2_Y15(12, 2, 7, 3) +} + +func LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() { + VMOVQ_SI_X11(5 * 8) + VMOVDQU(Mem{Base: SI}.Offset(11*8), X12) + VPINSRQ_1_SI_X11(15 * 8) + VINSERTI128(Imm(1), X11, Y12, Y12) + VMOVQ_SI_X13(8 * 8) + VMOVQ_SI_X11(2 * 8) + VPINSRQ_1_SI_X13_0() + VPINSRQ_1_SI_X11(13 * 8) + VINSERTI128(Imm(1), X11, Y13, Y13) + LOAD_MSG_AVX2_Y14(10, 3, 7, 9) + LOAD_MSG_AVX2_Y15(14, 6, 1, 4) +} + +func LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() { + LOAD_MSG_AVX2_Y12(7, 3, 13, 11) + LOAD_MSG_AVX2_Y13(9, 1, 12, 14) + LOAD_MSG_AVX2_Y14(2, 5, 4, 15) + VMOVQ_SI_X15(6 * 8) + VMOVQ_SI_X11_0() + VPINSRQ_1_SI_X15(10 * 8) + VPINSRQ_1_SI_X11(8 * 8) + VINSERTI128(Imm(1), X11, Y15, Y15) +} + +func LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() { + LOAD_MSG_AVX2_Y12(9, 5, 2, 10) + VMOVQ_SI_X13_0() + VMOVQ_SI_X11(4 * 8) + VPINSRQ_1_SI_X13(7 * 8) + VPINSRQ_1_SI_X11(15 * 8) + VINSERTI128(Imm(1), X11, Y13, Y13) + LOAD_MSG_AVX2_Y14(14, 11, 6, 3) + LOAD_MSG_AVX2_Y15(1, 12, 8, 13) +} + +func LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() { + VMOVQ_SI_X12(2 * 8) + VMOVQ_SI_X11_0() + VPINSRQ_1_SI_X12(6 * 8) + VPINSRQ_1_SI_X11(8 * 8) + VINSERTI128(Imm(1), X11, Y12, Y12) + LOAD_MSG_AVX2_Y13(12, 10, 11, 3) + LOAD_MSG_AVX2_Y14(4, 7, 15, 1) + LOAD_MSG_AVX2_Y15(13, 5, 14, 9) +} + +func LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() { + LOAD_MSG_AVX2_Y12(12, 1, 14, 4) + LOAD_MSG_AVX2_Y13(5, 15, 13, 10) + VMOVQ_SI_X14_0() + VPSHUFD(Imm(0x4E), Mem{Base: SI}.Offset(8*8), X11) + VPINSRQ_1_SI_X14(6 * 8) + VINSERTI128(Imm(1), X11, Y14, Y14) + LOAD_MSG_AVX2_Y15(7, 3, 2, 11) +} + +func LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() { + LOAD_MSG_AVX2_Y12(13, 7, 12, 3) + LOAD_MSG_AVX2_Y13(11, 14, 1, 9) + LOAD_MSG_AVX2_Y14(5, 15, 8, 2) + VMOVQ_SI_X15_0() + VMOVQ_SI_X11(6 * 8) + VPINSRQ_1_SI_X15(4 * 8) + VPINSRQ_1_SI_X11(10 * 8) + VINSERTI128(Imm(1), X11, Y15, Y15) +} + +func LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() { + VMOVQ_SI_X12(6 * 8) + VMOVQ_SI_X11(11 * 8) + VPINSRQ_1_SI_X12(14 * 8) + VPINSRQ_1_SI_X11_0() + VINSERTI128(Imm(1), X11, Y12, Y12) + LOAD_MSG_AVX2_Y13(15, 9, 3, 8) + VMOVQ_SI_X11(1 * 8) + VMOVDQU(Mem{Base: SI}.Offset(12*8), X14) + VPINSRQ_1_SI_X11(10 * 8) + VINSERTI128(Imm(1), X11, Y14, Y14) + VMOVQ_SI_X15(2 * 8) + VMOVDQU(Mem{Base: SI}.Offset(4*8), X11) + VPINSRQ_1_SI_X15(7 * 8) + VINSERTI128(Imm(1), X11, Y15, Y15) +} + +func LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() { + LOAD_MSG_AVX2_Y12(10, 8, 7, 1) + VMOVQ_SI_X13(2 * 8) + VPSHUFD(Imm(0x4E), Mem{Base: SI}.Offset(5*8), X11) + VPINSRQ_1_SI_X13(4 * 8) + VINSERTI128(Imm(1), X11, Y13, Y13) + LOAD_MSG_AVX2_Y14(15, 9, 3, 13) + VMOVQ_SI_X15(11 * 8) + VMOVQ_SI_X11(12 * 8) + VPINSRQ_1_SI_X15(14 * 8) + VPINSRQ_1_SI_X11_0() + VINSERTI128(Imm(1), X11, Y15, Y15) +} + +func hashBlocksAVX2() { + Implement("hashBlocksAVX2") + Attributes(4) + AllocLocal(320) // frame size = 288 + 32 byte alignment + + Load(Param("h"), RAX) + Load(Param("c"), RBX) + Load(Param("flag"), RCX) + Load(Param("blocks").Base(), RSI) + Load(Param("blocks").Len(), RDI) + + MOVQ(RSP, RDX) + ADDQ(I32(31), RDX) + ANDQ(I32(^31), RDX) + + MOVQ(RCX, Mem{Base: DX}.Offset(16)) + XORQ(RCX, RCX) + MOVQ(RCX, Mem{Base: DX}.Offset(24)) + + AVX2_c40 := AVX2_c40_DATA() + AVX2_c48 := AVX2_c48_DATA() + VMOVDQU(AVX2_c40, Y4) + VMOVDQU(AVX2_c48, Y5) + + VMOVDQU(Mem{Base: AX}.Offset(0), Y8) + VMOVDQU(Mem{Base: AX}.Offset(32), Y9) + AVX2_iv0 := AVX2_iv0_DATA() + AVX2_iv1 := AVX2_iv1_DATA() + VMOVDQU(AVX2_iv0, Y6) + VMOVDQU(AVX2_iv1, Y7) + + MOVQ(Mem{Base: BX}.Offset(0), R8) + MOVQ(Mem{Base: BX}.Offset(8), R9) + MOVQ(R9, Mem{Base: DX}.Offset(8)) + + loop_AVX2() + noinc_AVX2() +} + +func loop_AVX2() { + Label("loop") + ADDQ(Imm(128), R8) + MOVQ(R8, Mem{Base: DX}.Offset(0)) + CMPQ(R8, Imm(128)) + JGE(LabelRef("noinc")) + INCQ(R9) + MOVQ(R9, Mem{Base: DX}.Offset(8)) +} + +// line 312 +func noinc_AVX2() { + Label("noinc") + VMOVDQA(Y8, Y0) + VMOVDQA(Y9, Y1) + VMOVDQA(Y6, Y2) + VPXOR(Mem{Base: DX}.Offset(0), Y7, Y3) + + LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() + VMOVDQA(Y12, Mem{Base: DX}.Offset(32)) + VMOVDQA(Y13, Mem{Base: DX}.Offset(64)) + VMOVDQA(Y14, Mem{Base: DX}.Offset(96)) + VMOVDQA(Y15, Mem{Base: DX}.Offset(128)) + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() + VMOVDQA(Y12, Mem{Base: DX}.Offset(160)) + VMOVDQA(Y13, Mem{Base: DX}.Offset(192)) + VMOVDQA(Y14, Mem{Base: DX}.Offset(224)) + VMOVDQA(Y15, Mem{Base: DX}.Offset(256)) + + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + ROUND_AVX2(Mem{Base: DX}.Offset(32), Mem{Base: DX}.Offset(64), Mem{Base: DX}.Offset(96), Mem{Base: DX}.Offset(128), Y10, Y4, Y5) + ROUND_AVX2(Mem{Base: DX}.Offset(160), Mem{Base: DX}.Offset(192), Mem{Base: DX}.Offset(224), Mem{Base: DX}.Offset(256), Y10, Y4, Y5) + + VPXOR(Y0, Y8, Y8) + VPXOR(Y1, Y9, Y9) + VPXOR(Y2, Y8, Y8) + VPXOR(Y3, Y9, Y9) + + LEAQ(Mem{Base: SI}.Offset(128), RSI) + SUBQ(Imm(128), RDI) + JNE(LabelRef("loop")) + + MOVQ(R8, Mem{Base: BX}.Offset(0)) + MOVQ(R9, Mem{Base: BX}.Offset(8)) + + VMOVDQU(Y8, Mem{Base: AX}.Offset(0)) + VMOVDQU(Y9, Mem{Base: AX}.Offset(32)) + VZEROUPPER() + + RET() +} + +func VPUNPCKLQDQ_X2_X2_X15() { + BYTE(U8(0xC5)) + BYTE(U8(0x69)) + BYTE(U8(0x6C)) + BYTE(U8(0xFA)) +} + +func VPUNPCKLQDQ_X3_X3_X15() { + BYTE(U8(0xC5)) + BYTE(U8(0x61)) + BYTE(U8(0x6C)) + BYTE(U8(0xFB)) +} + +func VPUNPCKLQDQ_X7_X7_X15() { + BYTE(U8(0xC5)) + BYTE(U8(0x41)) + BYTE(U8(0x6C)) + BYTE(U8(0xFF)) +} + +func VPUNPCKLQDQ_X13_X13_X15() { + BYTE(U8(0xC4)) + BYTE(U8(0x41)) + BYTE(U8(0x11)) + BYTE(U8(0x6C)) + BYTE(U8(0xFD)) +} + +func VPUNPCKLQDQ_X14_X14_X15() { + BYTE(U8(0xC4)) + BYTE(U8(0x41)) + BYTE(U8(0x09)) + BYTE(U8(0x6C)) + BYTE(U8(0xFE)) +} + +func VPUNPCKHQDQ_X15_X2_X2() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x69)) + BYTE(U8(0x6D)) + BYTE(U8(0xD7)) +} + +func VPUNPCKHQDQ_X15_X3_X3() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x61)) + BYTE(U8(0x6D)) + BYTE(U8(0xDF)) +} + +func VPUNPCKHQDQ_X15_X6_X6() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x49)) + BYTE(U8(0x6D)) + BYTE(U8(0xF7)) +} + +func VPUNPCKHQDQ_X15_X7_X7() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x41)) + BYTE(U8(0x6D)) + BYTE(U8(0xFF)) +} + +func VPUNPCKHQDQ_X15_X3_X2() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x61)) + BYTE(U8(0x6D)) + BYTE(U8(0xD7)) +} + +func VPUNPCKHQDQ_X15_X7_X6() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x41)) + BYTE(U8(0x6D)) + BYTE(U8(0xF7)) +} + +func VPUNPCKHQDQ_X15_X13_X3() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x11)) + BYTE(U8(0x6D)) + BYTE(U8(0xDF)) +} + +func VPUNPCKHQDQ_X15_X13_X7() { + BYTE(U8(0xC4)) + BYTE(U8(0xC1)) + BYTE(U8(0x11)) + BYTE(U8(0x6D)) + BYTE(U8(0xFF)) +} + +func SHUFFLE_AVX() { + VMOVDQA(X6, X13) + VMOVDQA(X2, X14) + VMOVDQA(X4, X6) + VPUNPCKLQDQ_X13_X13_X15() + VMOVDQA(X5, X4) + VMOVDQA(X6, X5) + VPUNPCKHQDQ_X15_X7_X6() + VPUNPCKLQDQ_X7_X7_X15() + VPUNPCKHQDQ_X15_X13_X7() + VPUNPCKLQDQ_X3_X3_X15() + VPUNPCKHQDQ_X15_X2_X2() + VPUNPCKLQDQ_X14_X14_X15() + VPUNPCKHQDQ_X15_X3_X3() +} + +func SHUFFLE_AVX_INV() { + VMOVDQA(X2, X13) + VMOVDQA(X4, X14) + VPUNPCKLQDQ_X2_X2_X15() + VMOVDQA(X5, X4) + VPUNPCKHQDQ_X15_X3_X2() + VMOVDQA(X14, X5) + VPUNPCKLQDQ_X3_X3_X15() + VMOVDQA(X6, X14) + VPUNPCKHQDQ_X15_X13_X3() + VPUNPCKLQDQ_X7_X7_X15() + VPUNPCKHQDQ_X15_X6_X6() + VPUNPCKLQDQ_X14_X14_X15() + VPUNPCKHQDQ_X15_X7_X7() +} + +func HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7 VecPhysical, m0, m1, m2, m3 Op, t0, c40, c48 VecPhysical) { + VPADDQ(m0, v0, v0) + VPADDQ(v2, v0, v0) + VPADDQ(m1, v1, v1) + VPADDQ(v3, v1, v1) + VPXOR(v0, v6, v6) + VPXOR(v1, v7, v7) + VPSHUFD(I8(-79), v6, v6) + VPSHUFD(I8(-79), v7, v7) + VPADDQ(v6, v4, v4) + VPADDQ(v7, v5, v5) + VPXOR(v4, v2, v2) + VPXOR(v5, v3, v3) + VPSHUFB(c40, v2, v2) + VPSHUFB(c40, v3, v3) + VPADDQ(m2, v0, v0) + VPADDQ(v2, v0, v0) + VPADDQ(m3, v1, v1) + VPADDQ(v3, v1, v1) + VPXOR(v0, v6, v6) + VPXOR(v1, v7, v7) + VPSHUFB(c48, v6, v6) + VPSHUFB(c48, v7, v7) + VPADDQ(v6, v4, v4) + VPADDQ(v7, v5, v5) + VPXOR(v4, v2, v2) + VPXOR(v5, v3, v3) + VPADDQ(v2, v2, t0) + VPSRLQ(Imm(63), v2, v2) + VPXOR(t0, v2, v2) + VPADDQ(v3, v3, t0) + VPSRLQ(Imm(63), v3, v3) + VPXOR(t0, v3, v3) +} + +// load msg: +// +// X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) +// +// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 +func LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7 uint8) { + VMOVQ_SI_X12(i0 * 8) + VMOVQ_SI_X13(i2 * 8) + VMOVQ_SI_X14(i4 * 8) + VMOVQ_SI_X15(i6 * 8) + VPINSRQ_1_SI_X12(i1 * 8) + VPINSRQ_1_SI_X13(i3 * 8) + VPINSRQ_1_SI_X14(i5 * 8) + VPINSRQ_1_SI_X15(i7 * 8) +} + +// load msg: +// +// X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) +func LOAD_MSG_AVX_0_2_4_6_1_3_5_7() { + VMOVQ_SI_X12_0() + VMOVQ_SI_X13(4 * 8) + VMOVQ_SI_X14(1 * 8) + VMOVQ_SI_X15(5 * 8) + VPINSRQ_1_SI_X12(2 * 8) + VPINSRQ_1_SI_X13(6 * 8) + VPINSRQ_1_SI_X14(3 * 8) + VPINSRQ_1_SI_X15(7 * 8) +} + +// load msg: +// +// X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) +func LOAD_MSG_AVX_1_0_11_5_12_2_7_3() { + VPSHUFD(Imm(0x4E), Mem{Base: SI}.Offset(0*8), X12) + VMOVQ_SI_X13(11 * 8) + VMOVQ_SI_X14(12 * 8) + VMOVQ_SI_X15(7 * 8) + VPINSRQ_1_SI_X13(5 * 8) + VPINSRQ_1_SI_X14(2 * 8) + VPINSRQ_1_SI_X15(3 * 8) +} + +// load msg: +// +// X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) +func LOAD_MSG_AVX_11_12_5_15_8_0_2_13() { + VMOVDQU(Mem{Base: SI}.Offset(11*8), X12) + VMOVQ_SI_X13(5 * 8) + VMOVQ_SI_X14(8 * 8) + VMOVQ_SI_X15(2 * 8) + VPINSRQ_1_SI_X13(15 * 8) + VPINSRQ_1_SI_X14_0() + VPINSRQ_1_SI_X15(13 * 8) +} + +// load msg: +// +// X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) +func LOAD_MSG_AVX_2_5_4_15_6_10_0_8() { + VMOVQ_SI_X12(2 * 8) + VMOVQ_SI_X13(4 * 8) + VMOVQ_SI_X14(6 * 8) + VMOVQ_SI_X15_0() + VPINSRQ_1_SI_X12(5 * 8) + VPINSRQ_1_SI_X13(15 * 8) + VPINSRQ_1_SI_X14(10 * 8) + VPINSRQ_1_SI_X15(8 * 8) +} + +// load msg: +// +// X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) +func LOAD_MSG_AVX_9_5_2_10_0_7_4_15() { + VMOVQ_SI_X12(9 * 8) + VMOVQ_SI_X13(2 * 8) + VMOVQ_SI_X14_0() + VMOVQ_SI_X15(4 * 8) + VPINSRQ_1_SI_X12(5 * 8) + VPINSRQ_1_SI_X13(10 * 8) + VPINSRQ_1_SI_X14(7 * 8) + VPINSRQ_1_SI_X15(15 * 8) +} + +// load msg: +// +// X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) +func LOAD_MSG_AVX_2_6_0_8_12_10_11_3() { + VMOVQ_SI_X12(2 * 8) + VMOVQ_SI_X13_0() + VMOVQ_SI_X14(12 * 8) + VMOVQ_SI_X15(11 * 8) + VPINSRQ_1_SI_X12(6 * 8) + VPINSRQ_1_SI_X13(8 * 8) + VPINSRQ_1_SI_X14(10 * 8) + VPINSRQ_1_SI_X15(3 * 8) +} + +// load msg: +// +// X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) +func LOAD_MSG_AVX_0_6_9_8_7_3_2_11() { + MOVQ(Mem{Base: SI}.Offset(0*8), X12) + VPSHUFD(Imm(0x4E), Mem{Base: SI}.Offset(8*8), X13) + MOVQ(Mem{Base: SI}.Offset(7*8), X14) + MOVQ(Mem{Base: SI}.Offset(2*8), X15) + VPINSRQ_1_SI_X12(6 * 8) + VPINSRQ_1_SI_X14(3 * 8) + VPINSRQ_1_SI_X15(11 * 8) +} + +// load msg: +// +// X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) +func LOAD_MSG_AVX_6_14_11_0_15_9_3_8() { + MOVQ(Mem{Base: SI}.Offset(6*8), X12) + MOVQ(Mem{Base: SI}.Offset(11*8), X13) + MOVQ(Mem{Base: SI}.Offset(15*8), X14) + MOVQ(Mem{Base: SI}.Offset(3*8), X15) + VPINSRQ_1_SI_X12(14 * 8) + VPINSRQ_1_SI_X13_0() + VPINSRQ_1_SI_X14(9 * 8) + VPINSRQ_1_SI_X15(8 * 8) +} + +// load msg: +// +// X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) +func LOAD_MSG_AVX_5_15_8_2_0_4_6_10() { + MOVQ(Mem{Base: SI}.Offset(5*8), X12) + MOVQ(Mem{Base: SI}.Offset(8*8), X13) + MOVQ(Mem{Base: SI}.Offset(0*8), X14) + MOVQ(Mem{Base: SI}.Offset(6*8), X15) + VPINSRQ_1_SI_X12(15 * 8) + VPINSRQ_1_SI_X13(2 * 8) + VPINSRQ_1_SI_X14(4 * 8) + VPINSRQ_1_SI_X15(10 * 8) +} + +// load msg: +// +// X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) +func LOAD_MSG_AVX_12_13_1_10_2_7_4_5() { + VMOVDQU(Mem{Base: SI}.Offset(12*8), X12) + MOVQ(Mem{Base: SI}.Offset(1*8), X13) + MOVQ(Mem{Base: SI}.Offset(2*8), X14) + VPINSRQ_1_SI_X13(10 * 8) + VPINSRQ_1_SI_X14(7 * 8) + VMOVDQU(Mem{Base: SI}.Offset(4*8), X15) +} + +// load msg: +// +// X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) +func LOAD_MSG_AVX_15_9_3_13_11_14_12_0() { + MOVQ(Mem{Base: SI}.Offset(15*8), X12) + MOVQ(Mem{Base: SI}.Offset(3*8), X13) + MOVQ(Mem{Base: SI}.Offset(11*8), X14) + MOVQ(Mem{Base: SI}.Offset(12*8), X15) + VPINSRQ_1_SI_X12(9 * 8) + VPINSRQ_1_SI_X13(13 * 8) + VPINSRQ_1_SI_X14(14 * 8) + VPINSRQ_1_SI_X15_0() +} + +func hashBlocksAVX() { + Implement("hashBlocksAVX") + Attributes(4) + AllocLocal(288) // frame size = 272 + 16 byte alignment + + Load(Param("h"), RAX) + Load(Param("c"), RBX) + Load(Param("flag"), RCX) + Load(Param("blocks").Base(), RSI) + Load(Param("blocks").Len(), RDI) + + MOVQ(RSP, R10) + ADDQ(Imm(15), R10) + ANDQ(I32(^15), R10) + + AVX_c40 := AVX_c40_DATA() + AVX_c48 := AVX_c48_DATA() + VMOVDQU(AVX_c40, X0) + VMOVDQU(AVX_c48, X1) + VMOVDQA(X0, X8) + VMOVDQA(X1, X9) + + AVX_iv3 := AVX_iv3_DATA() + VMOVDQU(AVX_iv3, X0) + VMOVDQA(X0, Mem{Base: R10}.Offset(0)) + XORQ(RCX, Mem{Base: R10}.Offset(0)) // 0(R10) = ·AVX_iv3 ^ (CX || 0) + + VMOVDQU(Mem{Base: AX}.Offset(0), X10) + VMOVDQU(Mem{Base: AX}.Offset(16), X11) + VMOVDQU(Mem{Base: AX}.Offset(32), X2) + VMOVDQU(Mem{Base: AX}.Offset(48), X3) + + MOVQ(Mem{Base: BX}.Offset(0), R8) + MOVQ(Mem{Base: BX}.Offset(8), R9) + + loop_AVX() + noinc_AVX() +} + +func loop_AVX() { + Label("loop") + ADDQ(Imm(128), R8) + CMPQ(R8, Imm(128)) + JGE(LabelRef("noinc")) + INCQ(R9) +} + +func noinc_AVX() { + Label("noinc") + VMOVQ_R8_X15() + VPINSRQ_1_R9_X15() + + AVX_iv0 := AVX_iv0_DATA() + AVX_iv1 := AVX_iv1_DATA() + AVX_iv2 := AVX_iv2_DATA() + VMOVDQA(X10, X0) + VMOVDQA(X11, X1) + VMOVDQU(AVX_iv0, X4) + VMOVDQU(AVX_iv1, X5) + VMOVDQU(AVX_iv2, X6) + + VPXOR(X15, X6, X6) + VMOVDQA(Mem{Base: R10}.Offset(0), X7) + + LOAD_MSG_AVX_0_2_4_6_1_3_5_7() + VMOVDQA(X12, Mem{Base: R10}.Offset(16)) + VMOVDQA(X13, Mem{Base: R10}.Offset(32)) + VMOVDQA(X14, Mem{Base: R10}.Offset(48)) + VMOVDQA(X15, Mem{Base: R10}.Offset(64)) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) + VMOVDQA(X12, Mem{Base: R10}.Offset(80)) + VMOVDQA(X13, Mem{Base: R10}.Offset(96)) + VMOVDQA(X14, Mem{Base: R10}.Offset(112)) + VMOVDQA(X15, Mem{Base: R10}.Offset(128)) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) + VMOVDQA(X12, Mem{Base: R10}.Offset(144)) + VMOVDQA(X13, Mem{Base: R10}.Offset(160)) + VMOVDQA(X14, Mem{Base: R10}.Offset(176)) + VMOVDQA(X15, Mem{Base: R10}.Offset(192)) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_1_0_11_5_12_2_7_3() + VMOVDQA(X12, Mem{Base: R10}.Offset(208)) + VMOVDQA(X13, Mem{Base: R10}.Offset(224)) + VMOVDQA(X14, Mem{Base: R10}.Offset(240)) + VMOVDQA(X15, Mem{Base: R10}.Offset(256)) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_11_12_5_15_8_0_2_13() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_2_5_4_15_6_10_0_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_9_5_2_10_0_7_4_15() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_2_6_0_8_12_10_11_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_0_6_9_8_7_3_2_11() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_5_15_8_2_0_4_6_10() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_6_14_11_0_15_9_3_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_12_13_1_10_2_7_4_5() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_15_9_3_13_11_14_12_0() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(16), Mem{Base: R10}.Offset(32), Mem{Base: R10}.Offset(48), Mem{Base: R10}.Offset(64), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(80), Mem{Base: R10}.Offset(96), Mem{Base: R10}.Offset(112), Mem{Base: R10}.Offset(128), X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(144), Mem{Base: R10}.Offset(160), Mem{Base: R10}.Offset(176), Mem{Base: R10}.Offset(192), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(208), Mem{Base: R10}.Offset(224), Mem{Base: R10}.Offset(240), Mem{Base: R10}.Offset(256), X15, X8, X9) + SHUFFLE_AVX_INV() + + VMOVDQU(Mem{Base: AX}.Offset(32), X14) + VMOVDQU(Mem{Base: AX}.Offset(48), X15) + VPXOR(X0, X10, X10) + VPXOR(X1, X11, X11) + VPXOR(X2, X14, X14) + VPXOR(X3, X15, X15) + VPXOR(X4, X10, X10) + VPXOR(X5, X11, X11) + VPXOR(X6, X14, X2) + VPXOR(X7, X15, X3) + VMOVDQU(X2, Mem{Base: AX}.Offset(32)) + VMOVDQU(X3, Mem{Base: AX}.Offset(48)) + + LEAQ(Mem{Base: SI}.Offset(128), RSI) + SUBQ(Imm(128), RDI) + JNE(LabelRef("loop")) + + VMOVDQU(X10, Mem{Base: AX}.Offset(0)) + VMOVDQU(X11, Mem{Base: AX}.Offset(16)) + + MOVQ(R8, Mem{Base: BX}.Offset(0)) + MOVQ(R9, Mem{Base: BX}.Offset(8)) + VZEROUPPER() + + RET() +} + +// ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATA SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~## + +var ( + AVX2_iv0_ptr, + AVX2_iv1_ptr, + AVX2_c40_ptr, + AVX2_c48_ptr, + + AVX_iv0_ptr, + AVX_iv1_ptr, + AVX_iv2_ptr, + AVX_iv3_ptr, + AVX_c40_ptr, + AVX_c48_ptr *Mem +) + +func AVX2_iv0_DATA() Mem { + if AVX2_iv0_ptr != nil { + return *AVX2_iv0_ptr + } + AVX2_iv0 := GLOBL(ThatPeskyUnicodeDot+"AVX2_iv0", NOPTR|RODATA) + DATA(0x00, U64(0x6a09e667f3bcc908)) + DATA(0x08, U64(0xbb67ae8584caa73b)) + DATA(0x10, U64(0x3c6ef372fe94f82b)) + DATA(0x18, U64(0xa54ff53a5f1d36f1)) + return AVX2_iv0 +} + +func AVX2_iv1_DATA() Mem { + if AVX2_iv1_ptr != nil { + return *AVX2_iv1_ptr + } + AVX2_iv1 := GLOBL(ThatPeskyUnicodeDot+"AVX2_iv1", NOPTR|RODATA) + DATA(0x00, U64(0x510e527fade682d1)) + DATA(0x08, U64(0x9b05688c2b3e6c1f)) + DATA(0x10, U64(0x1f83d9abfb41bd6b)) + DATA(0x18, U64(0x5be0cd19137e2179)) + return AVX2_iv1 +} + +func AVX2_c40_DATA() Mem { + if AVX2_c40_ptr != nil { + return *AVX2_c40_ptr + } + AVX2_c40 := GLOBL(ThatPeskyUnicodeDot+"AVX2_c40", NOPTR|RODATA) + DATA(0x00, U64(0x0201000706050403)) + DATA(0x08, U64(0x0a09080f0e0d0c0b)) + DATA(0x10, U64(0x0201000706050403)) + DATA(0x18, U64(0x0a09080f0e0d0c0b)) + return AVX2_c40 +} + +func AVX2_c48_DATA() Mem { + if AVX2_c48_ptr != nil { + return *AVX2_c48_ptr + } + AVX2_c48 := GLOBL(ThatPeskyUnicodeDot+"AVX2_c48", NOPTR|RODATA) + DATA(0x00, U64(0x0100070605040302)) + DATA(0x08, U64(0x09080f0e0d0c0b0a)) + DATA(0x10, U64(0x0100070605040302)) + DATA(0x18, U64(0x09080f0e0d0c0b0a)) + return AVX2_c48 +} + +func AVX_iv0_DATA() Mem { + if AVX_iv0_ptr != nil { + return *AVX_iv0_ptr + } + AVX_iv0 := GLOBL(ThatPeskyUnicodeDot+"AVX_iv0", NOPTR|RODATA) + DATA(0x00, U64(0x6a09e667f3bcc908)) + DATA(0x08, U64(0xbb67ae8584caa73b)) + return AVX_iv0 +} + +func AVX_iv1_DATA() Mem { + if AVX_iv1_ptr != nil { + return *AVX_iv1_ptr + } + AVX_iv1 := GLOBL(ThatPeskyUnicodeDot+"AVX_iv1", NOPTR|RODATA) + DATA(0x00, U64(0x3c6ef372fe94f82b)) + DATA(0x08, U64(0xa54ff53a5f1d36f1)) + return AVX_iv1 +} + +func AVX_iv2_DATA() Mem { + if AVX_iv2_ptr != nil { + return *AVX_iv2_ptr + } + AVX_iv2 := GLOBL(ThatPeskyUnicodeDot+"AVX_iv2", NOPTR|RODATA) + DATA(0x00, U64(0x510e527fade682d1)) + DATA(0x08, U64(0x9b05688c2b3e6c1f)) + return AVX_iv2 +} + +func AVX_iv3_DATA() Mem { + if AVX_iv3_ptr != nil { + return *AVX_iv3_ptr + } + AVX_iv3 := GLOBL(ThatPeskyUnicodeDot+"AVX_iv3", NOPTR|RODATA) + DATA(0x00, U64(0x1f83d9abfb41bd6b)) + DATA(0x08, U64(0x5be0cd19137e2179)) + return AVX_iv3 +} + +func AVX_c40_DATA() Mem { + if AVX_c40_ptr != nil { + return *AVX_c40_ptr + } + AVX_c40 := GLOBL(ThatPeskyUnicodeDot+"AVX_c40", NOPTR|RODATA) + DATA(0x00, U64(0x0201000706050403)) + DATA(0x08, U64(0x0a09080f0e0d0c0b)) + return AVX_c40 +} + +func AVX_c48_DATA() Mem { + if AVX_c48_ptr != nil { + return *AVX_c48_ptr + } + AVX_c48 := GLOBL(ThatPeskyUnicodeDot+"AVX_c48", NOPTR|RODATA) + DATA(0x00, U64(0x0100070605040302)) + DATA(0x08, U64(0x09080f0e0d0c0b0a)) + return AVX_c48 +} diff --git a/blake2b/_asm/AVX2/go.mod b/blake2b/_asm/AVX2/go.mod new file mode 100644 index 0000000000..78f9070a41 --- /dev/null +++ b/blake2b/_asm/AVX2/go.mod @@ -0,0 +1,16 @@ +module blake2b/_asm/AVX2 + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 + +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/blake2b/_asm/AVX2/go.sum b/blake2b/_asm/AVX2/go.sum new file mode 100644 index 0000000000..39dd154050 --- /dev/null +++ b/blake2b/_asm/AVX2/go.sum @@ -0,0 +1,12 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/blake2b/_asm/standard/blake2b_amd64_asm.go b/blake2b/_asm/standard/blake2b_amd64_asm.go new file mode 100644 index 0000000000..a34db3fca5 --- /dev/null +++ b/blake2b/_asm/standard/blake2b_amd64_asm.go @@ -0,0 +1,361 @@ +// Copyright 2024 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 main + +import ( + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/blake2b" +) + +//go:generate go run . -out ../../blake2b_amd64.s -pkg blake2b + +const ThatPeskyUnicodeDot = "\u00b7" + +var iv0_DATA_ptr, iv1_DATA_ptr, iv2_DATA_ptr, iv3_DATA_ptr, c40_DATA_ptr, c48_DATA_ptr *Mem + +func main() { + Package("golang.org/x/crypto/blake2b") + ConstraintExpr("amd64,gc,!purego") + hashBlocksSSE4() + Generate() +} + +func SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { + MOVO(v4, t1) + MOVO(v5, v4) + MOVO(t1, v5) + MOVO(v6, t1) + PUNPCKLQDQ(v6, t2) + PUNPCKHQDQ(v7, v6) + PUNPCKHQDQ(t2, v6) + PUNPCKLQDQ(v7, t2) + MOVO(t1, v7) + MOVO(v2, t1) + PUNPCKHQDQ(t2, v7) + PUNPCKLQDQ(v3, t2) + PUNPCKHQDQ(t2, v2) + PUNPCKLQDQ(t1, t2) + PUNPCKHQDQ(t2, v3) +} + +func SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { + MOVO(v4, t1) + MOVO(v5, v4) + MOVO(t1, v5) + MOVO(v2, t1) + PUNPCKLQDQ(v2, t2) + PUNPCKHQDQ(v3, v2) + PUNPCKHQDQ(t2, v2) + PUNPCKLQDQ(v3, t2) + MOVO(t1, v3) + MOVO(v6, t1) + PUNPCKHQDQ(t2, v3) + PUNPCKLQDQ(v7, t2) + PUNPCKHQDQ(t2, v6) + PUNPCKLQDQ(t1, t2) + PUNPCKHQDQ(t2, v7) +} + +func HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7 VecPhysical, m0, m1, m2, m3 Op, t0, c40, c48 VecPhysical) { + PADDQ(m0, v0) + PADDQ(m1, v1) + PADDQ(v2, v0) + PADDQ(v3, v1) + PXOR(v0, v6) + PXOR(v1, v7) + PSHUFD(Imm(0xB1), v6, v6) + PSHUFD(Imm(0xB1), v7, v7) + PADDQ(v6, v4) + PADDQ(v7, v5) + PXOR(v4, v2) + PXOR(v5, v3) + PSHUFB(c40, v2) + PSHUFB(c40, v3) + PADDQ(m2, v0) + PADDQ(m3, v1) + PADDQ(v2, v0) + PADDQ(v3, v1) + PXOR(v0, v6) + PXOR(v1, v7) + PSHUFB(c48, v6) + PSHUFB(c48, v7) + PADDQ(v6, v4) + PADDQ(v7, v5) + PXOR(v4, v2) + PXOR(v5, v3) + MOVOU(v2, t0) + PADDQ(v2, t0) + PSRLQ(Imm(63), v2) + PXOR(t0, v2) + MOVOU(v3, t0) + PADDQ(v3, t0) + PSRLQ(Imm(63), v3) + PXOR(t0, v3) +} + +func LOAD_MSG(m0, m1, m2, m3 VecPhysical, src GPPhysical, i0, i1, i2, i3, i4, i5, i6, i7 int) { + MOVQ(Mem{Base: src}.Offset(i0*8), m0) + PINSRQ(Imm(1), Mem{Base: src}.Offset(i1*8), m0) + MOVQ(Mem{Base: src}.Offset(i2*8), m1) + PINSRQ(Imm(1), Mem{Base: src}.Offset(i3*8), m1) + MOVQ(Mem{Base: src}.Offset(i4*8), m2) + PINSRQ(Imm(1), Mem{Base: src}.Offset(i5*8), m2) + MOVQ(Mem{Base: src}.Offset(i6*8), m3) + PINSRQ(Imm(1), Mem{Base: src}.Offset(i7*8), m3) +} + +func hashBlocksSSE4() { + Implement("hashBlocksSSE4") + Attributes(4) + AllocLocal(288) // frame size = 272 + 16 byte alignment + + Load(Param("h"), RAX) + Load(Param("c"), RBX) + Load(Param("flag"), RCX) + Load(Param("blocks").Base(), RSI) + Load(Param("blocks").Len(), RDI) + + MOVQ(RSP, R10) + ADDQ(Imm(15), R10) + ANDQ(I32(-16), R10) + + iv3 := iv3_DATA() + MOVOU(iv3, X0) + MOVO(X0, Mem{Base: R10}.Offset(0)) + XORQ(RCX, Mem{Base: R10}.Offset(0)) // 0(R10) = ·iv3 ^ (CX || 0) + + c40 := c40_DATA() + c48 := c48_DATA() + MOVOU(c40, X13) + MOVOU(c48, X14) + + MOVOU(Mem{Base: AX}.Offset(0), X12) + MOVOU(Mem{Base: AX}.Offset(16), X15) + + MOVQ(Mem{Base: BX}.Offset(0), R8) + MOVQ(Mem{Base: BX}.Offset(8), R9) + + Label("loop") + ADDQ(Imm(128), R8) + CMPQ(R8, Imm(128)) + JGE(LabelRef("noinc")) + INCQ(R9) + + Label("noinc") + MOVQ(R8, X8) + PINSRQ(Imm(1), R9, X8) + + iv0 := iv0_DATA() + iv1 := iv1_DATA() + iv2 := iv2_DATA() + + MOVO(X12, X0) + MOVO(X15, X1) + MOVOU(Mem{Base: AX}.Offset(32), X2) + MOVOU(Mem{Base: AX}.Offset(48), X3) + MOVOU(iv0, X4) + MOVOU(iv1, X5) + MOVOU(iv2, X6) + + PXOR(X8, X6) + MOVO(Mem{Base: R10}.Offset(0), X7) + + LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) + MOVO(X8, Mem{Base: R10}.Offset(16)) + MOVO(X9, Mem{Base: R10}.Offset(32)) + MOVO(X10, Mem{Base: R10}.Offset(48)) + MOVO(X11, Mem{Base: R10}.Offset(64)) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) + MOVO(X8, Mem{Base: R10}.Offset(80)) + MOVO(X9, Mem{Base: R10}.Offset(96)) + MOVO(X10, Mem{Base: R10}.Offset(112)) + MOVO(X11, Mem{Base: R10}.Offset(128)) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) + MOVO(X8, Mem{Base: R10}.Offset(144)) + MOVO(X9, Mem{Base: R10}.Offset(160)) + MOVO(X10, Mem{Base: R10}.Offset(176)) + MOVO(X11, Mem{Base: R10}.Offset(192)) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) + MOVO(X8, Mem{Base: R10}.Offset(208)) + MOVO(X9, Mem{Base: R10}.Offset(224)) + MOVO(X10, Mem{Base: R10}.Offset(240)) + MOVO(X11, Mem{Base: R10}.Offset(256)) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(16), Mem{Base: R10}.Offset(32), Mem{Base: R10}.Offset(48), Mem{Base: R10}.Offset(64), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(80), Mem{Base: R10}.Offset(96), Mem{Base: R10}.Offset(112), Mem{Base: R10}.Offset(128), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(144), Mem{Base: R10}.Offset(160), Mem{Base: R10}.Offset(176), Mem{Base: R10}.Offset(192), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(208), Mem{Base: R10}.Offset(224), Mem{Base: R10}.Offset(240), Mem{Base: R10}.Offset(256), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + MOVOU(Mem{Base: AX}.Offset(32), X10) + MOVOU(Mem{Base: AX}.Offset(48), X11) + PXOR(X0, X12) + PXOR(X1, X15) + PXOR(X2, X10) + PXOR(X3, X11) + PXOR(X4, X12) + PXOR(X5, X15) + PXOR(X6, X10) + PXOR(X7, X11) + MOVOU(X10, Mem{Base: AX}.Offset(32)) + MOVOU(X11, Mem{Base: AX}.Offset(48)) + + LEAQ(Mem{Base: SI}.Offset(128), RSI) + SUBQ(Imm(128), RDI) + JNE(LabelRef("loop")) + + MOVOU(X12, Mem{Base: AX}.Offset(0)) + MOVOU(X15, Mem{Base: AX}.Offset(16)) + + MOVQ(R8, Mem{Base: BX}.Offset(0)) + MOVQ(R9, Mem{Base: BX}.Offset(8)) + + RET() +} + +// #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATA SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~## + +func iv0_DATA() Mem { + if iv0_DATA_ptr != nil { + return *iv0_DATA_ptr + } + + iv0 := GLOBL(ThatPeskyUnicodeDot+"iv0", NOPTR|RODATA) + iv0_DATA_ptr = &iv0 + DATA(0x00, U64(0x6a09e667f3bcc908)) + DATA(0x08, U64(0xbb67ae8584caa73b)) + return iv0 +} + +func iv1_DATA() Mem { + if iv1_DATA_ptr != nil { + return *iv1_DATA_ptr + } + + iv1 := GLOBL(ThatPeskyUnicodeDot+"iv1", NOPTR|RODATA) + iv1_DATA_ptr = &iv1 + DATA(0x00, U64(0x3c6ef372fe94f82b)) + DATA(0x08, U64(0xa54ff53a5f1d36f1)) + return iv1 +} + +func iv2_DATA() Mem { + if iv2_DATA_ptr != nil { + return *iv2_DATA_ptr + } + + iv2 := GLOBL(ThatPeskyUnicodeDot+"iv2", NOPTR|RODATA) + iv2_DATA_ptr = &iv2 + DATA(0x00, U64(0x510e527fade682d1)) + DATA(0x08, U64(0x9b05688c2b3e6c1f)) + return iv2 +} + +func iv3_DATA() Mem { + if iv3_DATA_ptr != nil { + return *iv3_DATA_ptr + } + + iv3 := GLOBL(ThatPeskyUnicodeDot+"iv3", NOPTR|RODATA) + iv3_DATA_ptr = &iv3 + DATA(0x00, U64(0x1f83d9abfb41bd6b)) + DATA(0x08, U64(0x5be0cd19137e2179)) + return iv3 +} + +func c40_DATA() Mem { + if c40_DATA_ptr != nil { + return *c40_DATA_ptr + } + + c40 := GLOBL(ThatPeskyUnicodeDot+"c40", NOPTR|RODATA) + c40_DATA_ptr = &c40 + DATA(0x00, U64(0x0201000706050403)) + DATA(0x08, U64(0x0a09080f0e0d0c0b)) + return c40 +} + +func c48_DATA() Mem { + if c48_DATA_ptr != nil { + return *c48_DATA_ptr + } + + c48 := GLOBL(ThatPeskyUnicodeDot+"c48", NOPTR|RODATA) + c48_DATA_ptr = &c48 + DATA(0x00, U64(0x0100070605040302)) + DATA(0x08, U64(0x09080f0e0d0c0b0a)) + return c48 +} diff --git a/blake2b/_asm/standard/go.mod b/blake2b/_asm/standard/go.mod new file mode 100644 index 0000000000..a0c60b9e24 --- /dev/null +++ b/blake2b/_asm/standard/go.mod @@ -0,0 +1,15 @@ +module blake2b/_asm + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/blake2b/_asm/standard/go.sum b/blake2b/_asm/standard/go.sum new file mode 100644 index 0000000000..39dd154050 --- /dev/null +++ b/blake2b/_asm/standard/go.sum @@ -0,0 +1,12 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/blake2b/blake2b.go b/blake2b/blake2b.go index c160e1a4e3..d2e98d4295 100644 --- a/blake2b/blake2b.go +++ b/blake2b/blake2b.go @@ -5,6 +5,8 @@ // Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 // and the extendable output function (XOF) BLAKE2Xb. // +// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and +// produces digests of any size between 1 and 64 bytes. // For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf // and for BLAKE2Xb see https://blake2.net/blake2x.pdf // diff --git a/blake2b/blake2bAVX2_amd64.go b/blake2b/blake2bAVX2_amd64.go index 4d31dd0fdc..199c21d27a 100644 --- a/blake2b/blake2bAVX2_amd64.go +++ b/blake2b/blake2bAVX2_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.7,amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego package blake2b diff --git a/blake2b/blake2bAVX2_amd64.s b/blake2b/blake2bAVX2_amd64.s index 5593b1b3dc..f75162e039 100644 --- a/blake2b/blake2bAVX2_amd64.s +++ b/blake2b/blake2bAVX2_amd64.s @@ -1,727 +1,4517 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run blake2bAVX2_amd64_asm.go -out ../../blake2bAVX2_amd64.s -pkg blake2b. DO NOT EDIT. -// +build go1.7,amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego #include "textflag.h" -DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b -DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 -GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 -DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b -DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 -GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 -DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 -DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 -DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 - -#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 -#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 -#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e -#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 -#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 - -#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ - VPADDQ m0, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFD $-79, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPSHUFB c40, Y1, Y1; \ - VPADDQ m1, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFB c48, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPADDQ Y1, Y1, t; \ - VPSRLQ $63, Y1, Y1; \ - VPXOR t, Y1, Y1; \ - VPERMQ_0x39_Y1_Y1; \ - VPERMQ_0x4E_Y2_Y2; \ - VPERMQ_0x93_Y3_Y3; \ - VPADDQ m2, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFD $-79, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPSHUFB c40, Y1, Y1; \ - VPADDQ m3, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFB c48, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPADDQ Y1, Y1, t; \ - VPSRLQ $63, Y1, Y1; \ - VPXOR t, Y1, Y1; \ - VPERMQ_0x39_Y3_Y3; \ - VPERMQ_0x4E_Y2_Y2; \ - VPERMQ_0x93_Y1_Y1 - -#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E -#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 -#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E -#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 -#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E - -#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n -#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n -#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n -#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n -#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n - -#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 -#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 -#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 -#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 -#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 - -#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 - -#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 -#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 - -// load msg: Y12 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ - VMOVQ_SI_X12(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X12(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y12, Y12 - -// load msg: Y13 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ - VMOVQ_SI_X13(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X13(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y13, Y13 - -// load msg: Y14 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ - VMOVQ_SI_X14(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X14(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y14, Y14 - -// load msg: Y15 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ - VMOVQ_SI_X15(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X15(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ - VMOVQ_SI_X12_0; \ - VMOVQ_SI_X11(4*8); \ - VPINSRQ_1_SI_X12(2*8); \ - VPINSRQ_1_SI_X11(6*8); \ - VINSERTI128 $1, X11, Y12, Y12; \ - LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ - LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ - LOAD_MSG_AVX2_Y15(9, 11, 13, 15) - -#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ - LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ - LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ - VMOVQ_SI_X11(11*8); \ - VPSHUFD $0x4E, 0*8(SI), X14; \ - VPINSRQ_1_SI_X11(5*8); \ - VINSERTI128 $1, X11, Y14, Y14; \ - LOAD_MSG_AVX2_Y15(12, 2, 7, 3) - -#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ - VMOVQ_SI_X11(5*8); \ - VMOVDQU 11*8(SI), X12; \ - VPINSRQ_1_SI_X11(15*8); \ - VINSERTI128 $1, X11, Y12, Y12; \ - VMOVQ_SI_X13(8*8); \ - VMOVQ_SI_X11(2*8); \ - VPINSRQ_1_SI_X13_0; \ - VPINSRQ_1_SI_X11(13*8); \ - VINSERTI128 $1, X11, Y13, Y13; \ - LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ - LOAD_MSG_AVX2_Y15(14, 6, 1, 4) - -#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ - LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ - LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ - LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ - VMOVQ_SI_X15(6*8); \ - VMOVQ_SI_X11_0; \ - VPINSRQ_1_SI_X15(10*8); \ - VPINSRQ_1_SI_X11(8*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ - LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ - VMOVQ_SI_X13_0; \ - VMOVQ_SI_X11(4*8); \ - VPINSRQ_1_SI_X13(7*8); \ - VPINSRQ_1_SI_X11(15*8); \ - VINSERTI128 $1, X11, Y13, Y13; \ - LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ - LOAD_MSG_AVX2_Y15(1, 12, 8, 13) - -#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ - VMOVQ_SI_X12(2*8); \ - VMOVQ_SI_X11_0; \ - VPINSRQ_1_SI_X12(6*8); \ - VPINSRQ_1_SI_X11(8*8); \ - VINSERTI128 $1, X11, Y12, Y12; \ - LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ - LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ - LOAD_MSG_AVX2_Y15(13, 5, 14, 9) - -#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ - LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ - LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ - VMOVQ_SI_X14_0; \ - VPSHUFD $0x4E, 8*8(SI), X11; \ - VPINSRQ_1_SI_X14(6*8); \ - VINSERTI128 $1, X11, Y14, Y14; \ - LOAD_MSG_AVX2_Y15(7, 3, 2, 11) - -#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ - LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ - LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ - LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ - VMOVQ_SI_X15_0; \ - VMOVQ_SI_X11(6*8); \ - VPINSRQ_1_SI_X15(4*8); \ - VPINSRQ_1_SI_X11(10*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ - VMOVQ_SI_X12(6*8); \ - VMOVQ_SI_X11(11*8); \ - VPINSRQ_1_SI_X12(14*8); \ - VPINSRQ_1_SI_X11_0; \ - VINSERTI128 $1, X11, Y12, Y12; \ - LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ - VMOVQ_SI_X11(1*8); \ - VMOVDQU 12*8(SI), X14; \ - VPINSRQ_1_SI_X11(10*8); \ - VINSERTI128 $1, X11, Y14, Y14; \ - VMOVQ_SI_X15(2*8); \ - VMOVDQU 4*8(SI), X11; \ - VPINSRQ_1_SI_X15(7*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ - LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ - VMOVQ_SI_X13(2*8); \ - VPSHUFD $0x4E, 5*8(SI), X11; \ - VPINSRQ_1_SI_X13(4*8); \ - VINSERTI128 $1, X11, Y13, Y13; \ - LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ - VMOVQ_SI_X15(11*8); \ - VMOVQ_SI_X11(12*8); \ - VPINSRQ_1_SI_X15(14*8); \ - VPINSRQ_1_SI_X11_0; \ - VINSERTI128 $1, X11, Y15, Y15 - // func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment - MOVQ h+0(FP), AX - MOVQ c+8(FP), BX - MOVQ flag+16(FP), CX - MOVQ blocks_base+24(FP), SI - MOVQ blocks_len+32(FP), DI - - MOVQ SP, DX - MOVQ SP, R9 - ADDQ $31, R9 - ANDQ $~31, R9 - MOVQ R9, SP - - MOVQ CX, 16(SP) - XORQ CX, CX - MOVQ CX, 24(SP) - - VMOVDQU ·AVX2_c40<>(SB), Y4 - VMOVDQU ·AVX2_c48<>(SB), Y5 - - VMOVDQU 0(AX), Y8 +// Requires: AVX, AVX2 +TEXT ·hashBlocksAVX2(SB), NOSPLIT, $320-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + MOVQ SP, DX + ADDQ $+31, DX + ANDQ $-32, DX + MOVQ CX, 16(DX) + XORQ CX, CX + MOVQ CX, 24(DX) + VMOVDQU ·AVX2_c40<>+0(SB), Y4 + VMOVDQU ·AVX2_c48<>+0(SB), Y5 + VMOVDQU (AX), Y8 VMOVDQU 32(AX), Y9 - VMOVDQU ·AVX2_iv0<>(SB), Y6 - VMOVDQU ·AVX2_iv1<>(SB), Y7 - - MOVQ 0(BX), R8 - MOVQ 8(BX), R9 - MOVQ R9, 8(SP) + VMOVDQU ·AVX2_iv0<>+0(SB), Y6 + VMOVDQU ·AVX2_iv1<>+0(SB), Y7 + MOVQ (BX), R8 + MOVQ 8(BX), R9 + MOVQ R9, 8(DX) loop: - ADDQ $128, R8 - MOVQ R8, 0(SP) - CMPQ R8, $128 + ADDQ $0x80, R8 + MOVQ R8, (DX) + CMPQ R8, $0x80 JGE noinc INCQ R9 - MOVQ R9, 8(SP) + MOVQ R9, 8(DX) noinc: - VMOVDQA Y8, Y0 - VMOVDQA Y9, Y1 - VMOVDQA Y6, Y2 - VPXOR 0(SP), Y7, Y3 - - LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() - VMOVDQA Y12, 32(SP) - VMOVDQA Y13, 64(SP) - VMOVDQA Y14, 96(SP) - VMOVDQA Y15, 128(SP) - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() - VMOVDQA Y12, 160(SP) - VMOVDQA Y13, 192(SP) - VMOVDQA Y14, 224(SP) - VMOVDQA Y15, 256(SP) - - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5) - ROUND_AVX2(160(SP), 192(SP), 224(SP), 256(SP), Y10, Y4, Y5) - - VPXOR Y0, Y8, Y8 - VPXOR Y1, Y9, Y9 - VPXOR Y2, Y8, Y8 - VPXOR Y3, Y9, Y9 - - LEAQ 128(SI), SI - SUBQ $128, DI - JNE loop - - MOVQ R8, 0(BX) - MOVQ R9, 8(BX) - - VMOVDQU Y8, 0(AX) - VMOVDQU Y9, 32(AX) + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR (DX), Y7, Y3 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x26 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x30 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x28 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x38 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x70 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VMOVDQA Y12, 32(DX) + VMOVDQA Y13, 64(DX) + VMOVDQA Y14, 96(DX) + VMOVDQA Y15, 128(DX) + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x48 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x78 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x30 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x58 + VPSHUFD $0x4e, (SI), X14 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x28 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VMOVDQA Y12, 160(DX) + VMOVDQA Y13, 192(DX) + VMOVDQA Y14, 224(DX) + VMOVDQA Y15, 256(DX) + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x28 + VMOVDQU 88(SI), X12 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x2e + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x48 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x20 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x58 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x70 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x1e + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x40 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x2e + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x78 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x30 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x40 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x60 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x1e + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x40 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x58 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x78 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x08 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x70 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x48 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x70 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x20 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x36 + VPSHUFD $0x4e, 64(SI), X11 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x30 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x58 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x18 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x48 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x40 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x10 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x3e + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x30 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x58 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x1e + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x78 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x18 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x40 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x08 + VMOVDQU 96(SI), X14 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x50 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x10 + VMOVDQU 32(SI), X11 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x38 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x08 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y12, Y12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x10 + VPSHUFD $0x4e, 40(SI), X11 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x20 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y13, Y13 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x78 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x18 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x5e + BYTE $0x68 + BYTE $0x01 + VINSERTI128 $0x01, X11, Y14, Y14 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x5e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0xa1 + BYTE $0x22 + BYTE $0x1e + BYTE $0x01 + VINSERTI128 $0x01, X11, Y15, Y15 + VPADDQ Y12, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y13, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ Y14, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ Y15, Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + VPADDQ 32(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 64(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ 96(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 128(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + VPADDQ 160(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 192(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x93 + VPADDQ 224(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFD $-79, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPSHUFB Y4, Y1, Y1 + VPADDQ 256(DX), Y0, Y0 + VPADDQ Y1, Y0, Y0 + VPXOR Y0, Y3, Y3 + VPSHUFB Y5, Y3, Y3 + VPADDQ Y3, Y2, Y2 + VPXOR Y2, Y1, Y1 + VPADDQ Y1, Y1, Y10 + VPSRLQ $0x3f, Y1, Y1 + VPXOR Y10, Y1, Y1 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xdb + BYTE $0x39 + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xd2 + BYTE $0x4e + BYTE $0xc4 + BYTE $0xe3 + BYTE $0xfd + BYTE $0x00 + BYTE $0xc9 + BYTE $0x93 + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + LEAQ 128(SI), SI + SUBQ $0x80, DI + JNE loop + MOVQ R8, (BX) + MOVQ R9, 8(BX) + VMOVDQU Y8, (AX) + VMOVDQU Y9, 32(AX) VZEROUPPER - - MOVQ DX, SP RET -#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA -#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB -#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF -#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD -#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE - -#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 -#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF -#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 -#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF -#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 -#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 -#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF -#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF - -#define SHUFFLE_AVX() \ - VMOVDQA X6, X13; \ - VMOVDQA X2, X14; \ - VMOVDQA X4, X6; \ - VPUNPCKLQDQ_X13_X13_X15; \ - VMOVDQA X5, X4; \ - VMOVDQA X6, X5; \ - VPUNPCKHQDQ_X15_X7_X6; \ - VPUNPCKLQDQ_X7_X7_X15; \ - VPUNPCKHQDQ_X15_X13_X7; \ - VPUNPCKLQDQ_X3_X3_X15; \ - VPUNPCKHQDQ_X15_X2_X2; \ - VPUNPCKLQDQ_X14_X14_X15; \ - VPUNPCKHQDQ_X15_X3_X3; \ - -#define SHUFFLE_AVX_INV() \ - VMOVDQA X2, X13; \ - VMOVDQA X4, X14; \ - VPUNPCKLQDQ_X2_X2_X15; \ - VMOVDQA X5, X4; \ - VPUNPCKHQDQ_X15_X3_X2; \ - VMOVDQA X14, X5; \ - VPUNPCKLQDQ_X3_X3_X15; \ - VMOVDQA X6, X14; \ - VPUNPCKHQDQ_X15_X13_X3; \ - VPUNPCKLQDQ_X7_X7_X15; \ - VPUNPCKHQDQ_X15_X6_X6; \ - VPUNPCKLQDQ_X14_X14_X15; \ - VPUNPCKHQDQ_X15_X7_X7; \ - -#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ - VPADDQ m0, v0, v0; \ - VPADDQ v2, v0, v0; \ - VPADDQ m1, v1, v1; \ - VPADDQ v3, v1, v1; \ - VPXOR v0, v6, v6; \ - VPXOR v1, v7, v7; \ - VPSHUFD $-79, v6, v6; \ - VPSHUFD $-79, v7, v7; \ - VPADDQ v6, v4, v4; \ - VPADDQ v7, v5, v5; \ - VPXOR v4, v2, v2; \ - VPXOR v5, v3, v3; \ - VPSHUFB c40, v2, v2; \ - VPSHUFB c40, v3, v3; \ - VPADDQ m2, v0, v0; \ - VPADDQ v2, v0, v0; \ - VPADDQ m3, v1, v1; \ - VPADDQ v3, v1, v1; \ - VPXOR v0, v6, v6; \ - VPXOR v1, v7, v7; \ - VPSHUFB c48, v6, v6; \ - VPSHUFB c48, v7, v7; \ - VPADDQ v6, v4, v4; \ - VPADDQ v7, v5, v5; \ - VPXOR v4, v2, v2; \ - VPXOR v5, v3, v3; \ - VPADDQ v2, v2, t0; \ - VPSRLQ $63, v2, v2; \ - VPXOR t0, v2, v2; \ - VPADDQ v3, v3, t0; \ - VPSRLQ $63, v3, v3; \ - VPXOR t0, v3, v3 - -// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) -// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 -#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ - VMOVQ_SI_X12(i0*8); \ - VMOVQ_SI_X13(i2*8); \ - VMOVQ_SI_X14(i4*8); \ - VMOVQ_SI_X15(i6*8); \ - VPINSRQ_1_SI_X12(i1*8); \ - VPINSRQ_1_SI_X13(i3*8); \ - VPINSRQ_1_SI_X14(i5*8); \ - VPINSRQ_1_SI_X15(i7*8) - -// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) -#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ - VMOVQ_SI_X12_0; \ - VMOVQ_SI_X13(4*8); \ - VMOVQ_SI_X14(1*8); \ - VMOVQ_SI_X15(5*8); \ - VPINSRQ_1_SI_X12(2*8); \ - VPINSRQ_1_SI_X13(6*8); \ - VPINSRQ_1_SI_X14(3*8); \ - VPINSRQ_1_SI_X15(7*8) - -// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) -#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ - VPSHUFD $0x4E, 0*8(SI), X12; \ - VMOVQ_SI_X13(11*8); \ - VMOVQ_SI_X14(12*8); \ - VMOVQ_SI_X15(7*8); \ - VPINSRQ_1_SI_X13(5*8); \ - VPINSRQ_1_SI_X14(2*8); \ - VPINSRQ_1_SI_X15(3*8) - -// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) -#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ - VMOVDQU 11*8(SI), X12; \ - VMOVQ_SI_X13(5*8); \ - VMOVQ_SI_X14(8*8); \ - VMOVQ_SI_X15(2*8); \ - VPINSRQ_1_SI_X13(15*8); \ - VPINSRQ_1_SI_X14_0; \ - VPINSRQ_1_SI_X15(13*8) - -// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) -#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ - VMOVQ_SI_X12(2*8); \ - VMOVQ_SI_X13(4*8); \ - VMOVQ_SI_X14(6*8); \ - VMOVQ_SI_X15_0; \ - VPINSRQ_1_SI_X12(5*8); \ - VPINSRQ_1_SI_X13(15*8); \ - VPINSRQ_1_SI_X14(10*8); \ - VPINSRQ_1_SI_X15(8*8) - -// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) -#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ - VMOVQ_SI_X12(9*8); \ - VMOVQ_SI_X13(2*8); \ - VMOVQ_SI_X14_0; \ - VMOVQ_SI_X15(4*8); \ - VPINSRQ_1_SI_X12(5*8); \ - VPINSRQ_1_SI_X13(10*8); \ - VPINSRQ_1_SI_X14(7*8); \ - VPINSRQ_1_SI_X15(15*8) +DATA ·AVX2_c40<>+0(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+16(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+24(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), RODATA|NOPTR, $32 -// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) -#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ - VMOVQ_SI_X12(2*8); \ - VMOVQ_SI_X13_0; \ - VMOVQ_SI_X14(12*8); \ - VMOVQ_SI_X15(11*8); \ - VPINSRQ_1_SI_X12(6*8); \ - VPINSRQ_1_SI_X13(8*8); \ - VPINSRQ_1_SI_X14(10*8); \ - VPINSRQ_1_SI_X15(3*8) +DATA ·AVX2_c48<>+0(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+16(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+24(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), RODATA|NOPTR, $32 -// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) -#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ - MOVQ 0*8(SI), X12; \ - VPSHUFD $0x4E, 8*8(SI), X13; \ - MOVQ 7*8(SI), X14; \ - MOVQ 2*8(SI), X15; \ - VPINSRQ_1_SI_X12(6*8); \ - VPINSRQ_1_SI_X14(3*8); \ - VPINSRQ_1_SI_X15(11*8) +DATA ·AVX2_iv0<>+0(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+8(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+16(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+24(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), RODATA|NOPTR, $32 -// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) -#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ - MOVQ 6*8(SI), X12; \ - MOVQ 11*8(SI), X13; \ - MOVQ 15*8(SI), X14; \ - MOVQ 3*8(SI), X15; \ - VPINSRQ_1_SI_X12(14*8); \ - VPINSRQ_1_SI_X13_0; \ - VPINSRQ_1_SI_X14(9*8); \ - VPINSRQ_1_SI_X15(8*8) - -// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) -#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ - MOVQ 5*8(SI), X12; \ - MOVQ 8*8(SI), X13; \ - MOVQ 0*8(SI), X14; \ - MOVQ 6*8(SI), X15; \ - VPINSRQ_1_SI_X12(15*8); \ - VPINSRQ_1_SI_X13(2*8); \ - VPINSRQ_1_SI_X14(4*8); \ - VPINSRQ_1_SI_X15(10*8) - -// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) -#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ - VMOVDQU 12*8(SI), X12; \ - MOVQ 1*8(SI), X13; \ - MOVQ 2*8(SI), X14; \ - VPINSRQ_1_SI_X13(10*8); \ - VPINSRQ_1_SI_X14(7*8); \ - VMOVDQU 4*8(SI), X15 - -// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) -#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ - MOVQ 15*8(SI), X12; \ - MOVQ 3*8(SI), X13; \ - MOVQ 11*8(SI), X14; \ - MOVQ 12*8(SI), X15; \ - VPINSRQ_1_SI_X12(9*8); \ - VPINSRQ_1_SI_X13(13*8); \ - VPINSRQ_1_SI_X14(14*8); \ - VPINSRQ_1_SI_X15_0 +DATA ·AVX2_iv1<>+0(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+8(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+16(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+24(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), RODATA|NOPTR, $32 // func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment - MOVQ h+0(FP), AX - MOVQ c+8(FP), BX - MOVQ flag+16(FP), CX - MOVQ blocks_base+24(FP), SI - MOVQ blocks_len+32(FP), DI - - MOVQ SP, BP - MOVQ SP, R9 - ADDQ $15, R9 - ANDQ $~15, R9 - MOVQ R9, SP - - VMOVDQU ·AVX_c40<>(SB), X0 - VMOVDQU ·AVX_c48<>(SB), X1 +// Requires: AVX, SSE2 +TEXT ·hashBlocksAVX(SB), NOSPLIT, $288-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + MOVQ SP, R10 + ADDQ $0x0f, R10 + ANDQ $-16, R10 + VMOVDQU ·AVX_c40<>+0(SB), X0 + VMOVDQU ·AVX_c48<>+0(SB), X1 VMOVDQA X0, X8 VMOVDQA X1, X9 - - VMOVDQU ·AVX_iv3<>(SB), X0 - VMOVDQA X0, 0(SP) - XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0) - - VMOVDQU 0(AX), X10 + VMOVDQU ·AVX_iv3<>+0(SB), X0 + VMOVDQA X0, (R10) + XORQ CX, (R10) + VMOVDQU (AX), X10 VMOVDQU 16(AX), X11 VMOVDQU 32(AX), X2 VMOVDQU 48(AX), X3 - - MOVQ 0(BX), R8 - MOVQ 8(BX), R9 + MOVQ (BX), R8 + MOVQ 8(BX), R9 loop: - ADDQ $128, R8 - CMPQ R8, $128 + ADDQ $0x80, R8 + CMPQ R8, $0x80 JGE noinc INCQ R9 noinc: - VMOVQ_R8_X15 - VPINSRQ_1_R9_X15 - + BYTE $0xc4 + BYTE $0x41 + BYTE $0xf9 + BYTE $0x6e + BYTE $0xf8 + BYTE $0xc4 + BYTE $0x43 + BYTE $0x81 + BYTE $0x22 + BYTE $0xf9 + BYTE $0x01 VMOVDQA X10, X0 VMOVDQA X11, X1 - VMOVDQU ·AVX_iv0<>(SB), X4 - VMOVDQU ·AVX_iv1<>(SB), X5 - VMOVDQU ·AVX_iv2<>(SB), X6 - + VMOVDQU ·AVX_iv0<>+0(SB), X4 + VMOVDQU ·AVX_iv1<>+0(SB), X5 + VMOVDQU ·AVX_iv2<>+0(SB), X6 VPXOR X15, X6, X6 - VMOVDQA 0(SP), X7 - - LOAD_MSG_AVX_0_2_4_6_1_3_5_7() - VMOVDQA X12, 16(SP) - VMOVDQA X13, 32(SP) - VMOVDQA X14, 48(SP) - VMOVDQA X15, 64(SP) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) - VMOVDQA X12, 80(SP) - VMOVDQA X13, 96(SP) - VMOVDQA X14, 112(SP) - VMOVDQA X15, 128(SP) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) - VMOVDQA X12, 144(SP) - VMOVDQA X13, 160(SP) - VMOVDQA X14, 176(SP) - VMOVDQA X15, 192(SP) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_1_0_11_5_12_2_7_3() - VMOVDQA X12, 208(SP) - VMOVDQA X13, 224(SP) - VMOVDQA X14, 240(SP) - VMOVDQA X15, 256(SP) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX_11_12_5_15_8_0_2_13() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_2_5_4_15_6_10_0_8() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX_9_5_2_10_0_7_4_15() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX_2_6_0_8_12_10_11_3() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_0_6_9_8_7_3_2_11() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_5_15_8_2_0_4_6_10() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX_6_14_11_0_15_9_3_8() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_12_13_1_10_2_7_4_5() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_15_9_3_13_11_14_12_0() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9) - SHUFFLE_AVX() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9) - SHUFFLE_AVX_INV() - - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9) - SHUFFLE_AVX() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9) - SHUFFLE_AVX_INV() - + VMOVDQA (R10), X7 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x26 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x28 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x38 + BYTE $0x01 + VMOVDQA X12, 16(R10) + VMOVDQA X13, 32(R10) + VMOVDQA X14, 48(R10) + VMOVDQA X15, 64(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x78 + BYTE $0x01 + VMOVDQA X12, 80(R10) + VMOVDQA X13, 96(R10) + VMOVDQA X14, 112(R10) + VMOVDQA X15, 128(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x78 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x68 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x30 + BYTE $0x01 + VMOVDQA X12, 144(R10) + VMOVDQA X13, 160(R10) + VMOVDQA X14, 176(R10) + VMOVDQA X15, 192(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VPSHUFD $0x4e, (SI), X12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x38 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x18 + BYTE $0x01 + VMOVDQA X12, 208(R10) + VMOVDQA X13, 224(R10) + VMOVDQA X14, 240(R10) + VMOVDQA X15, 256(R10) + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VMOVDQU 88(SI), X12 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x40 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x10 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x36 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x68 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x20 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x60 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x70 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x3e + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x40 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x48 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x36 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x20 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x78 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x30 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x08 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x40 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x58 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x60 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x68 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x2e + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x58 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x18 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x20 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x78 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x70 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x28 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x48 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x70 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x28 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x68 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x50 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + MOVQ (SI), X12 + VPSHUFD $0x4e, 64(SI), X13 + MOVQ 56(SI), X14 + MOVQ 16(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x30 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x58 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x68 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x60 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x58 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x08 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x38 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x18 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x48 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + MOVQ 40(SI), X12 + MOVQ 64(SI), X13 + MOVQ (SI), X14 + MOVQ 48(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x78 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x10 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x50 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + MOVQ 48(SI), X12 + MOVQ 88(SI), X13 + MOVQ 120(SI), X14 + MOVQ 24(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x2e + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x40 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VMOVDQU 96(SI), X12 + MOVQ 8(SI), X13 + MOVQ 16(SI), X14 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x50 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x38 + BYTE $0x01 + VMOVDQU 32(SI), X15 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x66 + BYTE $0x50 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x6e + BYTE $0x38 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x76 + BYTE $0x10 + BYTE $0xc5 + BYTE $0x7a + BYTE $0x7e + BYTE $0x7e + BYTE $0x30 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x40 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x08 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x20 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x7e + BYTE $0x28 + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + MOVQ 120(SI), X12 + MOVQ 24(SI), X13 + MOVQ 88(SI), X14 + MOVQ 96(SI), X15 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x99 + BYTE $0x22 + BYTE $0x66 + BYTE $0x48 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x91 + BYTE $0x22 + BYTE $0x6e + BYTE $0x68 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x89 + BYTE $0x22 + BYTE $0x76 + BYTE $0x70 + BYTE $0x01 + BYTE $0xc4 + BYTE $0x63 + BYTE $0x81 + BYTE $0x22 + BYTE $0x3e + BYTE $0x01 + VPADDQ X12, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X13, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ X14, X0, X0 + VPADDQ X2, X0, X0 + VPADDQ X15, X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VPADDQ 16(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 32(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 48(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 64(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VPADDQ 80(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 96(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 112(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 128(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff + VPADDQ 144(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 160(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 176(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 192(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X6, X13 + VMOVDQA X2, X14 + VMOVDQA X4, X6 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x11 + BYTE $0x6c + BYTE $0xfd + VMOVDQA X5, X4 + VMOVDQA X6, X5 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xff + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x69 + BYTE $0x6d + BYTE $0xd7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xdf + VPADDQ 208(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 224(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFD $-79, X6, X6 + VPSHUFD $-79, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPSHUFB X8, X2, X2 + VPSHUFB X8, X3, X3 + VPADDQ 240(R10), X0, X0 + VPADDQ X2, X0, X0 + VPADDQ 256(R10), X1, X1 + VPADDQ X3, X1, X1 + VPXOR X0, X6, X6 + VPXOR X1, X7, X7 + VPSHUFB X9, X6, X6 + VPSHUFB X9, X7, X7 + VPADDQ X6, X4, X4 + VPADDQ X7, X5, X5 + VPXOR X4, X2, X2 + VPXOR X5, X3, X3 + VPADDQ X2, X2, X15 + VPSRLQ $0x3f, X2, X2 + VPXOR X15, X2, X2 + VPADDQ X3, X3, X15 + VPSRLQ $0x3f, X3, X3 + VPXOR X15, X3, X3 + VMOVDQA X2, X13 + VMOVDQA X4, X14 + BYTE $0xc5 + BYTE $0x69 + BYTE $0x6c + BYTE $0xfa + VMOVDQA X5, X4 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x61 + BYTE $0x6d + BYTE $0xd7 + VMOVDQA X14, X5 + BYTE $0xc5 + BYTE $0x61 + BYTE $0x6c + BYTE $0xfb + VMOVDQA X6, X14 + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x11 + BYTE $0x6d + BYTE $0xdf + BYTE $0xc5 + BYTE $0x41 + BYTE $0x6c + BYTE $0xff + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x49 + BYTE $0x6d + BYTE $0xf7 + BYTE $0xc4 + BYTE $0x41 + BYTE $0x09 + BYTE $0x6c + BYTE $0xfe + BYTE $0xc4 + BYTE $0xc1 + BYTE $0x41 + BYTE $0x6d + BYTE $0xff VMOVDQU 32(AX), X14 VMOVDQU 48(AX), X15 VPXOR X0, X10, X10 @@ -734,17 +4524,36 @@ noinc: VPXOR X7, X15, X3 VMOVDQU X2, 32(AX) VMOVDQU X3, 48(AX) + LEAQ 128(SI), SI + SUBQ $0x80, DI + JNE loop + VMOVDQU X10, (AX) + VMOVDQU X11, 16(AX) + MOVQ R8, (BX) + MOVQ R9, 8(BX) + VZEROUPPER + RET - LEAQ 128(SI), SI - SUBQ $128, DI - JNE loop +DATA ·AVX_c40<>+0(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), RODATA|NOPTR, $16 - VMOVDQU X10, 0(AX) - VMOVDQU X11, 16(AX) +DATA ·AVX_c48<>+0(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), RODATA|NOPTR, $16 - MOVQ R8, 0(BX) - MOVQ R9, 8(BX) - VZEROUPPER +DATA ·AVX_iv3<>+0(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+8(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), RODATA|NOPTR, $16 - MOVQ BP, SP - RET +DATA ·AVX_iv0<>+0(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+8(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_iv1<>+0(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+8(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), RODATA|NOPTR, $16 + +DATA ·AVX_iv2<>+0(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+8(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), RODATA|NOPTR, $16 diff --git a/blake2b/blake2b_amd64.go b/blake2b/blake2b_amd64.go deleted file mode 100644 index 30e2fcd581..0000000000 --- a/blake2b/blake2b_amd64.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.7,amd64,!gccgo,!appengine - -package blake2b - -import "golang.org/x/sys/cpu" - -func init() { - useSSE4 = cpu.X86.HasSSE41 -} - -//go:noescape -func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) - -func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { - if useSSE4 { - hashBlocksSSE4(h, c, flag, blocks) - } else { - hashBlocksGeneric(h, c, flag, blocks) - } -} diff --git a/blake2b/blake2b_amd64.s b/blake2b/blake2b_amd64.s index 578e947b3b..9a0ce21244 100644 --- a/blake2b/blake2b_amd64.s +++ b/blake2b/blake2b_amd64.s @@ -1,281 +1,1441 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run blake2b_amd64_asm.go -out ../../blake2b_amd64.s -pkg blake2b. DO NOT EDIT. -// +build amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego #include "textflag.h" -DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 - -DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 - -DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 -DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 - -DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 - -DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 - -DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 - -#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ - MOVO v4, t1; \ - MOVO v5, v4; \ - MOVO t1, v5; \ - MOVO v6, t1; \ - PUNPCKLQDQ v6, t2; \ - PUNPCKHQDQ v7, v6; \ - PUNPCKHQDQ t2, v6; \ - PUNPCKLQDQ v7, t2; \ - MOVO t1, v7; \ - MOVO v2, t1; \ - PUNPCKHQDQ t2, v7; \ - PUNPCKLQDQ v3, t2; \ - PUNPCKHQDQ t2, v2; \ - PUNPCKLQDQ t1, t2; \ - PUNPCKHQDQ t2, v3 - -#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ - MOVO v4, t1; \ - MOVO v5, v4; \ - MOVO t1, v5; \ - MOVO v2, t1; \ - PUNPCKLQDQ v2, t2; \ - PUNPCKHQDQ v3, v2; \ - PUNPCKHQDQ t2, v2; \ - PUNPCKLQDQ v3, t2; \ - MOVO t1, v3; \ - MOVO v6, t1; \ - PUNPCKHQDQ t2, v3; \ - PUNPCKLQDQ v7, t2; \ - PUNPCKHQDQ t2, v6; \ - PUNPCKLQDQ t1, t2; \ - PUNPCKHQDQ t2, v7 - -#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ - PADDQ m0, v0; \ - PADDQ m1, v1; \ - PADDQ v2, v0; \ - PADDQ v3, v1; \ - PXOR v0, v6; \ - PXOR v1, v7; \ - PSHUFD $0xB1, v6, v6; \ - PSHUFD $0xB1, v7, v7; \ - PADDQ v6, v4; \ - PADDQ v7, v5; \ - PXOR v4, v2; \ - PXOR v5, v3; \ - PSHUFB c40, v2; \ - PSHUFB c40, v3; \ - PADDQ m2, v0; \ - PADDQ m3, v1; \ - PADDQ v2, v0; \ - PADDQ v3, v1; \ - PXOR v0, v6; \ - PXOR v1, v7; \ - PSHUFB c48, v6; \ - PSHUFB c48, v7; \ - PADDQ v6, v4; \ - PADDQ v7, v5; \ - PXOR v4, v2; \ - PXOR v5, v3; \ - MOVOU v2, t0; \ - PADDQ v2, t0; \ - PSRLQ $63, v2; \ - PXOR t0, v2; \ - MOVOU v3, t0; \ - PADDQ v3, t0; \ - PSRLQ $63, v3; \ - PXOR t0, v3 - -#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ - MOVQ i0*8(src), m0; \ - PINSRQ $1, i1*8(src), m0; \ - MOVQ i2*8(src), m1; \ - PINSRQ $1, i3*8(src), m1; \ - MOVQ i4*8(src), m2; \ - PINSRQ $1, i5*8(src), m2; \ - MOVQ i6*8(src), m3; \ - PINSRQ $1, i7*8(src), m3 - // func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment - MOVQ h+0(FP), AX - MOVQ c+8(FP), BX - MOVQ flag+16(FP), CX - MOVQ blocks_base+24(FP), SI - MOVQ blocks_len+32(FP), DI - - MOVQ SP, BP - MOVQ SP, R9 - ADDQ $15, R9 - ANDQ $~15, R9 - MOVQ R9, SP - - MOVOU ·iv3<>(SB), X0 - MOVO X0, 0(SP) - XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0) - - MOVOU ·c40<>(SB), X13 - MOVOU ·c48<>(SB), X14 - - MOVOU 0(AX), X12 +// Requires: SSE2, SSE4.1, SSSE3 +TEXT ·hashBlocksSSE4(SB), NOSPLIT, $288-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + MOVQ SP, R10 + ADDQ $0x0f, R10 + ANDQ $-16, R10 + MOVOU ·iv3<>+0(SB), X0 + MOVO X0, (R10) + XORQ CX, (R10) + MOVOU ·c40<>+0(SB), X13 + MOVOU ·c48<>+0(SB), X14 + MOVOU (AX), X12 MOVOU 16(AX), X15 - - MOVQ 0(BX), R8 - MOVQ 8(BX), R9 + MOVQ (BX), R8 + MOVQ 8(BX), R9 loop: - ADDQ $128, R8 - CMPQ R8, $128 + ADDQ $0x80, R8 + CMPQ R8, $0x80 JGE noinc INCQ R9 noinc: - MOVQ R8, X8 - PINSRQ $1, R9, X8 - - MOVO X12, X0 - MOVO X15, X1 - MOVOU 32(AX), X2 - MOVOU 48(AX), X3 - MOVOU ·iv0<>(SB), X4 - MOVOU ·iv1<>(SB), X5 - MOVOU ·iv2<>(SB), X6 - - PXOR X8, X6 - MOVO 0(SP), X7 - - LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) - MOVO X8, 16(SP) - MOVO X9, 32(SP) - MOVO X10, 48(SP) - MOVO X11, 64(SP) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) - MOVO X8, 80(SP) - MOVO X9, 96(SP) - MOVO X10, 112(SP) - MOVO X11, 128(SP) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) - MOVO X8, 144(SP) - MOVO X9, 160(SP) - MOVO X10, 176(SP) - MOVO X11, 192(SP) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) - MOVO X8, 208(SP) - MOVO X9, 224(SP) - MOVO X10, 240(SP) - MOVO X11, 256(SP) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + MOVQ R8, X8 + PINSRQ $0x01, R9, X8 + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>+0(SB), X4 + MOVOU ·iv1<>+0(SB), X5 + MOVOU ·iv2<>+0(SB), X6 + PXOR X8, X6 + MOVO (R10), X7 + MOVQ (SI), X8 + PINSRQ $0x01, 16(SI), X8 + MOVQ 32(SI), X9 + PINSRQ $0x01, 48(SI), X9 + MOVQ 8(SI), X10 + PINSRQ $0x01, 24(SI), X10 + MOVQ 40(SI), X11 + PINSRQ $0x01, 56(SI), X11 + MOVO X8, 16(R10) + MOVO X9, 32(R10) + MOVO X10, 48(R10) + MOVO X11, 64(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 64(SI), X8 + PINSRQ $0x01, 80(SI), X8 + MOVQ 96(SI), X9 + PINSRQ $0x01, 112(SI), X9 + MOVQ 72(SI), X10 + PINSRQ $0x01, 88(SI), X10 + MOVQ 104(SI), X11 + PINSRQ $0x01, 120(SI), X11 + MOVO X8, 80(R10) + MOVO X9, 96(R10) + MOVO X10, 112(R10) + MOVO X11, 128(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 112(SI), X8 + PINSRQ $0x01, 32(SI), X8 + MOVQ 72(SI), X9 + PINSRQ $0x01, 104(SI), X9 + MOVQ 80(SI), X10 + PINSRQ $0x01, 64(SI), X10 + MOVQ 120(SI), X11 + PINSRQ $0x01, 48(SI), X11 + MOVO X8, 144(R10) + MOVO X9, 160(R10) + MOVO X10, 176(R10) + MOVO X11, 192(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 8(SI), X8 + PINSRQ $0x01, (SI), X8 + MOVQ 88(SI), X9 + PINSRQ $0x01, 40(SI), X9 + MOVQ 96(SI), X10 + PINSRQ $0x01, 16(SI), X10 + MOVQ 56(SI), X11 + PINSRQ $0x01, 24(SI), X11 + MOVO X8, 208(R10) + MOVO X9, 224(R10) + MOVO X10, 240(R10) + MOVO X11, 256(R10) + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 88(SI), X8 + PINSRQ $0x01, 96(SI), X8 + MOVQ 40(SI), X9 + PINSRQ $0x01, 120(SI), X9 + MOVQ 64(SI), X10 + PINSRQ $0x01, (SI), X10 + MOVQ 16(SI), X11 + PINSRQ $0x01, 104(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 80(SI), X8 + PINSRQ $0x01, 24(SI), X8 + MOVQ 56(SI), X9 + PINSRQ $0x01, 72(SI), X9 + MOVQ 112(SI), X10 + PINSRQ $0x01, 48(SI), X10 + MOVQ 8(SI), X11 + PINSRQ $0x01, 32(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 56(SI), X8 + PINSRQ $0x01, 24(SI), X8 + MOVQ 104(SI), X9 + PINSRQ $0x01, 88(SI), X9 + MOVQ 72(SI), X10 + PINSRQ $0x01, 8(SI), X10 + MOVQ 96(SI), X11 + PINSRQ $0x01, 112(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 16(SI), X8 + PINSRQ $0x01, 40(SI), X8 + MOVQ 32(SI), X9 + PINSRQ $0x01, 120(SI), X9 + MOVQ 48(SI), X10 + PINSRQ $0x01, 80(SI), X10 + MOVQ (SI), X11 + PINSRQ $0x01, 64(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 72(SI), X8 + PINSRQ $0x01, 40(SI), X8 + MOVQ 16(SI), X9 + PINSRQ $0x01, 80(SI), X9 + MOVQ (SI), X10 + PINSRQ $0x01, 56(SI), X10 + MOVQ 32(SI), X11 + PINSRQ $0x01, 120(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 112(SI), X8 + PINSRQ $0x01, 88(SI), X8 + MOVQ 48(SI), X9 + PINSRQ $0x01, 24(SI), X9 + MOVQ 8(SI), X10 + PINSRQ $0x01, 96(SI), X10 + MOVQ 64(SI), X11 + PINSRQ $0x01, 104(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 16(SI), X8 + PINSRQ $0x01, 48(SI), X8 + MOVQ (SI), X9 + PINSRQ $0x01, 64(SI), X9 + MOVQ 96(SI), X10 + PINSRQ $0x01, 80(SI), X10 + MOVQ 88(SI), X11 + PINSRQ $0x01, 24(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 32(SI), X8 + PINSRQ $0x01, 56(SI), X8 + MOVQ 120(SI), X9 + PINSRQ $0x01, 8(SI), X9 + MOVQ 104(SI), X10 + PINSRQ $0x01, 40(SI), X10 + MOVQ 112(SI), X11 + PINSRQ $0x01, 72(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 96(SI), X8 + PINSRQ $0x01, 8(SI), X8 + MOVQ 112(SI), X9 + PINSRQ $0x01, 32(SI), X9 + MOVQ 40(SI), X10 + PINSRQ $0x01, 120(SI), X10 + MOVQ 104(SI), X11 + PINSRQ $0x01, 80(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ (SI), X8 + PINSRQ $0x01, 48(SI), X8 + MOVQ 72(SI), X9 + PINSRQ $0x01, 64(SI), X9 + MOVQ 56(SI), X10 + PINSRQ $0x01, 24(SI), X10 + MOVQ 16(SI), X11 + PINSRQ $0x01, 88(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 104(SI), X8 + PINSRQ $0x01, 56(SI), X8 + MOVQ 96(SI), X9 + PINSRQ $0x01, 24(SI), X9 + MOVQ 88(SI), X10 + PINSRQ $0x01, 112(SI), X10 + MOVQ 8(SI), X11 + PINSRQ $0x01, 72(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 40(SI), X8 + PINSRQ $0x01, 120(SI), X8 + MOVQ 64(SI), X9 + PINSRQ $0x01, 16(SI), X9 + MOVQ (SI), X10 + PINSRQ $0x01, 32(SI), X10 + MOVQ 48(SI), X11 + PINSRQ $0x01, 80(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 48(SI), X8 + PINSRQ $0x01, 112(SI), X8 + MOVQ 88(SI), X9 + PINSRQ $0x01, (SI), X9 + MOVQ 120(SI), X10 + PINSRQ $0x01, 72(SI), X10 + MOVQ 24(SI), X11 + PINSRQ $0x01, 64(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 96(SI), X8 + PINSRQ $0x01, 104(SI), X8 + MOVQ 8(SI), X9 + PINSRQ $0x01, 80(SI), X9 + MOVQ 16(SI), X10 + PINSRQ $0x01, 56(SI), X10 + MOVQ 32(SI), X11 + PINSRQ $0x01, 40(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVQ 80(SI), X8 + PINSRQ $0x01, 64(SI), X8 + MOVQ 56(SI), X9 + PINSRQ $0x01, 8(SI), X9 + MOVQ 16(SI), X10 + PINSRQ $0x01, 32(SI), X10 + MOVQ 48(SI), X11 + PINSRQ $0x01, 40(SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + MOVQ 120(SI), X8 + PINSRQ $0x01, 72(SI), X8 + MOVQ 24(SI), X9 + PINSRQ $0x01, 104(SI), X9 + MOVQ 88(SI), X10 + PINSRQ $0x01, 112(SI), X10 + MOVQ 96(SI), X11 + PINSRQ $0x01, (SI), X11 + PADDQ X8, X0 + PADDQ X9, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ X10, X0 + PADDQ X11, X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + PADDQ 16(R10), X0 + PADDQ 32(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 48(R10), X0 + PADDQ 64(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + PADDQ 80(R10), X0 + PADDQ 96(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 112(R10), X0 + PADDQ 128(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + PADDQ 144(R10), X0 + PADDQ 160(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 176(R10), X0 + PADDQ 192(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X6, X8 + PUNPCKLQDQ X6, X9 + PUNPCKHQDQ X7, X6 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X7, X9 + MOVO X8, X7 + MOVO X2, X8 + PUNPCKHQDQ X9, X7 + PUNPCKLQDQ X3, X9 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X3 + PADDQ 208(R10), X0 + PADDQ 224(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFD $0xb1, X6, X6 + PSHUFD $0xb1, X7, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + PSHUFB X13, X2 + PSHUFB X13, X3 + PADDQ 240(R10), X0 + PADDQ 256(R10), X1 + PADDQ X2, X0 + PADDQ X3, X1 + PXOR X0, X6 + PXOR X1, X7 + PSHUFB X14, X6 + PSHUFB X14, X7 + PADDQ X6, X4 + PADDQ X7, X5 + PXOR X4, X2 + PXOR X5, X3 + MOVOU X2, X11 + PADDQ X2, X11 + PSRLQ $0x3f, X2 + PXOR X11, X2 + MOVOU X3, X11 + PADDQ X3, X11 + PSRLQ $0x3f, X3 + PXOR X11, X3 + MOVO X4, X8 + MOVO X5, X4 + MOVO X8, X5 + MOVO X2, X8 + PUNPCKLQDQ X2, X9 + PUNPCKHQDQ X3, X2 + PUNPCKHQDQ X9, X2 + PUNPCKLQDQ X3, X9 + MOVO X8, X3 + MOVO X6, X8 + PUNPCKHQDQ X9, X3 + PUNPCKLQDQ X7, X9 + PUNPCKHQDQ X9, X6 + PUNPCKLQDQ X8, X9 + PUNPCKHQDQ X9, X7 + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + LEAQ 128(SI), SI + SUBQ $0x80, DI + JNE loop + MOVOU X12, (AX) + MOVOU X15, 16(AX) + MOVQ R8, (BX) + MOVQ R9, 8(BX) + RET - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) +DATA ·iv3<>+0(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+8(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), RODATA|NOPTR, $16 - MOVOU 32(AX), X10 - MOVOU 48(AX), X11 - PXOR X0, X12 - PXOR X1, X15 - PXOR X2, X10 - PXOR X3, X11 - PXOR X4, X12 - PXOR X5, X15 - PXOR X6, X10 - PXOR X7, X11 - MOVOU X10, 32(AX) - MOVOU X11, 48(AX) +DATA ·c40<>+0(SB)/8, $0x0201000706050403 +DATA ·c40<>+8(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), RODATA|NOPTR, $16 - LEAQ 128(SI), SI - SUBQ $128, DI - JNE loop +DATA ·c48<>+0(SB)/8, $0x0100070605040302 +DATA ·c48<>+8(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), RODATA|NOPTR, $16 - MOVOU X12, 0(AX) - MOVOU X15, 16(AX) +DATA ·iv0<>+0(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+8(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), RODATA|NOPTR, $16 - MOVQ R8, 0(BX) - MOVQ R9, 8(BX) +DATA ·iv1<>+0(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+8(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), RODATA|NOPTR, $16 - MOVQ BP, SP - RET +DATA ·iv2<>+0(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+8(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), RODATA|NOPTR, $16 diff --git a/blake2b/blake2b_ref.go b/blake2b/blake2b_ref.go index da156a1ba6..6e28668cd1 100644 --- a/blake2b/blake2b_ref.go +++ b/blake2b/blake2b_ref.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine gccgo +//go:build !amd64 || purego || !gc package blake2b diff --git a/blake2b/blake2x.go b/blake2b/blake2x.go index 52c414db0e..7692bb3460 100644 --- a/blake2b/blake2x.go +++ b/blake2b/blake2x.go @@ -12,6 +12,8 @@ import ( // XOF defines the interface to hash functions that // support arbitrary-length output. +// +// New callers should prefer the standard library [hash.XOF]. type XOF interface { // Write absorbs more data into the hash's state. It panics if called // after Read. @@ -47,6 +49,8 @@ const maxOutputLength = (1 << 32) * 64 // // A non-nil key turns the hash into a MAC. The key must between // zero and 32 bytes long. +// +// The result can be safely interface-upgraded to [hash.XOF]. func NewXOF(size uint32, key []byte) (XOF, error) { if len(key) > Size { return nil, errKeySize @@ -93,6 +97,10 @@ func (x *xof) Clone() XOF { return &clone } +func (x *xof) BlockSize() int { + return x.d.BlockSize() +} + func (x *xof) Reset() { x.cfg[0] = byte(Size) binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length diff --git a/blake2b/go125.go b/blake2b/go125.go new file mode 100644 index 0000000000..67e990b7e1 --- /dev/null +++ b/blake2b/go125.go @@ -0,0 +1,11 @@ +// Copyright 2025 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. + +//go:build go1.25 + +package blake2b + +import "hash" + +var _ hash.XOF = (*xof)(nil) diff --git a/blake2b/register.go b/blake2b/register.go index efd689af4b..54e446e1d2 100644 --- a/blake2b/register.go +++ b/blake2b/register.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.9 - package blake2b import ( diff --git a/blake2s/_asm/blake2s_amd64_asm.go b/blake2s/_asm/blake2s_amd64_asm.go new file mode 100644 index 0000000000..48ddd6118a --- /dev/null +++ b/blake2s/_asm/blake2s_amd64_asm.go @@ -0,0 +1,525 @@ +// Copyright 2024 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 main + +import ( + . "github.com/mmcloughlin/avo/build" + "github.com/mmcloughlin/avo/ir" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/blake2s" +) + +//go:generate go run . -out ../blake2s_amd64.s -pkg blake2s + +func main() { + Package("golang.org/x/crypto/blake2s") + ConstraintExpr("amd64,gc,!purego") + hashBlocksSSE2() + hashBlocksSSSE3() + hashBlocksSSE4() + Generate() +} + +func ROTL_SSE2(n uint64, t, v VecPhysical) { + MOVO(v, t) + PSLLL(Imm(n), t) + PSRLL(Imm(32-n), v) + PXOR(t, v) +} + +func ROTL_SSSE3(c, v VecPhysical) { + PSHUFB(c, v) +} + +func ROUND_SSE2(v0, v1, v2, v3 VecPhysical, m0, m1, m2, m3 Mem, t VecPhysical) { + PADDL(m0, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSE2(16, t, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(20, t, v1) + PADDL(m1, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSE2(24, t, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(25, t, v1) + PSHUFL(Imm(0x39), v1, v1) + PSHUFL(Imm(0x4E), v2, v2) + PSHUFL(Imm(0x93), v3, v3) + PADDL(m2, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSE2(16, t, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(20, t, v1) + PADDL(m3, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSE2(24, t, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(25, t, v1) + PSHUFL(Imm(0x39), v3, v3) + PSHUFL(Imm(0x4E), v2, v2) + PSHUFL(Imm(0x93), v1, v1) +} + +func ROUND_SSSE3(v0, v1, v2, v3 VecPhysical, m0, m1, m2, m3 Op, t, c16, c8 VecPhysical) { + PADDL(m0, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSSE3(c16, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(20, t, v1) + PADDL(m1, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSSE3(c8, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(25, t, v1) + PSHUFL(Imm(0x39), v1, v1) + PSHUFL(Imm(0x4E), v2, v2) + PSHUFL(Imm(0x93), v3, v3) + PADDL(m2, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSSE3(c16, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(20, t, v1) + PADDL(m3, v0) + PADDL(v1, v0) + PXOR(v0, v3) + ROTL_SSSE3(c8, v3) + PADDL(v3, v2) + PXOR(v2, v1) + ROTL_SSE2(25, t, v1) + PSHUFL(Imm(0x39), v3, v3) + PSHUFL(Imm(0x4E), v2, v2) + PSHUFL(Imm(0x93), v1, v1) +} + +func LOAD_MSG_SSE4(m0, m1, m2, m3 VecPhysical, src GPPhysical, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15 int) { + // Hack to get Avo to emit a MOVL instruction with a VecPhysical as the destination + Instruction(&ir.Instruction{Opcode: "MOVL", Operands: []Op{Mem{Base: src}.Offset(i0 * 4), m0}}) + PINSRD(Imm(1), Mem{Base: src}.Offset(i1*4), m0) + PINSRD(Imm(2), Mem{Base: src}.Offset(i2*4), m0) + PINSRD(Imm(3), Mem{Base: src}.Offset(i3*4), m0) + Instruction(&ir.Instruction{Opcode: "MOVL", Operands: []Op{Mem{Base: src}.Offset(i4 * 4), m1}}) + PINSRD(Imm(1), Mem{Base: src}.Offset(i5*4), m1) + PINSRD(Imm(2), Mem{Base: src}.Offset(i6*4), m1) + PINSRD(Imm(3), Mem{Base: src}.Offset(i7*4), m1) + Instruction(&ir.Instruction{Opcode: "MOVL", Operands: []Op{Mem{Base: src}.Offset(i8 * 4), m2}}) + PINSRD(Imm(1), Mem{Base: src}.Offset(i9*4), m2) + PINSRD(Imm(2), Mem{Base: src}.Offset(i10*4), m2) + PINSRD(Imm(3), Mem{Base: src}.Offset(i11*4), m2) + Instruction(&ir.Instruction{Opcode: "MOVL", Operands: []Op{Mem{Base: src}.Offset(i12 * 4), m3}}) + PINSRD(Imm(1), Mem{Base: src}.Offset(i13*4), m3) + PINSRD(Imm(2), Mem{Base: src}.Offset(i14*4), m3) + PINSRD(Imm(3), Mem{Base: src}.Offset(i15*4), m3) +} + +func PRECOMPUTE_MSG(dst GPPhysical, off int, src, R8, R9, R10, R11, R12, R13, R14, R15 GPPhysical) { + MOVQ(Mem{Base: src}.Offset(0*4), R8) + MOVQ(Mem{Base: src}.Offset(2*4), R9) + MOVQ(Mem{Base: src}.Offset(4*4), R10) + MOVQ(Mem{Base: src}.Offset(6*4), R11) + MOVQ(Mem{Base: src}.Offset(8*4), R12) + MOVQ(Mem{Base: src}.Offset(10*4), R13) + MOVQ(Mem{Base: src}.Offset(12*4), R14) + MOVQ(Mem{Base: src}.Offset(14*4), R15) + + MOVL(R8L, Mem{Base: dst}.Offset(0*4+off+0)) + MOVL(R8L, Mem{Base: dst}.Offset(9*4+off+64)) + MOVL(R8L, Mem{Base: dst}.Offset(5*4+off+128)) + MOVL(R8L, Mem{Base: dst}.Offset(14*4+off+192)) + MOVL(R8L, Mem{Base: dst}.Offset(4*4+off+256)) + MOVL(R8L, Mem{Base: dst}.Offset(2*4+off+320)) + MOVL(R8L, Mem{Base: dst}.Offset(8*4+off+384)) + MOVL(R8L, Mem{Base: dst}.Offset(12*4+off+448)) + MOVL(R8L, Mem{Base: dst}.Offset(3*4+off+512)) + MOVL(R8L, Mem{Base: dst}.Offset(15*4+off+576)) + SHRQ(Imm(32), R8) + MOVL(R8L, Mem{Base: dst}.Offset(4*4+off+0)) + MOVL(R8L, Mem{Base: dst}.Offset(8*4+off+64)) + MOVL(R8L, Mem{Base: dst}.Offset(14*4+off+128)) + MOVL(R8L, Mem{Base: dst}.Offset(5*4+off+192)) + MOVL(R8L, Mem{Base: dst}.Offset(12*4+off+256)) + MOVL(R8L, Mem{Base: dst}.Offset(11*4+off+320)) + MOVL(R8L, Mem{Base: dst}.Offset(1*4+off+384)) + MOVL(R8L, Mem{Base: dst}.Offset(6*4+off+448)) + MOVL(R8L, Mem{Base: dst}.Offset(10*4+off+512)) + MOVL(R8L, Mem{Base: dst}.Offset(3*4+off+576)) + + MOVL(R9L, Mem{Base: dst}.Offset(1*4+off+0)) + MOVL(R9L, Mem{Base: dst}.Offset(13*4+off+64)) + MOVL(R9L, Mem{Base: dst}.Offset(6*4+off+128)) + MOVL(R9L, Mem{Base: dst}.Offset(8*4+off+192)) + MOVL(R9L, Mem{Base: dst}.Offset(2*4+off+256)) + MOVL(R9L, Mem{Base: dst}.Offset(0*4+off+320)) + MOVL(R9L, Mem{Base: dst}.Offset(14*4+off+384)) + MOVL(R9L, Mem{Base: dst}.Offset(11*4+off+448)) + MOVL(R9L, Mem{Base: dst}.Offset(12*4+off+512)) + MOVL(R9L, Mem{Base: dst}.Offset(4*4+off+576)) + SHRQ(Imm(32), R9) + MOVL(R9L, Mem{Base: dst}.Offset(5*4+off+0)) + MOVL(R9L, Mem{Base: dst}.Offset(15*4+off+64)) + MOVL(R9L, Mem{Base: dst}.Offset(9*4+off+128)) + MOVL(R9L, Mem{Base: dst}.Offset(1*4+off+192)) + MOVL(R9L, Mem{Base: dst}.Offset(11*4+off+256)) + MOVL(R9L, Mem{Base: dst}.Offset(7*4+off+320)) + MOVL(R9L, Mem{Base: dst}.Offset(13*4+off+384)) + MOVL(R9L, Mem{Base: dst}.Offset(3*4+off+448)) + MOVL(R9L, Mem{Base: dst}.Offset(6*4+off+512)) + MOVL(R9L, Mem{Base: dst}.Offset(10*4+off+576)) + + MOVL(R10L, Mem{Base: dst}.Offset(2*4+off+0)) + MOVL(R10L, Mem{Base: dst}.Offset(1*4+off+64)) + MOVL(R10L, Mem{Base: dst}.Offset(15*4+off+128)) + MOVL(R10L, Mem{Base: dst}.Offset(10*4+off+192)) + MOVL(R10L, Mem{Base: dst}.Offset(6*4+off+256)) + MOVL(R10L, Mem{Base: dst}.Offset(8*4+off+320)) + MOVL(R10L, Mem{Base: dst}.Offset(3*4+off+384)) + MOVL(R10L, Mem{Base: dst}.Offset(13*4+off+448)) + MOVL(R10L, Mem{Base: dst}.Offset(14*4+off+512)) + MOVL(R10L, Mem{Base: dst}.Offset(5*4+off+576)) + SHRQ(Imm(32), R10) + MOVL(R10L, Mem{Base: dst}.Offset(6*4+off+0)) + MOVL(R10L, Mem{Base: dst}.Offset(11*4+off+64)) + MOVL(R10L, Mem{Base: dst}.Offset(2*4+off+128)) + MOVL(R10L, Mem{Base: dst}.Offset(9*4+off+192)) + MOVL(R10L, Mem{Base: dst}.Offset(1*4+off+256)) + MOVL(R10L, Mem{Base: dst}.Offset(13*4+off+320)) + MOVL(R10L, Mem{Base: dst}.Offset(4*4+off+384)) + MOVL(R10L, Mem{Base: dst}.Offset(8*4+off+448)) + MOVL(R10L, Mem{Base: dst}.Offset(15*4+off+512)) + MOVL(R10L, Mem{Base: dst}.Offset(7*4+off+576)) + + MOVL(R11L, Mem{Base: dst}.Offset(3*4+off+0)) + MOVL(R11L, Mem{Base: dst}.Offset(7*4+off+64)) + MOVL(R11L, Mem{Base: dst}.Offset(13*4+off+128)) + MOVL(R11L, Mem{Base: dst}.Offset(12*4+off+192)) + MOVL(R11L, Mem{Base: dst}.Offset(10*4+off+256)) + MOVL(R11L, Mem{Base: dst}.Offset(1*4+off+320)) + MOVL(R11L, Mem{Base: dst}.Offset(9*4+off+384)) + MOVL(R11L, Mem{Base: dst}.Offset(14*4+off+448)) + MOVL(R11L, Mem{Base: dst}.Offset(0*4+off+512)) + MOVL(R11L, Mem{Base: dst}.Offset(6*4+off+576)) + SHRQ(Imm(32), R11) + MOVL(R11L, Mem{Base: dst}.Offset(7*4+off+0)) + MOVL(R11L, Mem{Base: dst}.Offset(14*4+off+64)) + MOVL(R11L, Mem{Base: dst}.Offset(10*4+off+128)) + MOVL(R11L, Mem{Base: dst}.Offset(0*4+off+192)) + MOVL(R11L, Mem{Base: dst}.Offset(5*4+off+256)) + MOVL(R11L, Mem{Base: dst}.Offset(9*4+off+320)) + MOVL(R11L, Mem{Base: dst}.Offset(12*4+off+384)) + MOVL(R11L, Mem{Base: dst}.Offset(1*4+off+448)) + MOVL(R11L, Mem{Base: dst}.Offset(13*4+off+512)) + MOVL(R11L, Mem{Base: dst}.Offset(2*4+off+576)) + + MOVL(R12L, Mem{Base: dst}.Offset(8*4+off+0)) + MOVL(R12L, Mem{Base: dst}.Offset(5*4+off+64)) + MOVL(R12L, Mem{Base: dst}.Offset(4*4+off+128)) + MOVL(R12L, Mem{Base: dst}.Offset(15*4+off+192)) + MOVL(R12L, Mem{Base: dst}.Offset(14*4+off+256)) + MOVL(R12L, Mem{Base: dst}.Offset(3*4+off+320)) + MOVL(R12L, Mem{Base: dst}.Offset(11*4+off+384)) + MOVL(R12L, Mem{Base: dst}.Offset(10*4+off+448)) + MOVL(R12L, Mem{Base: dst}.Offset(7*4+off+512)) + MOVL(R12L, Mem{Base: dst}.Offset(1*4+off+576)) + SHRQ(Imm(32), R12) + MOVL(R12L, Mem{Base: dst}.Offset(12*4+off+0)) + MOVL(R12L, Mem{Base: dst}.Offset(2*4+off+64)) + MOVL(R12L, Mem{Base: dst}.Offset(11*4+off+128)) + MOVL(R12L, Mem{Base: dst}.Offset(4*4+off+192)) + MOVL(R12L, Mem{Base: dst}.Offset(0*4+off+256)) + MOVL(R12L, Mem{Base: dst}.Offset(15*4+off+320)) + MOVL(R12L, Mem{Base: dst}.Offset(10*4+off+384)) + MOVL(R12L, Mem{Base: dst}.Offset(7*4+off+448)) + MOVL(R12L, Mem{Base: dst}.Offset(5*4+off+512)) + MOVL(R12L, Mem{Base: dst}.Offset(9*4+off+576)) + + MOVL(R13L, Mem{Base: dst}.Offset(9*4+off+0)) + MOVL(R13L, Mem{Base: dst}.Offset(4*4+off+64)) + MOVL(R13L, Mem{Base: dst}.Offset(8*4+off+128)) + MOVL(R13L, Mem{Base: dst}.Offset(13*4+off+192)) + MOVL(R13L, Mem{Base: dst}.Offset(3*4+off+256)) + MOVL(R13L, Mem{Base: dst}.Offset(5*4+off+320)) + MOVL(R13L, Mem{Base: dst}.Offset(7*4+off+384)) + MOVL(R13L, Mem{Base: dst}.Offset(15*4+off+448)) + MOVL(R13L, Mem{Base: dst}.Offset(11*4+off+512)) + MOVL(R13L, Mem{Base: dst}.Offset(0*4+off+576)) + SHRQ(Imm(32), R13) + MOVL(R13L, Mem{Base: dst}.Offset(13*4+off+0)) + MOVL(R13L, Mem{Base: dst}.Offset(10*4+off+64)) + MOVL(R13L, Mem{Base: dst}.Offset(0*4+off+128)) + MOVL(R13L, Mem{Base: dst}.Offset(3*4+off+192)) + MOVL(R13L, Mem{Base: dst}.Offset(9*4+off+256)) + MOVL(R13L, Mem{Base: dst}.Offset(6*4+off+320)) + MOVL(R13L, Mem{Base: dst}.Offset(15*4+off+384)) + MOVL(R13L, Mem{Base: dst}.Offset(4*4+off+448)) + MOVL(R13L, Mem{Base: dst}.Offset(2*4+off+512)) + MOVL(R13L, Mem{Base: dst}.Offset(12*4+off+576)) + + MOVL(R14L, Mem{Base: dst}.Offset(10*4+off+0)) + MOVL(R14L, Mem{Base: dst}.Offset(12*4+off+64)) + MOVL(R14L, Mem{Base: dst}.Offset(1*4+off+128)) + MOVL(R14L, Mem{Base: dst}.Offset(6*4+off+192)) + MOVL(R14L, Mem{Base: dst}.Offset(13*4+off+256)) + MOVL(R14L, Mem{Base: dst}.Offset(4*4+off+320)) + MOVL(R14L, Mem{Base: dst}.Offset(0*4+off+384)) + MOVL(R14L, Mem{Base: dst}.Offset(2*4+off+448)) + MOVL(R14L, Mem{Base: dst}.Offset(8*4+off+512)) + MOVL(R14L, Mem{Base: dst}.Offset(14*4+off+576)) + SHRQ(Imm(32), R14) + MOVL(R14L, Mem{Base: dst}.Offset(14*4+off+0)) + MOVL(R14L, Mem{Base: dst}.Offset(3*4+off+64)) + MOVL(R14L, Mem{Base: dst}.Offset(7*4+off+128)) + MOVL(R14L, Mem{Base: dst}.Offset(2*4+off+192)) + MOVL(R14L, Mem{Base: dst}.Offset(15*4+off+256)) + MOVL(R14L, Mem{Base: dst}.Offset(12*4+off+320)) + MOVL(R14L, Mem{Base: dst}.Offset(6*4+off+384)) + MOVL(R14L, Mem{Base: dst}.Offset(0*4+off+448)) + MOVL(R14L, Mem{Base: dst}.Offset(9*4+off+512)) + MOVL(R14L, Mem{Base: dst}.Offset(11*4+off+576)) + + MOVL(R15L, Mem{Base: dst}.Offset(11*4+off+0)) + MOVL(R15L, Mem{Base: dst}.Offset(0*4+off+64)) + MOVL(R15L, Mem{Base: dst}.Offset(12*4+off+128)) + MOVL(R15L, Mem{Base: dst}.Offset(7*4+off+192)) + MOVL(R15L, Mem{Base: dst}.Offset(8*4+off+256)) + MOVL(R15L, Mem{Base: dst}.Offset(14*4+off+320)) + MOVL(R15L, Mem{Base: dst}.Offset(2*4+off+384)) + MOVL(R15L, Mem{Base: dst}.Offset(5*4+off+448)) + MOVL(R15L, Mem{Base: dst}.Offset(1*4+off+512)) + MOVL(R15L, Mem{Base: dst}.Offset(13*4+off+576)) + SHRQ(Imm(32), R15) + MOVL(R15L, Mem{Base: dst}.Offset(15*4+off+0)) + MOVL(R15L, Mem{Base: dst}.Offset(6*4+off+64)) + MOVL(R15L, Mem{Base: dst}.Offset(3*4+off+128)) + MOVL(R15L, Mem{Base: dst}.Offset(11*4+off+192)) + MOVL(R15L, Mem{Base: dst}.Offset(7*4+off+256)) + MOVL(R15L, Mem{Base: dst}.Offset(10*4+off+320)) + MOVL(R15L, Mem{Base: dst}.Offset(5*4+off+384)) + MOVL(R15L, Mem{Base: dst}.Offset(9*4+off+448)) + MOVL(R15L, Mem{Base: dst}.Offset(4*4+off+512)) + MOVL(R15L, Mem{Base: dst}.Offset(8*4+off+576)) +} + +func BLAKE2s_SSE2() { + PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15) + for i := 0; i < 10; i++ { + ROUND_SSE2(X4, X5, X6, X7, Mem{Base: BP}.Offset(16+64*i), Mem{Base: BP}.Offset(32+64*i), Mem{Base: BP}.Offset(48+64*i), Mem{Base: BP}.Offset(64+64*i), X8) + } +} + +func BLAKE2s_SSSE3() { + PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15) + for i := 0; i < 10; i++ { + ROUND_SSSE3(X4, X5, X6, X7, Mem{Base: BP}.Offset(16+64*i), Mem{Base: BP}.Offset(32+64*i), Mem{Base: BP}.Offset(48+64*i), Mem{Base: BP}.Offset(64+64*i), X8, X13, X14) + } +} + +func BLAKE2s_SSE4() { + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0) + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) +} + +func HASH_BLOCKS(h, c, flag, blocks_base, blocks_len Mem, BLAKE2s_FUNC func()) { + MOVQ(h, RAX) + MOVQ(c, RBX) + MOVL(flag, ECX) + MOVQ(blocks_base, RSI) + MOVQ(blocks_len, RDX) + + MOVQ(RSP, RBP) + ADDQ(Imm(15), RBP) + ANDQ(I32(^15), RBP) + + MOVQ(Mem{Base: BX}.Offset(0), R9) + MOVQ(R9, Mem{Base: BP}.Offset(0)) + MOVQ(RCX, Mem{Base: BP}.Offset(8)) + + MOVOU(Mem{Base: AX}.Offset(0), X0) + MOVOU(Mem{Base: AX}.Offset(16), X1) + + iv0 := iv0_DATA() + iv1 := iv1_DATA() + MOVOU(iv0, X2) + MOVOU(iv1, X3) + + counter := counter_DATA() + rol16 := rol16_DATA() + rol8 := rol8_DATA() + MOVOU(counter, X12) + MOVOU(rol16, X13) + MOVOU(rol8, X14) + MOVO(Mem{Base: BP}.Offset(0), X15) + + Label("loop") + MOVO(X0, X4) + MOVO(X1, X5) + MOVO(X2, X6) + MOVO(X3, X7) + + PADDQ(X12, X15) + PXOR(X15, X7) + + BLAKE2s_FUNC() + + PXOR(X4, X0) + PXOR(X5, X1) + PXOR(X6, X0) + PXOR(X7, X1) + + LEAQ(Mem{Base: SI}.Offset(64), RSI) + SUBQ(Imm(64), RDX) + JNE(LabelRef("loop")) + + MOVO(X15, Mem{Base: BP}.Offset(0)) + MOVQ(Mem{Base: BP}.Offset(0), R9) + MOVQ(R9, Mem{Base: BX}.Offset(0)) + + MOVOU(X0, Mem{Base: AX}.Offset(0)) + MOVOU(X1, Mem{Base: AX}.Offset(16)) +} + +func hashBlocksSSE2() { + Implement("hashBlocksSSE2") + Attributes(0) + AllocLocal(672) // frame = 656 + 16 byte alignment + + h := NewParamAddr("h", 0) + c := NewParamAddr("c", 8) + flag := NewParamAddr("flag", 16) + blocks_base := NewParamAddr("blocks_base", 24) + blocks_len := NewParamAddr("blocks_len", 32) + + HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_SSE2) + RET() +} + +func hashBlocksSSSE3() { + Implement("hashBlocksSSSE3") + Attributes(0) + AllocLocal(672) // frame = 656 + 16 byte alignment + + h := NewParamAddr("h", 0) + c := NewParamAddr("c", 8) + flag := NewParamAddr("flag", 16) + blocks_base := NewParamAddr("blocks_base", 24) + blocks_len := NewParamAddr("blocks_len", 32) + + HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_SSSE3) + RET() +} + +func hashBlocksSSE4() { + Implement("hashBlocksSSE4") + Attributes(0) + AllocLocal(32) // frame = 16 + 16 byte alignment + + h := NewParamAddr("h", 0) + c := NewParamAddr("c", 8) + flag := NewParamAddr("flag", 16) + blocks_base := NewParamAddr("blocks_base", 24) + blocks_len := NewParamAddr("blocks_len", 32) + + HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_SSE4) + RET() +} + +// ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATA SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~## + +var iv0_DATA_ptr, iv1_DATA_ptr, rol16_DATA_ptr, rol8_DATA_ptr, counter_DATA_ptr *Mem + +func iv0_DATA() Mem { + if iv0_DATA_ptr != nil { + return *iv0_DATA_ptr + } + + iv0_DATA := GLOBL("iv0", NOPTR|RODATA) + iv0_DATA_ptr = &iv0_DATA + DATA(0x00, U32(0x6a09e667)) + DATA(0x04, U32(0xbb67ae85)) + DATA(0x08, U32(0x3c6ef372)) + DATA(0x0c, U32(0xa54ff53a)) + return iv0_DATA +} + +func iv1_DATA() Mem { + if iv1_DATA_ptr != nil { + return *iv1_DATA_ptr + } + + iv1_DATA := GLOBL("iv1", NOPTR|RODATA) + iv1_DATA_ptr = &iv1_DATA + DATA(0x00, U32(0x510e527f)) + DATA(0x04, U32(0x9b05688c)) + DATA(0x08, U32(0x1f83d9ab)) + DATA(0x0c, U32(0x5be0cd19)) + return iv1_DATA +} + +func rol16_DATA() Mem { + if rol16_DATA_ptr != nil { + return *rol16_DATA_ptr + } + + rol16_DATA := GLOBL("rol16", NOPTR|RODATA) + rol16_DATA_ptr = &rol16_DATA + DATA(0x00, U64(0x0504070601000302)) + DATA(0x08, U64(0x0D0C0F0E09080B0A)) + return rol16_DATA +} + +func rol8_DATA() Mem { + if rol8_DATA_ptr != nil { + return *rol8_DATA_ptr + } + + rol8_DATA := GLOBL("rol8", NOPTR|RODATA) + rol8_DATA_ptr = &rol8_DATA + DATA(0x00, U64(0x0407060500030201)) + DATA(0x08, U64(0x0C0F0E0D080B0A09)) + return rol8_DATA +} + +func counter_DATA() Mem { + if counter_DATA_ptr != nil { + return *counter_DATA_ptr + } + + counter_DATA := GLOBL("counter", NOPTR|RODATA) + counter_DATA_ptr = &counter_DATA + DATA(0x00, U64(0x0000000000000040)) + DATA(0x08, U64(0x0000000000000000)) + return counter_DATA +} diff --git a/blake2s/_asm/go.mod b/blake2s/_asm/go.mod new file mode 100644 index 0000000000..2f6ffc2c6d --- /dev/null +++ b/blake2s/_asm/go.mod @@ -0,0 +1,15 @@ +module blake2s/_asm + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/blake2s/_asm/go.sum b/blake2s/_asm/go.sum new file mode 100644 index 0000000000..39dd154050 --- /dev/null +++ b/blake2s/_asm/go.sum @@ -0,0 +1,12 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/blake2s/blake2s.go b/blake2s/blake2s.go index 5fb4a9ecd1..c25d07d4f4 100644 --- a/blake2s/blake2s.go +++ b/blake2s/blake2s.go @@ -5,6 +5,8 @@ // Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 // and the extendable output function (XOF) BLAKE2Xs. // +// BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any +// size between 1 and 32 bytes. // For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf // and for BLAKE2Xs see https://blake2.net/blake2x.pdf // @@ -14,9 +16,10 @@ // // BLAKE2X is a construction to compute hash values larger than 32 bytes. It // can produce hash values between 0 and 65535 bytes. -package blake2s // import "golang.org/x/crypto/blake2s" +package blake2s import ( + "crypto" "encoding/binary" "errors" "hash" @@ -53,6 +56,13 @@ func Sum256(data []byte) [Size]byte { // and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } +func init() { + crypto.RegisterHash(crypto.BLAKE2s_256, func() hash.Hash { + h, _ := New256(nil) + return h + }) +} + // New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a // non-empty key. Note that a 128-bit digest is too small to be secure as a // cryptographic hash and should only be used as a MAC, thus the key argument diff --git a/blake2s/blake2s_386.go b/blake2s/blake2s_386.go index d8f9cea938..97f629617e 100644 --- a/blake2s/blake2s_386.go +++ b/blake2s/blake2s_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386,!gccgo,!appengine +//go:build 386 && gc && !purego package blake2s diff --git a/blake2s/blake2s_386.s b/blake2s/blake2s_386.s index c123e5d608..919c026541 100644 --- a/blake2s/blake2s_386.s +++ b/blake2s/blake2s_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386,!gccgo,!appengine +//go:build 386 && gc && !purego #include "textflag.h" @@ -297,19 +297,17 @@ TEXT ·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment MOVL blocks_base+12(FP), SI MOVL blocks_len+16(FP), DX - MOVL SP, BP MOVL SP, DI ADDL $15, DI ANDL $~15, DI - MOVL DI, SP - MOVL CX, 8(SP) + MOVL CX, 8(DI) MOVL 0(BX), CX - MOVL CX, 0(SP) + MOVL CX, 0(DI) MOVL 4(BX), CX - MOVL CX, 4(SP) + MOVL CX, 4(DI) XORL CX, CX - MOVL CX, 12(SP) + MOVL CX, 12(DI) MOVOU 0(AX), X0 MOVOU 16(AX), X1 @@ -321,22 +319,22 @@ loop: MOVOU iv0<>(SB), X6 MOVOU iv1<>(SB), X7 - MOVO 0(SP), X3 + MOVO 0(DI), X3 PADDQ X2, X3 PXOR X3, X7 - MOVO X3, 0(SP) - - PRECOMPUTE(SP, 16, SI, CX) - ROUND_SSE2(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X3) - ROUND_SSE2(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X3) + MOVO X3, 0(DI) + + PRECOMPUTE(DI, 16, SI, CX) + ROUND_SSE2(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3) PXOR X4, X0 PXOR X5, X1 @@ -347,15 +345,14 @@ loop: SUBL $64, DX JNE loop - MOVL 0(SP), CX + MOVL 0(DI), CX MOVL CX, 0(BX) - MOVL 4(SP), CX + MOVL 4(DI), CX MOVL CX, 4(BX) MOVOU X0, 0(AX) MOVOU X1, 16(AX) - MOVL BP, SP RET // func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) @@ -366,54 +363,52 @@ TEXT ·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment MOVL blocks_base+12(FP), SI MOVL blocks_len+16(FP), DX - MOVL SP, BP MOVL SP, DI ADDL $15, DI ANDL $~15, DI - MOVL DI, SP - MOVL CX, 8(SP) + MOVL CX, 8(DI) MOVL 0(BX), CX - MOVL CX, 0(SP) + MOVL CX, 0(DI) MOVL 4(BX), CX - MOVL CX, 4(SP) + MOVL CX, 4(DI) XORL CX, CX - MOVL CX, 12(SP) + MOVL CX, 12(DI) MOVOU 0(AX), X0 MOVOU 16(AX), X1 MOVOU counter<>(SB), X2 loop: - MOVO X0, 656(SP) - MOVO X1, 672(SP) + MOVO X0, 656(DI) + MOVO X1, 672(DI) MOVO X0, X4 MOVO X1, X5 MOVOU iv0<>(SB), X6 MOVOU iv1<>(SB), X7 - MOVO 0(SP), X3 + MOVO 0(DI), X3 PADDQ X2, X3 PXOR X3, X7 - MOVO X3, 0(SP) + MOVO X3, 0(DI) MOVOU rol16<>(SB), X0 MOVOU rol8<>(SB), X1 - PRECOMPUTE(SP, 16, SI, CX) - ROUND_SSSE3(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X3, X0, X1) - ROUND_SSSE3(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X3, X0, X1) - - MOVO 656(SP), X0 - MOVO 672(SP), X1 + PRECOMPUTE(DI, 16, SI, CX) + ROUND_SSSE3(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3, X0, X1) + + MOVO 656(DI), X0 + MOVO 672(DI), X1 PXOR X4, X0 PXOR X5, X1 PXOR X6, X0 @@ -423,13 +418,12 @@ loop: SUBL $64, DX JNE loop - MOVL 0(SP), CX + MOVL 0(DI), CX MOVL CX, 0(BX) - MOVL 4(SP), CX + MOVL 4(DI), CX MOVL CX, 4(BX) MOVOU X0, 0(AX) MOVOU X1, 16(AX) - MOVL BP, SP RET diff --git a/blake2s/blake2s_amd64.go b/blake2s/blake2s_amd64.go index 4e8d2d7452..8a7310254e 100644 --- a/blake2s/blake2s_amd64.go +++ b/blake2s/blake2s_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego package blake2s diff --git a/blake2s/blake2s_amd64.s b/blake2s/blake2s_amd64.s index 8da280262e..57d510fc08 100644 --- a/blake2s/blake2s_amd64.s +++ b/blake2s/blake2s_amd64.s @@ -1,438 +1,2173 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run blake2s_amd64_asm.go -out ../blake2s_amd64.s -pkg blake2s. DO NOT EDIT. -// +build amd64,!gccgo,!appengine +//go:build amd64 && gc && !purego #include "textflag.h" -DATA iv0<>+0x00(SB)/4, $0x6a09e667 -DATA iv0<>+0x04(SB)/4, $0xbb67ae85 -DATA iv0<>+0x08(SB)/4, $0x3c6ef372 -DATA iv0<>+0x0c(SB)/4, $0xa54ff53a -GLOBL iv0<>(SB), (NOPTR+RODATA), $16 - -DATA iv1<>+0x00(SB)/4, $0x510e527f -DATA iv1<>+0x04(SB)/4, $0x9b05688c -DATA iv1<>+0x08(SB)/4, $0x1f83d9ab -DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 -GLOBL iv1<>(SB), (NOPTR+RODATA), $16 - -DATA rol16<>+0x00(SB)/8, $0x0504070601000302 -DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -GLOBL rol16<>(SB), (NOPTR+RODATA), $16 - -DATA rol8<>+0x00(SB)/8, $0x0407060500030201 -DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 -GLOBL rol8<>(SB), (NOPTR+RODATA), $16 - -DATA counter<>+0x00(SB)/8, $0x40 -DATA counter<>+0x08(SB)/8, $0x0 -GLOBL counter<>(SB), (NOPTR+RODATA), $16 - -#define ROTL_SSE2(n, t, v) \ - MOVO v, t; \ - PSLLL $n, t; \ - PSRLL $(32-n), v; \ - PXOR t, v - -#define ROTL_SSSE3(c, v) \ - PSHUFB c, v - -#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ - PADDL m0, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSE2(16, t, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(20, t, v1); \ - PADDL m1, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSE2(24, t, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(25, t, v1); \ - PSHUFL $0x39, v1, v1; \ - PSHUFL $0x4E, v2, v2; \ - PSHUFL $0x93, v3, v3; \ - PADDL m2, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSE2(16, t, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(20, t, v1); \ - PADDL m3, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSE2(24, t, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(25, t, v1); \ - PSHUFL $0x39, v3, v3; \ - PSHUFL $0x4E, v2, v2; \ - PSHUFL $0x93, v1, v1 - -#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ - PADDL m0, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSSE3(c16, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(20, t, v1); \ - PADDL m1, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSSE3(c8, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(25, t, v1); \ - PSHUFL $0x39, v1, v1; \ - PSHUFL $0x4E, v2, v2; \ - PSHUFL $0x93, v3, v3; \ - PADDL m2, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSSE3(c16, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(20, t, v1); \ - PADDL m3, v0; \ - PADDL v1, v0; \ - PXOR v0, v3; \ - ROTL_SSSE3(c8, v3); \ - PADDL v3, v2; \ - PXOR v2, v1; \ - ROTL_SSE2(25, t, v1); \ - PSHUFL $0x39, v3, v3; \ - PSHUFL $0x4E, v2, v2; \ - PSHUFL $0x93, v1, v1 - - -#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \ - MOVL i0*4(src), m0; \ - PINSRD $1, i1*4(src), m0; \ - PINSRD $2, i2*4(src), m0; \ - PINSRD $3, i3*4(src), m0; \ - MOVL i4*4(src), m1; \ - PINSRD $1, i5*4(src), m1; \ - PINSRD $2, i6*4(src), m1; \ - PINSRD $3, i7*4(src), m1; \ - MOVL i8*4(src), m2; \ - PINSRD $1, i9*4(src), m2; \ - PINSRD $2, i10*4(src), m2; \ - PINSRD $3, i11*4(src), m2; \ - MOVL i12*4(src), m3; \ - PINSRD $1, i13*4(src), m3; \ - PINSRD $2, i14*4(src), m3; \ - PINSRD $3, i15*4(src), m3 +// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +// Requires: SSE2 +TEXT ·hashBlocksSSE2(SB), $672-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVL flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DX + MOVQ SP, BP + ADDQ $0x0f, BP + ANDQ $-16, BP + MOVQ (BX), R9 + MOVQ R9, (BP) + MOVQ CX, 8(BP) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU iv0<>+0(SB), X2 + MOVOU iv1<>+0(SB), X3 + MOVOU counter<>+0(SB), X12 + MOVOU rol16<>+0(SB), X13 + MOVOU rol8<>+0(SB), X14 + MOVO (BP), X15 -#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \ - MOVQ 0*4(src), R8; \ - MOVQ 2*4(src), R9; \ - MOVQ 4*4(src), R10; \ - MOVQ 6*4(src), R11; \ - MOVQ 8*4(src), R12; \ - MOVQ 10*4(src), R13; \ - MOVQ 12*4(src), R14; \ - MOVQ 14*4(src), R15; \ - \ - MOVL R8, 0*4+off+0(dst); \ - MOVL R8, 9*4+off+64(dst); \ - MOVL R8, 5*4+off+128(dst); \ - MOVL R8, 14*4+off+192(dst); \ - MOVL R8, 4*4+off+256(dst); \ - MOVL R8, 2*4+off+320(dst); \ - MOVL R8, 8*4+off+384(dst); \ - MOVL R8, 12*4+off+448(dst); \ - MOVL R8, 3*4+off+512(dst); \ - MOVL R8, 15*4+off+576(dst); \ - SHRQ $32, R8; \ - MOVL R8, 4*4+off+0(dst); \ - MOVL R8, 8*4+off+64(dst); \ - MOVL R8, 14*4+off+128(dst); \ - MOVL R8, 5*4+off+192(dst); \ - MOVL R8, 12*4+off+256(dst); \ - MOVL R8, 11*4+off+320(dst); \ - MOVL R8, 1*4+off+384(dst); \ - MOVL R8, 6*4+off+448(dst); \ - MOVL R8, 10*4+off+512(dst); \ - MOVL R8, 3*4+off+576(dst); \ - \ - MOVL R9, 1*4+off+0(dst); \ - MOVL R9, 13*4+off+64(dst); \ - MOVL R9, 6*4+off+128(dst); \ - MOVL R9, 8*4+off+192(dst); \ - MOVL R9, 2*4+off+256(dst); \ - MOVL R9, 0*4+off+320(dst); \ - MOVL R9, 14*4+off+384(dst); \ - MOVL R9, 11*4+off+448(dst); \ - MOVL R9, 12*4+off+512(dst); \ - MOVL R9, 4*4+off+576(dst); \ - SHRQ $32, R9; \ - MOVL R9, 5*4+off+0(dst); \ - MOVL R9, 15*4+off+64(dst); \ - MOVL R9, 9*4+off+128(dst); \ - MOVL R9, 1*4+off+192(dst); \ - MOVL R9, 11*4+off+256(dst); \ - MOVL R9, 7*4+off+320(dst); \ - MOVL R9, 13*4+off+384(dst); \ - MOVL R9, 3*4+off+448(dst); \ - MOVL R9, 6*4+off+512(dst); \ - MOVL R9, 10*4+off+576(dst); \ - \ - MOVL R10, 2*4+off+0(dst); \ - MOVL R10, 1*4+off+64(dst); \ - MOVL R10, 15*4+off+128(dst); \ - MOVL R10, 10*4+off+192(dst); \ - MOVL R10, 6*4+off+256(dst); \ - MOVL R10, 8*4+off+320(dst); \ - MOVL R10, 3*4+off+384(dst); \ - MOVL R10, 13*4+off+448(dst); \ - MOVL R10, 14*4+off+512(dst); \ - MOVL R10, 5*4+off+576(dst); \ - SHRQ $32, R10; \ - MOVL R10, 6*4+off+0(dst); \ - MOVL R10, 11*4+off+64(dst); \ - MOVL R10, 2*4+off+128(dst); \ - MOVL R10, 9*4+off+192(dst); \ - MOVL R10, 1*4+off+256(dst); \ - MOVL R10, 13*4+off+320(dst); \ - MOVL R10, 4*4+off+384(dst); \ - MOVL R10, 8*4+off+448(dst); \ - MOVL R10, 15*4+off+512(dst); \ - MOVL R10, 7*4+off+576(dst); \ - \ - MOVL R11, 3*4+off+0(dst); \ - MOVL R11, 7*4+off+64(dst); \ - MOVL R11, 13*4+off+128(dst); \ - MOVL R11, 12*4+off+192(dst); \ - MOVL R11, 10*4+off+256(dst); \ - MOVL R11, 1*4+off+320(dst); \ - MOVL R11, 9*4+off+384(dst); \ - MOVL R11, 14*4+off+448(dst); \ - MOVL R11, 0*4+off+512(dst); \ - MOVL R11, 6*4+off+576(dst); \ - SHRQ $32, R11; \ - MOVL R11, 7*4+off+0(dst); \ - MOVL R11, 14*4+off+64(dst); \ - MOVL R11, 10*4+off+128(dst); \ - MOVL R11, 0*4+off+192(dst); \ - MOVL R11, 5*4+off+256(dst); \ - MOVL R11, 9*4+off+320(dst); \ - MOVL R11, 12*4+off+384(dst); \ - MOVL R11, 1*4+off+448(dst); \ - MOVL R11, 13*4+off+512(dst); \ - MOVL R11, 2*4+off+576(dst); \ - \ - MOVL R12, 8*4+off+0(dst); \ - MOVL R12, 5*4+off+64(dst); \ - MOVL R12, 4*4+off+128(dst); \ - MOVL R12, 15*4+off+192(dst); \ - MOVL R12, 14*4+off+256(dst); \ - MOVL R12, 3*4+off+320(dst); \ - MOVL R12, 11*4+off+384(dst); \ - MOVL R12, 10*4+off+448(dst); \ - MOVL R12, 7*4+off+512(dst); \ - MOVL R12, 1*4+off+576(dst); \ - SHRQ $32, R12; \ - MOVL R12, 12*4+off+0(dst); \ - MOVL R12, 2*4+off+64(dst); \ - MOVL R12, 11*4+off+128(dst); \ - MOVL R12, 4*4+off+192(dst); \ - MOVL R12, 0*4+off+256(dst); \ - MOVL R12, 15*4+off+320(dst); \ - MOVL R12, 10*4+off+384(dst); \ - MOVL R12, 7*4+off+448(dst); \ - MOVL R12, 5*4+off+512(dst); \ - MOVL R12, 9*4+off+576(dst); \ - \ - MOVL R13, 9*4+off+0(dst); \ - MOVL R13, 4*4+off+64(dst); \ - MOVL R13, 8*4+off+128(dst); \ - MOVL R13, 13*4+off+192(dst); \ - MOVL R13, 3*4+off+256(dst); \ - MOVL R13, 5*4+off+320(dst); \ - MOVL R13, 7*4+off+384(dst); \ - MOVL R13, 15*4+off+448(dst); \ - MOVL R13, 11*4+off+512(dst); \ - MOVL R13, 0*4+off+576(dst); \ - SHRQ $32, R13; \ - MOVL R13, 13*4+off+0(dst); \ - MOVL R13, 10*4+off+64(dst); \ - MOVL R13, 0*4+off+128(dst); \ - MOVL R13, 3*4+off+192(dst); \ - MOVL R13, 9*4+off+256(dst); \ - MOVL R13, 6*4+off+320(dst); \ - MOVL R13, 15*4+off+384(dst); \ - MOVL R13, 4*4+off+448(dst); \ - MOVL R13, 2*4+off+512(dst); \ - MOVL R13, 12*4+off+576(dst); \ - \ - MOVL R14, 10*4+off+0(dst); \ - MOVL R14, 12*4+off+64(dst); \ - MOVL R14, 1*4+off+128(dst); \ - MOVL R14, 6*4+off+192(dst); \ - MOVL R14, 13*4+off+256(dst); \ - MOVL R14, 4*4+off+320(dst); \ - MOVL R14, 0*4+off+384(dst); \ - MOVL R14, 2*4+off+448(dst); \ - MOVL R14, 8*4+off+512(dst); \ - MOVL R14, 14*4+off+576(dst); \ - SHRQ $32, R14; \ - MOVL R14, 14*4+off+0(dst); \ - MOVL R14, 3*4+off+64(dst); \ - MOVL R14, 7*4+off+128(dst); \ - MOVL R14, 2*4+off+192(dst); \ - MOVL R14, 15*4+off+256(dst); \ - MOVL R14, 12*4+off+320(dst); \ - MOVL R14, 6*4+off+384(dst); \ - MOVL R14, 0*4+off+448(dst); \ - MOVL R14, 9*4+off+512(dst); \ - MOVL R14, 11*4+off+576(dst); \ - \ - MOVL R15, 11*4+off+0(dst); \ - MOVL R15, 0*4+off+64(dst); \ - MOVL R15, 12*4+off+128(dst); \ - MOVL R15, 7*4+off+192(dst); \ - MOVL R15, 8*4+off+256(dst); \ - MOVL R15, 14*4+off+320(dst); \ - MOVL R15, 2*4+off+384(dst); \ - MOVL R15, 5*4+off+448(dst); \ - MOVL R15, 1*4+off+512(dst); \ - MOVL R15, 13*4+off+576(dst); \ - SHRQ $32, R15; \ - MOVL R15, 15*4+off+0(dst); \ - MOVL R15, 6*4+off+64(dst); \ - MOVL R15, 3*4+off+128(dst); \ - MOVL R15, 11*4+off+192(dst); \ - MOVL R15, 7*4+off+256(dst); \ - MOVL R15, 10*4+off+320(dst); \ - MOVL R15, 5*4+off+384(dst); \ - MOVL R15, 9*4+off+448(dst); \ - MOVL R15, 4*4+off+512(dst); \ - MOVL R15, 8*4+off+576(dst) +loop: + MOVO X0, X4 + MOVO X1, X5 + MOVO X2, X6 + MOVO X3, X7 + PADDQ X12, X15 + PXOR X15, X7 + MOVQ (SI), R8 + MOVQ 8(SI), R9 + MOVQ 16(SI), R10 + MOVQ 24(SI), R11 + MOVQ 32(SI), R12 + MOVQ 40(SI), R13 + MOVQ 48(SI), R14 + MOVQ 56(SI), R15 + MOVL R8, 16(BP) + MOVL R8, 116(BP) + MOVL R8, 164(BP) + MOVL R8, 264(BP) + MOVL R8, 288(BP) + MOVL R8, 344(BP) + MOVL R8, 432(BP) + MOVL R8, 512(BP) + MOVL R8, 540(BP) + MOVL R8, 652(BP) + SHRQ $0x20, R8 + MOVL R8, 32(BP) + MOVL R8, 112(BP) + MOVL R8, 200(BP) + MOVL R8, 228(BP) + MOVL R8, 320(BP) + MOVL R8, 380(BP) + MOVL R8, 404(BP) + MOVL R8, 488(BP) + MOVL R8, 568(BP) + MOVL R8, 604(BP) + MOVL R9, 20(BP) + MOVL R9, 132(BP) + MOVL R9, 168(BP) + MOVL R9, 240(BP) + MOVL R9, 280(BP) + MOVL R9, 336(BP) + MOVL R9, 456(BP) + MOVL R9, 508(BP) + MOVL R9, 576(BP) + MOVL R9, 608(BP) + SHRQ $0x20, R9 + MOVL R9, 36(BP) + MOVL R9, 140(BP) + MOVL R9, 180(BP) + MOVL R9, 212(BP) + MOVL R9, 316(BP) + MOVL R9, 364(BP) + MOVL R9, 452(BP) + MOVL R9, 476(BP) + MOVL R9, 552(BP) + MOVL R9, 632(BP) + MOVL R10, 24(BP) + MOVL R10, 84(BP) + MOVL R10, 204(BP) + MOVL R10, 248(BP) + MOVL R10, 296(BP) + MOVL R10, 368(BP) + MOVL R10, 412(BP) + MOVL R10, 516(BP) + MOVL R10, 584(BP) + MOVL R10, 612(BP) + SHRQ $0x20, R10 + MOVL R10, 40(BP) + MOVL R10, 124(BP) + MOVL R10, 152(BP) + MOVL R10, 244(BP) + MOVL R10, 276(BP) + MOVL R10, 388(BP) + MOVL R10, 416(BP) + MOVL R10, 496(BP) + MOVL R10, 588(BP) + MOVL R10, 620(BP) + MOVL R11, 28(BP) + MOVL R11, 108(BP) + MOVL R11, 196(BP) + MOVL R11, 256(BP) + MOVL R11, 312(BP) + MOVL R11, 340(BP) + MOVL R11, 436(BP) + MOVL R11, 520(BP) + MOVL R11, 528(BP) + MOVL R11, 616(BP) + SHRQ $0x20, R11 + MOVL R11, 44(BP) + MOVL R11, 136(BP) + MOVL R11, 184(BP) + MOVL R11, 208(BP) + MOVL R11, 292(BP) + MOVL R11, 372(BP) + MOVL R11, 448(BP) + MOVL R11, 468(BP) + MOVL R11, 580(BP) + MOVL R11, 600(BP) + MOVL R12, 48(BP) + MOVL R12, 100(BP) + MOVL R12, 160(BP) + MOVL R12, 268(BP) + MOVL R12, 328(BP) + MOVL R12, 348(BP) + MOVL R12, 444(BP) + MOVL R12, 504(BP) + MOVL R12, 556(BP) + MOVL R12, 596(BP) + SHRQ $0x20, R12 + MOVL R12, 64(BP) + MOVL R12, 88(BP) + MOVL R12, 188(BP) + MOVL R12, 224(BP) + MOVL R12, 272(BP) + MOVL R12, 396(BP) + MOVL R12, 440(BP) + MOVL R12, 492(BP) + MOVL R12, 548(BP) + MOVL R12, 628(BP) + MOVL R13, 52(BP) + MOVL R13, 96(BP) + MOVL R13, 176(BP) + MOVL R13, 260(BP) + MOVL R13, 284(BP) + MOVL R13, 356(BP) + MOVL R13, 428(BP) + MOVL R13, 524(BP) + MOVL R13, 572(BP) + MOVL R13, 592(BP) + SHRQ $0x20, R13 + MOVL R13, 68(BP) + MOVL R13, 120(BP) + MOVL R13, 144(BP) + MOVL R13, 220(BP) + MOVL R13, 308(BP) + MOVL R13, 360(BP) + MOVL R13, 460(BP) + MOVL R13, 480(BP) + MOVL R13, 536(BP) + MOVL R13, 640(BP) + MOVL R14, 56(BP) + MOVL R14, 128(BP) + MOVL R14, 148(BP) + MOVL R14, 232(BP) + MOVL R14, 324(BP) + MOVL R14, 352(BP) + MOVL R14, 400(BP) + MOVL R14, 472(BP) + MOVL R14, 560(BP) + MOVL R14, 648(BP) + SHRQ $0x20, R14 + MOVL R14, 72(BP) + MOVL R14, 92(BP) + MOVL R14, 172(BP) + MOVL R14, 216(BP) + MOVL R14, 332(BP) + MOVL R14, 384(BP) + MOVL R14, 424(BP) + MOVL R14, 464(BP) + MOVL R14, 564(BP) + MOVL R14, 636(BP) + MOVL R15, 60(BP) + MOVL R15, 80(BP) + MOVL R15, 192(BP) + MOVL R15, 236(BP) + MOVL R15, 304(BP) + MOVL R15, 392(BP) + MOVL R15, 408(BP) + MOVL R15, 484(BP) + MOVL R15, 532(BP) + MOVL R15, 644(BP) + SHRQ $0x20, R15 + MOVL R15, 76(BP) + MOVL R15, 104(BP) + MOVL R15, 156(BP) + MOVL R15, 252(BP) + MOVL R15, 300(BP) + MOVL R15, 376(BP) + MOVL R15, 420(BP) + MOVL R15, 500(BP) + MOVL R15, 544(BP) + MOVL R15, 624(BP) + PADDL 16(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 32(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 48(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 64(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 80(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 96(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 112(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 128(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 144(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 160(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 176(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 192(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 208(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 224(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 240(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 256(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 272(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 288(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 304(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 320(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 336(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 352(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 368(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 384(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 400(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 416(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 432(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 448(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 464(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 480(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 496(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 512(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 528(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 544(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 560(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 576(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 592(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 608(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 624(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x10, X8 + PSRLL $0x10, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 640(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + MOVO X7, X8 + PSLLL $0x18, X8 + PSRLL $0x08, X7 + PXOR X8, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + LEAQ 64(SI), SI + SUBQ $0x40, DX + JNE loop + MOVO X15, (BP) + MOVQ (BP), R9 + MOVQ R9, (BX) + MOVOU X0, (AX) + MOVOU X1, 16(AX) + RET -#define BLAKE2s_SSE2() \ - PRECOMPUTE_MSG(SP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ - ROUND_SSE2(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X8); \ - ROUND_SSE2(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X8) +DATA iv0<>+0(SB)/4, $0x6a09e667 +DATA iv0<>+4(SB)/4, $0xbb67ae85 +DATA iv0<>+8(SB)/4, $0x3c6ef372 +DATA iv0<>+12(SB)/4, $0xa54ff53a +GLOBL iv0<>(SB), RODATA|NOPTR, $16 -#define BLAKE2s_SSSE3() \ - PRECOMPUTE_MSG(SP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ - ROUND_SSSE3(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X8, X13, X14); \ - ROUND_SSSE3(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X8, X13, X14) +DATA iv1<>+0(SB)/4, $0x510e527f +DATA iv1<>+4(SB)/4, $0x9b05688c +DATA iv1<>+8(SB)/4, $0x1f83d9ab +DATA iv1<>+12(SB)/4, $0x5be0cd19 +GLOBL iv1<>(SB), RODATA|NOPTR, $16 -#define BLAKE2s_SSE4() \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ - LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \ - ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) +DATA counter<>+0(SB)/8, $0x0000000000000040 +DATA counter<>+8(SB)/8, $0x0000000000000000 +GLOBL counter<>(SB), RODATA|NOPTR, $16 -#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \ - MOVQ h, AX; \ - MOVQ c, BX; \ - MOVL flag, CX; \ - MOVQ blocks_base, SI; \ - MOVQ blocks_len, DX; \ - \ - MOVQ SP, BP; \ - MOVQ SP, R9; \ - ADDQ $15, R9; \ - ANDQ $~15, R9; \ - MOVQ R9, SP; \ - \ - MOVQ 0(BX), R9; \ - MOVQ R9, 0(SP); \ - XORQ R9, R9; \ - MOVQ R9, 8(SP); \ - MOVL CX, 8(SP); \ - \ - MOVOU 0(AX), X0; \ - MOVOU 16(AX), X1; \ - MOVOU iv0<>(SB), X2; \ - MOVOU iv1<>(SB), X3 \ - \ - MOVOU counter<>(SB), X12; \ - MOVOU rol16<>(SB), X13; \ - MOVOU rol8<>(SB), X14; \ - MOVO 0(SP), X15; \ - \ - loop: \ - MOVO X0, X4; \ - MOVO X1, X5; \ - MOVO X2, X6; \ - MOVO X3, X7; \ - \ - PADDQ X12, X15; \ - PXOR X15, X7; \ - \ - BLAKE2s_FUNC(); \ - \ - PXOR X4, X0; \ - PXOR X5, X1; \ - PXOR X6, X0; \ - PXOR X7, X1; \ - \ - LEAQ 64(SI), SI; \ - SUBQ $64, DX; \ - JNE loop; \ - \ - MOVO X15, 0(SP); \ - MOVQ 0(SP), R9; \ - MOVQ R9, 0(BX); \ - \ - MOVOU X0, 0(AX); \ - MOVOU X1, 16(AX); \ - \ - MOVQ BP, SP +DATA rol16<>+0(SB)/8, $0x0504070601000302 +DATA rol16<>+8(SB)/8, $0x0d0c0f0e09080b0a +GLOBL rol16<>(SB), RODATA|NOPTR, $16 -// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -TEXT ·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment - HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2) - RET +DATA rol8<>+0(SB)/8, $0x0407060500030201 +DATA rol8<>+8(SB)/8, $0x0c0f0e0d080b0a09 +GLOBL rol8<>(SB), RODATA|NOPTR, $16 // func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment - HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3) +// Requires: SSE2, SSSE3 +TEXT ·hashBlocksSSSE3(SB), $672-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVL flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DX + MOVQ SP, BP + ADDQ $0x0f, BP + ANDQ $-16, BP + MOVQ (BX), R9 + MOVQ R9, (BP) + MOVQ CX, 8(BP) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU iv0<>+0(SB), X2 + MOVOU iv1<>+0(SB), X3 + MOVOU counter<>+0(SB), X12 + MOVOU rol16<>+0(SB), X13 + MOVOU rol8<>+0(SB), X14 + MOVO (BP), X15 + +loop: + MOVO X0, X4 + MOVO X1, X5 + MOVO X2, X6 + MOVO X3, X7 + PADDQ X12, X15 + PXOR X15, X7 + MOVQ (SI), R8 + MOVQ 8(SI), R9 + MOVQ 16(SI), R10 + MOVQ 24(SI), R11 + MOVQ 32(SI), R12 + MOVQ 40(SI), R13 + MOVQ 48(SI), R14 + MOVQ 56(SI), R15 + MOVL R8, 16(BP) + MOVL R8, 116(BP) + MOVL R8, 164(BP) + MOVL R8, 264(BP) + MOVL R8, 288(BP) + MOVL R8, 344(BP) + MOVL R8, 432(BP) + MOVL R8, 512(BP) + MOVL R8, 540(BP) + MOVL R8, 652(BP) + SHRQ $0x20, R8 + MOVL R8, 32(BP) + MOVL R8, 112(BP) + MOVL R8, 200(BP) + MOVL R8, 228(BP) + MOVL R8, 320(BP) + MOVL R8, 380(BP) + MOVL R8, 404(BP) + MOVL R8, 488(BP) + MOVL R8, 568(BP) + MOVL R8, 604(BP) + MOVL R9, 20(BP) + MOVL R9, 132(BP) + MOVL R9, 168(BP) + MOVL R9, 240(BP) + MOVL R9, 280(BP) + MOVL R9, 336(BP) + MOVL R9, 456(BP) + MOVL R9, 508(BP) + MOVL R9, 576(BP) + MOVL R9, 608(BP) + SHRQ $0x20, R9 + MOVL R9, 36(BP) + MOVL R9, 140(BP) + MOVL R9, 180(BP) + MOVL R9, 212(BP) + MOVL R9, 316(BP) + MOVL R9, 364(BP) + MOVL R9, 452(BP) + MOVL R9, 476(BP) + MOVL R9, 552(BP) + MOVL R9, 632(BP) + MOVL R10, 24(BP) + MOVL R10, 84(BP) + MOVL R10, 204(BP) + MOVL R10, 248(BP) + MOVL R10, 296(BP) + MOVL R10, 368(BP) + MOVL R10, 412(BP) + MOVL R10, 516(BP) + MOVL R10, 584(BP) + MOVL R10, 612(BP) + SHRQ $0x20, R10 + MOVL R10, 40(BP) + MOVL R10, 124(BP) + MOVL R10, 152(BP) + MOVL R10, 244(BP) + MOVL R10, 276(BP) + MOVL R10, 388(BP) + MOVL R10, 416(BP) + MOVL R10, 496(BP) + MOVL R10, 588(BP) + MOVL R10, 620(BP) + MOVL R11, 28(BP) + MOVL R11, 108(BP) + MOVL R11, 196(BP) + MOVL R11, 256(BP) + MOVL R11, 312(BP) + MOVL R11, 340(BP) + MOVL R11, 436(BP) + MOVL R11, 520(BP) + MOVL R11, 528(BP) + MOVL R11, 616(BP) + SHRQ $0x20, R11 + MOVL R11, 44(BP) + MOVL R11, 136(BP) + MOVL R11, 184(BP) + MOVL R11, 208(BP) + MOVL R11, 292(BP) + MOVL R11, 372(BP) + MOVL R11, 448(BP) + MOVL R11, 468(BP) + MOVL R11, 580(BP) + MOVL R11, 600(BP) + MOVL R12, 48(BP) + MOVL R12, 100(BP) + MOVL R12, 160(BP) + MOVL R12, 268(BP) + MOVL R12, 328(BP) + MOVL R12, 348(BP) + MOVL R12, 444(BP) + MOVL R12, 504(BP) + MOVL R12, 556(BP) + MOVL R12, 596(BP) + SHRQ $0x20, R12 + MOVL R12, 64(BP) + MOVL R12, 88(BP) + MOVL R12, 188(BP) + MOVL R12, 224(BP) + MOVL R12, 272(BP) + MOVL R12, 396(BP) + MOVL R12, 440(BP) + MOVL R12, 492(BP) + MOVL R12, 548(BP) + MOVL R12, 628(BP) + MOVL R13, 52(BP) + MOVL R13, 96(BP) + MOVL R13, 176(BP) + MOVL R13, 260(BP) + MOVL R13, 284(BP) + MOVL R13, 356(BP) + MOVL R13, 428(BP) + MOVL R13, 524(BP) + MOVL R13, 572(BP) + MOVL R13, 592(BP) + SHRQ $0x20, R13 + MOVL R13, 68(BP) + MOVL R13, 120(BP) + MOVL R13, 144(BP) + MOVL R13, 220(BP) + MOVL R13, 308(BP) + MOVL R13, 360(BP) + MOVL R13, 460(BP) + MOVL R13, 480(BP) + MOVL R13, 536(BP) + MOVL R13, 640(BP) + MOVL R14, 56(BP) + MOVL R14, 128(BP) + MOVL R14, 148(BP) + MOVL R14, 232(BP) + MOVL R14, 324(BP) + MOVL R14, 352(BP) + MOVL R14, 400(BP) + MOVL R14, 472(BP) + MOVL R14, 560(BP) + MOVL R14, 648(BP) + SHRQ $0x20, R14 + MOVL R14, 72(BP) + MOVL R14, 92(BP) + MOVL R14, 172(BP) + MOVL R14, 216(BP) + MOVL R14, 332(BP) + MOVL R14, 384(BP) + MOVL R14, 424(BP) + MOVL R14, 464(BP) + MOVL R14, 564(BP) + MOVL R14, 636(BP) + MOVL R15, 60(BP) + MOVL R15, 80(BP) + MOVL R15, 192(BP) + MOVL R15, 236(BP) + MOVL R15, 304(BP) + MOVL R15, 392(BP) + MOVL R15, 408(BP) + MOVL R15, 484(BP) + MOVL R15, 532(BP) + MOVL R15, 644(BP) + SHRQ $0x20, R15 + MOVL R15, 76(BP) + MOVL R15, 104(BP) + MOVL R15, 156(BP) + MOVL R15, 252(BP) + MOVL R15, 300(BP) + MOVL R15, 376(BP) + MOVL R15, 420(BP) + MOVL R15, 500(BP) + MOVL R15, 544(BP) + MOVL R15, 624(BP) + PADDL 16(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 32(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 48(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 64(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 80(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 96(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 112(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 128(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 144(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 160(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 176(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 192(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 208(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 224(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 240(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 256(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 272(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 288(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 304(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 320(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 336(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 352(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 368(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 384(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 400(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 416(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 432(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 448(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 464(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 480(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 496(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 512(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 528(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 544(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 560(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 576(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PADDL 592(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 608(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL 624(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL 640(BP), X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + LEAQ 64(SI), SI + SUBQ $0x40, DX + JNE loop + MOVO X15, (BP) + MOVQ (BP), R9 + MOVQ R9, (BX) + MOVOU X0, (AX) + MOVOU X1, 16(AX) RET // func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment - HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) +// Requires: SSE2, SSE4.1, SSSE3 +TEXT ·hashBlocksSSE4(SB), $32-48 + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVL flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DX + MOVQ SP, BP + ADDQ $0x0f, BP + ANDQ $-16, BP + MOVQ (BX), R9 + MOVQ R9, (BP) + MOVQ CX, 8(BP) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU iv0<>+0(SB), X2 + MOVOU iv1<>+0(SB), X3 + MOVOU counter<>+0(SB), X12 + MOVOU rol16<>+0(SB), X13 + MOVOU rol8<>+0(SB), X14 + MOVO (BP), X15 + +loop: + MOVO X0, X4 + MOVO X1, X5 + MOVO X2, X6 + MOVO X3, X7 + PADDQ X12, X15 + PXOR X15, X7 + MOVL (SI), X8 + PINSRD $0x01, 8(SI), X8 + PINSRD $0x02, 16(SI), X8 + PINSRD $0x03, 24(SI), X8 + MOVL 4(SI), X9 + PINSRD $0x01, 12(SI), X9 + PINSRD $0x02, 20(SI), X9 + PINSRD $0x03, 28(SI), X9 + MOVL 32(SI), X10 + PINSRD $0x01, 40(SI), X10 + PINSRD $0x02, 48(SI), X10 + PINSRD $0x03, 56(SI), X10 + MOVL 36(SI), X11 + PINSRD $0x01, 44(SI), X11 + PINSRD $0x02, 52(SI), X11 + PINSRD $0x03, 60(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 56(SI), X8 + PINSRD $0x01, 16(SI), X8 + PINSRD $0x02, 36(SI), X8 + PINSRD $0x03, 52(SI), X8 + MOVL 40(SI), X9 + PINSRD $0x01, 32(SI), X9 + PINSRD $0x02, 60(SI), X9 + PINSRD $0x03, 24(SI), X9 + MOVL 4(SI), X10 + PINSRD $0x01, (SI), X10 + PINSRD $0x02, 44(SI), X10 + PINSRD $0x03, 20(SI), X10 + MOVL 48(SI), X11 + PINSRD $0x01, 8(SI), X11 + PINSRD $0x02, 28(SI), X11 + PINSRD $0x03, 12(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 44(SI), X8 + PINSRD $0x01, 48(SI), X8 + PINSRD $0x02, 20(SI), X8 + PINSRD $0x03, 60(SI), X8 + MOVL 32(SI), X9 + PINSRD $0x01, (SI), X9 + PINSRD $0x02, 8(SI), X9 + PINSRD $0x03, 52(SI), X9 + MOVL 40(SI), X10 + PINSRD $0x01, 12(SI), X10 + PINSRD $0x02, 28(SI), X10 + PINSRD $0x03, 36(SI), X10 + MOVL 56(SI), X11 + PINSRD $0x01, 24(SI), X11 + PINSRD $0x02, 4(SI), X11 + PINSRD $0x03, 16(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 28(SI), X8 + PINSRD $0x01, 12(SI), X8 + PINSRD $0x02, 52(SI), X8 + PINSRD $0x03, 44(SI), X8 + MOVL 36(SI), X9 + PINSRD $0x01, 4(SI), X9 + PINSRD $0x02, 48(SI), X9 + PINSRD $0x03, 56(SI), X9 + MOVL 8(SI), X10 + PINSRD $0x01, 20(SI), X10 + PINSRD $0x02, 16(SI), X10 + PINSRD $0x03, 60(SI), X10 + MOVL 24(SI), X11 + PINSRD $0x01, 40(SI), X11 + PINSRD $0x02, (SI), X11 + PINSRD $0x03, 32(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 36(SI), X8 + PINSRD $0x01, 20(SI), X8 + PINSRD $0x02, 8(SI), X8 + PINSRD $0x03, 40(SI), X8 + MOVL (SI), X9 + PINSRD $0x01, 28(SI), X9 + PINSRD $0x02, 16(SI), X9 + PINSRD $0x03, 60(SI), X9 + MOVL 56(SI), X10 + PINSRD $0x01, 44(SI), X10 + PINSRD $0x02, 24(SI), X10 + PINSRD $0x03, 12(SI), X10 + MOVL 4(SI), X11 + PINSRD $0x01, 48(SI), X11 + PINSRD $0x02, 32(SI), X11 + PINSRD $0x03, 52(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 8(SI), X8 + PINSRD $0x01, 24(SI), X8 + PINSRD $0x02, (SI), X8 + PINSRD $0x03, 32(SI), X8 + MOVL 48(SI), X9 + PINSRD $0x01, 40(SI), X9 + PINSRD $0x02, 44(SI), X9 + PINSRD $0x03, 12(SI), X9 + MOVL 16(SI), X10 + PINSRD $0x01, 28(SI), X10 + PINSRD $0x02, 60(SI), X10 + PINSRD $0x03, 4(SI), X10 + MOVL 52(SI), X11 + PINSRD $0x01, 20(SI), X11 + PINSRD $0x02, 56(SI), X11 + PINSRD $0x03, 36(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 48(SI), X8 + PINSRD $0x01, 4(SI), X8 + PINSRD $0x02, 56(SI), X8 + PINSRD $0x03, 16(SI), X8 + MOVL 20(SI), X9 + PINSRD $0x01, 60(SI), X9 + PINSRD $0x02, 52(SI), X9 + PINSRD $0x03, 40(SI), X9 + MOVL (SI), X10 + PINSRD $0x01, 24(SI), X10 + PINSRD $0x02, 36(SI), X10 + PINSRD $0x03, 32(SI), X10 + MOVL 28(SI), X11 + PINSRD $0x01, 12(SI), X11 + PINSRD $0x02, 8(SI), X11 + PINSRD $0x03, 44(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 52(SI), X8 + PINSRD $0x01, 28(SI), X8 + PINSRD $0x02, 48(SI), X8 + PINSRD $0x03, 12(SI), X8 + MOVL 44(SI), X9 + PINSRD $0x01, 56(SI), X9 + PINSRD $0x02, 4(SI), X9 + PINSRD $0x03, 36(SI), X9 + MOVL 20(SI), X10 + PINSRD $0x01, 60(SI), X10 + PINSRD $0x02, 32(SI), X10 + PINSRD $0x03, 8(SI), X10 + MOVL (SI), X11 + PINSRD $0x01, 16(SI), X11 + PINSRD $0x02, 24(SI), X11 + PINSRD $0x03, 40(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 24(SI), X8 + PINSRD $0x01, 56(SI), X8 + PINSRD $0x02, 44(SI), X8 + PINSRD $0x03, (SI), X8 + MOVL 60(SI), X9 + PINSRD $0x01, 36(SI), X9 + PINSRD $0x02, 12(SI), X9 + PINSRD $0x03, 32(SI), X9 + MOVL 48(SI), X10 + PINSRD $0x01, 52(SI), X10 + PINSRD $0x02, 4(SI), X10 + PINSRD $0x03, 40(SI), X10 + MOVL 8(SI), X11 + PINSRD $0x01, 28(SI), X11 + PINSRD $0x02, 16(SI), X11 + PINSRD $0x03, 20(SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + MOVL 40(SI), X8 + PINSRD $0x01, 32(SI), X8 + PINSRD $0x02, 28(SI), X8 + PINSRD $0x03, 4(SI), X8 + MOVL 8(SI), X9 + PINSRD $0x01, 16(SI), X9 + PINSRD $0x02, 24(SI), X9 + PINSRD $0x03, 20(SI), X9 + MOVL 60(SI), X10 + PINSRD $0x01, 36(SI), X10 + PINSRD $0x02, 12(SI), X10 + PINSRD $0x03, 52(SI), X10 + MOVL 44(SI), X11 + PINSRD $0x01, 56(SI), X11 + PINSRD $0x02, 48(SI), X11 + PINSRD $0x03, (SI), X11 + PADDL X8, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X9, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X5, X5 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X7, X7 + PADDL X10, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X13, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x14, X8 + PSRLL $0x0c, X5 + PXOR X8, X5 + PADDL X11, X4 + PADDL X5, X4 + PXOR X4, X7 + PSHUFB X14, X7 + PADDL X7, X6 + PXOR X6, X5 + MOVO X5, X8 + PSLLL $0x19, X8 + PSRLL $0x07, X5 + PXOR X8, X5 + PSHUFL $0x39, X7, X7 + PSHUFL $0x4e, X6, X6 + PSHUFL $0x93, X5, X5 + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + LEAQ 64(SI), SI + SUBQ $0x40, DX + JNE loop + MOVO X15, (BP) + MOVQ (BP), R9 + MOVQ R9, (BX) + MOVOU X0, (AX) + MOVOU X1, 16(AX) RET diff --git a/blake2s/blake2s_ref.go b/blake2s/blake2s_ref.go index a311273454..38ce8e283f 100644 --- a/blake2s/blake2s_ref.go +++ b/blake2s/blake2s_ref.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!386 gccgo appengine +//go:build (!amd64 && !386) || !gc || purego package blake2s diff --git a/blake2s/register.go b/blake2s/register.go deleted file mode 100644 index d277459a1c..0000000000 --- a/blake2s/register.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.9 - -package blake2s - -import ( - "crypto" - "hash" -) - -func init() { - newHash256 := func() hash.Hash { - h, _ := New256(nil) - return h - } - - crypto.RegisterHash(crypto.BLAKE2s_256, newHash256) -} diff --git a/blowfish/cipher.go b/blowfish/cipher.go index 213bf204af..0898956807 100644 --- a/blowfish/cipher.go +++ b/blowfish/cipher.go @@ -11,7 +11,7 @@ // Deprecated: any new system should use AES (from crypto/aes, if necessary in // an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from // golang.org/x/crypto/chacha20poly1305). -package blowfish // import "golang.org/x/crypto/blowfish" +package blowfish // The code is a port of Bruce Schneier's C implementation. // See https://www.schneier.com/blowfish.html. diff --git a/bn256/bn256.go b/bn256/bn256.go index 9c99fcdb5d..6661687551 100644 --- a/bn256/bn256.go +++ b/bn256/bn256.go @@ -23,7 +23,7 @@ // elliptic curve. This package is frozen, and not implemented in constant time. // There is a more complete implementation at github.com/cloudflare/bn256, but // note that it suffers from the same security issues of the underlying curve. -package bn256 // import "golang.org/x/crypto/bn256" +package bn256 import ( "crypto/rand" @@ -162,7 +162,7 @@ type G2 struct { p *twistPoint } -// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r. +// RandomG2 returns x and g₂ˣ where x is a random, non-zero number read from r. func RandomG2(r io.Reader) (*big.Int, *G2, error) { var k *big.Int var err error diff --git a/bn256/gfp12.go b/bn256/gfp12.go index 2b0151ebcc..b05a8b727f 100644 --- a/bn256/gfp12.go +++ b/bn256/gfp12.go @@ -5,7 +5,7 @@ package bn256 // For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. +// Pairing-Friendly Fields", Devegili et al. // http://eprint.iacr.org/2006/471.pdf. import ( diff --git a/bn256/gfp2.go b/bn256/gfp2.go index 97f3f1f3fa..aa39a3043b 100644 --- a/bn256/gfp2.go +++ b/bn256/gfp2.go @@ -5,7 +5,7 @@ package bn256 // For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. +// Pairing-Friendly Fields", Devegili et al. // http://eprint.iacr.org/2006/471.pdf. import ( diff --git a/bn256/gfp6.go b/bn256/gfp6.go index f98ae782cc..7dec5eabd6 100644 --- a/bn256/gfp6.go +++ b/bn256/gfp6.go @@ -5,7 +5,7 @@ package bn256 // For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. +// Pairing-Friendly Fields", Devegili et al. // http://eprint.iacr.org/2006/471.pdf. import ( diff --git a/cast5/cast5.go b/cast5/cast5.go index ddcbeb6f2a..016e90215c 100644 --- a/cast5/cast5.go +++ b/cast5/cast5.go @@ -11,9 +11,12 @@ // Deprecated: any new system should use AES (from crypto/aes, if necessary in // an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from // golang.org/x/crypto/chacha20poly1305). -package cast5 // import "golang.org/x/crypto/cast5" +package cast5 -import "errors" +import ( + "errors" + "math/bits" +) const BlockSize = 8 const KeySize = 16 @@ -241,19 +244,19 @@ func (c *Cipher) keySchedule(in []byte) { // These are the three 'f' functions. See RFC 2144, section 2.2. func f1(d, m uint32, r uint8) uint32 { t := m + d - I := (t << r) | (t >> (32 - r)) + I := bits.RotateLeft32(t, int(r)) return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] } func f2(d, m uint32, r uint8) uint32 { t := m ^ d - I := (t << r) | (t >> (32 - r)) + I := bits.RotateLeft32(t, int(r)) return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] } func f3(d, m uint32, r uint8) uint32 { t := m - d - I := (t << r) | (t >> (32 - r)) + I := bits.RotateLeft32(t, int(r)) return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] } diff --git a/chacha20/chacha_arm64.go b/chacha20/chacha_arm64.go new file mode 100644 index 0000000000..661ea132e0 --- /dev/null +++ b/chacha20/chacha_arm64.go @@ -0,0 +1,16 @@ +// 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. + +//go:build gc && !purego + +package chacha20 + +const bufSize = 256 + +//go:noescape +func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) +} diff --git a/internal/chacha20/asm_arm64.s b/chacha20/chacha_arm64.s similarity index 99% rename from internal/chacha20/asm_arm64.s rename to chacha20/chacha_arm64.s index b3a16ef751..769af387e2 100644 --- a/internal/chacha20/asm_arm64.s +++ b/chacha20/chacha_arm64.s @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.11 -// +build !gccgo,!appengine +//go:build gc && !purego #include "textflag.h" @@ -30,7 +29,7 @@ loop: MOVD $NUM_ROUNDS, R21 VLD1 (R11), [V30.S4, V31.S4] - // load contants + // load constants // VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] WORD $0x4D60E940 diff --git a/chacha20/chacha_generic.go b/chacha20/chacha_generic.go new file mode 100644 index 0000000000..93eb5ae6de --- /dev/null +++ b/chacha20/chacha_generic.go @@ -0,0 +1,398 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms +// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01. +package chacha20 + +import ( + "crypto/cipher" + "encoding/binary" + "errors" + "math/bits" + + "golang.org/x/crypto/internal/alias" +) + +const ( + // KeySize is the size of the key used by this cipher, in bytes. + KeySize = 32 + + // NonceSize is the size of the nonce used with the standard variant of this + // cipher, in bytes. + // + // Note that this is too short to be safely generated at random if the same + // key is reused more than 2³² times. + NonceSize = 12 + + // NonceSizeX is the size of the nonce used with the XChaCha20 variant of + // this cipher, in bytes. + NonceSizeX = 24 +) + +// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key +// and nonce. A *Cipher implements the cipher.Stream interface. +type Cipher struct { + // The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter + // (incremented after each block), and 3 of nonce. + key [8]uint32 + counter uint32 + nonce [3]uint32 + + // The last len bytes of buf are leftover key stream bytes from the previous + // XORKeyStream invocation. The size of buf depends on how many blocks are + // computed at a time by xorKeyStreamBlocks. + buf [bufSize]byte + len int + + // overflow is set when the counter overflowed, no more blocks can be + // generated, and the next XORKeyStream call should panic. + overflow bool + + // The counter-independent results of the first round are cached after they + // are computed the first time. + precompDone bool + p1, p5, p9, p13 uint32 + p2, p6, p10, p14 uint32 + p3, p7, p11, p15 uint32 +} + +var _ cipher.Stream = (*Cipher)(nil) + +// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given +// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided, +// the XChaCha20 construction will be used. It returns an error if key or nonce +// have any other length. +// +// Note that ChaCha20, like all stream ciphers, is not authenticated and allows +// attackers to silently tamper with the plaintext. For this reason, it is more +// appropriate as a building block than as a standalone encryption mechanism. +// Instead, consider using package golang.org/x/crypto/chacha20poly1305. +func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) { + // This function is split into a wrapper so that the Cipher allocation will + // be inlined, and depending on how the caller uses the return value, won't + // escape to the heap. + c := &Cipher{} + return newUnauthenticatedCipher(c, key, nonce) +} + +func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20: wrong key size") + } + if len(nonce) == NonceSizeX { + // XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a + // derived key, allowing it to operate on a nonce of 24 bytes. See + // draft-irtf-cfrg-xchacha-01, Section 2.3. + key, _ = HChaCha20(key, nonce[0:16]) + cNonce := make([]byte, NonceSize) + copy(cNonce[4:12], nonce[16:24]) + nonce = cNonce + } else if len(nonce) != NonceSize { + return nil, errors.New("chacha20: wrong nonce size") + } + + key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint + c.key = [8]uint32{ + binary.LittleEndian.Uint32(key[0:4]), + binary.LittleEndian.Uint32(key[4:8]), + binary.LittleEndian.Uint32(key[8:12]), + binary.LittleEndian.Uint32(key[12:16]), + binary.LittleEndian.Uint32(key[16:20]), + binary.LittleEndian.Uint32(key[20:24]), + binary.LittleEndian.Uint32(key[24:28]), + binary.LittleEndian.Uint32(key[28:32]), + } + c.nonce = [3]uint32{ + binary.LittleEndian.Uint32(nonce[0:4]), + binary.LittleEndian.Uint32(nonce[4:8]), + binary.LittleEndian.Uint32(nonce[8:12]), + } + return c, nil +} + +// The constant first 4 words of the ChaCha20 state. +const ( + j0 uint32 = 0x61707865 // expa + j1 uint32 = 0x3320646e // nd 3 + j2 uint32 = 0x79622d32 // 2-by + j3 uint32 = 0x6b206574 // te k +) + +const blockSize = 64 + +// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words. +// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16 +// words each round, in columnar or diagonal groups of 4 at a time. +func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { + a += b + d ^= a + d = bits.RotateLeft32(d, 16) + c += d + b ^= c + b = bits.RotateLeft32(b, 12) + a += b + d ^= a + d = bits.RotateLeft32(d, 8) + c += d + b ^= c + b = bits.RotateLeft32(b, 7) + return a, b, c, d +} + +// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will +// behave as if (64 * counter) bytes had been encrypted so far. +// +// To prevent accidental counter reuse, SetCounter panics if counter is less +// than the current value. +// +// Note that the execution time of XORKeyStream is not independent of the +// counter value. +func (s *Cipher) SetCounter(counter uint32) { + // Internally, s may buffer multiple blocks, which complicates this + // implementation slightly. When checking whether the counter has rolled + // back, we must use both s.counter and s.len to determine how many blocks + // we have already output. + outputCounter := s.counter - uint32(s.len)/blockSize + if s.overflow || counter < outputCounter { + panic("chacha20: SetCounter attempted to rollback counter") + } + + // In the general case, we set the new counter value and reset s.len to 0, + // causing the next call to XORKeyStream to refill the buffer. However, if + // we're advancing within the existing buffer, we can save work by simply + // setting s.len. + if counter < s.counter { + s.len = int(s.counter-counter) * blockSize + } else { + s.counter = counter + s.len = 0 + } +} + +// XORKeyStream XORs each byte in the given slice with a byte from the +// cipher's key stream. Dst and src must overlap entirely or not at all. +// +// If len(dst) < len(src), XORKeyStream will panic. It is acceptable +// to pass a dst bigger than src, and in that case, XORKeyStream will +// only update dst[:len(src)] and will not touch the rest of dst. +// +// Multiple calls to XORKeyStream behave as if the concatenation of +// the src buffers was passed in a single run. That is, Cipher +// maintains state and does not reset at each XORKeyStream call. +func (s *Cipher) XORKeyStream(dst, src []byte) { + if len(src) == 0 { + return + } + if len(dst) < len(src) { + panic("chacha20: output smaller than input") + } + dst = dst[:len(src)] + if alias.InexactOverlap(dst, src) { + panic("chacha20: invalid buffer overlap") + } + + // First, drain any remaining key stream from a previous XORKeyStream. + if s.len != 0 { + keyStream := s.buf[bufSize-s.len:] + if len(src) < len(keyStream) { + keyStream = keyStream[:len(src)] + } + _ = src[len(keyStream)-1] // bounds check elimination hint + for i, b := range keyStream { + dst[i] = src[i] ^ b + } + s.len -= len(keyStream) + dst, src = dst[len(keyStream):], src[len(keyStream):] + } + if len(src) == 0 { + return + } + + // If we'd need to let the counter overflow and keep generating output, + // panic immediately. If instead we'd only reach the last block, remember + // not to generate any more output after the buffer is drained. + numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize + if s.overflow || uint64(s.counter)+numBlocks > 1<<32 { + panic("chacha20: counter overflow") + } else if uint64(s.counter)+numBlocks == 1<<32 { + s.overflow = true + } + + // xorKeyStreamBlocks implementations expect input lengths that are a + // multiple of bufSize. Platform-specific ones process multiple blocks at a + // time, so have bufSizes that are a multiple of blockSize. + + full := len(src) - len(src)%bufSize + if full > 0 { + s.xorKeyStreamBlocks(dst[:full], src[:full]) + } + dst, src = dst[full:], src[full:] + + // If using a multi-block xorKeyStreamBlocks would overflow, use the generic + // one that does one block at a time. + const blocksPerBuf = bufSize / blockSize + if uint64(s.counter)+blocksPerBuf > 1<<32 { + s.buf = [bufSize]byte{} + numBlocks := (len(src) + blockSize - 1) / blockSize + buf := s.buf[bufSize-numBlocks*blockSize:] + copy(buf, src) + s.xorKeyStreamBlocksGeneric(buf, buf) + s.len = len(buf) - copy(dst, buf) + return + } + + // If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and + // keep the leftover keystream for the next XORKeyStream invocation. + if len(src) > 0 { + s.buf = [bufSize]byte{} + copy(s.buf[:], src) + s.xorKeyStreamBlocks(s.buf[:], s.buf[:]) + s.len = bufSize - copy(dst, s.buf[:]) + } +} + +func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { + if len(dst) != len(src) || len(dst)%blockSize != 0 { + panic("chacha20: internal error: wrong dst and/or src length") + } + + // To generate each block of key stream, the initial cipher state + // (represented below) is passed through 20 rounds of shuffling, + // alternatively applying quarterRounds by columns (like 1, 5, 9, 13) + // or by diagonals (like 1, 6, 11, 12). + // + // 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc + // 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk + // 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk + // 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn + // + // c=constant k=key b=blockcount n=nonce + var ( + c0, c1, c2, c3 = j0, j1, j2, j3 + c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3] + c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7] + _, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2] + ) + + // Three quarters of the first round don't depend on the counter, so we can + // calculate them here, and reuse them for multiple blocks in the loop, and + // for future XORKeyStream invocations. + if !s.precompDone { + s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13) + s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14) + s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15) + s.precompDone = true + } + + // A condition of len(src) > 0 would be sufficient, but this also + // acts as a bounds check elimination hint. + for len(src) >= 64 && len(dst) >= 64 { + // The remainder of the first column round. + fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter) + + // The second diagonal round. + x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15) + x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12) + x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13) + x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14) + + // The remaining 18 rounds. + for i := 0; i < 9; i++ { + // Column round. + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + // Diagonal round. + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + // Add back the initial state to generate the key stream, then + // XOR the key stream with the source and write out the result. + addXor(dst[0:4], src[0:4], x0, c0) + addXor(dst[4:8], src[4:8], x1, c1) + addXor(dst[8:12], src[8:12], x2, c2) + addXor(dst[12:16], src[12:16], x3, c3) + addXor(dst[16:20], src[16:20], x4, c4) + addXor(dst[20:24], src[20:24], x5, c5) + addXor(dst[24:28], src[24:28], x6, c6) + addXor(dst[28:32], src[28:32], x7, c7) + addXor(dst[32:36], src[32:36], x8, c8) + addXor(dst[36:40], src[36:40], x9, c9) + addXor(dst[40:44], src[40:44], x10, c10) + addXor(dst[44:48], src[44:48], x11, c11) + addXor(dst[48:52], src[48:52], x12, s.counter) + addXor(dst[52:56], src[52:56], x13, c13) + addXor(dst[56:60], src[56:60], x14, c14) + addXor(dst[60:64], src[60:64], x15, c15) + + s.counter += 1 + + src, dst = src[blockSize:], dst[blockSize:] + } +} + +// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes +// key and a 16 bytes nonce. It returns an error if key or nonce have any other +// length. It is used as part of the XChaCha20 construction. +func HChaCha20(key, nonce []byte) ([]byte, error) { + // This function is split into a wrapper so that the slice allocation will + // be inlined, and depending on how the caller uses the return value, won't + // escape to the heap. + out := make([]byte, 32) + return hChaCha20(out, key, nonce) +} + +func hChaCha20(out, key, nonce []byte) ([]byte, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20: wrong HChaCha20 key size") + } + if len(nonce) != 16 { + return nil, errors.New("chacha20: wrong HChaCha20 nonce size") + } + + x0, x1, x2, x3 := j0, j1, j2, j3 + x4 := binary.LittleEndian.Uint32(key[0:4]) + x5 := binary.LittleEndian.Uint32(key[4:8]) + x6 := binary.LittleEndian.Uint32(key[8:12]) + x7 := binary.LittleEndian.Uint32(key[12:16]) + x8 := binary.LittleEndian.Uint32(key[16:20]) + x9 := binary.LittleEndian.Uint32(key[20:24]) + x10 := binary.LittleEndian.Uint32(key[24:28]) + x11 := binary.LittleEndian.Uint32(key[28:32]) + x12 := binary.LittleEndian.Uint32(nonce[0:4]) + x13 := binary.LittleEndian.Uint32(nonce[4:8]) + x14 := binary.LittleEndian.Uint32(nonce[8:12]) + x15 := binary.LittleEndian.Uint32(nonce[12:16]) + + for i := 0; i < 10; i++ { + // Diagonal round. + x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) + x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) + x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) + x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) + + // Column round. + x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) + x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) + x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) + x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) + } + + _ = out[31] // bounds check elimination hint + binary.LittleEndian.PutUint32(out[0:4], x0) + binary.LittleEndian.PutUint32(out[4:8], x1) + binary.LittleEndian.PutUint32(out[8:12], x2) + binary.LittleEndian.PutUint32(out[12:16], x3) + binary.LittleEndian.PutUint32(out[16:20], x12) + binary.LittleEndian.PutUint32(out[20:24], x13) + binary.LittleEndian.PutUint32(out[24:28], x14) + binary.LittleEndian.PutUint32(out[28:32], x15) + return out, nil +} diff --git a/chacha20/chacha_noasm.go b/chacha20/chacha_noasm.go new file mode 100644 index 0000000000..c709b72847 --- /dev/null +++ b/chacha20/chacha_noasm.go @@ -0,0 +1,13 @@ +// 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. + +//go:build (!arm64 && !s390x && !ppc64 && !ppc64le) || !gc || purego + +package chacha20 + +const bufSize = blockSize + +func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) { + s.xorKeyStreamBlocksGeneric(dst, src) +} diff --git a/chacha20/chacha_ppc64x.go b/chacha20/chacha_ppc64x.go new file mode 100644 index 0000000000..bd183d9ba1 --- /dev/null +++ b/chacha20/chacha_ppc64x.go @@ -0,0 +1,16 @@ +// Copyright 2019 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. + +//go:build gc && !purego && (ppc64 || ppc64le) + +package chacha20 + +const bufSize = 256 + +//go:noescape +func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter) +} diff --git a/chacha20/chacha_ppc64x.s b/chacha20/chacha_ppc64x.s new file mode 100644 index 0000000000..a660b4112f --- /dev/null +++ b/chacha20/chacha_ppc64x.s @@ -0,0 +1,501 @@ +// Copyright 2019 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. + +// Based on CRYPTOGAMS code with the following comment: +// # ==================================================================== +// # Written by Andy Polyakov for the OpenSSL +// # project. The module is, however, dual licensed under OpenSSL and +// # CRYPTOGAMS licenses depending on where you obtain it. For further +// # details see http://www.openssl.org/~appro/cryptogams/. +// # ==================================================================== + +// Code for the perl script that generates the ppc64 assembler +// can be found in the cryptogams repository at the link below. It is based on +// the original from openssl. + +// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91 + +// The differences in this and the original implementation are +// due to the calling conventions and initialization of constants. + +//go:build gc && !purego && (ppc64 || ppc64le) + +#include "textflag.h" + +#define OUT R3 +#define INP R4 +#define LEN R5 +#define KEY R6 +#define CNT R7 +#define TMP R15 + +#define CONSTBASE R16 +#define BLOCKS R17 + +// for VPERMXOR +#define MASK R18 + +DATA consts<>+0x00(SB)/4, $0x61707865 +DATA consts<>+0x04(SB)/4, $0x3320646e +DATA consts<>+0x08(SB)/4, $0x79622d32 +DATA consts<>+0x0c(SB)/4, $0x6b206574 +DATA consts<>+0x10(SB)/4, $0x00000001 +DATA consts<>+0x14(SB)/4, $0x00000000 +DATA consts<>+0x18(SB)/4, $0x00000000 +DATA consts<>+0x1c(SB)/4, $0x00000000 +DATA consts<>+0x20(SB)/4, $0x00000004 +DATA consts<>+0x24(SB)/4, $0x00000000 +DATA consts<>+0x28(SB)/4, $0x00000000 +DATA consts<>+0x2c(SB)/4, $0x00000000 +DATA consts<>+0x30(SB)/4, $0x0e0f0c0d +DATA consts<>+0x34(SB)/4, $0x0a0b0809 +DATA consts<>+0x38(SB)/4, $0x06070405 +DATA consts<>+0x3c(SB)/4, $0x02030001 +DATA consts<>+0x40(SB)/4, $0x0d0e0f0c +DATA consts<>+0x44(SB)/4, $0x090a0b08 +DATA consts<>+0x48(SB)/4, $0x05060704 +DATA consts<>+0x4c(SB)/4, $0x01020300 +DATA consts<>+0x50(SB)/4, $0x61707865 +DATA consts<>+0x54(SB)/4, $0x61707865 +DATA consts<>+0x58(SB)/4, $0x61707865 +DATA consts<>+0x5c(SB)/4, $0x61707865 +DATA consts<>+0x60(SB)/4, $0x3320646e +DATA consts<>+0x64(SB)/4, $0x3320646e +DATA consts<>+0x68(SB)/4, $0x3320646e +DATA consts<>+0x6c(SB)/4, $0x3320646e +DATA consts<>+0x70(SB)/4, $0x79622d32 +DATA consts<>+0x74(SB)/4, $0x79622d32 +DATA consts<>+0x78(SB)/4, $0x79622d32 +DATA consts<>+0x7c(SB)/4, $0x79622d32 +DATA consts<>+0x80(SB)/4, $0x6b206574 +DATA consts<>+0x84(SB)/4, $0x6b206574 +DATA consts<>+0x88(SB)/4, $0x6b206574 +DATA consts<>+0x8c(SB)/4, $0x6b206574 +DATA consts<>+0x90(SB)/4, $0x00000000 +DATA consts<>+0x94(SB)/4, $0x00000001 +DATA consts<>+0x98(SB)/4, $0x00000002 +DATA consts<>+0x9c(SB)/4, $0x00000003 +DATA consts<>+0xa0(SB)/4, $0x11223300 +DATA consts<>+0xa4(SB)/4, $0x55667744 +DATA consts<>+0xa8(SB)/4, $0x99aabb88 +DATA consts<>+0xac(SB)/4, $0xddeeffcc +DATA consts<>+0xb0(SB)/4, $0x22330011 +DATA consts<>+0xb4(SB)/4, $0x66774455 +DATA consts<>+0xb8(SB)/4, $0xaabb8899 +DATA consts<>+0xbc(SB)/4, $0xeeffccdd +GLOBL consts<>(SB), RODATA, $0xc0 + +#ifdef GOARCH_ppc64 +#define BE_XXBRW_INIT() \ + LVSL (R0)(R0), V24 \ + VSPLTISB $3, V25 \ + VXOR V24, V25, V24 \ + +#define BE_XXBRW(vr) VPERM vr, vr, V24, vr +#else +#define BE_XXBRW_INIT() +#define BE_XXBRW(vr) +#endif + +//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) +TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 + MOVD out+0(FP), OUT + MOVD inp+8(FP), INP + MOVD len+16(FP), LEN + MOVD key+24(FP), KEY + MOVD counter+32(FP), CNT + + // Addressing for constants + MOVD $consts<>+0x00(SB), CONSTBASE + MOVD $16, R8 + MOVD $32, R9 + MOVD $48, R10 + MOVD $64, R11 + SRD $6, LEN, BLOCKS + // for VPERMXOR + MOVD $consts<>+0xa0(SB), MASK + MOVD $16, R20 + // V16 + LXVW4X (CONSTBASE)(R0), VS48 + ADD $80,CONSTBASE + + // Load key into V17,V18 + LXVW4X (KEY)(R0), VS49 + LXVW4X (KEY)(R8), VS50 + + // Load CNT, NONCE into V19 + LXVW4X (CNT)(R0), VS51 + + // Clear V27 + VXOR V27, V27, V27 + + BE_XXBRW_INIT() + + // V28 + LXVW4X (CONSTBASE)(R11), VS60 + + // Load mask constants for VPERMXOR + LXVW4X (MASK)(R0), V20 + LXVW4X (MASK)(R20), V21 + + // splat slot from V19 -> V26 + VSPLTW $0, V19, V26 + + VSLDOI $4, V19, V27, V19 + VSLDOI $12, V27, V19, V19 + + VADDUWM V26, V28, V26 + + MOVD $10, R14 + MOVD R14, CTR + PCALIGN $16 +loop_outer_vsx: + // V0, V1, V2, V3 + LXVW4X (R0)(CONSTBASE), VS32 + LXVW4X (R8)(CONSTBASE), VS33 + LXVW4X (R9)(CONSTBASE), VS34 + LXVW4X (R10)(CONSTBASE), VS35 + + // splat values from V17, V18 into V4-V11 + VSPLTW $0, V17, V4 + VSPLTW $1, V17, V5 + VSPLTW $2, V17, V6 + VSPLTW $3, V17, V7 + VSPLTW $0, V18, V8 + VSPLTW $1, V18, V9 + VSPLTW $2, V18, V10 + VSPLTW $3, V18, V11 + + // VOR + VOR V26, V26, V12 + + // splat values from V19 -> V13, V14, V15 + VSPLTW $1, V19, V13 + VSPLTW $2, V19, V14 + VSPLTW $3, V19, V15 + + // splat const values + VSPLTISW $-16, V27 + VSPLTISW $12, V28 + VSPLTISW $8, V29 + VSPLTISW $7, V30 + PCALIGN $16 +loop_vsx: + VADDUWM V0, V4, V0 + VADDUWM V1, V5, V1 + VADDUWM V2, V6, V2 + VADDUWM V3, V7, V3 + + VPERMXOR V12, V0, V21, V12 + VPERMXOR V13, V1, V21, V13 + VPERMXOR V14, V2, V21, V14 + VPERMXOR V15, V3, V21, V15 + + VADDUWM V8, V12, V8 + VADDUWM V9, V13, V9 + VADDUWM V10, V14, V10 + VADDUWM V11, V15, V11 + + VXOR V4, V8, V4 + VXOR V5, V9, V5 + VXOR V6, V10, V6 + VXOR V7, V11, V7 + + VRLW V4, V28, V4 + VRLW V5, V28, V5 + VRLW V6, V28, V6 + VRLW V7, V28, V7 + + VADDUWM V0, V4, V0 + VADDUWM V1, V5, V1 + VADDUWM V2, V6, V2 + VADDUWM V3, V7, V3 + + VPERMXOR V12, V0, V20, V12 + VPERMXOR V13, V1, V20, V13 + VPERMXOR V14, V2, V20, V14 + VPERMXOR V15, V3, V20, V15 + + VADDUWM V8, V12, V8 + VADDUWM V9, V13, V9 + VADDUWM V10, V14, V10 + VADDUWM V11, V15, V11 + + VXOR V4, V8, V4 + VXOR V5, V9, V5 + VXOR V6, V10, V6 + VXOR V7, V11, V7 + + VRLW V4, V30, V4 + VRLW V5, V30, V5 + VRLW V6, V30, V6 + VRLW V7, V30, V7 + + VADDUWM V0, V5, V0 + VADDUWM V1, V6, V1 + VADDUWM V2, V7, V2 + VADDUWM V3, V4, V3 + + VPERMXOR V15, V0, V21, V15 + VPERMXOR V12, V1, V21, V12 + VPERMXOR V13, V2, V21, V13 + VPERMXOR V14, V3, V21, V14 + + VADDUWM V10, V15, V10 + VADDUWM V11, V12, V11 + VADDUWM V8, V13, V8 + VADDUWM V9, V14, V9 + + VXOR V5, V10, V5 + VXOR V6, V11, V6 + VXOR V7, V8, V7 + VXOR V4, V9, V4 + + VRLW V5, V28, V5 + VRLW V6, V28, V6 + VRLW V7, V28, V7 + VRLW V4, V28, V4 + + VADDUWM V0, V5, V0 + VADDUWM V1, V6, V1 + VADDUWM V2, V7, V2 + VADDUWM V3, V4, V3 + + VPERMXOR V15, V0, V20, V15 + VPERMXOR V12, V1, V20, V12 + VPERMXOR V13, V2, V20, V13 + VPERMXOR V14, V3, V20, V14 + + VADDUWM V10, V15, V10 + VADDUWM V11, V12, V11 + VADDUWM V8, V13, V8 + VADDUWM V9, V14, V9 + + VXOR V5, V10, V5 + VXOR V6, V11, V6 + VXOR V7, V8, V7 + VXOR V4, V9, V4 + + VRLW V5, V30, V5 + VRLW V6, V30, V6 + VRLW V7, V30, V7 + VRLW V4, V30, V4 + BDNZ loop_vsx + + VADDUWM V12, V26, V12 + + VMRGEW V0, V1, V27 + VMRGEW V2, V3, V28 + + VMRGOW V0, V1, V0 + VMRGOW V2, V3, V2 + + VMRGEW V4, V5, V29 + VMRGEW V6, V7, V30 + + XXPERMDI VS32, VS34, $0, VS33 + XXPERMDI VS32, VS34, $3, VS35 + XXPERMDI VS59, VS60, $0, VS32 + XXPERMDI VS59, VS60, $3, VS34 + + VMRGOW V4, V5, V4 + VMRGOW V6, V7, V6 + + VMRGEW V8, V9, V27 + VMRGEW V10, V11, V28 + + XXPERMDI VS36, VS38, $0, VS37 + XXPERMDI VS36, VS38, $3, VS39 + XXPERMDI VS61, VS62, $0, VS36 + XXPERMDI VS61, VS62, $3, VS38 + + VMRGOW V8, V9, V8 + VMRGOW V10, V11, V10 + + VMRGEW V12, V13, V29 + VMRGEW V14, V15, V30 + + XXPERMDI VS40, VS42, $0, VS41 + XXPERMDI VS40, VS42, $3, VS43 + XXPERMDI VS59, VS60, $0, VS40 + XXPERMDI VS59, VS60, $3, VS42 + + VMRGOW V12, V13, V12 + VMRGOW V14, V15, V14 + + VSPLTISW $4, V27 + VADDUWM V26, V27, V26 + + XXPERMDI VS44, VS46, $0, VS45 + XXPERMDI VS44, VS46, $3, VS47 + XXPERMDI VS61, VS62, $0, VS44 + XXPERMDI VS61, VS62, $3, VS46 + + VADDUWM V0, V16, V0 + VADDUWM V4, V17, V4 + VADDUWM V8, V18, V8 + VADDUWM V12, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + // Bottom of loop + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V1, V16, V0 + VADDUWM V5, V17, V4 + VADDUWM V9, V18, V8 + VADDUWM V13, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(V10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V2, V16, V0 + VADDUWM V6, V17, V4 + VADDUWM V10, V18, V8 + VADDUWM V14, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + BEQ done_vsx + + VADDUWM V3, V16, V0 + VADDUWM V7, V17, V4 + VADDUWM V11, V18, V8 + VADDUWM V15, V19, V12 + + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + + CMPU LEN, $64 + BLT tail_vsx + + LXVW4X (INP)(R0), VS59 + LXVW4X (INP)(R8), VS60 + LXVW4X (INP)(R9), VS61 + LXVW4X (INP)(R10), VS62 + + VXOR V27, V0, V27 + VXOR V28, V4, V28 + VXOR V29, V8, V29 + VXOR V30, V12, V30 + + STXVW4X VS59, (OUT)(R0) + STXVW4X VS60, (OUT)(R8) + ADD $64, INP + STXVW4X VS61, (OUT)(R9) + ADD $-64, LEN + STXVW4X VS62, (OUT)(R10) + ADD $64, OUT + + MOVD $10, R14 + MOVD R14, CTR + BNE loop_outer_vsx + +done_vsx: + // Increment counter by number of 64 byte blocks + MOVWZ (CNT), R14 + ADD BLOCKS, R14 + MOVWZ R14, (CNT) + RET + +tail_vsx: + ADD $32, R1, R11 + MOVD LEN, CTR + + // Save values on stack to copy from + STXVW4X VS32, (R11)(R0) + STXVW4X VS36, (R11)(R8) + STXVW4X VS40, (R11)(R9) + STXVW4X VS44, (R11)(R10) + ADD $-1, R11, R12 + ADD $-1, INP + ADD $-1, OUT + PCALIGN $16 +looptail_vsx: + // Copying the result to OUT + // in bytes. + MOVBZU 1(R12), KEY + MOVBZU 1(INP), TMP + XOR KEY, TMP, KEY + MOVBU KEY, 1(OUT) + BDNZ looptail_vsx + + // Clear the stack values + STXVW4X VS48, (R11)(R0) + STXVW4X VS48, (R11)(R8) + STXVW4X VS48, (R11)(R9) + STXVW4X VS48, (R11)(R10) + BR done_vsx diff --git a/chacha20/chacha_s390x.go b/chacha20/chacha_s390x.go new file mode 100644 index 0000000000..683ccfd1c3 --- /dev/null +++ b/chacha20/chacha_s390x.go @@ -0,0 +1,27 @@ +// 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. + +//go:build gc && !purego + +package chacha20 + +import "golang.org/x/sys/cpu" + +var haveAsm = cpu.S390X.HasVX + +const bufSize = 256 + +// 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) + +func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { + if cpu.S390X.HasVX { + xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) + } else { + c.xorKeyStreamBlocksGeneric(dst, src) + } +} diff --git a/internal/chacha20/chacha_s390x.s b/chacha20/chacha_s390x.s similarity index 87% rename from internal/chacha20/chacha_s390x.s rename to chacha20/chacha_s390x.s index 57df404465..1eda91a3d4 100644 --- a/internal/chacha20/chacha_s390x.s +++ b/chacha20/chacha_s390x.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build s390x,!gccgo,!appengine +//go:build gc && !purego #include "go_asm.h" #include "textflag.h" @@ -24,15 +24,6 @@ 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 @@ -144,7 +135,7 @@ TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0 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) +// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 MOVD $·constants<>(SB), R1 MOVD dst+0(FP), R2 // R2=&dst[0] @@ -152,25 +143,10 @@ TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 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 @@ -217,9 +193,7 @@ 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) @@ -245,16 +219,6 @@ continue: 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 diff --git a/chacha20/chacha_test.go b/chacha20/chacha_test.go new file mode 100644 index 0000000000..60b11d92f6 --- /dev/null +++ b/chacha20/chacha_test.go @@ -0,0 +1,274 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package chacha20 + +import ( + "bytes" + "encoding/hex" + "fmt" + "math/rand" + "testing" +) + +func _() { + // Assert that bufSize is a multiple of blockSize. + var b [1]byte + _ = b[bufSize%blockSize] +} + +func hexDecode(s string) []byte { + ss, err := hex.DecodeString(s) + if err != nil { + panic(fmt.Sprintf("cannot decode input %#v: %v", s, err)) + } + return ss +} + +// Run the test cases with the input and output in different buffers. +func TestNoOverlap(t *testing.T) { + for _, c := range testVectors { + s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) + input := hexDecode(c.input) + output := make([]byte, len(input)) + s.XORKeyStream(output, input) + got := hex.EncodeToString(output) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", len(input), got, c.output) + } + } +} + +// Run the test cases with the input and output overlapping entirely. +func TestOverlap(t *testing.T) { + for _, c := range testVectors { + s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) + data := hexDecode(c.input) + s.XORKeyStream(data, data) + got := hex.EncodeToString(data) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", len(data), got, c.output) + } + } +} + +// Run the test cases with various source and destination offsets. +func TestUnaligned(t *testing.T) { + const max = 8 // max offset (+1) to test + for _, c := range testVectors { + data := hexDecode(c.input) + input := make([]byte, len(data)+max) + output := make([]byte, len(data)+max) + for i := 0; i < max; i++ { // input offsets + for j := 0; j < max; j++ { // output offsets + s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) + + input := input[i : i+len(data)] + output := output[j : j+len(data)] + + copy(input, data) + s.XORKeyStream(output, input) + got := hex.EncodeToString(output) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", len(data), got, c.output) + } + } + } + } +} + +// Run the test cases by calling XORKeyStream multiple times. +func TestStep(t *testing.T) { + // wide range of step sizes to try and hit edge cases + steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256} + rnd := rand.New(rand.NewSource(123)) + for _, c := range testVectors { + s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) + input := hexDecode(c.input) + output := make([]byte, len(input)) + + // step through the buffers + i, step := 0, steps[rnd.Intn(len(steps))] + for i+step < len(input) { + s.XORKeyStream(output[i:i+step], input[i:i+step]) + if i+step < len(input) && output[i+step] != 0 { + t.Errorf("length=%v, i=%v, step=%v: output overwritten", len(input), i, step) + } + i += step + step = steps[rnd.Intn(len(steps))] + } + // finish the encryption + s.XORKeyStream(output[i:], input[i:]) + // ensure we tolerate a call with an empty input + s.XORKeyStream(output[len(output):], input[len(input):]) + + got := hex.EncodeToString(output) + if got != c.output { + t.Errorf("length=%v: got %#v, want %#v", len(input), got, c.output) + } + } +} + +func TestSetCounter(t *testing.T) { + newCipher := func() *Cipher { + s, _ := NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) + return s + } + s := newCipher() + src := bytes.Repeat([]byte("test"), 32) // two 64-byte blocks + dst1 := make([]byte, len(src)) + s.XORKeyStream(dst1, src) + // advance counter to 1 and xor second block + s = newCipher() + s.SetCounter(1) + dst2 := make([]byte, len(src)) + s.XORKeyStream(dst2[64:], src[64:]) + if !bytes.Equal(dst1[64:], dst2[64:]) { + t.Error("failed to produce identical output using SetCounter") + } + + // test again with unaligned blocks; SetCounter should reset the buffer + s = newCipher() + s.XORKeyStream(dst1[:70], src[:70]) + s = newCipher() + s.XORKeyStream([]byte{0}, []byte{0}) + s.SetCounter(1) + s.XORKeyStream(dst2[64:70], src[64:70]) + if !bytes.Equal(dst1[64:70], dst2[64:70]) { + t.Error("SetCounter did not reset buffer") + } + + // advancing to a lower counter value should cause a panic + panics := func(fn func()) (p bool) { + defer func() { p = recover() != nil }() + fn() + return + } + if !panics(func() { s.SetCounter(0) }) { + t.Error("counter decreasing should trigger a panic") + } +} + +func TestLastBlock(t *testing.T) { + panics := func(fn func()) (p bool) { + defer func() { p = recover() != nil }() + fn() + return + } + + checkLastBlock := func(b []byte) { + t.Helper() + // Hardcoded result to check all implementations generate the same output. + lastBlock := "ace4cd09e294d1912d4ad205d06f95d9c2f2bfcf453e8753f128765b62215f4d" + + "92c74f2f626c6a640c0b1284d839ec81f1696281dafc3e684593937023b58b1d" + if got := hex.EncodeToString(b); got != lastBlock { + t.Errorf("wrong output for the last block, got %q, want %q", got, lastBlock) + } + } + + // setting the counter to 0xffffffff and crypting multiple blocks should + // trigger a panic + s, _ := NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) + s.SetCounter(0xffffffff) + blocks := make([]byte, blockSize*2) + if !panics(func() { s.XORKeyStream(blocks, blocks) }) { + t.Error("crypting multiple blocks should trigger a panic") + } + + // setting the counter to 0xffffffff - 1 and crypting two blocks should not + // trigger a panic + s, _ = NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) + s.SetCounter(0xffffffff - 1) + if panics(func() { s.XORKeyStream(blocks, blocks) }) { + t.Error("crypting the last blocks should not trigger a panic") + } + checkLastBlock(blocks[blockSize:]) + // once all the keystream is spent, setting the counter should panic + if !panics(func() { s.SetCounter(0xffffffff) }) { + t.Error("setting the counter after overflow should trigger a panic") + } + // crypting a subsequent block *should* panic + block := make([]byte, blockSize) + if !panics(func() { s.XORKeyStream(block, block) }) { + t.Error("crypting after overflow should trigger a panic") + } + + // if we crypt less than a full block, we should be able to crypt the rest + // in a subsequent call without panicking + s, _ = NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) + s.SetCounter(0xffffffff) + if panics(func() { s.XORKeyStream(block[:7], block[:7]) }) { + t.Error("crypting part of the last block should not trigger a panic") + } + if panics(func() { s.XORKeyStream(block[7:], block[7:]) }) { + t.Error("crypting part of the last block should not trigger a panic") + } + checkLastBlock(block) + // as before, a third call should trigger a panic because all keystream is spent + if !panics(func() { s.XORKeyStream(block[:1], block[:1]) }) { + t.Error("crypting after overflow should trigger a panic") + } +} + +func benchmarkChaCha20(b *testing.B, step, count int) { + tot := step * count + src := make([]byte, tot) + dst := make([]byte, tot) + key := make([]byte, KeySize) + nonce := make([]byte, NonceSize) + b.SetBytes(int64(tot)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + c, _ := NewUnauthenticatedCipher(key, nonce) + for i := 0; i < tot; i += step { + c.XORKeyStream(dst[i:], src[i:i+step]) + } + } +} + +func BenchmarkChaCha20(b *testing.B) { + b.Run("64", func(b *testing.B) { + benchmarkChaCha20(b, 64, 1) + }) + b.Run("256", func(b *testing.B) { + benchmarkChaCha20(b, 256, 1) + }) + b.Run("10x25", func(b *testing.B) { + benchmarkChaCha20(b, 10, 25) + }) + b.Run("4096", func(b *testing.B) { + benchmarkChaCha20(b, 4096, 1) + }) + b.Run("100x40", func(b *testing.B) { + benchmarkChaCha20(b, 100, 40) + }) + b.Run("65536", func(b *testing.B) { + benchmarkChaCha20(b, 65536, 1) + }) + b.Run("1000x65", func(b *testing.B) { + benchmarkChaCha20(b, 1000, 65) + }) +} + +func TestHChaCha20(t *testing.T) { + // See draft-irtf-cfrg-xchacha-00, Section 2.2.1. + key := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} + nonce := []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27} + expected := []byte{0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, + 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, + 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, + 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, + } + result, err := HChaCha20(key[:], nonce[:]) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(expected, result) { + t.Errorf("want %x, got %x", expected, result) + } +} diff --git a/internal/chacha20/vectors_test.go b/chacha20/vectors_test.go similarity index 81% rename from internal/chacha20/vectors_test.go rename to chacha20/vectors_test.go index b441fbd149..3d3bbcdc51 100644 --- a/internal/chacha20/vectors_test.go +++ b/chacha20/vectors_test.go @@ -7,571 +7,504 @@ package chacha20 // Test vectors for ChaCha20 implementations. type testCase struct { - length int - nonce [3]uint32 - key [8]uint32 + nonce string + key string input string output string } var testVectors = [...]testCase{ { - length: 0, - nonce: [3]uint32{0x94d13317, 0x6b6a2b3, 0x3ffe0036}, - key: [8]uint32{0x9da8a3b6, 0x3abf4ae6, 0xa2f19cae, 0x1068c707, 0x72e4801e, 0xce165d92, 0x61e7028f, 0x82ac3d57}, + // From libsodium/test/default/xchacha20.c + nonce: "c047548266b7c370d33566a2425cbf30d82d1eaf5294109e", + key: "9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232", + input: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + output: "a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc", + }, + { + // From draft-irtf-cfrg-xchacha-01 + nonce: "404142434445464748494a4b4c4d4e4f5051525354555658", + key: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + input: "5468652064686f6c65202870726f6e6f756e6365642022646f6c65222920697320616c736f206b6e6f776e2061732074686520417369617469632077696c6420646f672c2072656420646f672c20616e642077686973746c696e6720646f672e2049742069732061626f7574207468652073697a65206f662061204765726d616e20736865706865726420627574206c6f6f6b73206d6f7265206c696b652061206c6f6e672d6c656767656420666f782e205468697320686967686c7920656c757369766520616e6420736b696c6c6564206a756d70657220697320636c6173736966696564207769746820776f6c7665732c20636f796f7465732c206a61636b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d69632066616d696c792043616e696461652e", + output: "4559abba4e48c16102e8bb2c05e6947f50a786de162f9b0b7e592a9b53d0d4e98d8d6410d540a1a6375b26d80dace4fab52384c731acbf16a5923c0c48d3575d4d0d2c673b666faa731061277701093a6bf7a158a8864292a41c48e3a9b4c0daece0f8d98d0d7e05b37a307bbb66333164ec9e1b24ea0d6c3ffddcec4f68e7443056193a03c810e11344ca06d8ed8a2bfb1e8d48cfa6bc0eb4e2464b748142407c9f431aee769960e15ba8b96890466ef2457599852385c661f752ce20f9da0c09ab6b19df74e76a95967446f8d0fd415e7bee2a12a114c20eb5292ae7a349ae577820d5520a1f3fb62a17ce6a7e68fa7c79111d8860920bc048ef43fe84486ccb87c25f0ae045f0cce1e7989a9aa220a28bdd4827e751a24a6d5c62d790a66393b93111c1a55dd7421a10184974c7c5", + }, + { + nonce: "1733d194b3a2b6063600fe3f", + key: "b6a3a89de64abf3aae9cf1a207c768101e80e472925d16ce8f02e761573dac82", input: "", output: "", }, { - length: 5, - nonce: [3]uint32{0x469fadd, 0xee3fcc1e, 0x45cf77b0}, - key: [8]uint32{0x3477e02b, 0x45bf809f, 0x27f4a1fa, 0xdb901de8, 0xd8a190dc, 0x1d2c21d4, 0x87bdf2ac, 0xdfbf0000}, + nonce: "ddfa69041ecc3feeb077cf45", + key: "2be077349f80bf45faa1f427e81d90dbdc90a1d8d4212c1dacf2bd870000bfdf", input: "23dbad0780", output: "415a3e498d", }, { - length: 9, - nonce: [3]uint32{0x512a6b49, 0x8df9af6d, 0x5336a2a5}, - key: [8]uint32{0xe9124c25, 0x4fd1a373, 0x7945f7bb, 0xeed5f064, 0x29c4185d, 0x3c9acf13, 0x4c94a367, 0x7c2c2c53}, + nonce: "496b2a516daff98da5a23653", + key: "254c12e973a3d14fbbf7457964f0d5ee5d18c42913cf9a3c67a3944c532c2c7c", input: "f518831fab69c054a6", output: "cfe40f63f81391484b", }, { - length: 12, - nonce: [3]uint32{0xca697a9e, 0x6b2f6717, 0xb7859220}, - key: [8]uint32{0xfc825020, 0x5ca4410b, 0x7d5285d0, 0x160a1c9d, 0x15470b41, 0x3634742a, 0xe64aa7fa, 0xca0be67a}, + nonce: "9e7a69ca17672f6b209285b7", + key: "205082fc0b41a45cd085527d9d1c0a16410b47152a743436faa74ae67ae60bca", input: "805fad1d62951537aeed9859", output: "47bd303f93c3ce04bce44710", }, { - length: 14, - nonce: [3]uint32{0xcded3db3, 0x35770a7f, 0x6aede9b}, - key: [8]uint32{0x44632def, 0xa5e420a7, 0xfc12a8f, 0x63b79a15, 0x337de314, 0xb82fbf16, 0x3104bc57, 0x677c9227}, + nonce: "b33dedcd7f0a77359bdeae06", + key: "ef2d6344a720e4a58f2ac10f159ab76314e37d3316bf2fb857bc043127927c67", input: "f4e8a7577affb841cf48392cf5df", output: "f445c0fb7e3d5bfdab47090ddee6", }, { - length: 15, - nonce: [3]uint32{0x348a50b1, 0x4acc9280, 0x8d6014ce}, - key: [8]uint32{0x34bd31a8, 0x2808f47e, 0x9d8b19f9, 0x4df59683, 0x31584348, 0x34a74a45, 0xde174a2, 0x29d4c7dc}, + nonce: "b1508a348092cc4ace14608d", + key: "a831bd347ef40828f9198b9d8396f54d48435831454aa734a274e10ddcc7d429", input: "1179b71ec4dc34bd812f742b5a0b27", output: "cc7f80f333c647d6e592e4f7ecc834", }, { - length: 20, - nonce: [3]uint32{0xc8754703, 0x9188c521, 0xac8ce8a6}, - key: [8]uint32{0xe93c79ed, 0xce89162b, 0x116a8366, 0xecdc657f, 0x5bc81d98, 0xff5d2f52, 0x171f3ebb, 0x50773f2f}, + nonce: "034775c821c58891a6e88cac", + key: "ed793ce92b1689ce66836a117f65dcec981dc85b522f5dffbb3e1f172f3f7750", input: "7bd94943d55392d0311c413ac755ce0347872ba3", output: "c43665de15136af232675d9d5dbbeca77f3c542a", }, { - length: 21, - nonce: [3]uint32{0x9a8655cb, 0x6e9d6ea5, 0x5dad705e}, - key: [8]uint32{0x3542d5b3, 0x1f7bfd8f, 0x1038abf8, 0x7214e8ec, 0xedd05693, 0x60e663bd, 0xe8e5d506, 0xeea923a2}, + nonce: "cb55869aa56e9d6e5e70ad5d", + key: "b3d542358ffd7b1ff8ab3810ece814729356d0edbd63e66006d5e5e8a223a9ee", input: "1505f669acc5ad9aaa0e993ba8c24e744d13655e1f", output: "26cad1ccf4cf4c49b267ab7be10bc2ffa3ba66bc86", }, { - length: 25, - nonce: [3]uint32{0x3f202ca4, 0x63fc86, 0x7260a10e}, - key: [8]uint32{0xe28ab1d6, 0xe83b3d47, 0x671271ca, 0xb977bcff, 0xa2f64476, 0x311d79b4, 0x180d91d0, 0xec1a6e0c}, + nonce: "a42c203f86fc63000ea16072", + key: "d6b18ae2473d3be8ca711267ffbc77b97644f6a2b4791d31d0910d180c6e1aec", input: "20070523ddb4ebf0d5f20fd95aacf47fb269ebadda6879638a", output: "5ce972624cb2b7e7c28f5b865ba08c887911b4f5e361830a4b", }, { - length: 31, - nonce: [3]uint32{0xcf8671ea, 0x8d72df2f, 0x8b5a538a}, - key: [8]uint32{0xe46ca2bb, 0xd06ab5ef, 0xb0e2966b, 0x54dd0c2d, 0x8815d89a, 0x426c30a9, 0x15b0f1e, 0x254bae75}, + nonce: "ea7186cf2fdf728d8a535a8b", + key: "bba26ce4efb56ad06b96e2b02d0cdd549ad81588a9306c421e0f5b0175ae4b25", input: "d10f8050c1186f92e26f351db36490d82ea677498562d8d4f487a0a4058adf", output: "f30c11bc553b2baf6870760d735680897c9fee168f976b2a33ef395fdbd4fc", }, { - length: 34, - nonce: [3]uint32{0xd1be983a, 0xf5aa389, 0xfa26c7e1}, - key: [8]uint32{0x795c6da7, 0x8cb1aadc, 0xa042359a, 0x95ea2e27, 0x128253c4, 0xaabc592f, 0x391e810, 0xf641d971}, + nonce: "3a98bed189a35a0fe1c726fa", + key: "a76d5c79dcaab18c9a3542a0272eea95c45382122f59bcaa10e8910371d941f6", input: "e88dc380b7d45a4a762c34f310199587867516fac4a2634022b96a9f862e17714d17", output: "aac98ba3821399e55a5eab5862f7f1bfc63637d700125878c2b17151f306c9aec80e", }, { - length: 34, - nonce: [3]uint32{0x98f5f4b8, 0x3f181d73, 0x5bf4572e}, - key: [8]uint32{0xa86f8cf7, 0x8db41a2b, 0xe0e03156, 0x3dad8a59, 0xb3e4d1ba, 0x75f6fb38, 0xdb94709d, 0xc3db34f3}, + nonce: "b8f4f598731d183f2e57f45b", + key: "f78c6fa82b1ab48d5631e0e0598aad3dbad1e4b338fbf6759d7094dbf334dbc3", input: "b0fcf0a731e2902787309697db2384e1cda07b60002c95355a4e261fb601f034b2b3", output: "b6c8c40ddda029a70a21c25f724cc90c43f6edc407055683572a9f5e9690a1d571bb", }, { - length: 40, - nonce: [3]uint32{0x7289ae18, 0x7ebe7e50, 0x7d819176}, - key: [8]uint32{0x336c07a0, 0x4a2ea22b, 0xa8872f46, 0xa47b5e28, 0xbe645e3f, 0x371c6591, 0xd2dc237a, 0x92c59580}, + nonce: "18ae8972507ebe7e7691817d", + key: "a0076c332ba22e4a462f87a8285e7ba43f5e64be91651c377a23dcd28095c592", input: "cf9ec6fa3f0a67488adb5598a48ed916729a1e416d206f9675dfa9fd6585793f274f363bbca348b3", output: "bb7ed8a199aa329dcd18736ce705804ffae8c3e2ba341ae907f94f4672d57175df25d28e16962fd6", }, { - length: 47, - nonce: [3]uint32{0xfd3181de, 0x8b193e26, 0xbebc799}, - key: [8]uint32{0x781a4c2e, 0x27ab55e2, 0x814aaf43, 0xa0bab01, 0x9de62ce0, 0x472b03d2, 0xdfee18e8, 0x8b855b93}, + nonce: "de8131fd263e198b99c7eb0b", + key: "2e4c1a78e255ab2743af4a8101ab0b0ae02ce69dd2032b47e818eedf935b858b", input: "be9a8211d68642310724eda3dd02f63fcc03a101d9564b0ecee6f4ecececcb0099bb26aabee46b1a2c0416b4ac269e", output: "3152f317cf3626e26d02cff9392619ea02e22115b6d43d6dd2e1177c6bb3cb71c4a90c3d13b63c43e03605ec98d9a1", }, { - length: 51, - nonce: [3]uint32{0x27b02ff6, 0xa510613e, 0x218b22d8}, - key: [8]uint32{0x62fc7732, 0xcef06cf4, 0xa4f45ed5, 0x2f96654f, 0x9f2b956e, 0x42b572f4, 0x5bb59c86, 0x35e4784f}, + nonce: "f62fb0273e6110a5d8228b21", + key: "3277fc62f46cf0ced55ef4a44f65962f6e952b9ff472b542869cb55b4f78e435", input: "495343a257250f8970f791f493b89d10edba89806b88aaaeb3b5aefd078ba7b765746164bce653f5e6c096dd8499fb76d97d77", output: "62c01f426581551b5b16e8b1a3a23c86bcdd189ab695dbea4bf811a14741e6ebbb0261ef8ae47778a6be7e0ef11697b891412c", }, { - length: 52, - nonce: [3]uint32{0x9db97a63, 0xff50248, 0xf2b6df56}, - key: [8]uint32{0x2b657a8f, 0xfe67575d, 0xaa56d261, 0x30179a97, 0xaefcfff1, 0x9b8eb698, 0x1efe3756, 0xb4ea450c}, + nonce: "637ab99d4802f50f56dfb6f2", + key: "8f7a652b5d5767fe61d256aa979a1730f1fffcae98b68e9b5637fe1e0c45eab4", input: "e37fbbd3fe37ce5a99d18e5dcb0dafe7adf8b596528708f7d310569ab44c251377f7363a390c653965e0cb8dd217464b3d8f79c1", output: "b07d4c56fb83a49e8d9fc992e1230bb5086fecbd828cdbc7353f61b1a3cec0baf9c5bf67c9da06b49469a999ba3b37916ec125be", }, { - length: 56, - nonce: [3]uint32{0xc1dfec38, 0x7d7503d3, 0x9a3e3c66}, - key: [8]uint32{0x8614d8e7, 0xde9b0413, 0x2a48b4fa, 0xcbbde744, 0xad5ddc5e, 0x9144d83e, 0x74d9d617, 0x230bdb45}, + nonce: "38ecdfc1d303757d663c3e9a", + key: "e7d8148613049bdefab4482a44e7bdcb5edc5dad3ed8449117d6d97445db0b23", input: "9efab614388a7d99102bcc901e3623d31fd9dd9d3c3338d086f69c13e7aa8653f9ce76e722e5a6a8cbbbee067a6cb9c59aa9b4b4c518bbed", output: "829d9fe74b7a4b3aeb04580b41d38a156ffbebba5d49ad55d1b0370f25abcd41221304941ad8e0d5095e15fbd839295bf1e7a509a807c005", }, { - length: 63, - nonce: [3]uint32{0xc7e2521c, 0x795499b4, 0xc7946cd7}, - key: [8]uint32{0x53fce774, 0x9a4b53bf, 0x5f614134, 0xa3c39414, 0xa8a07c72, 0x93242311, 0x43aeec99, 0x216deb5a}, + nonce: "1c52e2c7b4995479d76c94c7", + key: "74e7fc53bf534b9a3441615f1494c3a3727ca0a81123249399ecae435aeb6d21", input: "03b5d7ab4bd8c9a4f47ec122cbeb595bd1a0d58de3bb3dcc66c4e288f29622d6863e846fdfb27a90740feb03a4761c6017250bc0f129cc65d19680ab9d6970", output: "83db55d9eb441a909268311da67d432c732ad6bda0a0dae710d1bce040b91269deb558a68ced4aa5760ca0b9c5efc84e725f297bdbdadbc368bea4e20261c5", }, { - length: 66, - nonce: [3]uint32{0x1d41f0a1, 0x7c3b7778, 0x6991eea5}, - key: [8]uint32{0x1f213e39, 0x56261d14, 0x15fc7c2c, 0x21feccc5, 0xa95684c5, 0x26600506, 0xdadcc06b, 0xf2c810b0}, + nonce: "a1f0411d78773b7ca5ee9169", + key: "393e211f141d26562c7cfc15c5ccfe21c58456a9060560266bc0dcdab010c8f2", input: "2f4da518578a2a82c8c855155645838ca431cdf35d9f8562f256746150580ca1c74f79b3e9ae78224573da8b47a4b3cc63fbed8d4e831a6b4d796c124d87c78a66e5", output: "6fc086ded3d1d5566577ccd9971e713c1126ec52d3894f09ab701116c7b5abda959cbb207f4468eb7b6a6b7e1b6d2bc6047f337499d63522f256ee751b91f84f70b6", }, { - length: 72, - nonce: [3]uint32{0x749f022c, 0xa021dab0, 0x648c2252}, - key: [8]uint32{0xa1ace7b0, 0x567a0ea1, 0x52af13b9, 0xcba30c08, 0xe07a6d74, 0x5c3bca39, 0x85b2ac07, 0x3b5afc0}, + nonce: "2c029f74b0da21a052228c64", + key: "b0e7aca1a10e7a56b913af52080ca3cb746d7ae039ca3b5c07acb285c0afb503", input: "55739a1738b4a4028021b21549e2661b050e3d830ad9a56f57bfcaca3e0f72051b9ca92411840061083e5e45124d8425061ab26c632ac7852118411ac80026da946357c630f27225", output: "8051bf98f8f2617e159ba205a9342ab700973dd045e09321805eed89e419f37f3211c5aa82666b9a097270babc26d3bfe0c990fe245ae982a31f23cfbf6156b5c8cfb77f340e2bf5", }, { - length: 74, - nonce: [3]uint32{0x23c16ba8, 0x9fd1cd4e, 0xcb224ecb}, - key: [8]uint32{0xb694404a, 0x86b5f198, 0x10fd1bff, 0x13a84e54, 0xab21e509, 0x7443d764, 0x931b3f1, 0x686e87f2}, + nonce: "a86bc1234ecdd19fcb4e22cb", + key: "4a4094b698f1b586ff1bfd10544ea81309e521ab64d74374f1b33109f2876e68", input: "7ffd8d5970fdee613eeae531d1c673fd379d64b0b6bfedd010433b080b561038f7f266fa7e15d7d8e10d23f21b9d7724bb200b0f58b9250483e784f4a6555d09c234e8d1c549ebb76a8e", output: "c173617e36ea20ce04c490803b2098bd4f1ff4b31fdca1c51c6475ade83892c5f12731652d5774631d55ae2938617a5e9462bb6083328a23a4fba52de50ca9075586f2efc22aae56e3a8", }, { - length: 81, - nonce: [3]uint32{0xd65f6f29, 0xf3f76219, 0x9a033c9e}, - key: [8]uint32{0xeba017c4, 0x69e0421a, 0x449e2317, 0x29858a11, 0xd0c8523a, 0xa8b0c9a2, 0xab2ca84, 0xaf011a45}, + nonce: "296f5fd61962f7f39e3c039a", + key: "c417a0eb1a42e06917239e44118a85293a52c8d0a2c9b0a884cab20a451a01af", input: "7a5766097562361cfaeac5b8a6175e1ceeeda30aec5e354df4302e7700ea48c505da9fdc57874da879480ecfea9c6c8904f330cbac5e27f296b33b667fea483348f031bef761d0b8e318a8132caa7a5943", output: "5e9fbf427c4f0fcf44db3180ea47d923f52bee933a985543622eff70e2b3f5c673be8e05cd7acbcadd8593da454c60d5f19131e61730a73b9c0f87e3921ee5a591a086446b2a0fadd8a4bc7b49a8e83764", }, { - length: 88, - nonce: [3]uint32{0xc70ee56e, 0xe58ec41, 0xafd96f61}, - key: [8]uint32{0x172af2bb, 0x9085d27c, 0x8ca2c44d, 0x8aa148da, 0x290c88b0, 0x88187439, 0x18d54781, 0x633f2cce}, + nonce: "6ee50ec741ec580e616fd9af", + key: "bbf22a177cd285904dc4a28cda48a18ab0880c29397418888147d518ce2c3f63", input: "0777c02a2900052d9b79f38387d2c234108a2ad066cbf7df6ea6acc5a3f86b3d6156abb5b18ad4ecf79e171383a1897e64a95ecdbba6aa3f1c7c12fe31283629ff547cb113a826cb348a7c10507cc645fa2eb97b5f22e44d", output: "368c90db3464ba488340b1960e9f75d2c3b5b392bdd5622ff70e85e6d00b1e6a996ba3978ce64f8f2b5a9a90576c8f32b908233e15d2f443cccc98af87745c93c8056603407a3fb37ce0c1f8ab6384cc37c69c98bfecf337", }, { - length: 92, - nonce: [3]uint32{0x3006da79, 0x2748051d, 0x72c17cdc}, - key: [8]uint32{0x60cdb7e8, 0xcecbe928, 0xe19b7ab9, 0x30d61537, 0xa0fbc199, 0x897738bf, 0xdd7705a9, 0x3e5c1763}, + nonce: "79da06301d054827dc7cc172", + key: "e8b7cd6028e9cbceb97a9be13715d63099c1fba0bf387789a90577dd63175c3e", input: "cf2dccbcfd781c030376f9019d841ca701cb54a1791f50f50bee0c2bf178182603a4712b5916eebd5001595c3f48283f1ba097ce2e7bf94f2b7fa957ce776e14a7a570093be2de386ececbd6525e72c5970c3e7d35974b8f0b831fbc", output: "7c92b8c75e6eb8675229660cedcb10334965a7737cde7336512d9eff846c670d1fa8f8a427ea4f43e66be609466711fd241ccff7d3f049bda3a2394e5aa2108abc80e859611dbd3c7ba2d044a3ececa4980dd65e823dd110fea7a548", }, { - length: 96, - nonce: [3]uint32{0xfc0fb1ee, 0x414cc60a, 0x4144bd67}, - key: [8]uint32{0x103291c6, 0x822b03b6, 0xd29ab548, 0xc88f3efe, 0x6936056a, 0x28aaa61f, 0xa0df7858, 0xdaa23519}, + nonce: "eeb10ffc0ac64c4167bd4441", + key: "c6913210b6032b8248b59ad2fe3e8fc86a0536691fa6aa285878dfa01935a2da", input: "e08a8949a1bfd6a8c1186b431b6ad59b106ae5552821db69b66dc03fbc4a2b970dcf9c7da4f5082572bc978f8ee27c554c8884b5a450b36d70453348cd6cac9b80c9900cf98a4088803f564bb1281d24507b2f61ba737c8145c71b50eb0f6dfc", output: "73d043acf9dcd758c7299bd1fd1f4100d61ff77d339e279bfbe6f9233b0d9afa24992a9c1c7a19545d469fdfb369c201322f6fe8c633fcdcffef31032bfb41b9fb55506e301d049fd447d61f974a713debeaed886f486a98efd3d6c3f25fbb30", }, { - length: 103, - nonce: [3]uint32{0xc2030c57, 0x1e3b59e1, 0x607ede1a}, - key: [8]uint32{0xd1bac2b5, 0x56a94583, 0x628b479b, 0x3056a51e, 0x69bf8f8f, 0x2df1e03d, 0x4b9d48d2, 0x7df5c379}, + nonce: "570c03c2e1593b1e1ade7e60", + key: "b5c2bad18345a9569b478b621ea556308f8fbf693de0f12dd2489d4b79c3f57d", input: "a0c302120111f00c99cff7d839cdf43207a7e2f73d5dd888daa00d84254db0e621a72493480420c9c61ce1cfc54188ff525bb7a0e6c1cd298f598973a1de9fd2d79a21401588775b0adbe261ba4e4f79a894d1bd5835b5924d09ba32ef03cb4bc0bd6eb4ee4274", output: "bc714bd7d8399beedc238f7ddeb0b99d94ad6bf8bf54548a3e4b90a76aa5673c91db6482591e8ff9126e1412bce56d52a4c2d89f22c29858e24482f177abacef428d0ae1779f0ae0778c44f9f02fe474da93c35c615b5fad29eca697978891f426714441317f2b", }, { - length: 109, - nonce: [3]uint32{0xf44dc81f, 0xcf6e03e7, 0xf4966796}, - key: [8]uint32{0xd7b12f4, 0x683f4789, 0xc7828fb4, 0x820fc6a0, 0xc51231eb, 0xe46716d7, 0x4036ef93, 0x26afb96c}, + nonce: "1fc84df4e7036ecf966796f4", + key: "f4127b0d89473f68b48f82c7a0c60f82eb3112c5d71667e493ef36406cb9af26", input: "ebce290c03c7cb65d053918ba2da0256dc700b337b8c124c43d5da4746888ca78387feea1a3a72c5e249d3d93a1907977dd4009699a15be5da2ca89c60e971c8df5d4553b61b710d92d3453dea595a0e45ae1e093f02ea70608b7b32f9c6aadc661a052f9b14c03ea0117a3192", output: "cbb8c4ec827a1123c1141327c594d4a8b0b4a74b0008115bb9ec4275db3a8e5529a4f145551af29c473764cbaa0794b2d1eb1066f32a07fd39f5f3fe51498c46fba5310ae7c3664571d6a851e673ded3badc25e426f9c6038724779aa6d2d8ec3f54865f7df612e25575635ab5", }, { - length: 115, - nonce: [3]uint32{0x8d3e461b, 0x7e05c360, 0x3bbbafdd}, - key: [8]uint32{0xf9b917c9, 0x9af89bf7, 0x7decbbc9, 0xe7e5ea7b, 0x9b4aab55, 0x90eff6be, 0xa19b6d90, 0xb9f69b1a}, + nonce: "1b463e8d60c3057eddafbb3b", + key: "c917b9f9f79bf89ac9bbec7d7beae5e755ab4a9bbef6ef90906d9ba11a9bf6b9", input: "275c97de985aa265332065ccce437770b110737a77dea62137a5d6cb62e9cb8b504d34334a58a71aba153d9b86f21377467b2fafaf54829331bf2ce0009acb37842b7a4b5f152aab650a393153f1ed479abc21f7a6fe205b9852ff2f7f3a0e3bfe76ca9770efada4e29e06db0569a99d08648e", output: "b225aa01d5c438d572deaea51ac12c0c694e0f9dc0ed2884a98e5e2943d52bb4692d7d8f12486de12d0559087e8c09e4f2d5b74e350838aa2bd36023032ccbcae56be75c6a17c59583d81a1fd60e305af5053ac89f753c9347f3040e48405232dc8428c49dcb3d9b899145f5b3bc955f34dbbe", }, { - length: 119, - nonce: [3]uint32{0x871f33f5, 0xe4fee3ba, 0xcb8c1e93}, - key: [8]uint32{0x33124903, 0x7e0287e5, 0xe9d6988f, 0x1962405f, 0x5f21c1b5, 0x2ac695e6, 0x46b200c9, 0x9fda98ba}, + nonce: "f5331f87bae3fee4931e8ccb", + key: "03491233e587027e8f98d6e95f406219b5c1215fe695c62ac900b246ba98da9f", input: "ceda15cfffd53ccebe31b5886facd863f6166e02ec65f46f54148860a5c2702e34fd204d881af6055952690cd1ffa8ba4d0e297cc165d981b371932adb935398c987baff335108c5e77f2e5dd5e1ca9a017bc376cbdbe3c0f45e079c212e8986b438444e79cd37927c1479f45c9e75b0076cc9f8679011", output: "a3f1c3f885583b999c85cd118e2ababfa5a2de0c8eb28aacc161b1efee89d8de36ddeb584174c0e92011b8d667cb64009049976082072e6262933dbf7b14839805e1face375b7cbb54f9828ba1ed8aa55634ec5d72b6351feff4d77a3a22b34203b02e096f5e5f9ae9ad6a9dd16c57ce6d94dcc8873d18", }, { - length: 120, - nonce: [3]uint32{0xef553ce8, 0xdfe120ea, 0x9a047e3a}, - key: [8]uint32{0xbef479c1, 0x59554f8b, 0xbf97f089, 0x52316f1e, 0x141e428, 0xff26dc04, 0xe10c8f57, 0xa7568a59}, + nonce: "e83c55efea20e1df3a7e049a", + key: "c179f4be8b4f555989f097bf1e6f315228e4410104dc26ff578f0ce1598a56a7", input: "799bb2d634406753416b3a2b67513293a0b3496ef5b2d019758dedaaac2edd72502fc4a375b3f0d4237bc16b0e3d47e7ddc315c6aef3a23fcae2eb3a6083bc7ac4fd1b5bf0025cc1cb266b40234b77db762c747d3a7b27956cf3a4cf72320fb60c0d0713fa60b37a6cb5b21a599e79d0f06a5b7201aeb5d2", output: "e84dfb3dbaac364085497aeabd197db852d3140c0c07f5f10e5c144c1fe26a50a9877649e88c6fe04283f4b7590a8d0d042ef577693f76f706e31c4979437590fe0ab03d89afb089d1be50ae173ea5458810372838eceac53bf4bac792735d8149e548efb432e236da92bf3168bbcf36f644c23efb478a4e", }, { - length: 123, - nonce: [3]uint32{0xd98124a0, 0x78cd80aa, 0x3dc55cfc}, - key: [8]uint32{0x2286e41, 0xf13e38e3, 0xf735476b, 0x33c44bfc, 0xd7978797, 0x4a9c4595, 0x6080413, 0x1299fdd8}, + nonce: "a02481d9aa80cd78fc5cc53d", + key: "416e2802e3383ef16b4735f7fc4bc433978797d795459c4a13040806d8fd9912", input: "b2d060bd173955f44ee01b8bfcf0a6fad017c3517e4e8c8da728379f6d54471c955615e2b1effe4ce3d0139df225223c361be1cac416ade10a749c5da324563696dae8272577e44e8588cd5306bff0bfbdb32af3ac7cbc78be24b51baf4d5e47cf8f1d6b0a63ed9359da45c3e7297b2314028848f5816feab885e2", output: "ffa4aa66dd5d39694ae64696bfa96f771accef68f195456ad815751e25c47ed4f27b436f1b3e3fcaa3e0d04133b53559c100cd633ced3d4321fc56225c85d2443727bce40434455aa4c1f3e6768c0fe58ad88b3a928313d41a7629f1ce874d2c8bcf822ebdaebfd9d95a31bb62daab5385eb8eefe026e8cbf1ff7a", }, { - length: 127, - nonce: [3]uint32{0x53106b0f, 0xdf11fd81, 0x69d1b6f3}, - key: [8]uint32{0x736b138, 0x55cde194, 0xf8273c1, 0xf7c268e6, 0x61362bd5, 0xbb3cb455, 0x44d3c9fc, 0x7d56d3fd}, + nonce: "0f6b105381fd11dff3b6d169", + key: "38b1360794e1cd55c173820fe668c2f7d52b366155b43cbbfcc9d344fdd3567d", input: "4f0171d7309493a349530940feece3c6200693f9cff38924114d53f723d090fffa3c80731b5ca989d3e924d1fa14266632cb9ab879e1a36df22dc9f8d1dadea229db72fded0c42187c38b9fa263c20e5fb5b4aa80eb90e8616e36d9b8c613b371c402343823184ecad3532058a46cf9e7ea5a9ecad043ac3028cbcc3f36d32", output: "88c773ff34b23e691e14018ba1b2bd48a4a6979b377eb0d68336ce6192dcd5177e6b4f1c4bea2df90af56b35fe2a1d6279d253c0194dcbca9bf136f92d69165b216e4c9d1ce6b3fbe40c71e32c3f4088de352732d0e2bad9c16fd0bb9bde3d6c30257ce063432d09f19da79d49aa7641124a6c9e3f09449e911edbae11a053", }, { - length: 130, - nonce: [3]uint32{0x5e90ffbd, 0xa898f173, 0x269f9a88}, - key: [8]uint32{0x5244e05f, 0xf9adbe9b, 0x9e9f54ac, 0x23460046, 0x6782cdea, 0xba982c96, 0xc721506b, 0xed10f7e3}, + nonce: "bdff905e73f198a8889a9f26", + key: "5fe044529bbeadf9ac549f9e46004623eacd8267962c98ba6b5021c7e3f710ed", input: "8f8d9e18d3212bd20b96d75c06d1a63622fd83d13f79d542e45996135368772ea81511302a0d87e246dd346314cfe019bae8a5c97f567f12d82aca98dfea397c6a47dd0c419f1c609d9c52dcfcbe7eee68b2635954206ed592b7081442ce9ce3187d10ccd41cc856fb924b011f817c676c9419f52a2938c7af5f76755a75eb065411", output: "4e130c5df384b9c3c84aa38a744260735e93783da0337ade99f777e692c5ea276ac4cc65880b4ae9c3b96888760fdddb74bc2e2694bedf1ee6f14619c8015f951ba81b274b466e318d09defe80bdbed57bc213ac4631d2eb14c8e348181d60f6295ceee1e9231ae047830ef4778ff66146621b76974773b5d11c8e17a476450f46ef", }, { - length: 130, - nonce: [3]uint32{0x308e39e8, 0x9aa4f14f, 0xf511db96}, - key: [8]uint32{0x833b5219, 0x4b82e588, 0x4b2d652c, 0x7c8f6ed7, 0xfe4be863, 0x9d3a50e5, 0xb888099b, 0x9f8d1968}, + nonce: "e8398e304ff1a49a96db11f5", + key: "19523b8388e5824b2c652d4bd76e8f7c63e84bfee5503a9d9b0988b868198d9f", input: "30d2379dd3ceae612182576f9acf6de505ab5a9445fe1a86ae75c5c29429e11c50fd9ec657b29b173a3763b1e171b5a7da1803ba5d64fccb2d32cb7788be194dbca00c3c91774c4c4c8ede48c1027d7cc8b387101a4fe5e44a1d9693b2f627626025072806083aadbced91c9711a0171f52ffb8ed5596cf34130022398c8a1da99c7", output: "b1e8da34ad0189038ee24673979b405ef73fdbdd6f376f800031d64005a4ebed51a37f2180571223848decbea6dd22b198ab9560d7edc047c5d69183dc69b5fca346911d25cb2a1a9f830dc6382ad0024e8c3eef3aa2d155abcfe43bff01956a5e20a862fbed5c5e8df8eed0601a120caac634b068314e221f175baa11ae29002bb9", }, { - length: 135, - nonce: [3]uint32{0xa5feca5a, 0x753ac1b4, 0xc5a46609}, - key: [8]uint32{0xabbf4859, 0x828d9bf6, 0xf7f7aa6d, 0x25208ca2, 0xd7a4c0ad, 0x2fdd3282, 0x2bfcb8c2, 0x8389d84b}, + nonce: "5acafea5b4c13a750966a4c5", + key: "5948bfabf69b8d826daaf7f7a28c2025adc0a4d78232dd2fc2b8fc2b4bd88983", input: "d9404ccdcc8ef128a1b1ace4f9f1669d274ec82aa914cac34b83ac00b236478fd6167e96ec658850c6c139eb0f6fc0dd7191ba9a39828032008f7f37eb9a8df9d6cdd54240e600efe7fc49a674000c5030d825b2c5c96d0f19b8ecdbf4eeb86d3e569c5e3131abc7d6359dd4255284ccacf150d42e7a899536d51ee6db329654a4581c5ac6e419", output: "c5534b5fb40b4834300e9577a9d87440c5272263d06e6aee84aa92cdf5d1b033145d336f26e5fe55c09a7e75753af93d0786dfc1cb435e86c67bd3ec8e766d0801b99e68691e2c3c3ffec539cf62e68285ea9027daa2716cd6f97e8eb7b9e266357a25eb2d4839a829508a6b7228f2832b3cd998f77597ae530430e6e4ecb53eb9efe456863a04", }, { - length: 135, - nonce: [3]uint32{0x12aa5846, 0x88604f6c, 0xc10d9585}, - key: [8]uint32{0x1491ccd6, 0x602f559d, 0xd4080c06, 0x202fabd, 0xffd3f4f8, 0xbf144c17, 0x88bf3f3c, 0x8083375}, + nonce: "4658aa126c4f608885950dc1", + key: "d6cc91149d552f60060c08d4bdfa0202f8f4d3ff174c14bf3c3fbf8875330808", input: "231765f832927461f338aceb0f4cf51fd8469348c69c549c1dec7333d4aa4968c1ed58b65ab3fe3d0562600a2b076d56fd9ef91f589752e0455dd1d2e614cacfc0d757a11a4a2264bd38f23d3cca108632201b4f6c3b06477467726dde0c2f3aee01d66d788247663f1d0e66b044da9393ede27b9905b44115b067914961bdade85a2eca2844e1", output: "1dd35f3f774f66d88cb7c2b23820ee078a093d0d85f86c4f103d869f93e2dbdd8a7cb8f101084fe1d7281a71754ec9aac5eb4fca8c365b24ed80e695caace1a8781a5a225938b50b8be96d0499752fdabd4f50d0b6ce396c6e2ca45308d1f2cc5a2a2361a8ca7a334e6ee62d466d74a1b0bf5b352f4ef6d8f8c589b733748bd3d7cda593243fab", }, { - length: 140, - nonce: [3]uint32{0x1c9d70f0, 0xa088a367, 0x4ec24d2b}, - key: [8]uint32{0x494e9775, 0xd07a852, 0xaf8af24a, 0xc65b825c, 0xc5e06780, 0x17fbbace, 0x651d71b5, 0xf548d8ef}, + nonce: "f0709d1c67a388a02b4dc24e", + key: "75974e4952a8070d4af28aaf5c825bc68067e0c5cebafb17b5711d65efd848f5", input: "e46841f12d98aeb7710b9162d342895a971b0e3a499886bbb6aa74dc744a28d89a54542b628acdc2f693cb7c03f73fc3b74069bc3f2d000a145fb8a806cdc7d6fa971da09a33b92851cc3d1f6f5646d7fa2b1d564876feefeb63b6e66dba1c0b86ca345235bb822e0f93132346840d2a3d6eb1b541178ea51affc7b31f8da02732cc4e5bcb5d8683ae0a91c9", output: "1dcbfd0bb2b905656c52bd7b1bcdad9b4d434ae9ac221a0d3a316115cdd4a463fa9b3444d2612a4e277d0dcd881fa6e80e59e5a54e35e1a14747aed31edf4ac24214f9d9c329ebe2157620b64efaded9976549bc4aa100d5c15be3f85f700f8a21dfe77590dfee2de9a23cc1ed1e44f32ebf68ca289b097bc13b42802dc7c75309c4afc25b5741839f7db3d5", }, { - length: 144, - nonce: [3]uint32{0x23067b8b, 0x5b276c6d, 0xaeca6c60}, - key: [8]uint32{0x29d64488, 0x893a2973, 0x32e3b4ef, 0x2af3d5d4, 0x95ec01b, 0xc805b64c, 0x884e8b7d, 0x798d7062}, + nonce: "8b7b06236d6c275b606ccaae", + key: "8844d62973293a89efb4e332d4d5f32a1bc05e094cb605c87d8b4e8862708d79", input: "e98e4a9550bdd29e4106f0cc8669dcc646a69438408e9a72c7cdb9b9d437b5f7a13fcb197629541c55bca1f8972a80cd1c1f591a0e24f977cdeb84763eab2648e42286e6473ea95e3a6a43b07a32b6a6cd80fe007ba0cf7f5ac7e651431f5e72690ec52a7134f9757daf0d8eff6b831a229db4ab8288f6bbf81e16fedebe621fd1737c8792cfd15fb3040f4f6a4cbc1e", output: "5c69cf522c058790a3bc38979e172b60e71f7896d362d754edc1668d4f388b3fc0acdf40786d2f34886e107a142b1e724b9b9b171cb0e38fd78b35f8ac5269d74296c39c9f8628d848f57af9d8525a33f19021db2b9c64ba113171ebb3882075019ec7e77b51ce80b063ed41d48dad481d9536c030002a75d15c1c10ce0ec3ff17bc483f8416055a99b53035f4b6ea60", }, { - length: 148, - nonce: [3]uint32{0x2b079658, 0xbdf5da85, 0x8a75450d}, - key: [8]uint32{0x49c9eaa3, 0x62048819, 0x9baacfa5, 0x3870addc, 0x5c682e1, 0xf4f9fff3, 0xa3848e4b, 0xac1ebc1}, + nonce: "5896072b85daf5bd0d45758a", + key: "a3eac94919880462a5cfaa9bdcad7038e182c605f3fff9f44b8e84a3c1ebc10a", input: "ce0f0d900dd0d31749d08631ec59f216a1391f66a73bae81d3b0e2919a461bc9a14d6a01b827e3bcb55bbccf27c1ed574157e6becd5cf47181a73c9d3e865ab48a20551027e560e965876b0e1a256bfa5cb5179bf54bd8ec65e5570e374b853b37bf4b3ef1ec612d288ebc19275fa88da9419e012f957f9b6a7e375b3377db0eb3619c731aebfeb0930772b4020d3a3e90723e72", output: "b06981b57fe184091ef9f8ccf522a5bcdb59bf9a68a3ddb817fdd999a6ecf81053a602141cf1b17017bae592b6b6e64756631a2b29a9e1b4f877c8b2ae30f71bc921e4f34b6f9cd8e587c57a30245f80e95005d0f18f5114400785140e6743da352d921fb4a74632a9c40115ad7706263ac9b41a11609fa0c42fc00f8d60931976162598df63ebad9496dd8943d25a03fa47475c", }, { - length: 148, - nonce: [3]uint32{0x98e8ab8, 0x84d8e77b, 0xbb305841}, - key: [8]uint32{0x46b5f93c, 0xc8b2778d, 0x2cc5278f, 0xd2a3904c, 0x6ce5d4f, 0xc4459e8, 0x4a35c30, 0x2feadc02}, + nonce: "b88a8e097be7d884415830bb", + key: "3cf9b5468d77b2c88f27c52c4c90a3d24f5dce06e859440c305ca30402dcea2f", input: "eccfd66bdc691478f354b8423d6a3f20932a1f591d8e6cefa734975fb8ee6881b6dc92c0d1d5ed54fd1999efd7f11ac697a1f130587dd895eb498c9a8fc7d1714c385ec156ecae3bdea2a3462834245e724531d0fedda2b77693a53ed7354b758e875b23cfc83219a091fb2076e7a88cd77f779ed96f8d81ffa3fe5059303ac706086494b9f2982f4f88a0c6fadc3748625004db", output: "925529047d4177b72bf50905ba77e47608815522c1829b24046e439d5451901257903a5409fb910373167e8b7f4fdfa543a477608ddfc11bbd1efc138366961463b9915b302a346b795dd593f6fcf4fa73529b6fe83079552aabbe99474a72806f59688d826675fa7f6649b9f5307e5028853c9821b8c4a1a0fc4bfdc7c8c78b25aeaba2b5821d17b36317381a3bd578917d2504", }, { - length: 152, - nonce: [3]uint32{0x2e2a6e4a, 0x9a6d488a, 0xf9966cb6}, - key: [8]uint32{0x58903bff, 0xc2be173f, 0xe26128b5, 0xb6b6af53, 0x92f8eeb, 0x38cf3336, 0x7fdf90fb, 0x7ae24b37}, + nonce: "4a6e2a2e8a486d9ab66c96f9", + key: "ff3b90583f17bec2b52861e253afb6b6eb8e2f093633cf38fb90df7f374be27a", input: "f0c7139c69413869bca980d7f192b2bc3f57e34ca4f26164e1a54a234e84e1aa285cc02cfbaef3dfba2dbb52a555ec1f6ef0e89d0b2f0bd1846e65b74444b5f003a7308965e67bed558689be2668ca10ca368fac072e0e4535a031af23b3c37c561e185872b86c9bceddb5c1199e43fb5f735384766d33710460b541b52d3f5b6c108c08e76724bcac7ad2d866a8bbeeea92a3d867660d2e", output: "d2c16c7a242b493038203daec65960de384c030eb698ef6a53c36eabb7556cbfa4770eaa8bc0a2b385ad97495eeb1c03ff4e6efcb804aefa81c177dc62700a9eefe6e8dd10cff5d43a2f47463cab5eb1ee260c3826cac9bfa070f1e0435541a89ebd224d13cc43f8fff12f38091c2b3f2102d5c20d8b1c3ae4f129364bbe9f9ce2147dcf0639668ddb90dffe6a50f939f53fa7ba358e913f", }, { - length: 155, - nonce: [3]uint32{0x243e0198, 0x884448c, 0x9a31e760}, - key: [8]uint32{0x37e017bc, 0x9b1e2e90, 0x15679daa, 0xf94a23ee, 0xda86dfe, 0xc3eea84c, 0xdd199799, 0x6eeffb92}, + nonce: "98013e248c44840860e7319a", + key: "bc17e037902e1e9baa9d6715ee234af9fe6da80d4ca8eec3999719dd92fbef6e", input: "7024974ebf3f66e25631c0699bcc057be0af06bc60d81a7131acaa620a998e15f385c4eaf51ff1e0a81ae5c6a7442d28a3cdc8aeb9701055e75d39ecac35f1e0ac9f9affb6f9197c0066bf39338a2286316e9d1bb7464398e411da1507c470d64f88d11d86d09e6958fa856583ace697f4ee4edc82618662cb3c5380cb4ce7f01c770aab3467d6367c409a83e447c36768a92fc78f9cbe5698c11e", output: "ff56a3a6e3867588c753260b320c301ce80de8c406545fdd69025abc21ce7430cba6b4f4a08ad3d95dc09be50e67beeff20d1983a98b9cb544b91165f9a0a5b803a66c4e21bd3a10b463b7c1f565e66064f7019362290c77238d72b0ea1e264c0939d76799843439b9f09e220982eb1dc075d449412f838709428a6b8975db25163c58f40bf320514abf7a685150d37a98bac8b34ccb5245edb551", }, { - length: 160, - nonce: [3]uint32{0xd24e866d, 0xc59d25d8, 0xfcf623f1}, - key: [8]uint32{0x5f32cca0, 0x4167cac5, 0xc04943ee, 0x507fa1ec, 0xad8fdfc0, 0x6266fa2d, 0x22f05341, 0x8074143e}, + nonce: "6d864ed2d8259dc5f123f6fc", + key: "a0cc325fc5ca6741ee4349c0eca17f50c0df8fad2dfa66624153f0223e147480", input: "8d79329cf647e966fde65a57fc959223c745801c55312046b791671773cca0af4cd48ead1f316eba0da44aa5d18025eced0c9ed97abaabb24570d89b5b00c179dca15dbae89c0b12bb9e67028e3ae4d6065041b76e508706bec36517a135554d8e6ef7cf3b613cbf894bec65d4dc4e8cb5ca8734ad397238e1e5f528fa11181a57dc71cc3d8c29f3aba45f746b1e8c7faace119c9ba23a05fffd9022c6c85260", output: "60aea840869f7be6fcc5584b87f43d7ba91ed2d246a8f0a58e82c5153772a9561bdf08e31a0a974f8a057b04a238feb014403cd5ffe9cf231db292199198271f9793c9202387f0835a1e1dc24f85dd86cb34608923783fd38226244a2dd745071b27d49cbffebea80d9dacad1578c09852406aa15250de58d6d09cf50c3fcfff3313fac92c8dad5cb0a61ccc02c91cecee3f628e30c666698edecf81831e55ec", }, { - length: 167, - nonce: [3]uint32{0x30b61047, 0x810cf901, 0x4d681524}, - key: [8]uint32{0xe51476d0, 0xdf98008d, 0x59dfe69e, 0xdb39166, 0x6c1e4a4a, 0xfb76165e, 0x5180f185, 0x7359fb35}, + nonce: "4710b63001f90c812415684d", + key: "d07614e58d0098df9ee6df596691b30d4a4a1e6c5e1676fb85f1805135fb5973", input: "85484293a843d2d80b72924b7972dfa97cbe5b8c6bcc096f4d5b38956eb3f13f47b02b0f759ea37014ecdecfb55f2707ef6d7e81fd4973c92b0043eac160aaf90a4f32b83067b708a08b48db7c5900d87e4f2f62b932cf0981de72b4feea50a5eb00e39429c374698cbe5b86cf3e1fc313a6156a1559f73c5bac146ceaaaf3ccf81917c3fdd0b639d57cf19ab5bc98295fff3c779242f8be486ba348bd757ba920ca6579be2156", output: "bb1650260ef2e86d96d39170f355411b6561082dcc763df0e018fdea8f10e9dc48489fb7a075f7f84260aecc10abcfadbc6e1cd26924b25dedb1cc887ada49bb4e3e02006bdd39098ef404c1c320fb3b294ded3e82b3920c8798727badfb0d63853138c29cf1ebf1759423a1457b3d2c252acf0d1cde8165f01c0b2266297e688ff03756d1b06cb79a2cc3ba649d161b8d9ef1f8fb792bd823c4eabb7fb799393f4106ab324d98", }, { - length: 172, - nonce: [3]uint32{0x42020cbe, 0xad62af90, 0x29e53cd}, - key: [8]uint32{0xabad2095, 0x601ec477, 0x3bc923a1, 0x1edede1a, 0x33612355, 0x285b4858, 0xd3fd6714, 0xe0f4bcc3}, + nonce: "be0c024290af62adcd539e02", + key: "9520adab77c41e60a123c93b1adede1e5523613358485b281467fdd3c3bcf4e0", input: "a2fc6e1b5281a4e0330eecd1ab4c41670570423173255979953142b78733b2910fa5540e8294208df6ae4f18672d5ac65acf851bcd394e1932db13c81b21e6f165e5538aff862e46126c650bbe055e54b31c78f2f0221d2631d66ef6d3f4c5ae25eada043b74d8770e2c29799c0954d8ccbd17766b79e6e94e88f478db3566a20cb890846917591a07738328d5c05f7ed4695a82607660f1239661faa9af0368aeb89726f13c2aaecf0deaf7", output: "d8fe402a641c388522842385de98be60f87d922c318215947d4b7562d4ca1e2dbc7ee86494e65fb0bfddfdebdb2ae6469312f95b32c722b2720d64bb8d7cc3dd82f9055b1d89f05b77984f91f94ba4ac79c5129cd7c91cc751b0defc3f2799518e372d27aa683f1e7bbd4f55414c48fe8a3a37ac1f179a1a329cda775aec0d31d75a5a38addb1de67c06bddbedf4c8d87abc18c9f9dd072d457ea29ad4dfb109ce7e99a4a82fbe330b0afbb5", }, { - length: 176, - nonce: [3]uint32{0xa8021c8f, 0x667a02c4, 0x7a68b693}, - key: [8]uint32{0xece401c8, 0xfa805a47, 0x6d572fca, 0x9c1c780c, 0x647545e5, 0xd7ef4c11, 0x91dc1e46, 0xba2a694e}, + nonce: "8f1c02a8c4027a6693b6687a", + key: "c801e4ec475a80faca2f576d0c781c9ce5457564114cefd7461edc914e692aba", input: "480387bc6d2bbc9e4ced2448d9ec39a4f27abe8cfb46752d773552ad7808a794058962b49e005fef4e403e6a391d1d3f59025eeb5fb8fbbe920f5361862c205d430eac613cd66108f2f2f0bd4d95a8f6ca7bd1f917eaeb388be87d8b7084a2eb98c575034578edf1b3dafff051a59313873a7be78908599e7e1c442d883d3fd3d26787eb7467eed3a3fb2d40046a4460d5d14215565606bcf8b6270af8500e3504d6d27dacf45bace32214472d525fdc", output: "ab81a9c28358dfe12e35a21e96f5f4190afb59214f3cf310c092ab273c63cd73a783d080c7d4db2faccd70d1180b954cd700c0a56b086691e2c2cd735c88e765e2266cd9ebe1830d63df4b34e2611a8abeeca9c8c4fac71135dafb1cb3569540ed1362ddeb744ed62f6fd21de87b836ec2980f165c02506e0c316ae3cf3d18a862954d9781f726ecc1723af4a730ccc6d6de82553450a52499acb58fb2008969401c45b2f20e12b58f308db1d199b4ff", }, { - length: 176, - nonce: [3]uint32{0x414e687c, 0xc6fc69c2, 0xd3ca12d3}, - key: [8]uint32{0x1b51cca, 0xbc8455af, 0x3f904842, 0x6042b452, 0xcd4dd164, 0xda83f3f0, 0xff04b972, 0xf972dd0e}, + nonce: "7c684e41c269fcc6d312cad3", + key: "ca1cb501af5584bc4248903f52b4426064d14dcdf0f383da72b904ff0edd72f9", input: "b274e61059f3215173ae226e30a92ee4b4f8a3da95f2e768e3fac2e54ddac92c200c525f190403a6ef9d13c0661c6a7e52ed14c73b821c9680f1f29711f28a6f3163cf762742ed9474dbea51ff94503a5a404adbbdfbf4c6041e57cb14ea90945dc6cb095a52a1c57c69c5f62ac1a91cd8784b925666335bbfee331820b5f7470bc566f8bbb303366aafe75d77c4df5de2649ed55b2e5e514c3cb9f632b567594a0cf02ec6089a950dbe00554ee4dfb9", output: "a0969730d48ee881792a3927b2f5d279aba9f2ed01e6b31b92d0e1fb8ba7f35a236d838e0ce5f8654957167de864f324c870864b4e7450a6050cd4950aa35e5a1a34a595e88dd6f6396300aff285de369691b6e0e894106dc5b31525e4539c1e56df3ceedbbab1e85da8c0914e816270a4bae3af294b04a3ea6e9ef7e2aab4da5f5370df2706b5e3f000d88179ac756deaa652a1cc85e80ad9622f1bf91a2776262eb7289846d44f7f8192e763cb37aa", }, { - length: 183, - nonce: [3]uint32{0xdd315c1d, 0x2335da98, 0xe0a0da0f}, - key: [8]uint32{0x6419c7d6, 0xd340f42, 0x7af2f4b8, 0x3536cf42, 0x2f68c6fb, 0xac9d855f, 0x7c4d490, 0x9711b1b1}, + nonce: "1d5c31dd98da35230fdaa0e0", + key: "d6c71964420f340db8f4f27a42cf3635fbc6682f5f859dac90d4c407b1b11197", input: "ee849039c6cd972dc943d2a4468844d130c0150276f4e0889047e2300c3ecc6792c4527bfe9437dad877eb986e6b1aa9b867d1798c9d314243f0a87ec9ee5b601c2554876c87cbf50df3334a077c4152f8b8fef4a2d301ddbfa90c887ece757c3eb6c4fc1e0212d6b5a8bb038acaec28cba064c9b34f5364cb7f0fc2ac4ef2c7ddde0f5ba17014459eaa78f08a46a01882ebf7c6e409dadda250bb899dc8b3b70e160bbcb4412a9963b174d0fc6bc16383a46ffaacb6e0", output: "3e272ded9c0a5cebe7cf17ac03f69eb20f62996e047501b6cc3c8691ddb2780ea72c21a81888bfea96e4373a412c55ca95648390de740102d661143043baec3976230e024477d134b8504a223c36a215b34164c9e9e1fa99a49fdc56f2f04ea525a6b82997d9bbc95c4b5baeab4dec50061efb7c1a757887acb8b47b142e0a2e61885a2c14c4642d83d718a0546b90699adc545a48129603862a1c89d8e665cde54b3ba487754db6d6f5acf6a4b95693cc569577a2dc48", }, { - length: 185, - nonce: [3]uint32{0xebb44f7c, 0xaf14c7dd, 0x4543cd7a}, - key: [8]uint32{0xce71977, 0x99790e86, 0x6510d6dc, 0x37968ae7, 0x2917fb9a, 0x19ef25f, 0xd282d085, 0x6128d043}, + nonce: "7c4fb4ebddc714af7acd4345", + key: "7719e70c860e7999dcd61065e78a96379afb17295ff29e0185d082d243d02861", input: "0992396a6f29b861dd0bc256e1d1b7dce88435733506a6aa20c62e43afa542d1c46e28b2e6d8e2eacb7c08db05e356fe404684b0e3a9849596db82eb788aa09258c28eb19e9838f757425b4edef12deeca56e30cf030272e325d4246d6e083219b2f965124963ca91f066d47bf5a8282a011a78b0155aa70038259a4a59135f241fd2f88c908b9f4eef7b7df0f3a1c16a52c009b522f89dabd52601bbf6e3ce68732e1a6d444469480f06da218786cf6c9666362e7a7f7be12", output: "545c05a84b5a4fffd1dd623c8f2b11443818560bdb0c26dadd3b694d4790d294b99059f4127b7cca122c4000954d745af96094ff4623f60db33e994bb6903263d775f48d7047427b3a498c2ecde65bd37bcb8ee7e240a1e08c884c0079cab518f4e1c38ba5ea547f4da83b7c6036e4259bee91c42e8fae895df07781cc166f1d50e1550a88ee0244bb2950070714dd80a891aa8a9f0580a67a35cb44609b82a5cc7235f16deea2c4f3667f2c2b33e8eeef944e1abdc25e48fa", }, { - length: 187, - nonce: [3]uint32{0x35cb7190, 0x212e9a86, 0xbc423ce4}, - key: [8]uint32{0xfa19cede, 0x576ae8f2, 0x58055dab, 0x91b3355d, 0x69d2501a, 0x736323c2, 0x266c1385, 0x134f4557}, + nonce: "9071cb35869a2e21e43c42bc", + key: "dece19faf2e86a57ab5d05585d35b3911a50d269c223637385136c2657454f13", input: "3b9efcbbb607fad5e9f1263dad014cc5c2617d439fcd980408f4f9a93acb1a33d1c3a22f38c037e4603dfbbfb5571bc08c4a1958cbbf510e3e4dd19007fe15fad7808369149a9c4db7ca0496f7a600a6f2454ee1cffd5a68d45c270e4b53ac9b77f33a1ffbb1804244f57d2b05b8036fe2cda9efead3d4eff074ea5c07128e0b354a4a11ffa179163933bc6bd10d200804cc93b64575746e94e975f990bddcc8a4335e99e2459fbe9bc0e004ffcd6cac52f48ef55cc0637a75c1dc", output: "631ba7301e33236da2477506ea98d3b732447389e849b68e1f09bd5fd814f40dc3247a1012fa654f08e3dda0c104ee2dff12ecf5cb018644de50d70dfb6c8cc1f5f552e5f1e50466bbb538ad6b98fd37f33fe615c326efc9cc97899b829b007f91569fa9b28ce0076c53daedf9cc0f838e22cf1125b86a6a2c2eb4a45dadea45ad00fb4f054e7d6b09c13ab1dd5328debfbf4f1b70af2b8a5b1d02df8a87d7661473e0c180ba4c815f14db87c5bdc15f11a29d8e0ce3d747d5dcd4", }, { - length: 191, - nonce: [3]uint32{0xccc941ac, 0xdba45b02, 0xab0d7ad6}, - key: [8]uint32{0x9b750752, 0xa627090a, 0x967c95f0, 0xf8ff2c3f, 0x69beb97e, 0xa30b99c1, 0xadddc83, 0x443f9baf}, + nonce: "ac41c9cc025ba4dbd67a0dab", + key: "5207759b0a0927a6f0957c963f2cfff87eb9be69c1990ba383dcdd0aaf9b3f44", input: "f28a71efd95e963e5e0bc0fcf04d8768ce93cb55dc73c32e6496022e214596314b7f843f5c7b136a371c2776a0bfbdd534dccbe7f55e9d3d3b5e938f2d7e74393e4caf6c38fa4b05c948e31dc6a9126817fa3d7892c478f75ab9f6ab85c0e12091bd06e89c7d3ca8d9dcdd4c21fead3d769a253919c2c72dd068474ea322b7e71cafa31684e05a63e179e6432fb70661792cc626a5060cec9e506b35d9286f15dc53cc220b1826314eec337dd8e7af688e5950b2316c30516620569ea65aab", output: "1bcea54b1bf4e6e17f87e0d16388abe49b988b9c785b31f67f49f2ca4011ecd2ad5283d52ef707dd3b803e73a17663b5bfa9027710e045a0da4237f77a725cf92792b178575456de731b2971718937dd0e9ea12558c3fa06e80bbf769e9799f7470db5b91476d6175f1a6d8e974fd505854c1230b252bb892a318e6d0c24dcc9ecb4861769cd746abab58805bc41c6086a6d22b951fba57b00c5b78f6dcb2831715b9d4d788b11c06086f1d6e6279cd130bc752218d7836abc77d255a9e7a1", }, { - length: 198, - nonce: [3]uint32{0x987e7c58, 0xcc839a94, 0x30952e60}, - key: [8]uint32{0xe34a286f, 0x4adcd996, 0x97168712, 0xa82dde8, 0x14249e5, 0x5e82810b, 0xb4a445e8, 0x9579adb0}, + nonce: "587c7e98949a83cc602e9530", + key: "6f284ae396d9dc4a12871697e8dd820ae54942010b81825ee845a4b4b0ad7995", input: "c1d1ede73bd89b7c3d4ea43b7d49c065a99f789c57452670d1f92f04f2e26f4f5325c825f545016c854f2db2b3448f3dc00afe37c547d0740223515de57fd7a0861b00acfb39931dc9b1681035d69702183e4b9c6559fb8196acbf80b45e8cc5348b638c6d12cea11f6ef3cc370073c5467d0e077d2fb75e6bf89cea9e93e5cf9612862219ca743ef1696783140d833cd2147d8821a33310e3a49360cb26e393b3fee6dba08fcda38d1b7e2310ec1f715e3d8fa0c6b5e291eea07c25afd5c82759a834a89cc5", output: "11a8493cdc495c179f0d29c2b4672997205a9080f596ee3c80d79b55162b1c875ac18eb94bf2a9e05b08024f524a1e9665912394a330c593d23260e6bdf87620c10a48f678693196fb744c49054182fba667c601e7b7ebf0f068e8d69ba004b804fda616a4a0d5350e1a3bd424b8266462be282308219c578569aefc1ccd09ecdf5da283356c9e524e14e69d25b0e19643dab26f54373a7272b43755c3f1ddaee6c5fb9e8e093110c41697e95f73a68c75454e050239197c9fbd8cec76698bd11894ebf6e2b2", }, { - length: 204, - nonce: [3]uint32{0x851f025a, 0xe6f3c800, 0x85ae7530}, - key: [8]uint32{0x2d0dbe47, 0xda05e465, 0x42f6b3b2, 0x7026e79e, 0x9e446680, 0x691df976, 0xf7b23da2, 0xbb3421fa}, + nonce: "5a021f8500c8f3e63075ae85", + key: "47be0d2d65e405dab2b3f6429ee726708066449e76f91d69a23db2f7fa2134bb", input: "37b2dc4b6a5203d3a753d2aeffcdaed5a7c1741ed04d755dd6325902128f63b6981f93c8cc540f678987f0ddb13aae6965abb975a565f0769528e2bc8c6c19d66b8934f2a39f1234f5a5e16f8f0e47789cd3042ca24d7e1d4ddb9f69d6a96e4fd648673a3a7e988a0730229512382caaded327b6bbbbd00a35df681aca21b186bc7ac3356d50889bbf891839a22bb85db4c00bfa43717b26699c485892eb5e16d1034b08d3afa61f3b5f798af502bba33d7281f2f1942b18fb733ca983244e57963615a43b64184f00a5e220", output: "b68c7a2a1c8d8c8a03fc33495199c432726b9a1500bc5b0f8034ce32c3e3a78c42c1078e087665bd93c72a41df6bfa4e5beb63e3d3226aeeba686128229a584fab0c8c074a65cef417ad06ab1565675a41cf06bb0fb38f51204eccccb75edd724cdd16b1d65a272f939c01508f0385ca55ac68a0e145806317cc12e6848b1124943a6b2d99a8c92083fc5f31ab2e7354db3f8f2d783dbf1cfec9c54f8bfcb93d6f28ef66f18f19b0fab8836458e9b09bee742ba936cb2b747dd9dcf97ca7f6c82bf0af6f1b433592d65143fe", }, { - length: 210, - nonce: [3]uint32{0xaebfd97f, 0xf583442d, 0x15ab2f1f}, - key: [8]uint32{0xd3d1cf9b, 0xe43187e6, 0x5071a757, 0x412a83b4, 0x3f27716f, 0x17fdc488, 0x271f77ed, 0x6c4bb056}, + nonce: "7fd9bfae2d4483f51f2fab15", + key: "9bcfd1d3e68731e457a77150b4832a416f71273f88c4fd17ed771f2756b04b6c", input: "68c2c5612912b5f994172720130dff092ee85a2c1395111efa64d5a281ca864d3db9600e685854d81c6de7e8747b92fb7c4c2efa829d3d4c0c9fc9d689e2e5c84c9eae8ba4ab536fb6c7523124b9e9f2997f0b36e05fb16163d6952eee066dd22fb7585925ffded0204cc76818bcead0d1f8095ca2cf9cd1ddcd0361b9c9451940e14332dac4e870e8b2af57f8c55996447e2a8c9d548255fe3ed6c08aedaf05bb599743ecb0df8655152bbb162a52e3f21bea51cb8bf29f6df8525eb1aa9f2dd73cd3d99f4cca31f90c05316a146aab2b5b", output: "d0ae327fa3c4d6270a2750b1125145bdeef8ab5d0a11662c25372e56f368c82c6f5fc99115a06a5968f22ffe1e4c3034c231614dd6304e6853090c5940b4d1f7905ef4588356d16d903199186167fec57e3d5ce72c900fe1330a389200ed61eec0bdc3672554f1588ec342961bf4be874139b95df66431178d1d10b178e11fcbd26963ff589d5d5faf301b7774a56bbfa836112a6ea9c3026ebdd051085f9131132c2700674bef6e6c2c5b96aace94eb2ba6c0e0aef0eefa88995e742ca51ac50af83683b801b7c2c5af4880e2b344cc5564", }, { - length: 216, - nonce: [3]uint32{0xf9e973b8, 0x2485a6a7, 0x2ea7dee6}, - key: [8]uint32{0x96edef11, 0x8cf57f26, 0xb6e3a83c, 0x9ef434c6, 0x4607ea48, 0xace87e4d, 0xa0d87475, 0x3a9c9458}, + nonce: "b873e9f9a7a68524e6dea72e", + key: "11efed96267ff58c3ca8e3b6c634f49e48ea07464d7ee8ac7574d8a058949c3a", input: "fed3d1efa309c8b50cb9da02b95167f3b77c76e0f213490a404f049270a9c105158160357b7922e6be78bc014053360534add61c2052265d9d1985022af6c2327cf2d565e9cef25a13202577948c01edc22337dc4c45defe6adbfb36385b2766e4fa7e9059b23754b1bad52e42fce76c87782918c5911f57a9394a565620d4b2d46716aa6b2ba73e9c4001298c77bfdca6e9f7df8c20807fa71278bd11d6c318ed323584978ad345c9d383b9186db3bd9cec6d128f43ff89998f315dd07fa56e2230c89d803c1c000a1b749107a3159a54398dac37487d9a", output: "6a95fba06be8147a269599bccda0ce8f5c693398a83738512e972808ec2f25bc72402d4bcd1bc808cc7772b6e863b0e49d1d70c58fcf4fcaa442215eeb3a4648ade085177b4e7a0b0e2198f0acf5465c97bd63f93781db3f0b9a0a184c3e06a76c4793a13923f83b2242b62511c2edff00b5304584cbe317c538de23785d2504fae8faabee81c5315298186ce3dcbf63370d1ccd9efec718cbc90b3d2e0b0b6aefb3a9b31e4311f8f518be22fdc2b0f00e79a283701c53f6936dd63734ecb24480d5365d1a81392498faf9a1ddee577007acc5f8c87895be", }, { - length: 217, - nonce: [3]uint32{0xe3bd4c44, 0xa3b75a31, 0xfe92010f}, - key: [8]uint32{0xdd05ab8b, 0x5ac7cd1, 0xb8113720, 0x53524706, 0x8e0ceea1, 0x52eb23e7, 0x1c85730b, 0xb33914d5}, + nonce: "444cbde3315ab7a30f0192fe", + key: "8bab05ddd17cac05203711b806475253a1ee0c8ee723eb520b73851cd51439b3", input: "d776bee5625d29a2ebf6fec4df94d2b9ac62e8e7c56704fd38a87ee932b787cbc555621535e76ea30183cb0ee30604f485b541f45feb8c01b9750d37fded5cdffbbc34fb90fdc9c7c7ddf949a1d50b796f1ea5db437238c7fb83c4b22c9e491f75b33d84746f1cd10bfda56851b8514ff0ded0adfd5092a66a85202d06bd967485d06a2c56011110da74bf40b6e59f61b0273164744da02ce2b285d5c3f03aee79eea4d4503e517177692ed3bb035071d77fc1b95c97a4d6cc0d41462ae4a357edf478d457c4805fa586515614697e647e19271091d5734d90", output: "60e9b2dd15da511770162345251edfb15cea929fb79285a42f6c616dfde6befc77f252e653b2d7902a403032fc4ce4934620931a2ec952a8d0f14bf1c0b65cc287b23c2300999ed993446eb416749bf0c9c7dfe60181903e5d78a92d85e7a46b5e1f824c6004d851810b0875ec7b4083e7d861aabdd251b255b3f1fd1ee64619a17d97fde45c5704ab1ef28242d607d9501709a3ac28ee7d91a3aac00cd7f27eb9e7feaf7279962b9d3468bb4367e8e725ecf168a2e1af0b0dc5ca3f5a205b8a7a2aae6534edd224efa2cf1a9cd113b372577decaaf83c1afd", }, { - length: 218, - nonce: [3]uint32{0xcdabfd50, 0xd10d5b99, 0x9e160a85}, - key: [8]uint32{0x8231a4e9, 0x89f33c8b, 0xf96b11b, 0x853cae9d, 0xf6624a33, 0xee9523ee, 0x28bb7853, 0x688ac6f8}, + nonce: "50fdabcd995b0dd1850a169e", + key: "e9a431828b3cf3891bb1960f9dae3c85334a62f6ee2395ee5378bb28f8c68a68", input: "4f57848ff5398e61bcafd4d4609bcd616ef109c0f5aa826c84f0e5055d475c6a3a90f978a38d0bd773df153179465ab6402b2c03a4bf43de1f7516eb8626d057ae1ab455316dd87f7636b15762a9e46a332645648b707b139e609b377165207bb501b8bccfa05f1bf0084631c648279afdf51c26798899777812de520f6a6f0d3c7f3ef866982f5d57f9c8d81c9a4eabb036651e8055a43c23a7f558b893dd66d8534bf8d179d8aa7d9e8987cfdaaa7b5a9381ba9c79d5c1161b1bdbd30defdd304ee07f19b7ba829a0d5b40a04b42edd6407b68399caac69069", output: "e096cc68956ed16d2dea1154a259e01647913eeea488be0b54bd1816c781a35e161772ae1f7a26b82e864ade297a51cc9be518641b2e5f195b557ec6fc183e4e5c1fc01d84fe6ca75e5b073af8339427569b1b8ee7fcff0ffa5e7e6237987c40deec0abf091c06a3b28469c8f955fc72e4f3727557f78e8606123e0639dff782e954d55e236448f4223ff6301accda9f8fa6cd43a8d6381e5dde61851a5aec0f23aeca7262659bc793ce71fa7992f80e44611ae080b7d36066e5c75c30851306f0af514591d4d5034ecdf0d6c704bfdf85473f86141c9eb59377", }, { - length: 219, - nonce: [3]uint32{0x67de323f, 0xa0442ac9, 0x9d77b1d9}, - key: [8]uint32{0xca8d33d4, 0x834349d9, 0x5e68d581, 0x99a7c30e, 0xdc7f6038, 0x697e8b63, 0x284c2ece, 0xee3e3bfa}, + nonce: "3f32de67c92a44a0d9b1779d", + key: "d4338dcad949438381d5685e0ec3a79938607fdc638b7e69ce2e4c28fa3b3eee", input: "046a61c0f09dcbf3e3af52fab8bbcded365092fad817b66ed8ca6603b649780ed812af0150adbc8b988c43a6ada564a70df677661aff7b9f380d62977d8180d2506c63637c0585dcef6fe3f7a2cf3bbb7b3d0df7769f04bf0f2e3af9439ab7615c304b32055aea0fc060890beb34fa9f90084814b6ed7363b400dfc52ee87925c5b4a14a98e3b50c7f65adc48c89ddd6414626c5e0bdefabab85c4a0e012243e682d4931be413af62fd7123ab7e7774fcae7e423bf1d3a31d036195437e9ea8f38aa40182daa9aacf3c9f3d90cc0050977c6065c9a46bcca6ba745", output: "cd5a6a263e3ee50dda0e34c614b94c3ec1b14b99a2f4095a6b5715fdfc3449fcdf8a09d1ae02d4c52e5e638f1ee87a4a629f99f15a23dd06718792f24285f5a415e40f698752c697ee81f2f9248da1506ce04a7f489f8e2b02e6834671a2da79acc1cdfb78ea01822d09a1c4a87ffa44e56c4f85f97507044cf946ccb6a2e06e2917bac013f608d75ee78fa422a5efc9c569226bf7068d4705fde3a9fad2030256db0acf9a1d12666e0acf9f5346ad62e5af4c01a008d67ab1224b3e98278d073116ff966cdc779fb3aff985ec9411a3eefa042d71dd4ae5b15d5e", }, { - length: 221, - nonce: [3]uint32{0xa36a3d5a, 0x1747a05f, 0x5440eb4}, - key: [8]uint32{0x2d701ee6, 0x143d5a1a, 0xbb67b9ab, 0xabc88ccc, 0x20baad8f, 0x6507e48b, 0xdb1e1b39, 0x9e521d80}, + nonce: "5a3d6aa35fa04717b40e4405", + key: "e61e702d1a5a3d14abb967bbcc8cc8ab8fadba208be40765391b1edb801d529e", input: "af516216f74a6344cbe458cbba820f7e25c0b10aa84b790da2ee6317e059171076d7246c2878be83fc00c200d546c007f849e4c163d52c7b0da31beff4abff481be3266b92e668cf4dd1c84d9d7b3e5191dcd6ddb51d17d337621046e83e9ac035fccfb239648bc3c6fd340fbb50707e5a33b3ef439d292192d0e4bc727690c61450e5a28789e5ea50e746bc66d039493e080fb70e9ae06d89004cb71de8178941c422f1e9862492fc9149a4864ff52b1277b9f5a63c2f16e9adb5263cf65a034a62ebb0f1a385d2681c87a35f1c45670b4edef1c68fe9544fcf411d95", output: "b22ffd8f0e549bd3e0206d7f01ff222f92d39b41cf995a331d5ef0cf5c24bcc3ddb36e64d351b5755400246fe4989b5f912e18daa46cdd33e52dafbd2872f16e94220b56315d72c1dbb1525fd34831d7202970c11711ff36de3fc479407c34fef0aea86e172f9beb0f393194355b9dd59625639f4a6bf72ba571c229f2fb053c1114e82793deb2dfe8232f1a327949689d2fb2820662dcd2a39a2546c7df12b3ff7e87e58c74badf568cddebd3c558f0f7874c834c4b8aa988653f138ec79620f5e3ed737690928a30f981dca9f2920ac7307607063b40f87c204de47c", }, { - length: 223, - nonce: [3]uint32{0xb92be022, 0x1e1257c7, 0xad7c01e}, - key: [8]uint32{0xca1dbb9c, 0xaadb9504, 0x77b8a95c, 0xc50deb5e, 0x2dbc0fb8, 0x9e654bc2, 0x94d8925a, 0xfe9cfb66}, + nonce: "22e02bb9c757121e1ec0d70a", + key: "9cbb1dca0495dbaa5ca9b8775eeb0dc5b80fbc2dc24b659e5a92d89466fb9cfe", input: "a3d70bdb509f10bb28a8caab96db61652467cf4d8e608ee365699d6148d4e84d5d93bdabe29aa4f0bc8ee155f0b1fb73293c5293929eaacdd070e770c7cccfb2de120b0c3811abeeddaf77b7214a375ca67d618a5d169bb274a477421d71a651cfb9370bcf7e0d38f913754c11002089cf6cd6a8de1c8a937fb216591d57b37efdf3797f280773950f7eddeb9c3385c8315ff5ff581c64610a86ada7ff6a1657e262df94892dff9fdfb6e958d101f4c26296470c138dc4e1ca4bb565b3ff877a7f78b3d11d64b7c24e27ba6f6b06f6e368f5ac218cd5d11b815ab0987678eb", output: "646314264896a6e25601e536f6e783d465b2ead1e0be4422bc9cc8eacabae4a749ad533eb28091be8397328dcfb34c92006bbda930ab070ed7b806095bb1c8f476350e7b08ffbd4d7d6055c8defaa8deff9d54f5215c2d7db27ce09e08f5d87a859145ea3126e2a01882921c3fddef3985bd451bca44063258390aec8ec725b07d064314fe43a9c83e9287b47616dfefbf539b82da209aa08a6d3176b7e3b4be4a17d44e581280a684e4a64414649bfcea82b541729f8178b580e8b972a89f5b8c4f9b68205e9396d8ae5e81873b61da074080fd44c52d50fb0880ee9c35da", }, { - length: 224, - nonce: [3]uint32{0x5091927, 0x661c75ba, 0xc23dad}, - key: [8]uint32{0x2e00499d, 0xafdc63db, 0xc3c62efb, 0xb4157a19, 0x84ce8b13, 0x85326279, 0x2ee71e9d, 0x318721e4}, + nonce: "27190905ba751c66ad3dc200", + key: "9d49002edb63dcaffb2ec6c3197a15b4138bce84796232859d1ee72ee4218731", input: "f48b5ae62f9968baa9ba0754276cd8e9dcfa8a88e4571856d483ee857b1e7bc98b4732e81f1b4421a3bf05ab9020d56c573474b2a2ac4a2daf0a7e0c3a692a097e746d12507ba6c47bec1d91d4c7cfc8993c6700c65a0e5f11b1ccd07a04eac41f59b15b085c1e2a38b7d3be9eb7d08984782753ae23acdafbd01ae0065ab9c6d2a2d157c1fc9c49c2444f2e5f9b0f0bbfb055cc04e29b2658b85d414b448a5b62d32af9a1e115d3d396387d4bb97ba656a9202f868b32353cc05f15ae46cbe983d47b78ba73d2578a94d149e2c64a48d0c1a04fc68baf34c24b641ea0b7a800", output: "b9af1016275eaff9905356292944168c3fe5fdffd9e4494eb33d539b34546680936c664420769204e91ead32c2bb33a8b4868b563174d1a46108b9dfe6d9ac6cc1e975f9662c8473b14950cbc9bc2c08de19d5d0653bb460bea37b4c20a9ab118a9550bfeb1b4892a3ff774e8efe3656adcdf48239f96e844d242525ee9f9559f6a469e920dcb3eaa283a0f31f5dfac3c4fac7befa586ac31bd17f8406f5c4379ba8c3e03a6992a1915afa526d5ed8cc7d5a2605423ece9f4a44f0c41d6dc35a5d2085916ca8cabd85ac257421eb78d73451f69aaedeb4ec57840231436654ce", }, { - length: 227, - nonce: [3]uint32{0x5d6d997c, 0x9d623987, 0x5742de36}, - key: [8]uint32{0x57b2a5ea, 0xc5bdd68b, 0x99c7b0c6, 0x26aea960, 0xba5c75f1, 0xa904cf6b, 0x685031de, 0xa0f0e99}, + nonce: "7c996d5d8739629d36de4257", + key: "eaa5b2578bd6bdc5c6b0c79960a9ae26f1755cba6bcf04a9de315068990e0f0a", input: "b39101601efa2ecdf41878b0fd920a3005ce709e4ec2970abb76e32c232ea21069f81b246eda75aace7555ce8ae203455d3723e684bd671389300e353eec0d2f499d10654fafda2e7a69bfca7198eb172249167ca8864b5d5f58d28723090ec86e251a1bac0346d52fd81f06e0c05429e0b2b895588290b7d00878a4da3378eb6c7e61487de2b318fedf68fa7ad7c88ee746827c1f60d98c7716f3f9695c5ffd4670f71a0fa78a1fb554ba482c5de83feaed7c65fc71acc9f541342eb8f7622b12bb2cfa222fa2ddd8b3ed210ce442275afa3132c8a0e17dd504ecbc92525c118952be", output: "50eb5b21c179a03b9a822f0075906a3ce4acc32486139f92635c7d834f69071d5a6dc0e15ed06a5cee37147071d59641d140a82ad5815b954e7f28e080c3dbbeaf13943d7b7c66d49d51ba1132eeadd4cb7a7e7d726d08d95f1578d55519f267f753f3e16ff39504a87b2286d8bfba0fe6bc28887b466bf276453a82cdd0abbbbf08db0e1c26c317d50ad9b8dc09cd621bc566d362024e8404739df6468869d2125c58b25d70e392f5e75924c4341be81c263915bb514ad436fb24c2c67450e84f6d1b72d1a02a3310c07a7814d930264fdbbf5ddca7067e18e8a44faa87169b7f2e35", }, { - length: 233, - nonce: [3]uint32{0x75bca707, 0x89f6d1f4, 0x2a6f657a}, - key: [8]uint32{0x949f42cc, 0x2b5d3c48, 0xfe0be473, 0x17ac92aa, 0xbdc9d9dd, 0x74f9df26, 0x26487508, 0x7c7b41a2}, + nonce: "07a7bc75f4d1f6897a656f2a", + key: "cc429f94483c5d2b73e40bfeaa92ac17ddd9c9bd26dff97408754826a2417b7c", input: "0a42f63b975ad0e12a1e32615813dfd6f79e53ce011e2a2f0534dd054689f8df73a8326fecfd517ff7fe530d78081af66c3a8c7c189eb9d9efed1e5577b5512d42ef1fe273f670ce380c64bc62e217a7e410a8ed89998344e29301e4e053a3a3cf7e71587fd056a6bd976f16e157476a06997dfaaff32172dd84190570621f2221420c0a0ea607ea756e9792c8c0e7157c95b89c9490e20b750ee85e4c27c9b8f409e848ec90afcad33342010bb9808358afbcb3d9b094127c38c243a204e76899677079758e7cbada9a5c18363449eebc07bab516a16372722403a046df85c7dd2ffc804c54d38aab", output: "87a47bcaa1c1eb8e55151011c4f39af4b9e108a55a7124cdcf66d0dee727306e6971f783b038bd6b215f530cdbb53e17975742ec304fdb3792a88b674504396978c6a5e4a9c87a7c3ca430d61165c1a3f6162eeaf38c93e18b6ccb6a595ad428cdc98efef8f84463eed757a72ffd827b71c0579fcc1f4baa11812be2bc5a2a95df8e41d04b33343df09ce628c367d1f88488f7a2787f013c8e76f0b9257cee777ec4adc6df8c5790e41ea02da85142b777a0d4e7c7157a48118046935f8888b5352d1750bf00b92843027a349cf5685e8a2a2efde16dcf5e1c1ed8c779bb38cabfb42ec4dd87d58273", }, { - length: 234, - nonce: [3]uint32{0x5003a4f7, 0x40bd8cde, 0xfe35fb25}, - key: [8]uint32{0x576e49d9, 0xe84e9df, 0x9f227a3, 0x437c9de0, 0xc46ac8de, 0x1a6a2d2b, 0x42ab7684, 0x4253fbb6}, + nonce: "f7a40350de8cbd4025fb35fe", + key: "d9496e57dfe9840ea327f209e09d7c43dec86ac42b2d6a1a8476ab42b6fb5342", input: "abeff48fa082dfe78cac33636c421991b0d94c3bc9e5bd6d22763601a55201fa47b09ce60cb959ba107020213c28ae31d54923d1e74ab1d9ddc2762b2d23d8c6961d81068230884a39682fa4b30676ffec19319362c075df0b879a0f083a67b23597bf95c4bb997fae4736479cb8a9c00520ba2f6e5962d54c313c576180d17779ff239ad60f1f1373627770d50a1c49718b2b2e536846299e052f8c1a5d3079e91cb1b8eac4661daac32d73b3b99e2051f8f694a61d1e9d3935f802921a4d979b6ade453cf30d73a4a498a6a2c5395c60fcf271d50b4967ac12b0d7bf818c2679d552e9b3b963f9f789", output: "a0d11e732984ad575570ed51031b8ac2d7b4c536f7e85f6fce9ef5d2b946cefe2ee009227d6747c7d133ba69609f4a1e2253d0eb59d1f930611e0c26a7c0cf2d2ce7ccea6e079eadf2eb1acf0463d90fb4b3269faae3febfc88cb9fb0873d8b74894506199394c8e44a96e6b479bd3e045749cce1c3f57243abdb37e67084eb573cd820c6cee424227019592a027e9da8f7b8997bfb292627a986f83c8fb8d156a91a12a8b52659cf9272924631745ed3a2453a4c2d87a167faa9104e799c715ed597bcb66949ab15dae29a86ba147507e8d8af66e96c09c53caa053ad3b79d9ed3c0c6c00169eaec3a3", }, { - length: 237, - nonce: [3]uint32{0xc6ae48ce, 0x26f0906f, 0xfd8ab8bf}, - key: [8]uint32{0x42b82c50, 0x7f519e0d, 0xcbb95098, 0x6f75e532, 0xe2c9f61b, 0x5a4af942, 0x2679777b, 0x6a8e1c9c}, + nonce: "ce48aec66f90f026bfb88afd", + key: "502cb8420d9e517f9850b9cb32e5756f1bf6c9e242f94a5a7b7779269c1c8e6a", input: "a77b7a5870335b9145fd2e08ec898ba2f158fda16e8a2661a7a416857b6ba6937b4843ecaa79d3635d28383af80290842de9ca0bb621ee22b7fd6bf379922741e812b1739c33dd6923d0607826fc84d46bbdbd1fe9d1255f56a167779a560a6eed1b9c9579b8f771147df467e67a070d9e9ce8ad92dc0543d1c28216c1dec82614ac5e853ed49b6abac7eb3426ef0c749febce2ca4e589d06ccfc8f9f622ede388282d69ceb2fd5122ba024b7a194da9dffc7acb481eabfcd127e9b854be1da727483452a83d1ca14238a496db89958afd7140dd057773ea9a1eee412875b552d464ba0fab31239c752d7dd3d9", output: "b330c33a511d9809436ab0c4b84253eeda63b095d5e8dc74803de5f070444a0256d21d6c1cf82054a231b43648c3547aa37919b32cfd9893e265b55545be6d7cd11d3f238ef66c3c278fcccb7dd0dc59f57750562cb28da05d86ee30265ff6a3991a466ba7e6208c56fc8862e19ac332e5fb3cbcc84e83a6205dee61a71acd363a3c9de96d54070a69860c152d4ceb9c4b4cc3b878547b6116699885654b11f888dc3c23483a4b24fbe27c52545c06dd80ab7223d4578ab89bff5f9cbf5d55b19611a5251031df5da5060a1f198226c638ab5e8ec5db459e9cd8210f64b2521a2329d79228cc484c5065ef8a1d", }, { - length: 244, - nonce: [3]uint32{0xea38678b, 0xc41eada, 0x3381147b}, - key: [8]uint32{0x268fc2ac, 0x21297e86, 0xdf9ef8cf, 0xd4b45234, 0x2a95c4f2, 0xcec36ce3, 0xd5fa38c9, 0x7dc43790}, + nonce: "8b6738eadaea410c7b148133", + key: "acc28f26867e2921cff89edf3452b4d4f2c4952ae36cc3cec938fad59037c47d", input: "322d634bc180458123e10d0509870b54e0f0a3a72a2bd9e9cf44324c7a1ca37dd6adf9db1fcc8dadabd881f91d47d93b58382802b42ee936802fac8612ea4dd9eca5f215935ea9ba6233b9c8bddba3385861de669d95c888c8977851cb305db577a4eb2360f362fa459d61ffc8fcaa1502905b073bd8e9567ac7cff8e5fb1002c55641a3af5fc47ac0131fae372f073e19721ffcce9821e0241d7fa67bfc499c8f100e050d39bd4d7cae4557d208629603ec4a007852762ec1905d0e81b873510fd334dedcd9c288eb8415db505913af06bea94d197ab627d58f6a9944f6c56247595fc54ae3f8604aa37c3466f74561131e11dc", output: "edbfb1090987762f75eba2439d746cdbefe8605b8ebad59e075d28b54edfe48813ccae891f6ed655c5ab5211ba896fff0c8e09bd1554aad987dc53f355d0822e9b0f524a99a79c68a9f3b4e30506cd725b07be135e4540078be88dac64fc545c433837b96a924452f6b844291c4c3fb5f8cc94f06d9f19dad7fc945f093020e82ed19f9eb3ddff68b813629991d1a460e5455e1cb41cf23bb3d96fdb6b96581c3bf9ef72814406329bbbba5b835e7724c728cebe88efcd996dea71d0fd5c53e081c21ce8b3764738d693e390fbf8e0137a716760fc9cd2014cd9bf3fd706bc3464d1f15803606976e96b1077cda0a62921ff7c32", }, { - length: 250, - nonce: [3]uint32{0x883ac584, 0x8fb8e7d5, 0xdf07de66}, - key: [8]uint32{0xc7747e47, 0x853d88c6, 0xbf9aa631, 0x78f16480, 0x7c248080, 0x15ff973b, 0x31528a40, 0x629686e5}, + nonce: "84c53a88d5e7b88f66de07df", + key: "477e74c7c6883d8531a69abf8064f1788080247c3b97ff15408a5231e5869662", input: "e6b8a9012cdfd2041ab2b65b4e4f1442794fdf1c3685e6622ce70f80b9c2252ba6d9e6384d474a7622053d35df946a3b19408b3e1712da00525070279ce381359b542a9ad7c07750e393e0834593777352c1f7dbc84cc1a2b1eba787377d2cb1d08a7d20e1393d44022107acac5d765be37f9075af02e4bbf8e60ceb262aa34e2b870cc7adcf54329a667249cb4958393bff4f4333338cae45cbca419d59e605aa0cecb1241080339198b9b283e4201afc07360b8ae2a57b0b9b97167c315f03fd7a87a00ae73f91ca560a1505f3cdf04576b9aee5ea775f719916f1e1942ad5311c7f87153f8e62855ace3f34afb08d4d7c7f4fd2bf83e42f76", output: "fc2673c80812d101bca7a2e0e105fa449550e695a016596f5c3cde11fb7dc518b94fdb74058e634546a726c37896110e1d1f9cdeccba1c89958041061ded8e8bc2751ec6dad76a305e70c57f9c81a5a65b5116390af4f7bf7053a03ec13f5d60a58cc5ba61f8c46ef6d2d291de490082dcfdf294aeb3a9414d64e4bd6497d4625acfa591627bfd98f0aec7e7def71515c09942db6911d73b96b4bd2d6df03bb729e945d71549d40e4bc401e1f73baf263a74280537692240638619f92645a5ade1eb8151191c7ff8bd715b3c1cd667e69745b806e16d46d9aa680a7367b8fb45a1598631cf3d44c1f5cfcd95bc8dafdb65a2083905a6937fcf21", }, { - length: 256, - nonce: [3]uint32{0x79cd7a62, 0xae619be, 0x7d96d236}, - key: [8]uint32{0x7dec8e64, 0x9f12b14, 0x6c70df2a, 0xeae0aa0d, 0x27b1ac14, 0x7a00d833, 0xe63c0aca, 0x189438e2}, + nonce: "627acd79be19e60a36d2967d", + key: "648eec7d142bf1092adf706c0daae0ea14acb12733d8007aca0a3ce6e2389418", input: "0cfd93b195e37dd15dfae83132c24ed5bfce7fe6fad4064b213b2c31a39e39ddad2f977e904c9c5b055ed03db46fcdd845bbb6ff0ab5a8c92e89295b6801f36ae63eba61fba24a3858aeb36f2da226b23b24d7b2c7d2670f23a9a1b60db85c0ecee584bef1b00e42d10ca17432a74bbb220d88356d82c850da4c09dd5baf413caf8f9479e02a330065fb865489c0f59605d56146ec8434182345de2d15e2a1dceeeee2fe94871d41913f6788738947ed9849ca0ae985e3e19a97bee82b96feeddceb196c9b6012264661945981c279f43db9599a4ef01116f592478619690daa64387290484d21e8d2444751194e1f361fb37f04014a3c7e4b409e5c828d8990", output: "0502848571d1472ff10bec06c1299fad23a2cb824d88bf91b5447c5139500bd837a2fddc629e4a964e84907c1e6740263f1fef4f5ed41062982c150d9e77a1047b7d86c0e191945e8db00ca3845a39560857fc9e0e4a394eea4ba80a689cb5714c4bab7124ffdbfa8bbb91c3eb3caa1621f49dba1eea3ebf1d547ee337f9085638a12317b86c11aa1525813445107038942fc519eebdc1b98d313ad822bf0b94a054259aa8cf1be4b3a68f974269729941747f9a23fa5d83453071b431dac62274c24f6a32248b0785ff90aad5840fadc89af0aef7553d9352cfb00d3999ffbe28cd9fde7854e95710f4532b8bf5011e518c93361e58d22a2302182e00e8bccd", }, { - length: 268, - nonce: [3]uint32{0xb7581e00, 0x9a1bba92, 0x64356674}, - key: [8]uint32{0xdc2c9fcd, 0x5e50de1a, 0x8546466b, 0xc1b49b21, 0x36a670cd, 0x2887f367, 0x2fbf4300, 0xf90a0374}, + nonce: "001e58b792ba1b9a74663564", + key: "cd9f2cdc1ade505e6b464685219bb4c1cd70a63667f387280043bf2f74030af9", input: "0d8d864010ce8df1c0179cf0236dce1c100f9c115eaa5294c24a2e1afa27f9d57ebc18f00482be0218d44262bd4db73002ff53c6388f5e333470aced2a42a73b376686c8d02e05ece27cdd8b1e3f675c715981f8b656d68d0e16227b529cf881d2433e4371fbcd933eaa72346e77e688ac80ee95324512c66a4c16338cf38c941b72c21c3d01e005a07c0eb436014fb1ee61806de7e96842ca3217ab8c7607d609dd2f637f9fda8a85cb0549f262c9e4a955c384319a6ad2b696e2593d7d174f5ddb98e2a8d5d12558c18ab67571e9a0202e91ce26d720cbe41a3a6a4f309296ca4d9d9a59a9043dd2e5a707ed7d5034023d5ea06ab14b39b7852e5c984848d5670c6f2f0b189c2a8a4a4bca", output: "d2a5693c9d503a8821751d085a0837579233e65b691366e4a7464481d22800e786939349f721a815f28b4e47c8889f0814fb95d592d1185e45d6dbcac14ffa4f1d6c79194f2f7eb7323439d9607edf80f01e3a968b483eb93c01d9cb9d3625d21d66927e7aeedc1d9bd589560ed2b61cbed5ad0e0310c8ebe140c64c67d4909c010902d5386efa359ab60a9573493d3e5d8761cfd4023eba23de48372032d4673b5f6ad66cd0dfab02a73aa81f269ae88fcabb3ae9cb09f6bf60fd3575a3046bc6843f444e1e9fb9ff9b991620344fb99da68df09496b40f8b9dfc34e830a87f65710940603ebab554d36e8b4c9228bc9c26c07b828f34cdfdd40b161717236ba325e8c20bd018b324345e09", }, { - length: 305, - nonce: [3]uint32{0x2c641fcb, 0x5170c7e2, 0x62a23688}, - key: [8]uint32{0x5aed5915, 0xc5c4cc18, 0xf0e51574, 0x75d894c6, 0x1b7082d1, 0x5d2ea1db, 0x709fd24, 0xf5f69898}, + nonce: "cb1f642ce2c770518836a262", + key: "1559ed5a18ccc4c57415e5f0c694d875d182701bdba12e5d24fd09079898f6f5", input: "07c50a69e168e388caf6f91471cf436886a3de58ef2c44795d94fba6538add8d414d84f3ef0ac9377fd5bed6aa6805a695f3a711025550bb6f014893c664e09bd05f4d3b850771991fc02f41c7353cd062156243b67fce9c1f0c21eb73087a5de0db0578923eb49bf87a583351e8441c7b121645bcb64ef5960fdca85af863dca7ebb56662e9707d541513bc91bf9b301431423b552e2c148e66ecfd48045ecb3a940dd65694d7fc8bf511e691b9cfd7547fe7bca6465b72ff9f1748723c4eb14f8bc1efb2fbc6726115c597a3881e0d5019335daf2e5ea8796c2a8b893ca798c4ef2639465505c4bd492bf7e934bb35be9b66c9f35730736c65fa4c1a2485378b9d71912cb924634a8e0db2802b75728818dc00fc28effdf1d8a05e4de4608bb6a78bb19c377d5ec77dca1b5ad38fded7", output: "3dff5fde2ca24bf419e13cb7d12368e70449d41f2aa22e4b567f5cbdbcf3257975e44097deb180f2621ec36acf375dad3b7a19234b9856dc6c7842a7f86be00304b41a8c1662a02e8390346cbd0ff6be7bc1ceb821dbd805ab5c93c9c6ea5093249b5dc52081cbbbe1b326e831ef3c6c42fb791790086d1586f7daf031e70a71b54e9134f942e9ce229fc77980eb80c985ee0c5965eaba375d156f9b423b0615f4ca6fd77de28e28f35aba327e4f1b75725730155b7b4d6c5c264bf3d9dc9a16e7ededcc261add8c666278bac5cf0b3275d6d6678060eae30bbf2ce5f63e6a53a450b65aa0adbd1c90cf045f5ddd9700c2a99c80586c5244cf4c08035b6ff630c82cec3a4fcc83860e987898b42fe746939f8b37c814f8dab65de276e9784fb90f0751d3ba0826889e1e7e4fdbf8a90942", }, { - length: 430, - nonce: [3]uint32{0x99b172cc, 0x91056d0, 0x48057533}, - key: [8]uint32{0xe6cf398e, 0xc3c56066, 0xc5ff194c, 0xf6d2d8c4, 0x6d1d8908, 0x63e62065, 0xcca485cb, 0x1eb03dd6}, + nonce: "cc72b199d056100933750548", + key: "8e39cfe66660c5c34c19ffc5c4d8d2f608891d6d6520e663cb85a4ccd63db01e", input: "3ddcd3c00014747903c95e49f64258615455a0b26c5070a9532382a9bbd18eeb19c9fe1a902f5c6baf544c5938fc256d310a9332223dc3c54a6eb79a4b4091c3b01c798d2800418863f2865c1cd8add760e445588576d4a6c945e1d6d50dc913674daa4737ac94d84eb0ff57cda95df915989c75adc97c4e3c1c837c798a432ba4803a246bb274b032db77e5c1bb554a5342ef2e5d3ff7f102adb5d4e282ad800ccae83f68c4bfd3b6046786a8cfaa2b63c62d64c938189b1039ae1a81ce5c91530772cca0f4a3470ba68e4e0548a221eb4addf91554e603155a4592dc5c338aa0f75a8cc2822b318fbfba4a8f73fa08512132705dae792eed6b809c251d35cca60c476406d964187b63cd59333771e37367671d0ccb393f5b8bde77bebc133485ec5c66bdd631d98cdbee78a3cf435d2f824fa2f9e91e89af28b2e155df4fb04bbe4ce0b6162dcd8e81ee8d5922ebf9c957b26c343a0396d91f6287a4af9e11b7fbb5a5a5c1fcdb186365a20617d4ff5037b0bfa97b6213a6ebcf0b78b81c65737378787b255cba03d715fed4addc2c70c1fb4d3ab16f2bff287186c26a164dae2fe9dbe3c4a2e1617f01cae79f", output: "ecea5fc18dc4aed23359cacb8f79a457512e0a27d9816f353e315519d2b2faf74d14ae8ae5e227b203823998a47a050c363a807f45f610942fed4518b8091b88dff8b2af8fb6552eb654c85d2b6a918bcf56fb898392941d983b1afd867ef840e12313059ed3e4d217498dd511563a939c3c536fbbf8e019deed29262f0a655fc680b15939475e0cee0ce2e8bab5834f7354b93e2e0958a5bc608fab369b6aee3c9d73a6898e402484eac7300150517bbd137bf55762897696a3dc4be74b0c141755ac8f2f6e59f707b1690c451a774c46bbe195d826a6784f8d807b78f8ebc343ecacf37cb9b1b2fdbff6a1237b5098853d783e77515c419894c2628f8b5117042294ee2ed58a33746f9e79b13fdfaa25a75fc95340a89076e786e0ecad7de437a9a3fb3092146d255005b22895310b1252a3e34572cf74665b97f4adc30dd0f34e3216c7757953a4b618a775bbe68f9e0922d75afc80a1379aaf1745f2263afb6f0b37553d9c984f1ef781ea75b1980c559c77565c83f3e0bd7a3cd7cdb594658beb7e5eb940633dbc6ae2f50383beea676cb6c814b17b1d73dd133f544da88ab371415889ead21803c1ffe3f2", }, { - length: 449, - nonce: [3]uint32{0x2adb4a6d, 0x33d00c1c, 0x10a0193c}, - key: [8]uint32{0x8bd707df, 0x70212019, 0xdb685581, 0x9cdbd1a3, 0x7db9ff1a, 0x1af119ee, 0xb1d8c0ff, 0x3c4a22cb}, + nonce: "6d4adb2a1c0cd0333c19a010", + key: "df07d78b19202170815568dba3d1db9c1affb97dee19f11affc0d8b1cb224a3c", input: "93ce72a518ae892e00c271a08ead720cc4a32b676016612b5bf2b45d9ae9a27da52e664dbbdf709d9a69ba0506e2c988bb5a587400bca8ae4773bf1f315a8f383826741bfd36afeae5219796f5ce34b229cac71c066988dbcae2cbcfcdbb49efcf335380519669aaf3058e9df7f364bfd66c84703d3faaf8747442bdd35ac98acdc719011d27beba39f62eab8656060df02fab7039223f2a96caac8649bc34da45f6f224f928d69c18b281a9b3065f376858c9fd10f26658ae21f5166a50fe9a0d20739402eec84f5240ee05e61268f34408089e264e7006a59bb63eeaa629ba72603e65718d48e94e244e7b39d21d85848d5f6f417631f3876f51b76b6c264356d7d7b1b27bbac78316c5167b689eff236078cf9e2e4626a4ae8bedeecbcaf6883e2e6e9304969b4fc7a4280dcdc5196267e9bb980e225fcbf7a9b2f7098f7f5c9edd06f50c8791edaf387ff3e85ff7bee1f61e4660fddd4eaf5ab0320508e3ccaa9823ae5a71faa86bd76e16d862d83ed57bf6a13de046a3095a74a10c4da952b3c9b8fbde36048537f76eef631a83d55d3a13096e48f02b96a5a8da74c287a9164ce03ddf2f868e9ca3119ec41f0233792e64086c903eb9247dbae80e923eae", output: "bcf49d62dcd1cff9dc37d7096df0c39031e64ccaeea3830fa485edb71b7fcf2ec709a4b327ef9c7d4ea2b35f113a8485d4c236e06b3baccee30e79c6c08739fe5fbed59db30479b56dfbe584a5d79b169b200430ed27072137e940a34170606b31f22095f2151b4d9b901f6337f991a23e4c8997a1ebf5105361fdade1c889b8dc9565e3b33e0bd608c39d725becbb60da8a797186fe0986736112da3d09906442364d6e253e5b27fd5ad72e877c120ea7a11d42b19948f0df5ddabf9cf661c5ce14b81adc2a95b6b0009ece48922b6a2b6efffdf961be8f8ec1b51ad7cfc5c1bca371f42cdac2389cbddcdc5373b6507cdf3ffc7bfb7e81487a778fcf380b934f7326b131cb568bbaa14c8f427920aa78cc0b323d6ea65260022113e2febfb93dcfce791ab6a18489e9b38de281169f1cd3b35eee0a57ed30533d7411a7e50641a78d2e80db1f872398e4ae49938b8d5aa930c0c0da2182bd176e3df56ab90af3e46cdb862cfc12070bc3bd62d6b0387e4eee66d90c50972427b34acaf2baff9d8a76002a20f43c22ac93686defc68b98b7b707d78d0e7265aabadde32507a67f425cbd16c22a426d56b9892bac3a73dd2d2c03efdb22ecc6483f8d1ca67fc7d5", }, { - length: 487, - nonce: [3]uint32{0xecf15215, 0x45e31add, 0x56499d31}, - key: [8]uint32{0xf5988496, 0x49bcc2df, 0x7b4ba3c3, 0x5d5138be, 0xd6cb466b, 0xe98c82f8, 0x147d3f27, 0xc82389f0}, + nonce: "1552f1ecdd1ae345319d4956", + key: "968498f5dfc2bc49c3a34b7bbe38515d6b46cbd6f8828ce9273f7d14f08923c8", input: "f72bec13b0f0b6f2317118f14c2a0d8e963b1bd49ae7584e710dbde75bb1e30c79281847cb822a5f3ae4fa56825e511212f17f0d293cfe80f872e6992d304e9283d08ce65ceeacb003b36a862c91282a22536e0b9c19953512a1bf9e20d3e7a8f1a2dff45dec0b9b04c592e88a7814540cf636a024d10008463d0b3aafbc4c9359889149433ef173124866aa6f53526ef3b3f2c630860ecdd08ffd9fc050e95da512cc87f812f9391085cdec5cc87258b8560806a52336d612da7ab05e0f60566b950904aa27c975a48c7d78455728c87f9b53aa4978374ab9592e12c22d9a760e26eb527133534ac5bbf969596b71cde8b4ef3587fa7ffa7116834348c275ad4dce68ab3397521ddc8e54380129cc81b981f9b32db20dddb0ecaa0f1ff7b06495a42b4a800a207b8e9ca38794e2fa9f40546e0e3aef7b5236d7fdadd72b1158714a5ad8d6264df1e75120088e449b9e911eddac59f1f19a795205ab7532783a93159876133b3fe3a518475a545fbe8dd2ac143f33c35d98e3ee13b63606b1e671917ac3ff9412773a3ac47b8c6627b8ba9dde6820f4f16c2ed9cb7d7086cfbb0cf2d7533eff253d14f634ab2aad3fb4289b9a0bb667a6fdd0acd5949185d53f1dd2b96ff060bb44f872a67259100669e6eaf1a7e2b11dd5fc35792db0c44a1127765934a068bf", output: "bb618ae6b7739a4dedde1dbacf864b0892b93dea3007237d2f6f23be0718bdd29321e6b0fcb6a44dacf0f5c53d91e16165997e2302ae7ebc2dbd02c0fd8e8606a4ad13e409a4e807f331cf4174171c5fff23ca232192906b4eefdf2ffb4c65af78be01b0ba7d15b4341dd5a2edd49b17db2812358c8af0a4a9724e0169f50d1d331936bc2400012a60849876c3ead52cc9fe60173c9992f83f3e41ebd24fe3961835109612994c7620280539d483f91ef9a64c16032a35612a119589efe6357fa35b19531274576e304be75bc7e91d58015792095bb00ce4de251a52b946554366ea7ed9ce9317020ec155ae0071e022af36ad10eda5d671e5090c136e381cecdb8bc179474fabc7dab2d8a134772976cf0791b6cebe2333d34b4b8e2b6b2eab2b5dc7c6a08a583d091df64328cbcde36bc1b81095d82c741a1503c55d833d551a855e098166c5efffb8e4146e32e54abcaa85076ca6660abdfca9e82824217b5d3f23f7ff3455872bc76751480c1a8e3e725365c82fc135cd3713cc0f1ea733754142f8c37716a2a4fa8a6b898215c287565325774c2510df6b49e78cb986853ac5ca532c9a7e2bceb7c0157f60433f29fe29009343d6035d7b5892c77f821b644590615dc505604501dd218dcab789e6f0525387919cf25c7c6d62a8979e39d346decbed2657", }, { - length: 511, - nonce: [3]uint32{0xba68c47, 0xbc020097, 0xbf7d14a7}, - key: [8]uint32{0x3bbeedde, 0x6e8f4d6c, 0x6e27cd72, 0x140ff360, 0xc891efa0, 0x4aaa227f, 0x733cfef2, 0x2b51f1f3}, + nonce: "478ca60b970002bca7147dbf", + key: "deedbe3b6c4d8f6e72cd276e60f30f14a0ef91c87f22aa4af2fe3c73f3f1512b", input: "96eb94e1adbcc0646440c8824a2fc0f2c4b17d9cbddbb8ba8d9dbd6482fbf7201c74eb923153e0138b2f6f182f9c3d5656ee40bb7c26a01740b5c7d125261d4e4197614800aa152b402ba581bfbf4288e73c9ef7e7e37491212b921420eaaff880eeb458e3d0aa108b01b53492c97e328e9d10e3220b924351d583c00e76aee9325d6b89b1f162ffa30b386b37b5eaf4dfc25d22987dde4496158818c4d8f19ea300fe140be921d3f1abdaf9ab8946833a57cda5f41f995ff80e98b0f10f7afd736dd33438dfd395547f11563056078ff8f7c202aac262955f0ca5dae2365472de40f069028104ac552ea5a45ff2773335e5d3242f1e62e0e98003333dc51a3c8abbaf368f284536672e55d005b24b7aeba8e4cef23289adc12db2213aa037c797e7e753ae985568199cfe14cf1704fbca443e6036bdd05859e3583897cbefe7a0cf268b75d554b2da6e503ee04b126fbf74eaac0ebca37e84ab9c726973af780fe2bc9869fe67b7d9e4a04062ee535b2c1740d1347224e211b5cd37ee14c3325f40abee930eb6a1634986e756b3a1f86a3d7ee7184d95ea948506d8ab8b23f92ecf3eb0586f7a8b1bc227e08a0e32ca75ca4eeffc5c0a2a623547788bca66f3dc2c48671e462544d52a87d34307a7f111aeacb7da50262deab33d9f29dd6b47c3bb555be598d619cc66be8c4b74b01772725268a43d467f39bc565e5efcd0", output: "590965d18ebdf1a89689662cfae1b8c8a73db8b26941313006b9b9bd6afa6a57149d09a27390b8883069e4fc2dfcf75035def1f8b865e24c21b1a1ed3e9f220d7b48046577b661bc92d9888a912984ad415ea2fc92c9e37da0bef5c7dab11495c612c27b5babe6eee28fd26482272fce69ca7f11bac95251735ad808365ac587830ec04105304f8e440a4da47d30e788718da4282941c9c76f18de4f954b8be750b54cb1145489edf273625a0df9a694a23fe7bfea12579b53c3b2a3de85705568cd7e603f3b8beba9a14cad9979ea283a8a291d3e1105b7f890e2a569804d9b7dd4c7e50bd0dcd11223fd7247af77f04212ece1b98c238d2fa0386a994bc502f83dcdd2e5a0d45b185155e1a395d91726d383c2c198fff1590e983c65ee041638510787c8c59c2e96f31678226a033e027bb40c416b73c3dbef31affc93a659c8ec7ffeca313fd5283a80533b2d63941c8f245d22b160c5fe57c5fa4b759c407b9acd6d9c4f80f244360b9acd11e2b43d4af757e16a6ef9d6756df39ca3a8a235e74351f50b2ebf54df633c8c400fd80b41b07117676d486377095660f2f20f62c034563b4560b473a8f4d6a740306d2a822fd8bd98012a840ba9b1709df9a0d61ecc305f7180fd764e334045d9a8ca23cb8036c05616a8b21fc488429ba4168c59dfa231f0ffa668a3be7b16583df1a55bb9c15d51660ddeca730d66f7a9", }, { - length: 607, - nonce: [3]uint32{0x9419df54, 0x4593f2a, 0x71c06dd6}, - key: [8]uint32{0x7b517740, 0x41e86353, 0xed629408, 0x5fe32cea, 0xb06bc5df, 0xaec9b350, 0xc00c2a6f, 0xb3aaf44f}, + nonce: "54df19942a3f5904d66dc071", + key: "4077517b5363e841089462edea2ce35fdfc56bb050b3c9ae6f2a0cc04ff4aab3", input: "be3f309c6e7b89e1ec4a855cf161156d09f8a04d5630534ee19e9e071e3f4603f23f0c59a7b7f8a32c4c203ec8c129a268faba09abde7b61135c6c37fd091e2d695f0e242488098ebed30c7d321f4dcef0bdd23fa85a53569868cf2008bf4d2ee7a12a6673298c7e797321b9f4559748223b590e6fcf17aa72251586b01181cefcd32c6a1a20a0fc27143426f6572b1aab0e7301e390cb857f912d78d5153906c698ee140b36cdc72693cc019cb7add747ca3a07b2b82a2332bfa76c962b186ad94209fcf590ed0f6a73b08a771a58eb9649f2f1da4f7c385da83d50c939231f745514d14b0920deedd9c4dc6d2e547f83643d13541870875e52c610372b14b602e7a47f0b3721cfca60ec68e2eee91f40ceba2d0fdb4ebe19cb1d1ab170726c9e600030454ef355f9a40033672be520e528937f38e7a862a5ae50cd94f667cd015a72ee3f91b1a09031bf4c207e0c516b2e7a4baedf373f1ee71843e560741ed3a3094d2b513e2248caf27ce135716f6887d9f1fe5b11e02c12c989d29054ab183a3f55d9b40d78e12ff56edf936ab966c7c3130bea472b71fd69e70165a76afbf720e2c1587a77943b35acfd81b2ab6f39476623edf3663024fb84da8057ed3a361e9533caf9fc58a5e4897e4bf84f58ed063b5c353bdca3792952eec0a1404149ebeb5b17cd6350ab3e27e44e40fbcb00780d001a48d0365d534ff830553409919608881e665f83bb5cf0736d728c41cc4e985c377f89ee1186303d0d76bc634875ab3ebd87059969f24b0464ae11967bcc47f300a34e3b917b1affceea716c5ad9abf1aa3a1106e2f4d006514dc62cfd2a52426968f2f3991c9f9d8fcd", output: "e4032c01bcece73fde73961ed216820dcb44ce20134678c98afb674bb03afec2f4aacbade7f87a32fff57ae9213eaf0509e9d9db1313b06fd1df53561f85896ba627cccd2d0e2ae4f24f5579bf02f6599f5e63412ba084cf53a5bc9a8061b5c029b755329fcd73f629fadd3bcf6cb4c572fea86466cb5159d19eaaf0f44c3471d0323bc7206bb514ed8117a61c6d98d44faff6a83716657531d965ba3efbcf067c452e0d2807db3423958d9a4421886fe132d7c47e82086db9507616b67f0051dffc1a49ecce3ca8e4d5f5af15684cd8837a471430ddd333ea0b6ee603b7d9e702692f857fab060ccf26f2a8e61dfd3b12923acca78b83a6004e4ff09113becf6bdd0bec3a449a195559dfeafd4e2a79ead5ae3c993a15ad9b1a2ce818e18edb010b7fece9aa437d85ba9841d89026d6aac1a3a6ab6dad932a26d7db6f3664b06d51584cf4d22a75c06e2840db7292798306e4d39379af85a6bc8dcaebb5246e07fadd5e336f122de0ecb99ca24a971701a1f43bd69933beef6e52d299b132e7510caf27b99739e32bd272afc36755ea80cc7ed3957d91325584b338d15b19fe554ee70bee903babe21d0cbecd49235c70a3a4f516ce16761d1cfcd70bb4b9c7c73c359f3fdd0753d6c1ac1a1463142f18266b6a9c84675f247d56563646fb2c8c3b6b81944c2ba2b76b685ba5ea40cf539bcf3850a8af3e0a69c0b38164de520a3bea82b91f67d36bbd87877b5be7f06c2d26b2dc747a26a51f51fe293197db0e91e6ac617c71ddc6edfeb7db8f067ac2012268deb7e5f00a640c1bbec5c4c71f10f921071308cadededad5c90e72d744d0bf790b043fd35729570889ebe5", }, { - length: 682, - nonce: [3]uint32{0x17cebe90, 0xeffe259b, 0xbdf9d4ca}, - key: [8]uint32{0x172d51e8, 0x5b80f5c6, 0xb9c9e438, 0xa56119c0, 0x62212323, 0xf5386589, 0xde7079a3, 0x669e643}, + nonce: "90bece179b25feefcad4f9bd", + key: "e8512d17c6f5805b38e4c9b9c01961a523232162896538f5a37970de43e66906", input: "0aa4fbce7e1774f0607e7ea01fc0e6d210bb283964ae75e180a9f6ff3d2c4d50914bfc32bca6d243eb33551521d54d66f377fdc1d31974ece79b157905ff7e7a9b064f349727ce37c83c15ae13df635c3e6b4baf994d9aa0bb90b06c6cda51deefda72c97a2993448e654b746b216d2b949bff1af5238558205cfc3162f1d7a020a919db4d4eb44bcf7b269d4df57e24133d1e540694b9148444cee16e64035ef006a6079dff449949c1b342991f2a27f21c8bd74ccf4bc944284a46e9fd9f9bfd4b95f80c05553950fabbf5e5aed6babb8427832266aa4d175114de9127ff6ee848534d6dd5aa6d2dc361319863cdf32cfb1b074faed17d368964393352df01fe8d86af0e994bc9dac315f7d9efa7bef47a16676cdf17a535ae71d399c4c11a3a3ba0491e8d41f419685258a4ec7d1ae588b3ca341719c0827ce5f5a653959a8671844f2d0293c09bc7d35497ed18c160fc7b6d073a311b621a7a37f7ded1df3d73dcba1821278c9e17a191997fa4dab0802e1ee1b468e91e4272c4569a17dc0b2805b980bde798640aa328a3605abea1865083d7446e960c27f69d32882a2a2295efc9c440dc203872373411925f8839715e9441d31dd9cc14bab09a3e03b4a63e14db3039d58725796326ea6327f189beecd63955f1409467c81f4691ecfe9f0ac5234f23dfb84e3199e415ee7b4f67189e8857ff6cb3f64c2ac1b554bfbd679a6ea8491cfd69d96d08ee2744d9103e0b044212560ff707974b1a9043e1f2c3592828fde8ab5e993652c00e2b3fdb19082611b67866ece6c4a2635f87e04d2136d679f632416b03ece4d7e9406f3437163f4fe0c8cc7b87d487f6de3b3022665bcafa847c2b9199e1ba9af7deb0e29b66ad41688d03a8369416dfbee6d03526adb3ebc4b4f8531d73589499a3010b5309e9d9d2f5a9cf347983a92722dbf6c4f0bae8aba57b37d322", output: "a31f9a532f35f20ba604a9ab9989260e5a4ed04e6ecfa1cb9e0e1d16943906acbbb4e761a2bebc86cad0ce8b3f26d98b455e4b0835eb8b43791cea29fe8fa6e5187b60198142059bbce98917aa2957ae2555bee70e6e9e21ff6197a51ac2ca2952c413efec4d9903a2f6883e88aebe7ca8316831f6a8f2cd0e486319b58dc8db862779adff98b7f35c33faa53d56acd7a81e0feffc286b728f3a11afab7cace4c30b1a45780276b1f0ab89242410d07cb1191c7b9da5d09db7c9a729d91ac3ed82f4350f2871a12d125ba672861d1b0af7219c360a0e023a8b7c23fb9d72631c72e032c097118d90e5db0576586d8224165a8376fe8d04de93516848e7c2653cb4f7d24a971ccf4f16c527ea5b4153fad5fd5bf473b15806671854507bf1a6d9e5fe4a6f6ec977197d21d69a041dd955e199031f895adefd850c8b0ae327ba0c18ca1783560e1ff0feb2f659137e34a91e9e9ff04fe3375b7db6e4326986e6265e5fef00297f6ae627c7563846e531762748fe8d0b6baff17acf1e6c5cfefa35a95ef634ff96f83f16342a6c62311fc653d314f8a6de109356ab7801316e69a48834cb6325816b1f66d5c67d6e9c9cbc8e1a0521fd6e4bf77a7d2609f99c9579e143f530677b99d198a97620d087f058edf35eb7271701ecebb8bfde5671641ed21aeee9e7db06b932e0def91be93cf2955159e9666c770cdffa03886eb6e98dfca8f91ff5cef1927c0f82b9226d65c68d011416cbef802c264e34244ead7a6ebbe28a510a37e1276f4f3cf27a3944a08aaa23bd321092761627dae20dc269b6150545c75e995cfee0a9bcedb1ad8b364beb8839fd5c9f7984fa0a08a1a354aebe18f62acf6d6664978fcfda2ce6fc16eaa2cda5b835339001b3b98d3a407a3e18e0ec2da6ee3d1448c1ece2ed67c3f51f01e76ed59f0e61102b103a3c65aea94275e8d1f0d331538efe", }, { - length: 768, - nonce: [3]uint32{0xb1c9bd09, 0xdbe6497d, 0x16c73b95}, - key: [8]uint32{0xbf9d9e5, 0x2eede668, 0x631dca95, 0x4233e36d, 0xd83fe644, 0x99b11f89, 0xef055717, 0x1ae9695f}, + nonce: "09bdc9b17d49e6db953bc716", + key: "e5d9f90b68e6ed2e95ca1d636de3334244e63fd8891fb199175705ef5f69e91a", input: "e097b1e8dea40f63714e63ab3ad9bdd518ac3e188926d1086a9850a5580affb592f6e421abc617c103479ba39a3924eea1c0bbbb051614c4b5003bbd5fcbb8093864fc1c130748194d6b560e203b889b98b574a98ec3e0e07cb2d9f271ba7794e5419123b4f2ebc7e0d65cd404104868905ff2c38d30c967fe9d77ebdd4b8fa836c3b0ad15e3e70e9a28236d5593e761e694b047f63bc62c7b0d493c3e2528c8af78f56725172ac9416ec2bdc54de92b92a63f9ccb61e686f9249c7cc337d99b2160400bb5535eb8f8eb1e3cafcbceaa821c1088edbacb3b01b5bed977e702de747ad00268ffe72e3d877dd75816db65b5459607cd1b963fe43bf2405ec223ddc0de514d59cde74f7522dc72285caa3eeb7eae527a7723b33d21ce91c91c8d26bf36eeb1dcdfc1e9e475c1565ed9c7e64ef601874a4f277280a5ceec26717e9385aee8b159379e3feed7952b87240c942970d63351259aa7a286ddb4a2620fa67565c92f592902e49422f1eecea2f44d1c0bbbf54a9e5612b86a9549aa3e6639a924c7bbe2d3c1b5669da73c0e2c6f6f6084f54a912ad2635d0141c2f5ac925414dce0da09ab8f86eae2a7b7e48741253189e5fd554d5c04d9807ac6ffd8a4f8229a3e8ab75ca5c778bd7ec5a5c02085faba9792cbc47f9e9311f3444e6544359769e1b3eb4d42ac8923ec94536e1a44497766b5da523f5763749dbc2738dfa8e13c191dfeac56c7614a96bd3ae23e4e6e5ac00be851ac9831108989b491eaade62113c531385ef3e964ce817c8ed0857adca946467682c2f4387fab2f31ce71b58370853171720268459588d5d216faca58d0bebbd7cd83a78445d9b49e83ec2cdb59b5d760880bf60532178d60372752b47d52562b316c7de5c74af9cd588643002d66bc6260595a540d2f82cf2c07fa64e0cdd1f79877b6a25b0608c735a7d35ca10852da441fcfb31061fd7e482a0989866f9eea8b0b39c3d519715c1c2766c3ad99f041143cdb36557ed647403458155dccbb80c3a365f0a85b1135695648ab67ac76b3d219c7b77e49d735c72ac947b1d7eeb279beb9d2602aba7b36ca", output: "7b6e07e6415660affba56047b988f4548b308e7a642c76791f5c3742cc4cb744cde48fc30e50d458084e06c6dd29a52cb4c306a69a493a17c0838d14b107d07b81c983a2dbad09b80f087ba48465a8beaae5b16e8093e17cfb9e84ea3bdb9af00889268a5c01ddf25af434de56f65882322432aa275fac8519e317ef4d89478f29182143f97350983050f5d37c4b518611da6fa2aed7bb73e614231a194fe17c9073e377fc6ea0aa491e15ca54808e0536c8c3f1bf657283f807ebfc89b55049ac8fb86f89f17974fcf0afc1a2c690c0442842d0f4af9ee29dd960e499d1077bfdad4c0c9189a6e83799bb585acdb853c1e99da7ce9c7eeb9bf431f8d364d0ea80b0a95a7807f196c6ee69fe90e6d1f5d23e5cb256e37e65826d7a111f2272884d6319f968580b3164b2697ea6556816cea3ca316651fe2fd68dfa905d080c28622606f7d24da216289fa2c54c6f42dc244ecb047512ace62f0801f2dfad8f0218f45e2b3bbac97c2176c842398b16dfa1fdfc9a68b7b5a1e785d2a0cc592bc491f5a69c81127b758ee02c66b81674d3135c5882d1dc89dadcffa06f4b0644df5c7fd65c72611d79be7ad637edd6fc38b39946aa2a2c6d08ca9d3ff9a8ffe2e7989546489539b1a623fa937c468e59e0978602526b4367de277526895aa222fbaeae2084f418c5745d8ee844da0baa47f592970c14cf710f49539c12104a62baddb3382f5773dd18c83ecb238ae2e749a51584a38e394ebadd175bf5c3cec787907abb1d94af70ae63d3b7d8d5ff254da90b78ec8fe2ea95dfbc6e3e69ecad856c9e54906df8fe39859f2014b74dc3ca0ee2a957001939d37a6c0b489bd3f1658b835a57b24aa282c23e875c9e67e6eb8b32fe44e7d7d8e285d85da0ce1b53990f9fdb5e2e74728e433ed2c1044df9e89cb9bb316c39fc6fc8bcc74a382093926a288170e857d6b7f47858a4c2d05c74263dc9e8199332d0179687f4a4cdfc80ee6737300cefba75905b22d21e897f887b67aa3051877fff11d98bf96ca5091bb225bddd5eae697f3dfb0efcdb788ebf6694b5b39dbb0d4bf9427382a3a58f0b", }, { - length: 828, - nonce: [3]uint32{0xc7e503e, 0xf8110ddf, 0x83316c8c}, - key: [8]uint32{0xfa2d1cd, 0x4fe7f905, 0x2b9e4c1b, 0x115bc881, 0x2922bcc5, 0x3f60aa25, 0x13c26d31, 0x2096af63}, + nonce: "3e507e0cdf0d11f88c6c3183", + key: "cdd1a20f05f9e74f1b4c9e2b81c85b11c5bc222925aa603f316dc21363af9620", input: "0a1064714f20d9e47fe53250ecfec759f4137e60afaf65755f4709a483504c3855833b6dcaf7aa0180fd735fa9a73d46697f6c45004adf12452ea4c04a720fd7c20b9783b74b8b3ea0c8b1563d5a85f44af8afd7d91ca6298ca22642a684f66e365edd6f6bdb2dd32dfa13c62dc497fb341b86f65d40655931171416e23e3b2623c0b4a67d448877b6e3d4e0fe284034a10162b2b5e21639047036874f4bcde22b145b5f18aa8ff32dec81e6a5ac68b3c30c24bd8fd3b8e098a1cf202e2ab2a3bb66a9393222b9f7384653cda7707f00bc3c81e9591fd040a07d3629410c2db78781a4c9db3df5f9d648162f1b087974f56a89db07aa21ba827e3864a1618945b2fba06853a13c35da2909f5013feb313bae09870b8eab904024adab0d6ac46c1a1499791b47413139dee59db676949b9e9ab8d3d6abaa954ec2a9fc83953c91b483c3b6bd6700b96484850734e72e3710a1b379c0d0698aeaf68f13a0d317bfd689471e3299288e7a383a58522f0daaff210cc4917fa05f0b8ceefc2afc46148a05a100d30787accfb4da094e61ea6b58f132692aedcabae928e53c2594b01507b8fc2d0a85a1d111d1f4de0b95258281ae01873a72606753b6f878ecd8c4f613fb3477710d260f0bca0d4c06f675ab7113eded395f88755a98a0ad22b4a002cfe9447c4e39eda13738f4eccb9c13367ebc2878257c4647d31b67e5e32b6a77f23e9593658d19c0a40e8a7228767afba1cf23072b013b2d76ee66e42b57bec2797ce3619c695a661004c8129cb5c5d6a2836be22483f3b7e40bf8ac5535bf6cd065c4821a87829948c88163cfe3c0f60cea4e7ff59df4cdbf80064b2d664b39487413039999b5e86f1d467b12682d0cd355e9f7cd980e87d584ddbda89f68632d3b8fd6bc3b80205d7feb97a46842b093f74aa14bb21accda7474247b5e39ac76ef75e9b5b52b6a829a7e2297ab88fb0eb690d54ab1af2d7437149a6202035ce15f1e6c6267458d62677c263d83d3f8119af191b7d766582620e0f08b411c996c25ba6a32c2d73f592e789ed662e94103329bfa5e6573f1116ec04438997f3e4ad91b4123b570743455020d914bde2d8417fb24671e6db261732fb89dda1a36614b095529e4f97374c9bc0e55aa577bfffa663c816ca9fae3472e0a", output: "b00a7caf5359c5bcebe590e6bab9aa03370050c55cbd45a257f4869937e922a15f2d38121b1493d6b5dd4a8a47d7b4e5cb049d396ad84ed421df774b0408b6939f18ebf5cf83f48c540affcc2a885967bf4bd222c42904b8a73c4185bde3f97e874fad25b46714235e60c9ff53ed2975c9c85ebad0752249e4b627ffa41555eb9074f63a5f7d61d207d2ce11b2a9fa23a13a0832eccb91efa2afd8d9acfee94ac78a733fa156bfea5006da1d0127c32aadbb75c015b68c627903e1c85bf3a1a9f99c6cfbdbb5c871f7f9661b78cf5e16d819f53e9930e201d4f58e69bcdce77ec5b9b1d2cf206a71f744342273c26b9abc71303c20df3d51f52222893d803fc8e0e0afcd99ee1c7f95b48680403566f7f9e296d7ccc0ec348b6ad515af58d11fd82c628ea29ee6a5d67aaeabd8823addc01a078b04313af73105d4ce4abef8e6ee8ce649640a19678292d4f1017d121549fd2c19ba6cdc0b613e512bc9551d759c6d38aea7e35c0847a142e273a16bb1495e652f9668b97801ba3f6d9931c0a1efaa4452e15732dca1ca9cb45ed289e0fd08d1cee1cdcc9dfba8d0b2562b0b1a180f4ee69d63573222c8d4789bf0d63d2a201a70c7b27c84e620e33e8a863cf49b784269a51ead3d4ad26f044d5859988d5485a11533ea805f5a8f6313caa6b421071a34f57170fdd8e4663e9a4cdcdcc1ddaa9f6e651fb365cf827667b018ae7d028c7f96295b2b4f9eeb4b361b48af86463a79f50b107ab0935e3cec3f4f203cea801ff95fb870d2c2f0e315dc8a6a547dd3c390a1f5403917315164bd2d40362489b389a54e8dc0ddb83e6a43a26c65923e6f76ee0ee0e3a33b0a9066620a01f0319e20b9f1beb3910ad962a3000e6aacb0ae57f3f6c5e0315be5de93edcf0e45e0e47332f9daf7f33e6e8bf1929910b78b8f88ca12bf5519a3217b7554c8c8350cc314561d580bf67a3878e3979430d070121a5e070a3458742e8549bda972f603222e2b30eb8a49a955805307e6e02f8c60a08188f69340e116422458d4a8841f46a78c833b1a822e3f6c9c97422c918f17c36175ca4b3d1c081ee4b175b4b07bf101c3836eb5b9e3cbd08a89b4a1c50edcb41ea8ea6ceb1532f5b842715d50dc21e2499e08c373d3dedb96bb477c8802ab7aa957e0b5810f38", }, { - length: 859, - nonce: [3]uint32{0xeb02dac9, 0xa7cba06c, 0xc24764c}, - key: [8]uint32{0xe9414a57, 0xd5e29546, 0x1a5e2f4c, 0x806e4c46, 0x48098d1f, 0x4351ca1a, 0x53ed97c, 0xa6a495ca}, + nonce: "c9da02eb6ca0cba74c76240c", + key: "574a41e94695e2d54c2f5e1a464c6e801f8d09481aca51437cd93e05ca95a4a6", input: "00fa3b13b5cfa9b5d65a41cc2d3c420518802c22c4582873f1ad52a22032d2cef7c975078b199787e852fb1f914529f60d1cc854e5d6d547216dce043e0fc94866bb2193343c3a07fde60e668266d1cee3067c6f2ce0f9f63456ad08094b6c7f515f7ca90caa96494e2a6835ba1f3f166012ad1ff6af6b5f8455d5c26e72402966af9066ca70ad027eed23b0eb02c751195064a62283975efeb29bc5993f83360d012a2f5275ac758a9e8fe458fc7cc0673e6b9e338678f0faff60a67fff3784c3054dcbd95d1b00ed4c6156b3831cc42a2ccdeee55541f228b88e6c318e2d797c6fc035ae12868c4a4e3843b5b25a530b1477dec3f5ac27644476b5766e0ee132d833f9a63200eb0980bf72c3666150e567e01e3e1f469cf36beea65946fce714a3f354983e54ca4315b57ea35c5f48bd5eada05f49db1004cbb39888ebab3afad62f6509abad77ca8c4ff28731c7ae545e6876c8f4a80b6cc26928ee05001a9764694b52edd605e182d5a3a5fd192bff58aba90f57e4debe612d02cf6f08af33a78ebf8823bb3eb46d4da25b7dfa15ad436c380633d3db3d0dc4dfec6c2324d105e7090e65342b554854e777b40b5dab8125a58e8b212364ff88459a8466ff5ae661034abc8286a78ad5aa582e2dabbcd7a0b0cedcb9fd5f0bb8c3bef9117f2ca6520a72b94e528c1a4a464398e654995d5f4c77cbabf2b204b96a058cf1b38284b34e41ac37b05a003ed51be9602050f21c6b9326714bc425c1e22833da95a6e77571691d4dcab4ef9056c4c7f85d5b445b902eb375b5164c6bdf629ccfd4127a6c024bb6c4da0b6b08350432e58f8229e04e2e76f704be17d36e0c04fcc7a98f721d4572aa7f66ae8e9664300a189bc3862da47b60c8b33424f6d577cc10f4755f36c2a6decc30ba81bf48f96616ccfcfb74965d6bdcab82728bb224c560d1cfd7a175413ad1c14c734746be3b062b4e7514e9075c688103515e32e3335dbd272a315024d56f4ecd354264da9bc712080657b2b51b06dc7c4c441d9858935a4c3e6b207bde38ea83bba4c6854b2bcf914d758e0a174c0528e0e385c7cff355c38db1c22440369141e91266824c59f1ed23e7d4b99d31b0baa7bed4526e24259dbef5c9ae275e97267b756645f804c274d65ac7ab0f7683435bc2e4f24075cd1b790aa2b53fbf044e8f2092bdf0dbe88a582ff8f8de291e8220", output: "bea32587095caac661c3ac49e65654b282192b2addf5b9a403aea6c8bd0096291a0a66ca4062acf1da91fb5749952096ec63ab652ecf94c29807f0aaac939b6896edcd6f0cd8dd8d208b906ef4d7a8766831fecd6ce98f4ea0c34fa9a5114dbeb23c2cd6d3aa962e39b18cb343c24e65d49fad0a0fb50736f8d2b24b011108932484399f4c4510ac9a5e6bc78ff0b450e67f87b49f253b99d95d6294e15a9934fc8b89a5913c08f75d3516766fb0f60f82e2b2647b4619991c78adbcf548c07c0dda30c629349d84f298313c3e629e03760b1cf860264205a950d6fd86732a6513827f72c0dff5aff96f7203464f60849c1065beb70f282cca1334f6f6c767dfff94f063361f592e85597de5d313eaed17bd533db24818d9ba9aea2afa797721fbd19eea7b8d46bbc4b9dc0164636d2e754f5e9e8c04e2a381096331731c645ea1f613a37bfa9a6fb2c6307e9bacacbeab7f5672163ff9742a8115049bce0269d7d5f6f35787be031dbee1535b0516ec0b46d12f5833cde5f2cc569edcdd20993e9776aacf48ace7bfadf79065f2803fba6b2b27aa622abb7ae023ff2b27b727f509f313f92026392485a5ed4fd53b2e22b2d2dc1538ce158d34921214638be30ae054a0f5f1d4f9c590a2d215ac2a5b23ed33871ab26c8bb6db7fe9d6f51e527c9547248a4e9734c64658b22893f4f6867a35f18e2bbfd7d62142025955cb51af8e40b6fcb91c7e959cea2c92022c87c29dae107a306f41b00e73c7bceef8cb070e8f9e830caeee463170e919cba6eee63092a5a7ee33b74db09cdd022fdafbcd5d524253a29a103ba6f4d668d31d18f867557871c0e0258221c3050d57c18bdae4cc4ff8da0daddb5c08619be127ee76a317b59a9d8e67808603a1bfce6b4e0d070082b283bf9c0e6ef8256208e482f3e2d1a40d30807f60a868e2279dfbc3586d44ee25fdca3505cd39fd469c2cd03bc2f921d22a8346750f346c919e7247301c1c8a4a3ddb8eabc6e80d85cd2459afe1cbb4851ea2c86b8075e0fef3177cb074894410ecf681242fac62b5fa4ed3a10ddaa595427851d376cf69e350207b667f7aa26d003f1ec739a8792532ebd93f3cafb1fea40d227bcadda2fb6da794cea3371240f257f80b1b8a857ea453b46938397c1f4b303a46257750003a60666a11d03bf2afb5c71e059933d617288891733b63784bd9c662234f", }, { - length: 985, - nonce: [3]uint32{0x3c2b47a4, 0xf614c813, 0xa26f7014}, - key: [8]uint32{0x39bd3d18, 0xc9aacd67, 0xcb5485b5, 0x20536a22, 0xbb22ac87, 0x1c9da580, 0x7d996b2e, 0x456fe461}, + nonce: "a4472b3c13c814f614706fa2", + key: "183dbd3967cdaac9b58554cb226a532087ac22bb80a59d1c2e6b997d61e46f45", input: "01847d8a97d56e55e12f89adb13c8c0f9dea5555e8dc61171fbb8e181f6cf846a4dd68b2c75335c0896fa215bf7f9eb7e398e4520aaaf33461ecfb61051f43d43569fb75fabd79d319bf39469f951e4da7932a74624c46d8d26a9499c701c00d3dea57a6f65b4c0f33b568d13989340294d17cd005b26d89cf6fa1c88e7b6ef4d074291fa8c117ae05d7c785459ef4561c45af63a811e9aa1c31b69a5bdac2356d955a0f579791247a757a691b3de447a53619878397cd82a74053f06da3574045bc856500ec01fd2afbc64d8dd283ac876a50e9396f78c424ab157f481316fd9c90cd899f5aca46dad32c68f1d64ea7f1c4bdb994ad847072609bd89adc2fa8382a5d573b680533640b8321b6adf27926274660b2cbaf04fbc9a4fb17ce8957c38c7bab1aafd5bf7263171e47d2e1ae5cf0494815642209d303dba561754479c24ea01a573c9083b68acc49907b1748924d3c6a82feb9417ca932578c123f9db35521c0d992565f7396f0c23e436289c1720e4e7c6e285c04a8159f93e06801334e523b18fe188355cc6a155febe64ba053e6b5d1cc87787fd5ae68fa86d8c51868b9f6a9664cf0d56aa6cb8463362bb671e6b8423bcbefe2a1a0acba3f135496736b5cec5e329494af46aba322bf5d1cc108c98298459558773a316e09b0bb960a26f4b0bfbaa493b5f98a0e522b6203c471b10e662abe9b9e60de2a1517843933add02017fadd62608383ad53796159f3d21b2c8ed7295802ca79ea65d550114ca2bcc7f7c3b4c6709fffc3c2de00da06e83d8f0cf04b8c8edd21c0fc11a0b2aa7f6adad255fef25e5c0a9d59546e97446e1fbf6a51a8ea6cad54cabfdd19cd10d7d33ff0549b710557e3931821dd8809ab0a9d3aaa761a01ae0f2e378906672924d6a1b12fb1cca7bed41f31974b9917a05de60c32796f502e7035a2c01cb49bc8e1734b9fa138b81b4dfe19d37f5942dd1b42f03e1e5a6a046ecd457174150e17dd148e4bfea44b72da35ef42a7251244700e59e702033677d42611168fd246e1b18b9a464b6c20fc7fcf6360cd00466ece059a69d7d54a4f5565d08799f85dd3c849a08ba43415077c1c0e5dbdba52bb3167ee99a11db551f0260493be1dde58d2072e8c02251f4f574b6e115cbb6136dc2c3fbce75fdcefe812d9c07a91a89088985a52cb1fb9f6cef80fa30364706414175e42c75e8e37f6e7cd028c99f59caa88c49db5b46e8d6301bc39034013718a9eeef5506415016fb21d70e46a03b4c5ba72f91dd9321ff5e210e5e5f7b0723a3bc4bb02b5a74c1f4a63aa5a993a31f79a768fe8033c9abfeb4deb536af1054be02d8d1c4a6a0fa75f3eb787d57a03b7ae994fb1b54b2c43b230ce32e6245d944b3cea4fa6", output: "785dbea5d1e50af4743ed5fd2209e441fc7c50bc7f6fd9cc7f24654c619e2606178dcbbd81a1f94c1b3176837024098bd31326145be326b32fd9277a55a6fb38780c8dc8b471a3184379d90da4aa87d80b889b1f4d8d0755c1704a526b99ac829b8ad157ca54b2b05ff8b2917e27b0c147ab54add9a89fdcad7b93ba1fe2d5be9de88b68a5324f1b42943e45ee31c4ef783ec9e2337b3f2834b10cf452b313fafdf0c03719140f64060da0a565e185cb8e544e1c185ca230ff2321739a285abe8be4be0ce76678a7b0902a77a645194de49fef8ff64cc464ea25e1f1d72c775e450f08ddd7680d27a4142879787b198583d93b84cd87fd5b4063d92d13d9c9cb580c01fac0174686a18f64e6fa0b3589624cfae04aad74950559bdf92b2b199c60cb04013aa0ef56d1f9ec5b7e968f6a83756ecc9cee7dd8b433f64649f948df5474a64549e71e46fd8bb16568d21f5fb67f5ed555f2b8aec4709383e8cbc45b9fe47c0434178ad4c6d0d42606d6eef0e21d0370898d1d5d646830a88d5f024094fe9c7a2003ca13d20ab7cd748dc11a22f578ddab416f3500eff3d89fc177b46436108e2e2c7973910cb8454a01c9e9b98f966848325444b2ac205b1ed6919fa76aaf63717574761b7f62b10649357df49f85a845a30b6acd57fa202fe58673930ec59399f537e9682b1f5f6f409988789a8e0c1f803478dded14b40d3b6eb3109758efeb6a7fe21f41c4dcc8027258da27ad74010839dbfdf8fe55050511f85c321e653f76e55f22248f46da529a380c6b1a16a19ce73af9715545c2cae098dc42dd61248dbcf7b295f4dc6b8930b41baeef677156c534869be65e723e1aa0336e8be8a3b138f840c9cd63bab6d9d61f239a47d8cf56258544e6ef65edca27069f7a57f087a7cc021fa1294b75c0c0f1093c025e426e4f041ed5187f358402676d5da5fb6ceba76a178f65c8c3046f258531c165b8808bdd221c59ff56e3e06247576e144aac01ea96a07f1be15d7a2b0b3b6c259a9133f8a50b56154ecf9f61022f470027247e6e70e6eaf7ece5e324ec8f95667ffed10337652b119e7cb8d197e306e81ea251340b9fb2c33aa230c0a16e1ca783f9344b3acbf413acd96616e6d477dba90e39326089934bc5ca6620855cdc442e25bf8b8debf335e16e7e25cceb68659cc81b13a507fbd9f30b347126beeb57016bd348fe3df592d4778011664a218227e70d7360d139480500b7f6f84153e61ca4dea105875e19ce3d11a3dfd0ad0074035ff6a9fac0ece91afd8be74c168da20c8baafcc14632eb0e774db758a3d90709cddf0266c27963788c35a842beea8ba2d916234431efde4bb32fd7e1cef51dcf580f4697206bbc3f991f4046360aea6e88ec", }, diff --git a/internal/chacha20/xor.go b/chacha20/xor.go similarity index 73% rename from internal/chacha20/xor.go rename to chacha20/xor.go index 9c5ba0b33a..c2d04851e0 100644 --- a/internal/chacha20/xor.go +++ b/chacha20/xor.go @@ -4,9 +4,7 @@ package chacha20 -import ( - "runtime" -) +import "runtime" // Platforms that have fast unaligned 32-bit little endian accesses. const unaligned = runtime.GOARCH == "386" || @@ -15,10 +13,10 @@ const unaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" -// xor reads a little endian uint32 from src, XORs it with u and +// addXor reads a little endian uint32 from src, XORs it with (a + b) and // places the result in little endian byte order in dst. -func xor(dst, src []byte, u uint32) { - _, _ = src[3], dst[3] // eliminate bounds checks +func addXor(dst, src []byte, a, b uint32) { + _, _ = src[3], dst[3] // bounds check elimination hint if unaligned { // The compiler should optimize this code into // 32-bit unaligned little endian loads and stores. @@ -29,15 +27,16 @@ func xor(dst, src []byte, u uint32) { v |= uint32(src[1]) << 8 v |= uint32(src[2]) << 16 v |= uint32(src[3]) << 24 - v ^= u + v ^= a + b dst[0] = byte(v) dst[1] = byte(v >> 8) dst[2] = byte(v >> 16) dst[3] = byte(v >> 24) } else { - dst[0] = src[0] ^ byte(u) - dst[1] = src[1] ^ byte(u>>8) - dst[2] = src[2] ^ byte(u>>16) - dst[3] = src[3] ^ byte(u>>24) + a += b + dst[0] = src[0] ^ byte(a) + dst[1] = src[1] ^ byte(a>>8) + dst[2] = src[2] ^ byte(a>>16) + dst[3] = src[3] ^ byte(a>>24) } } diff --git a/chacha20poly1305/_asm/chacha20poly1305_amd64_asm.go b/chacha20poly1305/_asm/chacha20poly1305_amd64_asm.go new file mode 100644 index 0000000000..66af868b3c --- /dev/null +++ b/chacha20poly1305/_asm/chacha20poly1305_amd64_asm.go @@ -0,0 +1,5516 @@ +// Copyright 2024 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. + +// This assembly implementation was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. + +package main + +import ( + "fmt" + "os" + "strings" + + . "github.com/mmcloughlin/avo/build" + "github.com/mmcloughlin/avo/ir" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/chacha20poly1305" +) + +//go:generate go run . -out ../chacha20poly1305_amd64.s -pkg chacha20poly1305 + +var ( + // General register allocation + oup GPPhysical = RDI + inp = RSI + inl = RBX + adp = RCX // free to reuse, after we hash the additional data + keyp = R8 // free to reuse, when we copy the key to stack + itr2 = R9 // general iterator + itr1 = RCX // general iterator + acc0 = R10 + acc1 = R11 + acc2 = R12 + t0 = R13 + t1 = R14 + t2 = R15 + t3 = R8 + + // Register and stack allocation for the SSE code + rStore Mem = Mem{Base: BP}.Offset(0 * 16) + sStore = Mem{Base: BP}.Offset(1 * 16) + state1Store = Mem{Base: BP}.Offset(2 * 16) + state2Store = Mem{Base: BP}.Offset(3 * 16) + tmpStore = Mem{Base: BP}.Offset(4 * 16) + ctr0Store = Mem{Base: BP}.Offset(5 * 16) + ctr1Store = Mem{Base: BP}.Offset(6 * 16) + ctr2Store = Mem{Base: BP}.Offset(7 * 16) + ctr3Store = Mem{Base: BP}.Offset(8 * 16) + A0 VecPhysical = X0 + A1 = X1 + A2 = X2 + B0 = X3 + B1 = X4 + B2 = X5 + C0 = X6 + C1 = X7 + C2 = X8 + D0 = X9 + D1 = X10 + D2 = X11 + T0 = X12 + T1 = X13 + T2 = X14 + T3 = X15 + A3 = T0 + B3 = T1 + C3 = T2 + D3 = T3 + + // Register and stack allocation for the AVX2 code + rsStoreAVX2 Mem = Mem{Base: BP}.Offset(0 * 32) + state1StoreAVX2 = Mem{Base: BP}.Offset(1 * 32) + state2StoreAVX2 = Mem{Base: BP}.Offset(2 * 32) + ctr0StoreAVX2 = Mem{Base: BP}.Offset(3 * 32) + ctr1StoreAVX2 = Mem{Base: BP}.Offset(4 * 32) + ctr2StoreAVX2 = Mem{Base: BP}.Offset(5 * 32) + ctr3StoreAVX2 = Mem{Base: BP}.Offset(6 * 32) + tmpStoreAVX2 = Mem{Base: BP}.Offset(7 * 32) // 256 bytes on stack + AA0 VecPhysical = Y0 + AA1 = Y5 + AA2 = Y6 + AA3 = Y7 + BB0 = Y14 + BB1 = Y9 + BB2 = Y10 + BB3 = Y11 + CC0 = Y12 + CC1 = Y13 + CC2 = Y8 + CC3 = Y15 + DD0 = Y4 + DD1 = Y1 + DD2 = Y2 + DD3 = Y3 + TT0 = DD3 + TT1 = AA3 + TT2 = BB3 + TT3 = CC3 +) + +const ThatPeskyUnicodeDot = "\u00b7" + +func main() { + Package("golang.org/x/crypto/chacha20poly1305") + ConstraintExpr("gc,!purego") + polyHashADInternal() + chacha20Poly1305Open() + chacha20Poly1305Seal() + Generate() + + var internalFunctions []string = []string{"·polyHashADInternal"} + removePeskyUnicodeDot(internalFunctions, "../chacha20poly1305_amd64.s") +} + +// Utility function to emit BYTE instruction +func BYTE(u8 U8) { + Instruction(&ir.Instruction{Opcode: "BYTE", Operands: []Op{u8}}) +} + +// PALIGNR $4, X3, X3 +func shiftB0Left() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xdb)) + BYTE(U8(0x04)) +} + +// PALIGNR $4, X4, X4 +func shiftB1Left() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xe4)) + BYTE(U8(0x04)) +} + +// PALIGNR $4, X5, X5 +func shiftB2Left() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xed)) + BYTE(U8(0x04)) +} + +// PALIGNR $4, X13, X13 +func shiftB3Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xed)) + BYTE(U8(0x04)) +} + +// PALIGNR $8, X6, X6 +func shiftC0Left() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xf6)) + BYTE(U8(0x08)) +} + +// PALIGNR $8, X7, X7 +func shiftC1Left() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xff)) + BYTE(U8(0x08)) +} + +// PALIGNR $8, X8, X8 +func shiftC2Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xc0)) + BYTE(U8(0x08)) +} + +// PALIGNR $8, X14, X14 +func shiftC3Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xf6)) + BYTE(U8(0x08)) +} + +// PALIGNR $12, X9, X9 +func shiftD0Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xc9)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X10, X10 +func shiftD1Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xd2)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X11, X11 +func shiftD2Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xdb)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X15, X15 +func shiftD3Left() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xff)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X3, X3 +func shiftB0Right() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xdb)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X4, X4 +func shiftB1Right() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xe4)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X5, X5 +func shiftB2Right() { + BYTE(U8(0x66)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xed)) + BYTE(U8(0x0c)) +} + +// PALIGNR $12, X13, X13 +func shiftB3Right() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xed)) + BYTE(U8(0x0c)) +} + +func shiftC0Right() { + shiftC0Left() +} + +func shiftC1Right() { + shiftC1Left() +} + +func shiftC2Right() { + shiftC2Left() +} + +func shiftC3Right() { + shiftC3Left() +} + +// PALIGNR $4, X9, X9 +func shiftD0Right() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xc9)) + BYTE(U8(0x04)) +} + +// PALIGNR $4, X10, X10 +func shiftD1Right() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xd2)) + BYTE(U8(0x04)) +} + +// PALIGNR $4, X11, X11 +func shiftD2Right() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xdb)) + BYTE(U8(0x04)) +} + +// PALIGNR $4, X15, X15 +func shiftD3Right() { + BYTE(U8(0x66)) + BYTE(U8(0x45)) + BYTE(U8(0x0f)) + BYTE(U8(0x3a)) + BYTE(U8(0x0f)) + BYTE(U8(0xff)) + BYTE(U8(0x04)) +} + +// ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~SOME MACROS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~## + +// Hack: ROL must be a #define macro as it is referenced by other macros +func defineROL() { + definition := + `#define ROL(N, R, T) \ + MOVO R, T; \ + PSLLL $(N), T; \ + PSRLL $(32-(N)), R; \ + PXOR T, R` + Comment("ROL rotates the uint32s in register R left by N bits, using temporary T.") + Instruction(&ir.Instruction{Opcode: definition}) +} + +// ROL rotates the uint32s in register R left by N bits, using temporary T. +func ROL(N uint64, R, T VecPhysical) { + // Hack: ROL must be a #define macro as it is referenced by other macros + Instruction(&ir.Instruction{Opcode: fmt.Sprintf("ROL(%s, %s, %s)", I8(N).Asm(), R.Asm(), T.Asm())}) +} + +// Hack to get Avo to generate an #ifdef +// +// ROL16(R, T) definition depends on a compiler flag that specifies amd64 architectural level. +func defineROL16() { + definition := + `#ifdef GOAMD64_v2 + #define ROL16(R, T) PSHUFB ·rol16<>(SB), R + #else + #define ROL16(R, T) ROL(16, R, T) + #endif` + + Comment("ROL16 rotates the uint32s in register R left by 16, using temporary T if needed.") + Instruction(&ir.Instruction{Opcode: definition}) +} + +// Hack to emit macro call +// +// ROL16 rotates the uint32s in register R left by 16, using temporary T if needed. +func ROL16(R, T VecPhysical) { + Instruction(&ir.Instruction{Opcode: fmt.Sprintf("ROL16(%s, %s)", R.Asm(), T.Asm())}) +} + +// Hack to get Avo to generate an #ifdef +// +// ROL8(R, T) definition depends on a compiler flag that specifies amd64 architectural level. +func defineROL8() { + definition := + `#ifdef GOAMD64_v2 + #define ROL8(R, T) PSHUFB ·rol8<>(SB), R + #else + #define ROL8(R, T) ROL(8, R, T) + #endif` + + Comment("ROL8 rotates the uint32s in register R left by 8, using temporary T if needed.") + Instruction(&ir.Instruction{Opcode: definition}) +} + +// Hack to emit macro call +// +// ROL8 rotates the uint32s in register R left by 8, using temporary T if needed. +func ROL8(R, T VecPhysical) { + Instruction(&ir.Instruction{Opcode: fmt.Sprintf("ROL8(%s, %s)", R.Asm(), T.Asm())}) +} + +func chachaQR(A, B, C, D, T VecPhysical) { + PADDD(B, A) + PXOR(A, D) + ROL16(D, T) + PADDD(D, C) + PXOR(C, B) + MOVO(B, T) + PSLLL(Imm(12), T) + PSRLL(Imm(20), B) + PXOR(T, B) + PADDD(B, A) + PXOR(A, D) + ROL8(D, T) + PADDD(D, C) + PXOR(C, B) + MOVO(B, T) + PSLLL(Imm(7), T) + PSRLL(Imm(25), B) + PXOR(T, B) +} + +func chachaQR_AVX2(A, B, C, D, T VecPhysical) { + VPADDD(B, A, A) + VPXOR(A, D, D) + rol16 := rol16_DATA() + VPSHUFB(rol16, D, D) + VPADDD(D, C, C) + VPXOR(C, B, B) + VPSLLD(Imm(12), B, T) + VPSRLD(Imm(20), B, B) + VPXOR(T, B, B) + VPADDD(B, A, A) + VPXOR(A, D, D) + rol8 := rol8_DATA() + VPSHUFB(rol8, D, D) + VPADDD(D, C, C) + VPXOR(C, B, B) + VPSLLD(Imm(7), B, T) + VPSRLD(Imm(25), B, B) + VPXOR(T, B, B) +} + +func polyAdd(S Mem) { + ADDQ(S, acc0) + ADCQ(S.Offset(8), acc1) + ADCQ(Imm(1), acc2) +} + +func polyMulStage1() { + MOVQ(Mem{Base: BP}.Offset(0*8), RAX) + MOVQ(RAX, t2) + MULQ(acc0) + MOVQ(RAX, t0) + MOVQ(RDX, t1) + MOVQ(Mem{Base: BP}.Offset(0*8), RAX) + MULQ(acc1) + IMULQ(acc2, t2) + ADDQ(RAX, t1) + ADCQ(RDX, t2) +} + +func polyMulStage2() { + MOVQ(Mem{Base: BP}.Offset(1*8), RAX) + MOVQ(RAX, t3) + MULQ(acc0) + ADDQ(RAX, t1) + ADCQ(Imm(0), RDX) + MOVQ(RDX, acc0) + MOVQ(Mem{Base: BP}.Offset(1*8), RAX) + MULQ(acc1) + ADDQ(RAX, t2) + ADCQ(Imm(0), RDX) +} + +func polyMulStage3() { + IMULQ(acc2, t3) + ADDQ(acc0, t2) + ADCQ(RDX, t3) +} + +func polyMulReduceStage() { + MOVQ(t0, acc0) + MOVQ(t1, acc1) + MOVQ(t2, acc2) + ANDQ(Imm(3), acc2) + MOVQ(t2, t0) + ANDQ(I8(-4), t0) + MOVQ(t3, t1) + SHRQ(Imm(2), t3, t2) + SHRQ(Imm(2), t3) + ADDQ(t0, acc0) + ADCQ(t1, acc1) + ADCQ(Imm(0), acc2) + ADDQ(t2, acc0) + ADCQ(t3, acc1) + ADCQ(Imm(0), acc2) +} + +func polyMulStage1_AVX2() { + MOVQ(Mem{Base: BP}.Offset(0*8), RDX) + MOVQ(RDX, t2) + MULXQ(acc0, t0, t1) + IMULQ(acc2, t2) + MULXQ(acc1, RAX, RDX) + ADDQ(RAX, t1) + ADCQ(RDX, t2) +} + +func polyMulStage2_AVX2() { + MOVQ(Mem{Base: BP}.Offset(1*8), RDX) + MULXQ(acc0, acc0, RAX) + ADDQ(acc0, t1) + MULXQ(acc1, acc1, t3) + ADCQ(acc1, t2) + ADCQ(Imm(0), t3) +} + +func polyMulStage3_AVX2() { + IMULQ(acc2, RDX) + ADDQ(RAX, t2) + ADCQ(RDX, t3) +} + +func polyMul() { + polyMulStage1() + polyMulStage2() + polyMulStage3() + polyMulReduceStage() +} + +func polyMulAVX2() { + polyMulStage1_AVX2() + polyMulStage2_AVX2() + polyMulStage3_AVX2() + polyMulReduceStage() +} + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +func polyHashADInternal() { + Function("polyHashADInternal<>") + Attributes(NOSPLIT) + AllocLocal(0) + + Comment("Hack: Must declare #define macros inside of a function due to Avo constraints") + defineROL() + defineROL8() + defineROL16() + + // adp points to beginning of additional data + // itr2 holds ad length + XORQ(acc0, acc0) + XORQ(acc1, acc1) + XORQ(acc2, acc2) + CMPQ(itr2, Imm(13)) + JNE(LabelRef("hashADLoop")) + + openFastTLSAD() + hashADLoop() + hashADTail() + hashADTailLoop() + hashADTailFinish() + hashADDone() +} + +// Special treatment for the TLS case of 13 bytes +func openFastTLSAD() { + Label("openFastTLSAD") + MOVQ(Mem{Base: adp}, acc0) + MOVQ(Mem{Base: adp}.Offset(5), acc1) + SHRQ(Imm(24), acc1) + MOVQ(U32(1), acc2) + polyMul() + RET() +} + +// Hash in 16 byte chunks +func hashADLoop() { + Label("hashADLoop") + Comment("Hash in 16 byte chunks") + CMPQ(itr2, Imm(16)) + JB(LabelRef("hashADTail")) + polyAdd(Mem{Base: adp}.Offset(0)) + LEAQ(Mem{Base: adp}.Offset(1*16), adp) + SUBQ(Imm(16), itr2) + polyMul() + JMP(LabelRef("hashADLoop")) +} + +func hashADTail() { + Label("hashADTail") + CMPQ(itr2, Imm(0)) + JE(LabelRef("hashADDone")) + + Comment("Hash last < 16 byte tail") + XORQ(t0, t0) + XORQ(t1, t1) + XORQ(t2, t2) + ADDQ(itr2, adp) +} + +func hashADTailLoop() { + Label("hashADTailLoop") + SHLQ(Imm(8), t0, t1) + SHLQ(Imm(8), t0) + // Hack to get Avo to emit: + // MOVB -1(adp), t2 + Instruction(&ir.Instruction{Opcode: "MOVB", Operands: []Op{Mem{Base: adp}.Offset(-1), t2}}) + XORQ(t2, t0) + DECQ(adp) + DECQ(itr2) + JNE(LabelRef("hashADTailLoop")) +} + +func hashADTailFinish() { + ADDQ(t0, acc0) + ADCQ(t1, acc1) + ADCQ(Imm(1), acc2) + polyMul() +} + +// Finished AD +func hashADDone() { + Label("hashADDone") + RET() +} + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +// Implements the following function signature: +// +// func chacha20Poly1305Open(dst []byte, key []uint32, src []byte, ad []byte) bool +func chacha20Poly1305Open() { + Implement("chacha20Poly1305Open") + Attributes(0) + AllocLocal(288) + + Comment("For aligned stack access") + MOVQ(RSP, RBP) + ADDQ(Imm(32), RBP) + ANDQ(I8(-32), RBP) + + Load(Param("dst").Base(), oup) + Load(Param("key").Base(), keyp) + Load(Param("src").Base(), inp) + Load(Param("src").Len(), inl) + Load(Param("ad").Base(), adp) + + Comment("Check for AVX2 support") + CMPB(Mem{Symbol: Symbol{Name: ThatPeskyUnicodeDot + "useAVX2"}, Base: StaticBase}, Imm(1)) + JE(LabelRef("chacha20Poly1305Open_AVX2")) + + Comment("Special optimization, for very short buffers") + CMPQ(inl, Imm(128)) + JBE(LabelRef("openSSE128")) // About 16% faster + + Comment("For long buffers, prepare the poly key first") + chacha20Constants := chacha20Constants_DATA() + MOVOU(chacha20Constants, A0) + MOVOU(Mem{Base: keyp}.Offset(1*16), B0) + MOVOU(Mem{Base: keyp}.Offset(2*16), C0) + MOVOU(Mem{Base: keyp}.Offset(3*16), D0) + MOVO(D0, T1) + + Comment("Store state on stack for future use") + MOVO(B0, state1Store) + MOVO(C0, state2Store) + MOVO(D0, ctr3Store) + MOVQ(U32(10), itr2) + + openSSEPreparePolyKey() + openSSEMainLoop() + openSSEInternalLoop() + openSSEMainLoopDone() + openSSEFinalize() + + // ---------------------------------------------------------------------------- + // Special optimization for buffers smaller than 129 bytes + openSSE128() + openSSE128InnerCipherLoop() + openSSE128Open() + openSSETail16() + openSSETail16Store() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 64 bytes of ciphertext + openSSETail64() + openSSETail64LoopA() + openSSETail64LoopB() + openSSETail64DecLoop() + openSSETail64DecLoopDone() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 128 bytes of ciphertext + openSSETail128() + openSSETail128LoopA() + openSSETail128LoopB() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 192 bytes of ciphertext + openSSETail192() + openSSLTail192LoopA() + openSSLTail192LoopB() + openSSLTail192Store() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 256 bytes of ciphertext + openSSETail256() + openSSETail256Loop() + openSSETail256HashLoop() + + // ---------------------------------------------------------------------------- + // ------------------------- AVX2 Code ---------------------------------------- + chacha20Poly1305Open_AVX2() + openAVX2PreparePolyKey() + openAVX2InitialHash64() + openAVX2MainLoop() + openAVX2InternalLoop() + openAVX2MainLoopDone() + + // ---------------------------------------------------------------------------- + // Special optimization for buffers smaller than 193 bytes + openAVX2192() + openAVX2192InnerCipherLoop() + openAVX2ShortOpen() + openAVX2ShortOpenLoop() + openAVX2ShortTail32() + openAVX2ShortDone() + + // ---------------------------------------------------------------------------- + // Special optimization for buffers smaller than 321 bytes + openAVX2320() + openAVX2320InnerCipherLoop() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 128 bytes of ciphertext + openAVX2Tail128() + openAVX2Tail128LoopA() + openAVX2Tail128LoopB() + openAVX2TailLoop() + openAVX2Tail() + openAVX2TailDone() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 256 bytes of ciphertext + openAVX2Tail256() + openAVX2Tail256LoopA() + openAVX2Tail256LoopB() + openAVX2Tail256Hash() + openAVX2Tail256HashEnd() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 384 bytes of ciphertext + openAVX2Tail384() + openAVX2Tail384LoopB() + openAVX2Tail384LoopA() + openAVX2Tail384Hash() + openAVX2Tail384HashEnd() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 512 bytes of ciphertext + openAVX2Tail512() + openAVX2Tail512LoopB() + openAVX2Tail512LoopA() + openAVX2Tail512HashLoop() + openAVX2Tail512HashEnd() +} + +func openSSEPreparePolyKey() { + Label("openSSEPreparePolyKey") + chachaQR(A0, B0, C0, D0, T0) + shiftB0Left() + shiftC0Left() + shiftD0Left() + chachaQR(A0, B0, C0, D0, T0) + shiftB0Right() + shiftC0Right() + shiftD0Right() + DECQ(itr2) + JNE(LabelRef("openSSEPreparePolyKey")) + + Comment("A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded") + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(state1Store, B0) + + Comment("Clamp and store the key") + polyClampMask := polyClampMask_DATA() + PAND(polyClampMask, A0) + MOVO(A0, rStore) + MOVO(B0, sStore) + + Comment("Hash AAD") + Load(Param("ad").Len(), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) +} + +func openSSEMainLoop() { + Label("openSSEMainLoop") + CMPQ(inl, U32(256)) + JB(LabelRef("openSSEMainLoopDone")) + + chacha20Constants := chacha20Constants_DATA() + sseIncMask := sseIncMask_DATA() + + Comment("Load state, increment counter blocks") + MOVO(chacha20Constants, A0) + MOVO(state1Store, B0) + MOVO(state2Store, C0) + MOVO(ctr3Store, D0) + PADDL(sseIncMask, D0) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + PADDL(sseIncMask, D1) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(A2, A3) + MOVO(B2, B3) + MOVO(C2, C3) + MOVO(D2, D3) + PADDL(sseIncMask, D3) + + Comment("Store counters") + MOVO(D0, ctr0Store) + MOVO(D1, ctr1Store) + MOVO(D2, ctr2Store) + MOVO(D3, ctr3Store) + + Comment("There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash") + Comment("2 blocks, and for the remaining 4 only 1 block - for a total of 16") + MOVQ(U32(4), itr1) + MOVQ(inp, itr2) +} + +func openSSEInternalLoop() { + Label("openSSEInternalLoop") + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + polyAdd(Mem{Base: itr2}.Offset(0)) + shiftB0Left() + shiftB1Left() + shiftB2Left() + shiftB3Left() + shiftC0Left() + shiftC1Left() + shiftC2Left() + shiftC3Left() + shiftD0Left() + shiftD1Left() + shiftD2Left() + shiftD3Left() + polyMulStage1() + polyMulStage2() + LEAQ(Mem{Base: itr2}.Offset(2*8), itr2) + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + polyMulStage3() + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + polyMulReduceStage() + shiftB0Right() + shiftB1Right() + shiftB2Right() + shiftB3Right() + shiftC0Right() + shiftC1Right() + shiftC2Right() + shiftC3Right() + shiftD0Right() + shiftD1Right() + shiftD2Right() + shiftD3Right() + DECQ(itr1) + JGE(LabelRef("openSSEInternalLoop")) + + polyAdd(Mem{Base: itr2}.Offset(0)) + polyMul() + LEAQ(Mem{Base: itr2}.Offset(2*8), itr2) + + CMPQ(itr1, I8(-6)) + JG(LabelRef("openSSEInternalLoop")) + + chacha20Constants := chacha20Constants_DATA() + Comment("Add in the state") + PADDD(chacha20Constants, A0) + PADDD(chacha20Constants, A1) + PADDD(chacha20Constants, A2) + PADDD(chacha20Constants, A3) + PADDD(state1Store, B0) + PADDD(state1Store, B1) + PADDD(state1Store, B2) + PADDD(state1Store, B3) + PADDD(state2Store, C0) + PADDD(state2Store, C1) + PADDD(state2Store, C2) + PADDD(state2Store, C3) + PADDD(ctr0Store, D0) + PADDD(ctr1Store, D1) + PADDD(ctr2Store, D2) + PADDD(ctr3Store, D3) + + Comment("Load - xor - store") + MOVO(D3, tmpStore) + MOVOU(Mem{Base: inp}.Offset(0*16), D3) + PXOR(D3, A0) + MOVOU(A0, Mem{Base: oup}.Offset(0*16)) + MOVOU(Mem{Base: inp}.Offset(1*16), D3) + PXOR(D3, B0) + MOVOU(B0, Mem{Base: oup}.Offset(1*16)) + MOVOU(Mem{Base: inp}.Offset(2*16), D3) + PXOR(D3, C0) + MOVOU(C0, Mem{Base: oup}.Offset(2*16)) + MOVOU(Mem{Base: inp}.Offset(3*16), D3) + PXOR(D3, D0) + MOVOU(D0, Mem{Base: oup}.Offset(3*16)) + MOVOU(Mem{Base: inp}.Offset(4*16), D0) + PXOR(D0, A1) + MOVOU(A1, Mem{Base: oup}.Offset(4*16)) + MOVOU(Mem{Base: inp}.Offset(5*16), D0) + PXOR(D0, B1) + MOVOU(B1, Mem{Base: oup}.Offset(5*16)) + MOVOU(Mem{Base: inp}.Offset(6*16), D0) + PXOR(D0, C1) + MOVOU(C1, Mem{Base: oup}.Offset(6*16)) + MOVOU(Mem{Base: inp}.Offset(7*16), D0) + PXOR(D0, D1) + MOVOU(D1, Mem{Base: oup}.Offset(7*16)) + MOVOU(Mem{Base: inp}.Offset(8*16), D0) + PXOR(D0, A2) + MOVOU(A2, Mem{Base: oup}.Offset(8*16)) + MOVOU(Mem{Base: inp}.Offset(9*16), D0) + PXOR(D0, B2) + MOVOU(B2, Mem{Base: oup}.Offset(9*16)) + MOVOU(Mem{Base: inp}.Offset(10*16), D0) + PXOR(D0, C2) + MOVOU(C2, Mem{Base: oup}.Offset(10*16)) + MOVOU(Mem{Base: inp}.Offset(11*16), D0) + PXOR(D0, D2) + MOVOU(D2, Mem{Base: oup}.Offset(11*16)) + MOVOU(Mem{Base: inp}.Offset(12*16), D0) + PXOR(D0, A3) + MOVOU(A3, Mem{Base: oup}.Offset(12*16)) + MOVOU(Mem{Base: inp}.Offset(13*16), D0) + PXOR(D0, B3) + MOVOU(B3, Mem{Base: oup}.Offset(13*16)) + MOVOU(Mem{Base: inp}.Offset(14*16), D0) + PXOR(D0, C3) + MOVOU(C3, Mem{Base: oup}.Offset(14*16)) + MOVOU(Mem{Base: inp}.Offset(15*16), D0) + PXOR(tmpStore, D0) + MOVOU(D0, Mem{Base: oup}.Offset(15*16)) + LEAQ(Mem{Base: inp}.Offset(256), inp) + LEAQ(Mem{Base: oup}.Offset(256), oup) + SUBQ(U32(256), inl) + JMP(LabelRef("openSSEMainLoop")) +} + +func openSSEMainLoopDone() { + Label("openSSEMainLoopDone") + Comment("Handle the various tail sizes efficiently") + TESTQ(inl, inl) + JE(LabelRef("openSSEFinalize")) + CMPQ(inl, Imm(64)) + JBE(LabelRef("openSSETail64")) + CMPQ(inl, Imm(128)) + JBE(LabelRef("openSSETail128")) + CMPQ(inl, Imm(192)) + JBE(LabelRef("openSSETail192")) + JMP(LabelRef("openSSETail256")) +} + +func openSSEFinalize() { + Label("openSSEFinalize") + Comment("Hash in the PT, AAD lengths") + ADDQ(NewParamAddr("ad_len", 80), acc0) + ADCQ(NewParamAddr("src_len", 56), acc1) + ADCQ(Imm(1), acc2) + polyMul() + + Comment("Final reduce") + MOVQ(acc0, t0) + MOVQ(acc1, t1) + MOVQ(acc2, t2) + SUBQ(I8(-5), acc0) + SBBQ(I8(-1), acc1) + SBBQ(Imm(3), acc2) + CMOVQCS(t0, acc0) + CMOVQCS(t1, acc1) + CMOVQCS(t2, acc2) + + Comment("Add in the \"s\" part of the key") + ADDQ(sStore.Offset(0), acc0) + ADCQ(sStore.Offset(8), acc1) + + Comment("Finally, constant time compare to the tag at the end of the message") + XORQ(RAX, RAX) + MOVQ(U32(1), RDX) + XORQ(Mem{Base: inp}.Offset(0*8), acc0) + XORQ(Mem{Base: inp}.Offset(1*8), acc1) + ORQ(acc1, acc0) + CMOVQEQ(RDX, RAX) + + Comment("Return true iff tags are equal") + // Hack to get Avo to emit: + // MOVB AX, ret+96(FP) + Instruction(&ir.Instruction{Opcode: "MOVB", Operands: []Op{AX, NewParamAddr("ret", 96)}}) + RET() +} + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 129 bytes + +// For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks +func openSSE128() { + Label("openSSE128") + + chacha20Constants := chacha20Constants_DATA() + sseIncMask := sseIncMask_DATA() + + MOVOU(chacha20Constants, A0) + MOVOU(Mem{Base: keyp}.Offset(1*16), B0) + MOVOU(Mem{Base: keyp}.Offset(2*16), C0) + MOVOU(Mem{Base: keyp}.Offset(3*16), D0) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + PADDL(sseIncMask, D1) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(B0, T1) + MOVO(C0, T2) + MOVO(D1, T3) + MOVQ(U32(10), itr2) +} + +func openSSE128InnerCipherLoop() { + Label("openSSE128InnerCipherLoop") + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Left() + shiftB1Left() + shiftB2Left() + shiftC0Left() + shiftC1Left() + shiftC2Left() + shiftD0Left() + shiftD1Left() + shiftD2Left() + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Right() + shiftB1Right() + shiftB2Right() + shiftC0Right() + shiftC1Right() + shiftC2Right() + shiftD0Right() + shiftD1Right() + shiftD2Right() + DECQ(itr2) + JNE(LabelRef("openSSE128InnerCipherLoop")) + + Comment("A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded") + + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(chacha20Constants, A1) + PADDL(chacha20Constants, A2) + PADDL(T1, B0) + PADDL(T1, B1) + PADDL(T1, B2) + PADDL(T2, C1) + PADDL(T2, C2) + PADDL(T3, D1) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, T3) + PADDL(T3, D2) + + Comment("Clamp and store the key") + polyClampMask := polyClampMask_DATA() + PAND(polyClampMask, A0) + MOVOU(A0, rStore) + MOVOU(B0, sStore) + + Comment("Hash") + Load(Param("ad").Len(), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) +} + +func openSSE128Open() { + Label("openSSE128Open") + CMPQ(inl, Imm(16)) + JB(LabelRef("openSSETail16")) + SUBQ(Imm(16), inl) + + Comment("Load for hashing") + polyAdd(Mem{Base: inp}.Offset(0)) + + Comment("Load for decryption") + MOVOU(Mem{Base: inp}, T0) + PXOR(T0, A1) + MOVOU(A1, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*16), inp) + LEAQ(Mem{Base: oup}.Offset(1*16), oup) + polyMul() + + Comment("Shift the stream \"left\"") + MOVO(B1, A1) + MOVO(C1, B1) + MOVO(D1, C1) + MOVO(A2, D1) + MOVO(B2, A2) + MOVO(C2, B2) + MOVO(D2, C2) + JMP(LabelRef("openSSE128Open")) +} + +func openSSETail16() { + Label("openSSETail16") + TESTQ(inl, inl) + JE(LabelRef("openSSEFinalize")) + + Comment("We can safely load the CT from the end, because it is padded with the MAC") + MOVQ(inl, itr2) + SHLQ(Imm(4), itr2) + andMask := andMask_DATA() + LEAQ(andMask, t0) + MOVOU(Mem{Base: inp}, T0) + ADDQ(inl, inp) + PAND(Mem{Base: t0, Index: itr2, Scale: 1}.Offset(-16), T0) + MOVO(T0, tmpStore.Offset(0)) + MOVQ(T0, t0) + MOVQ(tmpStore.Offset(8), t1) + PXOR(A1, T0) +} + +func openSSETail16Store() { + Comment("We can only store one byte at a time, since plaintext can be shorter than 16 bytes") + Label("openSSETail16Store") + MOVQ(T0, t3) + // Hack to get Avo to emit: + // MOVB t3, (oup) + Instruction(&ir.Instruction{Opcode: "MOVB", Operands: []Op{t3, Mem{Base: oup}}}) + PSRLDQ(Imm(1), T0) + INCQ(oup) + DECQ(inl) + JNE(LabelRef("openSSETail16Store")) + ADDQ(t0, acc0) + ADCQ(t1, acc1) + ADCQ(Imm(1), acc2) + polyMul() + JMP(LabelRef("openSSEFinalize")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 64 bytes of ciphertext + +// Need to decrypt up to 64 bytes - prepare single block +func openSSETail64() { + Label("openSSETail64") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A0) + MOVO(state1Store, B0) + MOVO(state2Store, C0) + MOVO(ctr3Store, D0) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D0) + MOVO(D0, ctr0Store) + XORQ(itr2, itr2) + MOVQ(inl, itr1) + CMPQ(itr1, Imm(16)) + JB(LabelRef("openSSETail64LoopB")) +} + +// Perform ChaCha rounds, while hashing the remaining input +func openSSETail64LoopA() { + Label("openSSETail64LoopA") + polyAdd(Mem{Base: inp, Index: itr2, Scale: 1}.Offset(0)) + polyMul() + SUBQ(Imm(16), itr1) +} + +func openSSETail64LoopB() { + Label("openSSETail64LoopB") + ADDQ(Imm(16), itr2) + chachaQR(A0, B0, C0, D0, T0) + shiftB0Left() + shiftC0Left() + shiftD0Left() + chachaQR(A0, B0, C0, D0, T0) + shiftB0Right() + shiftC0Right() + shiftD0Right() + + CMPQ(itr1, Imm(16)) + JAE(LabelRef("openSSETail64LoopA")) + + CMPQ(itr2, Imm(160)) + JNE(LabelRef("openSSETail64LoopB")) + + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(state1Store, B0) + PADDL(state2Store, C0) + PADDL(ctr0Store, D0) +} + +func openSSETail64DecLoop() { + Label("openSSETail64DecLoop") + CMPQ(inl, Imm(16)) + JB(LabelRef("openSSETail64DecLoopDone")) + SUBQ(Imm(16), inl) + MOVOU(Mem{Base: inp}, T0) + PXOR(T0, A0) + MOVOU(A0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(16), inp) + LEAQ(Mem{Base: oup}.Offset(16), oup) + MOVO(B0, A0) + MOVO(C0, B0) + MOVO(D0, C0) + JMP(LabelRef("openSSETail64DecLoop")) +} + +func openSSETail64DecLoopDone() { + Label("openSSETail64DecLoopDone") + MOVO(A0, A1) + JMP(LabelRef("openSSETail16")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of ciphertext + +// Need to decrypt up to 128 bytes - prepare two blocks +func openSSETail128() { + Label("openSSETail128") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A1) + MOVO(state1Store, B1) + MOVO(state2Store, C1) + MOVO(ctr3Store, D1) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D1) + MOVO(D1, ctr0Store) + MOVO(A1, A0) + MOVO(B1, B0) + MOVO(C1, C0) + MOVO(D1, D0) + PADDL(sseIncMask, D0) + MOVO(D0, ctr1Store) + XORQ(itr2, itr2) + MOVQ(inl, itr1) + ANDQ(I8(-16), itr1) +} + +// Perform ChaCha rounds, while hashing the remaining input +func openSSETail128LoopA() { + Label("openSSETail128LoopA") + polyAdd(Mem{Base: inp, Index: itr2, Scale: 1}.Offset(0)) + polyMul() +} + +func openSSETail128LoopB() { + Label("openSSETail128LoopB") + ADDQ(Imm(16), itr2) + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + shiftB0Left() + shiftC0Left() + shiftD0Left() + shiftB1Left() + shiftC1Left() + shiftD1Left() + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + shiftB0Right() + shiftC0Right() + shiftD0Right() + shiftB1Right() + shiftC1Right() + shiftD1Right() + + CMPQ(itr2, itr1) + JB(LabelRef("openSSETail128LoopA")) + + CMPQ(itr2, Imm(160)) + JNE(LabelRef("openSSETail128LoopB")) + + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(chacha20Constants, A1) + PADDL(state1Store, B0) + PADDL(state1Store, B1) + PADDL(state2Store, C0) + PADDL(state2Store, C1) + PADDL(ctr1Store, D0) + PADDL(ctr0Store, D1) + + MOVOU(Mem{Base: inp}.Offset(0*16), T0) + MOVOU(Mem{Base: inp}.Offset(1*16), T1) + MOVOU(Mem{Base: inp}.Offset(2*16), T2) + MOVOU(Mem{Base: inp}.Offset(3*16), T3) + PXOR(T0, A1) + PXOR(T1, B1) + PXOR(T2, C1) + PXOR(T3, D1) + MOVOU(A1, Mem{Base: oup}.Offset(0*16)) + MOVOU(B1, Mem{Base: oup}.Offset(1*16)) + MOVOU(C1, Mem{Base: oup}.Offset(2*16)) + MOVOU(D1, Mem{Base: oup}.Offset(3*16)) + + SUBQ(Imm(64), inl) + LEAQ(Mem{Base: inp}.Offset(64), inp) + LEAQ(Mem{Base: oup}.Offset(64), oup) + JMP(LabelRef("openSSETail64DecLoop")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 192 bytes of ciphertext + +// Need to decrypt up to 192 bytes - prepare three blocks +func openSSETail192() { + Label("openSSETail192") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A2) + MOVO(state1Store, B2) + MOVO(state2Store, C2) + MOVO(ctr3Store, D2) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D2) + MOVO(D2, ctr0Store) + MOVO(A2, A1) + MOVO(B2, B1) + MOVO(C2, C1) + MOVO(D2, D1) + PADDL(sseIncMask, D1) + MOVO(D1, ctr1Store) + MOVO(A1, A0) + MOVO(B1, B0) + MOVO(C1, C0) + MOVO(D1, D0) + PADDL(sseIncMask, D0) + MOVO(D0, ctr2Store) + + MOVQ(inl, itr1) + MOVQ(U32(160), itr2) + CMPQ(itr1, Imm(160)) + CMOVQGT(itr2, itr1) + ANDQ(I8(-16), itr1) + XORQ(itr2, itr2) +} + +// Perform ChaCha rounds, while hashing the remaining input +func openSSLTail192LoopA() { + Label("openSSLTail192LoopA") + polyAdd(Mem{Base: inp, Index: itr2, Scale: 1}.Offset(0)) + polyMul() +} + +func openSSLTail192LoopB() { + Label("openSSLTail192LoopB") + ADDQ(Imm(16), itr2) + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Left() + shiftC0Left() + shiftD0Left() + shiftB1Left() + shiftC1Left() + shiftD1Left() + shiftB2Left() + shiftC2Left() + shiftD2Left() + + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Right() + shiftC0Right() + shiftD0Right() + shiftB1Right() + shiftC1Right() + shiftD1Right() + shiftB2Right() + shiftC2Right() + shiftD2Right() + + CMPQ(itr2, itr1) + JB(LabelRef("openSSLTail192LoopA")) + + CMPQ(itr2, Imm(160)) + JNE(LabelRef("openSSLTail192LoopB")) + + CMPQ(inl, Imm(176)) + JB(LabelRef("openSSLTail192Store")) + + polyAdd(Mem{Base: inp}.Offset(160)) + polyMul() + + CMPQ(inl, Imm(192)) + JB(LabelRef("openSSLTail192Store")) + + polyAdd(Mem{Base: inp}.Offset(176)) + polyMul() +} + +func openSSLTail192Store() { + Label("openSSLTail192Store") + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(chacha20Constants, A1) + PADDL(chacha20Constants, A2) + PADDL(state1Store, B0) + PADDL(state1Store, B1) + PADDL(state1Store, B2) + PADDL(state2Store, C0) + PADDL(state2Store, C1) + PADDL(state2Store, C2) + PADDL(ctr2Store, D0) + PADDL(ctr1Store, D1) + PADDL(ctr0Store, D2) + + MOVOU(Mem{Base: inp}.Offset(0*16), T0) + MOVOU(Mem{Base: inp}.Offset(1*16), T1) + MOVOU(Mem{Base: inp}.Offset(2*16), T2) + MOVOU(Mem{Base: inp}.Offset(3*16), T3) + PXOR(T0, A2) + PXOR(T1, B2) + PXOR(T2, C2) + PXOR(T3, D2) + MOVOU(A2, Mem{Base: oup}.Offset(0*16)) + MOVOU(B2, Mem{Base: oup}.Offset(1*16)) + MOVOU(C2, Mem{Base: oup}.Offset(2*16)) + MOVOU(D2, Mem{Base: oup}.Offset(3*16)) + + MOVOU(Mem{Base: inp}.Offset(4*16), T0) + MOVOU(Mem{Base: inp}.Offset(5*16), T1) + MOVOU(Mem{Base: inp}.Offset(6*16), T2) + MOVOU(Mem{Base: inp}.Offset(7*16), T3) + PXOR(T0, A1) + PXOR(T1, B1) + PXOR(T2, C1) + PXOR(T3, D1) + MOVOU(A1, Mem{Base: oup}.Offset(4*16)) + MOVOU(B1, Mem{Base: oup}.Offset(5*16)) + MOVOU(C1, Mem{Base: oup}.Offset(6*16)) + MOVOU(D1, Mem{Base: oup}.Offset(7*16)) + + SUBQ(Imm(128), inl) + LEAQ(Mem{Base: inp}.Offset(128), inp) + LEAQ(Mem{Base: oup}.Offset(128), oup) + JMP(LabelRef("openSSETail64DecLoop")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 256 bytes of ciphertext + +// Need to decrypt up to 256 bytes - prepare four blocks +func openSSETail256() { + Label("openSSETail256") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A0) + MOVO(state1Store, B0) + MOVO(state2Store, C0) + MOVO(ctr3Store, D0) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D0) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + PADDL(sseIncMask, D1) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(A2, A3) + MOVO(B2, B3) + MOVO(C2, C3) + MOVO(D2, D3) + PADDL(sseIncMask, D3) + + Comment("Store counters") + MOVO(D0, ctr0Store) + MOVO(D1, ctr1Store) + MOVO(D2, ctr2Store) + MOVO(D3, ctr3Store) + XORQ(itr2, itr2) +} + +// This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication +func openSSETail256Loop() { + Label("openSSETail256Loop") + polyAdd(Mem{Base: inp, Index: itr2, Scale: 1}.Offset(0)) + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + shiftB0Left() + shiftB1Left() + shiftB2Left() + shiftB3Left() + shiftC0Left() + shiftC1Left() + shiftC2Left() + shiftC3Left() + shiftD0Left() + shiftD1Left() + shiftD2Left() + shiftD3Left() + polyMulStage1() + polyMulStage2() + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + polyMulStage3() + polyMulReduceStage() + shiftB0Right() + shiftB1Right() + shiftB2Right() + shiftB3Right() + shiftC0Right() + shiftC1Right() + shiftC2Right() + shiftC3Right() + shiftD0Right() + shiftD1Right() + shiftD2Right() + shiftD3Right() + ADDQ(Imm(2*8), itr2) + CMPQ(itr2, Imm(160)) + JB(LabelRef("openSSETail256Loop")) + MOVQ(inl, itr1) + ANDQ(I8(-16), itr1) +} + +func openSSETail256HashLoop() { + Label("openSSETail256HashLoop") + polyAdd(Mem{Base: inp, Index: itr2, Scale: 1}.Offset(0)) + polyMul() + ADDQ(Imm(2*8), itr2) + CMPQ(itr2, itr1) + JB(LabelRef("openSSETail256HashLoop")) + + Comment("Add in the state") + chacha20Constants := chacha20Constants_DATA() + PADDD(chacha20Constants, A0) + PADDD(chacha20Constants, A1) + PADDD(chacha20Constants, A2) + PADDD(chacha20Constants, A3) + PADDD(state1Store, B0) + PADDD(state1Store, B1) + PADDD(state1Store, B2) + PADDD(state1Store, B3) + PADDD(state2Store, C0) + PADDD(state2Store, C1) + PADDD(state2Store, C2) + PADDD(state2Store, C3) + PADDD(ctr0Store, D0) + PADDD(ctr1Store, D1) + PADDD(ctr2Store, D2) + PADDD(ctr3Store, D3) + MOVO(D3, tmpStore) + + Comment("Load - xor - store") + MOVOU(Mem{Base: inp}.Offset(0*16), D3) + PXOR(D3, A0) + MOVOU(Mem{Base: inp}.Offset(1*16), D3) + PXOR(D3, B0) + MOVOU(Mem{Base: inp}.Offset(2*16), D3) + PXOR(D3, C0) + MOVOU(Mem{Base: inp}.Offset(3*16), D3) + PXOR(D3, D0) + MOVOU(A0, Mem{Base: oup}.Offset(0*16)) + MOVOU(B0, Mem{Base: oup}.Offset(1*16)) + MOVOU(C0, Mem{Base: oup}.Offset(2*16)) + MOVOU(D0, Mem{Base: oup}.Offset(3*16)) + MOVOU(Mem{Base: inp}.Offset(4*16), A0) + MOVOU(Mem{Base: inp}.Offset(5*16), B0) + MOVOU(Mem{Base: inp}.Offset(6*16), C0) + MOVOU(Mem{Base: inp}.Offset(7*16), D0) + PXOR(A0, A1) + PXOR(B0, B1) + PXOR(C0, C1) + PXOR(D0, D1) + MOVOU(A1, Mem{Base: oup}.Offset(4*16)) + MOVOU(B1, Mem{Base: oup}.Offset(5*16)) + MOVOU(C1, Mem{Base: oup}.Offset(6*16)) + MOVOU(D1, Mem{Base: oup}.Offset(7*16)) + MOVOU(Mem{Base: inp}.Offset(8*16), A0) + MOVOU(Mem{Base: inp}.Offset(9*16), B0) + MOVOU(Mem{Base: inp}.Offset(10*16), C0) + MOVOU(Mem{Base: inp}.Offset(11*16), D0) + PXOR(A0, A2) + PXOR(B0, B2) + PXOR(C0, C2) + PXOR(D0, D2) + MOVOU(A2, Mem{Base: oup}.Offset(8*16)) + MOVOU(B2, Mem{Base: oup}.Offset(9*16)) + MOVOU(C2, Mem{Base: oup}.Offset(10*16)) + MOVOU(D2, Mem{Base: oup}.Offset(11*16)) + LEAQ(Mem{Base: inp}.Offset(192), inp) + LEAQ(Mem{Base: oup}.Offset(192), oup) + SUBQ(Imm(192), inl) + MOVO(A3, A0) + MOVO(B3, B0) + MOVO(C3, C0) + MOVO(tmpStore, D0) + + JMP(LabelRef("openSSETail64DecLoop")) +} + +// Functions to emit AVX instructions via BYTE directive + +// broadcasti128 16(r8), ymm14 +func VBROADCASTI128_16_R8_YMM14() { + BYTE(U8(0xc4)) + BYTE(U8(0x42)) + BYTE(U8(0x7d)) + BYTE(U8(0x5a)) + BYTE(U8(0x70)) + BYTE(U8(0x10)) +} + +// broadcasti128 32(r8), ymm12 +func VBROADCASTI128_32_R8_YMM12() { + BYTE(U8(0xc4)) + BYTE(U8(0x42)) + BYTE(U8(0x7d)) + BYTE(U8(0x5a)) + BYTE(U8(0x60)) + BYTE(U8(0x20)) +} + +// broadcasti128 48(r8), ymm4 +func VBROADCASTI128_48_R8_YMM4() { + BYTE(U8(0xc4)) + BYTE(U8(0xc2)) + BYTE(U8(0x7d)) + BYTE(U8(0x5a)) + BYTE(U8(0x60)) + BYTE(U8(0x30)) +} + +// ---------------------------------------------------------------------------- +// ------------------------- AVX2 Code ---------------------------------------- + +func chacha20Poly1305Open_AVX2() { + Label("chacha20Poly1305Open_AVX2") + VZEROUPPER() + chacha20Constants := chacha20Constants_DATA() + VMOVDQU(chacha20Constants, AA0) + VBROADCASTI128_16_R8_YMM14() + VBROADCASTI128_32_R8_YMM12() + VBROADCASTI128_48_R8_YMM4() + avx2InitMask := avx2InitMask_DATA() + VPADDD(avx2InitMask, DD0, DD0) + + Comment("Special optimization, for very short buffers") + CMPQ(inl, Imm(192)) + JBE(LabelRef("openAVX2192")) + CMPQ(inl, U32(320)) + JBE(LabelRef("openAVX2320")) + + Comment("For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream") + VMOVDQA(BB0, state1StoreAVX2) + VMOVDQA(CC0, state2StoreAVX2) + VMOVDQA(DD0, ctr3StoreAVX2) + MOVQ(U32(10), itr2) +} + +func openAVX2PreparePolyKey() { + Label("openAVX2PreparePolyKey") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(12), DD0, DD0, DD0) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(4), DD0, DD0, DD0) + DECQ(itr2) + JNE(LabelRef("openAVX2PreparePolyKey")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(ctr3StoreAVX2, DD0, DD0) + + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + + Comment("Clamp and store poly key") + polyClampMask := polyClampMask_DATA() + VPAND(polyClampMask, TT0, TT0) + VMOVDQA(TT0, rsStoreAVX2) + + Comment("Stream for the first 64 bytes") + VPERM2I128(Imm(0x13), AA0, BB0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, BB0) + + Comment("Hash AD + first 64 bytes") + // MOVQ ad_len+80(FP), itr2 + MOVQ(NewParamAddr("ad_len", 80), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) + XORQ(itr1, itr1) +} + +func openAVX2InitialHash64() { + Label("openAVX2InitialHash64") + // polyAdd(0(inp)(itr1*1)) + polyAdd(Mem{Base: inp, Index: itr1, Scale: 1}.Offset(0)) + polyMulAVX2() + ADDQ(Imm(16), itr1) + CMPQ(itr1, Imm(64)) + JNE(LabelRef("openAVX2InitialHash64")) + + Comment("Decrypt the first 64 bytes") + VPXOR(Mem{Base: inp}.Offset(0*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(1*32), BB0, BB0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(1*32)) + LEAQ(Mem{Base: inp}.Offset(2*32), inp) + LEAQ(Mem{Base: oup}.Offset(2*32), oup) + SUBQ(Imm(64), inl) +} + +func openAVX2MainLoop() { + Label("openAVX2MainLoop") + CMPQ(inl, U32(512)) + JB(LabelRef("openAVX2MainLoopDone")) + + Comment("Load state, increment counter blocks, store the incremented counters") + chacha20Constants := chacha20Constants_DATA() + VMOVDQU(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(AA0, AA3) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(BB0, BB3) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(CC0, CC3) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VPADDD(avx2IncMask, DD2, DD3) + VMOVDQA(DD0, ctr0StoreAVX2) + VMOVDQA(DD1, ctr1StoreAVX2) + VMOVDQA(DD2, ctr2StoreAVX2) + VMOVDQA(DD3, ctr3StoreAVX2) + XORQ(itr1, itr1) +} + +// Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications +// Effectively per 512 bytes of stream we hash 480 bytes of ciphertext +func openAVX2InternalLoop() { + Label("openAVX2InternalLoop") + polyAdd(Mem{Base: inp, Index: itr1, Scale: 1}.Offset(0 * 8)) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + polyMulStage1_AVX2() + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol16 := rol16_DATA() + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + polyMulStage2_AVX2() + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + polyMulStage3_AVX2() + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulReduceStage() + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol8 := rol8_DATA() + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + polyAdd(Mem{Base: inp, Index: itr1, Scale: 1}.Offset(2 * 8)) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + polyMulStage1_AVX2() + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulStage2_AVX2() + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(4), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + VPALIGNR(Imm(12), DD3, DD3, DD3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + polyMulStage3_AVX2() + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + polyMulReduceStage() + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + polyAdd(Mem{Base: inp, Index: itr1, Scale: 1}.Offset(4 * 8)) + LEAQ(Mem{Base: itr1}.Offset(6*8), itr1) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulStage1_AVX2() + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + polyMulStage2_AVX2() + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + polyMulStage3_AVX2() + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulReduceStage() + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(12), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + VPALIGNR(Imm(4), DD3, DD3, DD3) + CMPQ(itr1, U32(480)) + JNE(LabelRef("openAVX2InternalLoop")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(chacha20Constants, AA3, AA3) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state1StoreAVX2, BB3, BB3) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(state2StoreAVX2, CC3, CC3) + VPADDD(ctr0StoreAVX2, DD0, DD0) + VPADDD(ctr1StoreAVX2, DD1, DD1) + VPADDD(ctr2StoreAVX2, DD2, DD2) + VPADDD(ctr3StoreAVX2, DD3, DD3) + VMOVDQA(CC3, tmpStoreAVX2) + + Comment("We only hashed 480 of the 512 bytes available - hash the remaining 32 here") + polyAdd(Mem{Base: inp}.Offset(480)) + polyMulAVX2() + VPERM2I128(Imm(0x02), AA0, BB0, CC3) + VPERM2I128(Imm(0x13), AA0, BB0, BB0) + VPERM2I128(Imm(0x02), CC0, DD0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, CC0) + VPXOR(Mem{Base: inp}.Offset(0*32), CC3, CC3) + VPXOR(Mem{Base: inp}.Offset(1*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(2*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(3*32), CC0, CC0) + VMOVDQU(CC3, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(AA0, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(3*32)) + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + VPXOR(Mem{Base: inp}.Offset(4*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(5*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(6*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(7*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(5*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(7*32)) + + Comment("and here") + polyAdd(Mem{Base: inp}.Offset(496)) + polyMulAVX2() + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + VPXOR(Mem{Base: inp}.Offset(8*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(9*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(10*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(11*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(8*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(9*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(10*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(11*32)) + VPERM2I128(Imm(0x02), AA3, BB3, AA0) + VPERM2I128(Imm(0x02), tmpStoreAVX2, DD3, BB0) + VPERM2I128(Imm(0x13), AA3, BB3, CC0) + VPERM2I128(Imm(0x13), tmpStoreAVX2, DD3, DD0) + VPXOR(Mem{Base: inp}.Offset(12*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(13*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(14*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(15*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(12*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(13*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(14*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(15*32)) + LEAQ(Mem{Base: inp}.Offset(32*16), inp) + LEAQ(Mem{Base: oup}.Offset(32*16), oup) + SUBQ(U32(32*16), inl) + JMP(LabelRef("openAVX2MainLoop")) +} + +// Handle the various tail sizes efficiently +func openAVX2MainLoopDone() { + Label("openAVX2MainLoopDone") + Comment("Handle the various tail sizes efficiently") + TESTQ(inl, inl) + JE(LabelRef("openSSEFinalize")) + CMPQ(inl, Imm(128)) + JBE(LabelRef("openAVX2Tail128")) + CMPQ(inl, U32(256)) + JBE(LabelRef("openAVX2Tail256")) + CMPQ(inl, U32(384)) + JBE(LabelRef("openAVX2Tail384")) + JMP(LabelRef("openAVX2Tail512")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 193 bytes + +// For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks +func openAVX2192() { + Label("openAVX2192") + VMOVDQA(AA0, AA1) + VMOVDQA(BB0, BB1) + VMOVDQA(CC0, CC1) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(AA0, AA2) + VMOVDQA(BB0, BB2) + VMOVDQA(CC0, CC2) + VMOVDQA(DD0, DD2) + VMOVDQA(DD1, TT3) + MOVQ(U32(10), itr2) +} + +func openAVX2192InnerCipherLoop() { + Label("openAVX2192InnerCipherLoop") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + DECQ(itr2) + JNE(LabelRef("openAVX2192InnerCipherLoop")) + VPADDD(AA2, AA0, AA0) + VPADDD(AA2, AA1, AA1) + VPADDD(BB2, BB0, BB0) + VPADDD(BB2, BB1, BB1) + VPADDD(CC2, CC0, CC0) + VPADDD(CC2, CC1, CC1) + VPADDD(DD2, DD0, DD0) + VPADDD(TT3, DD1, DD1) + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + + Comment("Clamp and store poly key") + polyClampMask := polyClampMask_DATA() + VPAND(polyClampMask, TT0, TT0) + VMOVDQA(TT0, rsStoreAVX2) + + Comment("Stream for up to 192 bytes") + VPERM2I128(Imm(0x13), AA0, BB0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, BB0) + VPERM2I128(Imm(0x02), AA1, BB1, CC0) + VPERM2I128(Imm(0x02), CC1, DD1, DD0) + VPERM2I128(Imm(0x13), AA1, BB1, AA1) + VPERM2I128(Imm(0x13), CC1, DD1, BB1) +} + +func openAVX2ShortOpen() { + Label("openAVX2ShortOpen") + Comment("Hash") + Load(Param("ad").Len(), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) +} + +func openAVX2ShortOpenLoop() { + Label("openAVX2ShortOpenLoop") + CMPQ(inl, Imm(32)) + JB(LabelRef("openAVX2ShortTail32")) + SUBQ(Imm(32), inl) + + Comment("Load for hashing") + polyAdd(Mem{Base: inp}.Offset(0 * 8)) + polyMulAVX2() + polyAdd(Mem{Base: inp}.Offset(2 * 8)) + polyMulAVX2() + + Comment("Load for decryption") + VPXOR(Mem{Base: inp}, AA0, AA0) + VMOVDQU(AA0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*32), inp) + LEAQ(Mem{Base: oup}.Offset(1*32), oup) + + Comment("Shift stream left") + VMOVDQA(BB0, AA0) + VMOVDQA(CC0, BB0) + VMOVDQA(DD0, CC0) + VMOVDQA(AA1, DD0) + VMOVDQA(BB1, AA1) + VMOVDQA(CC1, BB1) + VMOVDQA(DD1, CC1) + VMOVDQA(AA2, DD1) + VMOVDQA(BB2, AA2) + JMP(LabelRef("openAVX2ShortOpenLoop")) +} + +func openAVX2ShortTail32() { + Label("openAVX2ShortTail32") + CMPQ(inl, Imm(16)) + VMOVDQA(A0, A1) + JB(LabelRef("openAVX2ShortDone")) + + SUBQ(Imm(16), inl) + + Comment("Load for hashing") + polyAdd(Mem{Base: inp}.Offset(0 * 8)) + polyMulAVX2() + + Comment("Load for decryption") + VPXOR(Mem{Base: inp}, A0, T0) + VMOVDQU(T0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*16), inp) + LEAQ(Mem{Base: oup}.Offset(1*16), oup) + VPERM2I128(Imm(0x11), AA0, AA0, AA0) + VMOVDQA(A0, A1) +} + +func openAVX2ShortDone() { + Label("openAVX2ShortDone") + VZEROUPPER() + JMP(LabelRef("openSSETail16")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 321 bytes + +// For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks +func openAVX2320() { + Label("openAVX2320") + VMOVDQA(AA0, AA1) + VMOVDQA(BB0, BB1) + VMOVDQA(CC0, CC1) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(AA0, AA2) + VMOVDQA(BB0, BB2) + VMOVDQA(CC0, CC2) + VPADDD(avx2IncMask, DD1, DD2) + VMOVDQA(BB0, TT1) + VMOVDQA(CC0, TT2) + VMOVDQA(DD0, TT3) + MOVQ(U32(10), itr2) +} + +func openAVX2320InnerCipherLoop() { + Label("openAVX2320InnerCipherLoop") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + DECQ(itr2) + JNE(LabelRef("openAVX2320InnerCipherLoop")) + + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, TT0) + VPADDD(TT0, AA0, AA0) + VPADDD(TT0, AA1, AA1) + VPADDD(TT0, AA2, AA2) + VPADDD(TT1, BB0, BB0) + VPADDD(TT1, BB1, BB1) + VPADDD(TT1, BB2, BB2) + VPADDD(TT2, CC0, CC0) + VPADDD(TT2, CC1, CC1) + VPADDD(TT2, CC2, CC2) + avx2IncMask := avx2IncMask_DATA() + VMOVDQA(avx2IncMask, TT0) + VPADDD(TT3, DD0, DD0) + VPADDD(TT0, TT3, TT3) + VPADDD(TT3, DD1, DD1) + VPADDD(TT0, TT3, TT3) + VPADDD(TT3, DD2, DD2) + + Comment("Clamp and store poly key") + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + polyClampMask := polyClampMask_DATA() + VPAND(polyClampMask, TT0, TT0) + VMOVDQA(TT0, rsStoreAVX2) + + Comment("Stream for up to 320 bytes") + VPERM2I128(Imm(0x13), AA0, BB0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, BB0) + VPERM2I128(Imm(0x02), AA1, BB1, CC0) + VPERM2I128(Imm(0x02), CC1, DD1, DD0) + VPERM2I128(Imm(0x13), AA1, BB1, AA1) + VPERM2I128(Imm(0x13), CC1, DD1, BB1) + VPERM2I128(Imm(0x02), AA2, BB2, CC1) + VPERM2I128(Imm(0x02), CC2, DD2, DD1) + VPERM2I128(Imm(0x13), AA2, BB2, AA2) + VPERM2I128(Imm(0x13), CC2, DD2, BB2) + JMP(LabelRef("openAVX2ShortOpen")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of ciphertext + +// Need to decrypt up to 128 bytes - prepare two blocks +func openAVX2Tail128() { + Label("openAVX2Tail128") + Comment("Need to decrypt up to 128 bytes - prepare two blocks") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA1) + VMOVDQA(state1StoreAVX2, BB1) + VMOVDQA(state2StoreAVX2, CC1) + VMOVDQA(ctr3StoreAVX2, DD1) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD1, DD1) + VMOVDQA(DD1, DD0) + + XORQ(itr2, itr2) + MOVQ(inl, itr1) + ANDQ(I8(-16), itr1) + TESTQ(itr1, itr1) + JE(LabelRef("openAVX2Tail128LoopB")) +} + +// Perform ChaCha rounds, while hashing the remaining input +func openAVX2Tail128LoopA() { + Label("openAVX2Tail128LoopA") + polyAdd(Mem{Base: inp, Index: itr2, Scale: 1}.Offset(0)) + polyMulAVX2() +} + +func openAVX2Tail128LoopB() { + Label("openAVX2Tail128LoopB") + ADDQ(Imm(16), itr2) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD1, DD1, DD1) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD1, DD1, DD1) + CMPQ(itr2, itr1) + JB(LabelRef("openAVX2Tail128LoopA")) + CMPQ(itr2, Imm(160)) + JNE(LabelRef("openAVX2Tail128LoopB")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(DD0, DD1, DD1) + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) +} + +func openAVX2TailLoop() { + Label("openAVX2TailLoop") + CMPQ(inl, Imm(32)) + JB(LabelRef("openAVX2Tail")) + SUBQ(Imm(32), inl) + + Comment("Load for decryption") + VPXOR(Mem{Base: inp}, AA0, AA0) + VMOVDQU(AA0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*32), inp) + LEAQ(Mem{Base: oup}.Offset(1*32), oup) + VMOVDQA(BB0, AA0) + VMOVDQA(CC0, BB0) + VMOVDQA(DD0, CC0) + JMP(LabelRef("openAVX2TailLoop")) +} + +func openAVX2Tail() { + Label("openAVX2Tail") + CMPQ(inl, Imm(16)) + VMOVDQA(A0, A1) + JB(LabelRef("openAVX2TailDone")) + SUBQ(Imm(16), inl) + + Comment("Load for decryption") + VPXOR(Mem{Base: inp}, A0, T0) + VMOVDQU(T0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*16), inp) + LEAQ(Mem{Base: oup}.Offset(1*16), oup) + VPERM2I128(Imm(0x11), AA0, AA0, AA0) + VMOVDQA(A0, A1) +} + +func openAVX2TailDone() { + Label("openAVX2TailDone") + VZEROUPPER() + JMP(LabelRef("openSSETail16")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 256 bytes of ciphertext + +// Need to decrypt up to 256 bytes - prepare four blocks +func openAVX2Tail256() { + Label("openAVX2Tail256") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(DD0, TT1) + VMOVDQA(DD1, TT2) + + Comment("Compute the number of iterations that will hash data") + MOVQ(inl, tmpStoreAVX2) + MOVQ(inl, itr1) + SUBQ(Imm(128), itr1) + SHRQ(Imm(4), itr1) + MOVQ(U32(10), itr2) + CMPQ(itr1, Imm(10)) + CMOVQGT(itr2, itr1) + MOVQ(inp, inl) + XORQ(itr2, itr2) +} + +func openAVX2Tail256LoopA() { + Label("openAVX2Tail256LoopA") + polyAdd(Mem{Base: inl}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: inl}.Offset(16), inl) +} + +// Perform ChaCha rounds, while hashing the remaining input +func openAVX2Tail256LoopB() { + Label("openAVX2Tail256LoopB") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + INCQ(itr2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + CMPQ(itr2, itr1) + JB(LabelRef("openAVX2Tail256LoopA")) + + CMPQ(itr2, Imm(10)) + JNE(LabelRef("openAVX2Tail256LoopB")) + + MOVQ(inl, itr2) + SUBQ(inp, inl) + MOVQ(inl, itr1) + MOVQ(tmpStoreAVX2, inl) +} + +// Hash the remainder of data (if any) +func openAVX2Tail256Hash() { + Label("openAVX2Tail256Hash") + ADDQ(Imm(16), itr1) + CMPQ(itr1, inl) + JGT(LabelRef("openAVX2Tail256HashEnd")) + polyAdd(Mem{Base: itr2}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: itr2}.Offset(16), itr2) + JMP(LabelRef("openAVX2Tail256Hash")) +} + +// Store 128 bytes safely, then go to store loop +func openAVX2Tail256HashEnd() { + Label("openAVX2Tail256HashEnd") + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(TT1, DD0, DD0) + VPADDD(TT2, DD1, DD1) + VPERM2I128(Imm(0x02), AA0, BB0, AA2) + VPERM2I128(Imm(0x02), CC0, DD0, BB2) + VPERM2I128(Imm(0x13), AA0, BB0, CC2) + VPERM2I128(Imm(0x13), CC0, DD0, DD2) + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + + VPXOR(Mem{Base: inp}.Offset(0*32), AA2, AA2) + VPXOR(Mem{Base: inp}.Offset(1*32), BB2, BB2) + VPXOR(Mem{Base: inp}.Offset(2*32), CC2, CC2) + VPXOR(Mem{Base: inp}.Offset(3*32), DD2, DD2) + VMOVDQU(AA2, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(BB2, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(CC2, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(DD2, Mem{Base: oup}.Offset(3*32)) + LEAQ(Mem{Base: inp}.Offset(4*32), inp) + LEAQ(Mem{Base: oup}.Offset(4*32), oup) + SUBQ(Imm(4*32), inl) + + JMP(LabelRef("openAVX2TailLoop")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 384 bytes of ciphertext + +// Need to decrypt up to 384 bytes - prepare six blocks +func openAVX2Tail384() { + Label("openAVX2Tail384") + Comment("Need to decrypt up to 384 bytes - prepare six blocks") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VMOVDQA(DD0, ctr0StoreAVX2) + VMOVDQA(DD1, ctr1StoreAVX2) + VMOVDQA(DD2, ctr2StoreAVX2) + + Comment("Compute the number of iterations that will hash two blocks of data") + MOVQ(inl, tmpStoreAVX2) + MOVQ(inl, itr1) + SUBQ(U32(256), itr1) + SHRQ(Imm(4), itr1) + ADDQ(Imm(6), itr1) + MOVQ(U32(10), itr2) + CMPQ(itr1, Imm(10)) + CMOVQGT(itr2, itr1) + MOVQ(inp, inl) + XORQ(itr2, itr2) +} + +// Perform ChaCha rounds, while hashing the remaining input +func openAVX2Tail384LoopB() { + Label("openAVX2Tail384LoopB") + polyAdd(Mem{Base: inl}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: inl}.Offset(16), inl) +} + +func openAVX2Tail384LoopA() { + Label("openAVX2Tail384LoopA") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + polyAdd(Mem{Base: inl}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: inl}.Offset(16), inl) + INCQ(itr2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + + CMPQ(itr2, itr1) + JB(LabelRef("openAVX2Tail384LoopB")) + + CMPQ(itr2, Imm(10)) + JNE(LabelRef("openAVX2Tail384LoopA")) + + MOVQ(inl, itr2) + SUBQ(inp, inl) + MOVQ(inl, itr1) + MOVQ(tmpStoreAVX2, inl) +} + +func openAVX2Tail384Hash() { + Label("openAVX2Tail384Hash") + ADDQ(Imm(16), itr1) + CMPQ(itr1, inl) + JGT(LabelRef("openAVX2Tail384HashEnd")) + polyAdd(Mem{Base: itr2}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: itr2}.Offset(16), itr2) + JMP(LabelRef("openAVX2Tail384Hash")) +} + +// Store 256 bytes safely, then go to store loop +func openAVX2Tail384HashEnd() { + Label("openAVX2Tail384HashEnd") + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(ctr0StoreAVX2, DD0, DD0) + VPADDD(ctr1StoreAVX2, DD1, DD1) + VPADDD(ctr2StoreAVX2, DD2, DD2) + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + VPERM2I128(Imm(0x02), CC0, DD0, TT1) + VPERM2I128(Imm(0x13), AA0, BB0, TT2) + VPERM2I128(Imm(0x13), CC0, DD0, TT3) + VPXOR(Mem{Base: inp}.Offset(0*32), TT0, TT0) + VPXOR(Mem{Base: inp}.Offset(1*32), TT1, TT1) + VPXOR(Mem{Base: inp}.Offset(2*32), TT2, TT2) + VPXOR(Mem{Base: inp}.Offset(3*32), TT3, TT3) + VMOVDQU(TT0, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(TT1, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(TT2, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(TT3, Mem{Base: oup}.Offset(3*32)) + VPERM2I128(Imm(0x02), AA1, BB1, TT0) + VPERM2I128(Imm(0x02), CC1, DD1, TT1) + VPERM2I128(Imm(0x13), AA1, BB1, TT2) + VPERM2I128(Imm(0x13), CC1, DD1, TT3) + VPXOR(Mem{Base: inp}.Offset(4*32), TT0, TT0) + VPXOR(Mem{Base: inp}.Offset(5*32), TT1, TT1) + VPXOR(Mem{Base: inp}.Offset(6*32), TT2, TT2) + VPXOR(Mem{Base: inp}.Offset(7*32), TT3, TT3) + VMOVDQU(TT0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(TT1, Mem{Base: oup}.Offset(5*32)) + VMOVDQU(TT2, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(TT3, Mem{Base: oup}.Offset(7*32)) + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + LEAQ(Mem{Base: inp}.Offset(8*32), inp) + LEAQ(Mem{Base: oup}.Offset(8*32), oup) + SUBQ(U32(8*32), inl) + JMP(LabelRef("openAVX2TailLoop")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 512 bytes of ciphertext + +func openAVX2Tail512() { + Label("openAVX2Tail512") + chacha20Constants := chacha20Constants_DATA() + VMOVDQU(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(AA0, AA3) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(BB0, BB3) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(CC0, CC3) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VPADDD(avx2IncMask, DD2, DD3) + VMOVDQA(DD0, ctr0StoreAVX2) + VMOVDQA(DD1, ctr1StoreAVX2) + VMOVDQA(DD2, ctr2StoreAVX2) + VMOVDQA(DD3, ctr3StoreAVX2) + XORQ(itr1, itr1) + MOVQ(inp, itr2) +} + +func openAVX2Tail512LoopB() { + Label("openAVX2Tail512LoopB") + polyAdd(Mem{Base: itr2}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: itr2}.Offset(2*8), itr2) +} + +func openAVX2Tail512LoopA() { + Label("openAVX2Tail512LoopA") + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol16 := rol16_DATA() + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyAdd(Mem{Base: itr2}.Offset(0 * 8)) + polyMulAVX2() + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol8 := rol8_DATA() + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(4), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + VPALIGNR(Imm(12), DD3, DD3, DD3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + polyAdd(Mem{Base: itr2}.Offset(2 * 8)) + polyMulAVX2() + LEAQ(Mem{Base: itr2}.Offset(4*8), itr2) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(12), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + VPALIGNR(Imm(4), DD3, DD3, DD3) + INCQ(itr1) + CMPQ(itr1, Imm(4)) + JLT(LabelRef("openAVX2Tail512LoopB")) + + CMPQ(itr1, Imm(10)) + JNE(LabelRef("openAVX2Tail512LoopA")) + + MOVQ(inl, itr1) + SUBQ(U32(384), itr1) + ANDQ(I8(-16), itr1) +} + +func openAVX2Tail512HashLoop() { + Label("openAVX2Tail512HashLoop") + TESTQ(itr1, itr1) + JE(LabelRef("openAVX2Tail512HashEnd")) + polyAdd(Mem{Base: itr2}.Offset(0)) + polyMulAVX2() + LEAQ(Mem{Base: itr2}.Offset(16), itr2) + SUBQ(Imm(16), itr1) + JMP(LabelRef("openAVX2Tail512HashLoop")) +} + +func openAVX2Tail512HashEnd() { + Label("openAVX2Tail512HashEnd") + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(chacha20Constants, AA3, AA3) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state1StoreAVX2, BB3, BB3) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(state2StoreAVX2, CC3, CC3) + VPADDD(ctr0StoreAVX2, DD0, DD0) + VPADDD(ctr1StoreAVX2, DD1, DD1) + VPADDD(ctr2StoreAVX2, DD2, DD2) + VPADDD(ctr3StoreAVX2, DD3, DD3) + VMOVDQA(CC3, tmpStoreAVX2) + VPERM2I128(Imm(0x02), AA0, BB0, CC3) + VPERM2I128(Imm(0x13), AA0, BB0, BB0) + VPERM2I128(Imm(0x02), CC0, DD0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, CC0) + VPXOR(Mem{Base: inp}.Offset(0*32), CC3, CC3) + VPXOR(Mem{Base: inp}.Offset(1*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(2*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(3*32), CC0, CC0) + VMOVDQU(CC3, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(AA0, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(3*32)) + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + VPXOR(Mem{Base: inp}.Offset(4*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(5*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(6*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(7*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(5*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(7*32)) + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + VPXOR(Mem{Base: inp}.Offset(8*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(9*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(10*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(11*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(8*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(9*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(10*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(11*32)) + VPERM2I128(Imm(0x02), AA3, BB3, AA0) + VPERM2I128(Imm(0x02), tmpStoreAVX2, DD3, BB0) + VPERM2I128(Imm(0x13), AA3, BB3, CC0) + VPERM2I128(Imm(0x13), tmpStoreAVX2, DD3, DD0) + + LEAQ(Mem{Base: inp}.Offset(12*32), inp) + LEAQ(Mem{Base: oup}.Offset(12*32), oup) + SUBQ(U32(12*32), inl) + + JMP(LabelRef("openAVX2TailLoop")) +} + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +// Implements the following function signature: +// +// func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) +func chacha20Poly1305Seal() { + Implement("chacha20Poly1305Seal") + Attributes(0) + AllocLocal(288) + + MOVQ(RSP, RBP) + ADDQ(Imm(32), RBP) + ANDQ(I32(-32), RBP) + Load(Param("dst").Base(), oup) + Load(Param("key").Base(), keyp) + Load(Param("src").Base(), inp) + Load(Param("src").Len(), inl) + Load(Param("ad").Base(), adp) + + CMPB(Mem{Symbol: Symbol{Name: ThatPeskyUnicodeDot + "useAVX2"}, Base: StaticBase}, Imm(1)) + JE(LabelRef("chacha20Poly1305Seal_AVX2")) + + Comment("Special optimization, for very short buffers") + CMPQ(inl, Imm(128)) + JBE(LabelRef("sealSSE128")) + + Comment("In the seal case - prepare the poly key + 3 blocks of stream in the first iteration") + chacha20Constants := chacha20Constants_DATA() + MOVOU(chacha20Constants, A0) + MOVOU(Mem{Base: keyp}.Offset(1*16), B0) + MOVOU(Mem{Base: keyp}.Offset(2*16), C0) + MOVOU(Mem{Base: keyp}.Offset(3*16), D0) + + Comment("Store state on stack for future use") + MOVO(B0, state1Store) + MOVO(C0, state2Store) + + Comment("Load state, increment counter blocks") + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D1) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(A2, A3) + MOVO(B2, B3) + MOVO(C2, C3) + MOVO(D2, D3) + PADDL(sseIncMask, D3) + + Comment("Store counters") + MOVO(D0, ctr0Store) + MOVO(D1, ctr1Store) + MOVO(D2, ctr2Store) + MOVO(D3, ctr3Store) + MOVQ(U32(10), itr2) + + sealSSEIntroLoop() + sealSSEMainLoop() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 64 bytes of plaintext + sealSSETail64() + sealSSETail64LoopA() + sealSSETail64LoopB() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 128 bytes of plaintext + sealSSETail128() + sealSSETail128LoopA() + sealSSETail128LoopB() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 192 bytes of plaintext + sealSSETail192() + sealSSETail192LoopA() + sealSSETail192LoopB() + + // ---------------------------------------------------------------------------- + // Special seal optimization for buffers smaller than 129 bytes + sealSSE128() + sealSSE128SealHash() + sealSSE128Seal() + sealSSETail() + sealSSETailLoadLoop() + sealSSEFinalize() + + // ---------------------------------------------------------------------------- + // ------------------------- AVX2 Code ---------------------------------------- + chacha20Poly1305Seal_AVX2() + sealAVX2IntroLoop() + sealAVX2MainLoop() + sealAVX2InternalLoop() + sealAVX2InternalLoopStart() + + // ---------------------------------------------------------------------------- + // Special optimization for buffers smaller than 193 bytes + seal192AVX2() + sealAVX2192InnerCipherLoop() + sealAVX2ShortSeal() + sealAVX2SealHash() + sealAVX2ShortSealLoop() + sealAVX2ShortTail32() + sealAVX2ShortDone() + + // ---------------------------------------------------------------------------- + // Special optimization for buffers smaller than 321 bytes + seal320AVX2() + sealAVX2320InnerCipherLoop() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 128 bytes of ciphertext + sealAVX2Tail128() + sealAVX2Tail128LoopA() + sealAVX2Tail128LoopB() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 256 bytes of ciphertext + sealAVX2Tail256() + sealAVX2Tail256LoopA() + sealAVX2Tail256LoopB() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 384 bytes of ciphertext + sealAVX2Tail384() + sealAVX2Tail384LoopA() + sealAVX2Tail384LoopB() + + // ---------------------------------------------------------------------------- + // Special optimization for the last 512 bytes of ciphertext + sealAVX2Tail512() + sealAVX2Tail512LoopA() + sealAVX2Tail512LoopB() +} + +func sealSSEIntroLoop() { + Label("sealSSEIntroLoop") + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + shiftB0Left() + shiftB1Left() + shiftB2Left() + shiftB3Left() + shiftC0Left() + shiftC1Left() + shiftC2Left() + shiftC3Left() + shiftD0Left() + shiftD1Left() + shiftD2Left() + shiftD3Left() + + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + shiftB0Right() + shiftB1Right() + shiftB2Right() + shiftB3Right() + shiftC0Right() + shiftC1Right() + shiftC2Right() + shiftC3Right() + shiftD0Right() + shiftD1Right() + shiftD2Right() + shiftD3Right() + DECQ(itr2) + JNE(LabelRef("sealSSEIntroLoop")) + + Comment("Add in the state") + chacha20Constants := chacha20Constants_DATA() + PADDD(chacha20Constants, A0) + PADDD(chacha20Constants, A1) + PADDD(chacha20Constants, A2) + PADDD(chacha20Constants, A3) + PADDD(state1Store, B0) + PADDD(state1Store, B1) + PADDD(state1Store, B2) + PADDD(state1Store, B3) + PADDD(state2Store, C1) + PADDD(state2Store, C2) + PADDD(state2Store, C3) + PADDD(ctr1Store, D1) + PADDD(ctr2Store, D2) + PADDD(ctr3Store, D3) + + Comment("Clamp and store the key") + polyClampMask := polyClampMask_DATA() + PAND(polyClampMask, A0) + MOVO(A0, rStore) + MOVO(B0, sStore) + + Comment("Hash AAD") + MOVQ(NewParamAddr("ad_len", 80), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) + + MOVOU(Mem{Base: inp}.Offset(0*16), A0) + MOVOU(Mem{Base: inp}.Offset(1*16), B0) + MOVOU(Mem{Base: inp}.Offset(2*16), C0) + MOVOU(Mem{Base: inp}.Offset(3*16), D0) + PXOR(A0, A1) + PXOR(B0, B1) + PXOR(C0, C1) + PXOR(D0, D1) + MOVOU(A1, Mem{Base: oup}.Offset(0*16)) + MOVOU(B1, Mem{Base: oup}.Offset(1*16)) + MOVOU(C1, Mem{Base: oup}.Offset(2*16)) + MOVOU(D1, Mem{Base: oup}.Offset(3*16)) + MOVOU(Mem{Base: inp}.Offset(4*16), A0) + MOVOU(Mem{Base: inp}.Offset(5*16), B0) + MOVOU(Mem{Base: inp}.Offset(6*16), C0) + MOVOU(Mem{Base: inp}.Offset(7*16), D0) + PXOR(A0, A2) + PXOR(B0, B2) + PXOR(C0, C2) + PXOR(D0, D2) + MOVOU(A2, Mem{Base: oup}.Offset(4*16)) + MOVOU(B2, Mem{Base: oup}.Offset(5*16)) + MOVOU(C2, Mem{Base: oup}.Offset(6*16)) + MOVOU(D2, Mem{Base: oup}.Offset(7*16)) + + MOVQ(U32(128), itr1) + SUBQ(Imm(128), inl) + LEAQ(Mem{Base: inp}.Offset(128), inp) + + MOVO(A3, A1) + MOVO(B3, B1) + MOVO(C3, C1) + MOVO(D3, D1) + + CMPQ(inl, Imm(64)) + JBE(LabelRef("sealSSE128SealHash")) + + MOVOU(Mem{Base: inp}.Offset(0*16), A0) + MOVOU(Mem{Base: inp}.Offset(1*16), B0) + MOVOU(Mem{Base: inp}.Offset(2*16), C0) + MOVOU(Mem{Base: inp}.Offset(3*16), D0) + PXOR(A0, A3) + PXOR(B0, B3) + PXOR(C0, C3) + PXOR(D0, D3) + MOVOU(A3, Mem{Base: oup}.Offset(8*16)) + MOVOU(B3, Mem{Base: oup}.Offset(9*16)) + MOVOU(C3, Mem{Base: oup}.Offset(10*16)) + MOVOU(D3, Mem{Base: oup}.Offset(11*16)) + + ADDQ(Imm(64), itr1) + SUBQ(Imm(64), inl) + LEAQ(Mem{Base: inp}.Offset(64), inp) + + MOVQ(U32(2), itr1) + MOVQ(U32(8), itr2) + + CMPQ(inl, Imm(64)) + JBE(LabelRef("sealSSETail64")) + CMPQ(inl, Imm(128)) + JBE(LabelRef("sealSSETail128")) + CMPQ(inl, Imm(192)) + JBE(LabelRef("sealSSETail192")) +} + +func sealSSEMainLoop() { + Label("sealSSEMainLoop") + Comment("Load state, increment counter blocks") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A0) + MOVO(state1Store, B0) + MOVO(state2Store, C0) + MOVO(ctr3Store, D0) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D0) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + PADDL(sseIncMask, D1) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(A2, A3) + MOVO(B2, B3) + MOVO(C2, C3) + MOVO(D2, D3) + PADDL(sseIncMask, D3) + + Comment("Store counters") + MOVO(D0, ctr0Store) + MOVO(D1, ctr1Store) + MOVO(D2, ctr2Store) + MOVO(D3, ctr3Store) + + Label("sealSSEInnerLoop") + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + polyAdd(Mem{Base: oup}.Offset(0)) + shiftB0Left() + shiftB1Left() + shiftB2Left() + shiftB3Left() + shiftC0Left() + shiftC1Left() + shiftC2Left() + shiftC3Left() + shiftD0Left() + shiftD1Left() + shiftD2Left() + shiftD3Left() + polyMulStage1() + polyMulStage2() + LEAQ(Mem{Base: oup}.Offset(2*8), oup) + MOVO(C3, tmpStore) + chachaQR(A0, B0, C0, D0, C3) + chachaQR(A1, B1, C1, D1, C3) + chachaQR(A2, B2, C2, D2, C3) + MOVO(tmpStore, C3) + MOVO(C1, tmpStore) + polyMulStage3() + chachaQR(A3, B3, C3, D3, C1) + MOVO(tmpStore, C1) + polyMulReduceStage() + shiftB0Right() + shiftB1Right() + shiftB2Right() + shiftB3Right() + shiftC0Right() + shiftC1Right() + shiftC2Right() + shiftC3Right() + shiftD0Right() + shiftD1Right() + shiftD2Right() + shiftD3Right() + DECQ(itr2) + JGE(LabelRef("sealSSEInnerLoop")) + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(2*8), oup) + DECQ(itr1) + JG(LabelRef("sealSSEInnerLoop")) + + Comment("Add in the state") + PADDD(chacha20Constants, A0) + PADDD(chacha20Constants, A1) + PADDD(chacha20Constants, A2) + PADDD(chacha20Constants, A3) + PADDD(state1Store, B0) + PADDD(state1Store, B1) + PADDD(state1Store, B2) + PADDD(state1Store, B3) + PADDD(state2Store, C0) + PADDD(state2Store, C1) + PADDD(state2Store, C2) + PADDD(state2Store, C3) + PADDD(ctr0Store, D0) + PADDD(ctr1Store, D1) + PADDD(ctr2Store, D2) + PADDD(ctr3Store, D3) + MOVO(D3, tmpStore) + + Comment("Load - xor - store") + MOVOU(Mem{Base: inp}.Offset(0*16), D3) + PXOR(D3, A0) + MOVOU(Mem{Base: inp}.Offset(1*16), D3) + PXOR(D3, B0) + MOVOU(Mem{Base: inp}.Offset(2*16), D3) + PXOR(D3, C0) + MOVOU(Mem{Base: inp}.Offset(3*16), D3) + PXOR(D3, D0) + MOVOU(A0, Mem{Base: oup}.Offset(0*16)) + MOVOU(B0, Mem{Base: oup}.Offset(1*16)) + MOVOU(C0, Mem{Base: oup}.Offset(2*16)) + MOVOU(D0, Mem{Base: oup}.Offset(3*16)) + MOVO(tmpStore, D3) + + MOVOU(Mem{Base: inp}.Offset(4*16), A0) + MOVOU(Mem{Base: inp}.Offset(5*16), B0) + MOVOU(Mem{Base: inp}.Offset(6*16), C0) + MOVOU(Mem{Base: inp}.Offset(7*16), D0) + PXOR(A0, A1) + PXOR(B0, B1) + PXOR(C0, C1) + PXOR(D0, D1) + MOVOU(A1, Mem{Base: oup}.Offset(4*16)) + MOVOU(B1, Mem{Base: oup}.Offset(5*16)) + MOVOU(C1, Mem{Base: oup}.Offset(6*16)) + MOVOU(D1, Mem{Base: oup}.Offset(7*16)) + MOVOU(Mem{Base: inp}.Offset(8*16), A0) + MOVOU(Mem{Base: inp}.Offset(9*16), B0) + MOVOU(Mem{Base: inp}.Offset(10*16), C0) + MOVOU(Mem{Base: inp}.Offset(11*16), D0) + PXOR(A0, A2) + PXOR(B0, B2) + PXOR(C0, C2) + PXOR(D0, D2) + MOVOU(A2, Mem{Base: oup}.Offset(8*16)) + MOVOU(B2, Mem{Base: oup}.Offset(9*16)) + MOVOU(C2, Mem{Base: oup}.Offset(10*16)) + MOVOU(D2, Mem{Base: oup}.Offset(11*16)) + ADDQ(Imm(192), inp) + MOVQ(U32(192), itr1) + SUBQ(Imm(192), inl) + MOVO(A3, A1) + MOVO(B3, B1) + MOVO(C3, C1) + MOVO(D3, D1) + CMPQ(inl, Imm(64)) + JBE(LabelRef("sealSSE128SealHash")) + MOVOU(Mem{Base: inp}.Offset(0*16), A0) + MOVOU(Mem{Base: inp}.Offset(1*16), B0) + MOVOU(Mem{Base: inp}.Offset(2*16), C0) + MOVOU(Mem{Base: inp}.Offset(3*16), D0) + PXOR(A0, A3) + PXOR(B0, B3) + PXOR(C0, C3) + PXOR(D0, D3) + MOVOU(A3, Mem{Base: oup}.Offset(12*16)) + MOVOU(B3, Mem{Base: oup}.Offset(13*16)) + MOVOU(C3, Mem{Base: oup}.Offset(14*16)) + MOVOU(D3, Mem{Base: oup}.Offset(15*16)) + LEAQ(Mem{Base: inp}.Offset(64), inp) + SUBQ(Imm(64), inl) + MOVQ(U32(6), itr1) + MOVQ(U32(4), itr2) + CMPQ(inl, Imm(192)) + JG(LabelRef("sealSSEMainLoop")) + + MOVQ(inl, itr1) + TESTQ(inl, inl) + JE(LabelRef("sealSSE128SealHash")) + MOVQ(U32(6), itr1) + CMPQ(inl, Imm(64)) + JBE(LabelRef("sealSSETail64")) + CMPQ(inl, Imm(128)) + JBE(LabelRef("sealSSETail128")) + JMP(LabelRef("sealSSETail192")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 64 bytes of plaintext + +// Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes +func sealSSETail64() { + Label("sealSSETail64") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A1) + MOVO(state1Store, B1) + MOVO(state2Store, C1) + MOVO(ctr3Store, D1) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D1) + MOVO(D1, ctr0Store) +} + +// Perform ChaCha rounds, while hashing the previously encrypted ciphertext +func sealSSETail64LoopA() { + Label("sealSSETail64LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +func sealSSETail64LoopB() { + Label("sealSSETail64LoopB") + chachaQR(A1, B1, C1, D1, T1) + shiftB1Left() + shiftC1Left() + shiftD1Left() + chachaQR(A1, B1, C1, D1, T1) + shiftB1Right() + shiftC1Right() + shiftD1Right() + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) + + DECQ(itr1) + JG(LabelRef("sealSSETail64LoopA")) + + DECQ(itr2) + JGE(LabelRef("sealSSETail64LoopB")) + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A1) + PADDL(state1Store, B1) + PADDL(state2Store, C1) + PADDL(ctr0Store, D1) + + JMP(LabelRef("sealSSE128Seal")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of plaintext + +// Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes +func sealSSETail128() { + Label("sealSSETail128") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A0) + MOVO(state1Store, B0) + MOVO(state2Store, C0) + MOVO(ctr3Store, D0) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D0) + MOVO(D0, ctr0Store) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + PADDL(sseIncMask, D1) + MOVO(D1, ctr1Store) +} + +// Perform ChaCha rounds, while hashing the previously encrypted ciphertext +func sealSSETail128LoopA() { + Label("sealSSETail128LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +func sealSSETail128LoopB() { + Label("sealSSETail128LoopB") + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + shiftB0Left() + shiftC0Left() + shiftD0Left() + shiftB1Left() + shiftC1Left() + shiftD1Left() + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + shiftB0Right() + shiftC0Right() + shiftD0Right() + shiftB1Right() + shiftC1Right() + shiftD1Right() + + DECQ(itr1) + JG(LabelRef("sealSSETail128LoopA")) + + DECQ(itr2) + JGE(LabelRef("sealSSETail128LoopB")) + + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(chacha20Constants, A1) + PADDL(state1Store, B0) + PADDL(state1Store, B1) + PADDL(state2Store, C0) + PADDL(state2Store, C1) + PADDL(ctr0Store, D0) + PADDL(ctr1Store, D1) + + MOVOU(Mem{Base: inp}.Offset(0*16), T0) + MOVOU(Mem{Base: inp}.Offset(1*16), T1) + MOVOU(Mem{Base: inp}.Offset(2*16), T2) + MOVOU(Mem{Base: inp}.Offset(3*16), T3) + PXOR(T0, A0) + PXOR(T1, B0) + PXOR(T2, C0) + PXOR(T3, D0) + MOVOU(A0, Mem{Base: oup}.Offset(0*16)) + MOVOU(B0, Mem{Base: oup}.Offset(1*16)) + MOVOU(C0, Mem{Base: oup}.Offset(2*16)) + MOVOU(D0, Mem{Base: oup}.Offset(3*16)) + + MOVQ(U32(64), itr1) + LEAQ(Mem{Base: inp}.Offset(64), inp) + SUBQ(Imm(64), inl) + + JMP(LabelRef("sealSSE128SealHash")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 192 bytes of plaintext + +// Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes +func sealSSETail192() { + Label("sealSSETail192") + chacha20Constants := chacha20Constants_DATA() + MOVO(chacha20Constants, A0) + MOVO(state1Store, B0) + MOVO(state2Store, C0) + MOVO(ctr3Store, D0) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D0) + MOVO(D0, ctr0Store) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + PADDL(sseIncMask, D1) + MOVO(D1, ctr1Store) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(D2, ctr2Store) +} + +// Perform ChaCha rounds, while hashing the previously encrypted ciphertext +func sealSSETail192LoopA() { + Label("sealSSETail192LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +func sealSSETail192LoopB() { + Label("sealSSETail192LoopB") + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Left() + shiftC0Left() + shiftD0Left() + shiftB1Left() + shiftC1Left() + shiftD1Left() + shiftB2Left() + shiftC2Left() + shiftD2Left() + + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) + + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Right() + shiftC0Right() + shiftD0Right() + shiftB1Right() + shiftC1Right() + shiftD1Right() + shiftB2Right() + shiftC2Right() + shiftD2Right() + + DECQ(itr1) + JG(LabelRef("sealSSETail192LoopA")) + + DECQ(itr2) + JGE(LabelRef("sealSSETail192LoopB")) + + chacha20Constants := chacha20Constants_DATA() + PADDL(chacha20Constants, A0) + PADDL(chacha20Constants, A1) + PADDL(chacha20Constants, A2) + PADDL(state1Store, B0) + PADDL(state1Store, B1) + PADDL(state1Store, B2) + PADDL(state2Store, C0) + PADDL(state2Store, C1) + PADDL(state2Store, C2) + PADDL(ctr0Store, D0) + PADDL(ctr1Store, D1) + PADDL(ctr2Store, D2) + + MOVOU(Mem{Base: inp}.Offset(0*16), T0) + MOVOU(Mem{Base: inp}.Offset(1*16), T1) + MOVOU(Mem{Base: inp}.Offset(2*16), T2) + MOVOU(Mem{Base: inp}.Offset(3*16), T3) + PXOR(T0, A0) + PXOR(T1, B0) + PXOR(T2, C0) + PXOR(T3, D0) + MOVOU(A0, Mem{Base: oup}.Offset(0*16)) + MOVOU(B0, Mem{Base: oup}.Offset(1*16)) + MOVOU(C0, Mem{Base: oup}.Offset(2*16)) + MOVOU(D0, Mem{Base: oup}.Offset(3*16)) + MOVOU(Mem{Base: inp}.Offset(4*16), T0) + MOVOU(Mem{Base: inp}.Offset(5*16), T1) + MOVOU(Mem{Base: inp}.Offset(6*16), T2) + MOVOU(Mem{Base: inp}.Offset(7*16), T3) + PXOR(T0, A1) + PXOR(T1, B1) + PXOR(T2, C1) + PXOR(T3, D1) + MOVOU(A1, Mem{Base: oup}.Offset(4*16)) + MOVOU(B1, Mem{Base: oup}.Offset(5*16)) + MOVOU(C1, Mem{Base: oup}.Offset(6*16)) + MOVOU(D1, Mem{Base: oup}.Offset(7*16)) + + MOVO(A2, A1) + MOVO(B2, B1) + MOVO(C2, C1) + MOVO(D2, D1) + MOVQ(U32(128), itr1) + LEAQ(Mem{Base: inp}.Offset(128), inp) + SUBQ(Imm(128), inl) + + JMP(LabelRef("sealSSE128SealHash")) +} + +// ---------------------------------------------------------------------------- +// Special seal optimization for buffers smaller than 129 bytes + +// For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks +func sealSSE128() { + Label("sealSSE128") + chacha20Constants := chacha20Constants_DATA() + MOVOU(chacha20Constants, A0) + MOVOU(Mem{Base: keyp}.Offset(1*16), B0) + MOVOU(Mem{Base: keyp}.Offset(2*16), C0) + MOVOU(Mem{Base: keyp}.Offset(3*16), D0) + MOVO(A0, A1) + MOVO(B0, B1) + MOVO(C0, C1) + MOVO(D0, D1) + sseIncMask := sseIncMask_DATA() + PADDL(sseIncMask, D1) + MOVO(A1, A2) + MOVO(B1, B2) + MOVO(C1, C2) + MOVO(D1, D2) + PADDL(sseIncMask, D2) + MOVO(B0, T1) + MOVO(C0, T2) + MOVO(D1, T3) + MOVQ(U32(10), itr2) + + Label("sealSSE128InnerCipherLoop") + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Left() + shiftB1Left() + shiftB2Left() + shiftC0Left() + shiftC1Left() + shiftC2Left() + shiftD0Left() + shiftD1Left() + shiftD2Left() + chachaQR(A0, B0, C0, D0, T0) + chachaQR(A1, B1, C1, D1, T0) + chachaQR(A2, B2, C2, D2, T0) + shiftB0Right() + shiftB1Right() + shiftB2Right() + shiftC0Right() + shiftC1Right() + shiftC2Right() + shiftD0Right() + shiftD1Right() + shiftD2Right() + DECQ(itr2) + JNE(LabelRef("sealSSE128InnerCipherLoop")) + + Comment("A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded") + PADDL(chacha20Constants, A0) + PADDL(chacha20Constants, A1) + PADDL(chacha20Constants, A2) + PADDL(T1, B0) + PADDL(T1, B1) + PADDL(T1, B2) + PADDL(T2, C1) + PADDL(T2, C2) + PADDL(T3, D1) + PADDL(sseIncMask, T3) + PADDL(T3, D2) + polyClampMask := polyClampMask_DATA() + PAND(polyClampMask, A0) + MOVOU(A0, rStore) + MOVOU(B0, sStore) + + Comment("Hash") + MOVQ(NewParamAddr("ad_len", 80), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) + XORQ(itr1, itr1) +} + +// itr1 holds the number of bytes encrypted but not yet hashed +func sealSSE128SealHash() { + Label("sealSSE128SealHash") + CMPQ(itr1, Imm(16)) + JB(LabelRef("sealSSE128Seal")) + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + + SUBQ(Imm(16), itr1) + ADDQ(Imm(16), oup) + + JMP(LabelRef("sealSSE128SealHash")) +} + +func sealSSE128Seal() { + Label("sealSSE128Seal") + CMPQ(inl, Imm(16)) + JB(LabelRef("sealSSETail")) + SUBQ(Imm(16), inl) + + Comment("Load for decryption") + MOVOU(Mem{Base: inp}, T0) + PXOR(T0, A1) + MOVOU(A1, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*16), inp) + LEAQ(Mem{Base: oup}.Offset(1*16), oup) + + Comment("Extract for hashing") + MOVQ(A1, t0) + PSRLDQ(Imm(8), A1) + MOVQ(A1, t1) + ADDQ(t0, acc0) + ADCQ(t1, acc1) + ADCQ(Imm(1), acc2) + polyMul() + + Comment("Shift the stream \"left\"") + MOVO(B1, A1) + MOVO(C1, B1) + MOVO(D1, C1) + MOVO(A2, D1) + MOVO(B2, A2) + MOVO(C2, B2) + MOVO(D2, C2) + JMP(LabelRef("sealSSE128Seal")) +} + +func sealSSETail() { + Label("sealSSETail") + TESTQ(inl, inl) + JE(LabelRef("sealSSEFinalize")) + + Comment("We can only load the PT one byte at a time to avoid read after end of buffer") + MOVQ(inl, itr2) + SHLQ(Imm(4), itr2) + andMask := andMask_DATA() + LEAQ(andMask, t0) + MOVQ(inl, itr1) + LEAQ(Mem{Base: inp, Index: inl, Scale: 1}.Offset(-1), inp) + XORQ(t2, t2) + XORQ(t3, t3) + XORQ(RAX, RAX) +} + +func sealSSETailLoadLoop() { + Label("sealSSETailLoadLoop") + SHLQ(Imm(8), t2, t3) + SHLQ(Imm(8), t2) + // Hack to get Avo to emit: + // MOVB (inp), AX + Instruction(&ir.Instruction{Opcode: "MOVB", Operands: []Op{Mem{Base: inp}, AX}}) + XORQ(RAX, t2) + LEAQ(Mem{Base: inp}.Offset(-1), inp) + DECQ(itr1) + JNE(LabelRef("sealSSETailLoadLoop")) + MOVQ(t2, tmpStore.Offset(0)) + MOVQ(t3, tmpStore.Offset(8)) + PXOR(tmpStore.Offset(0), A1) + MOVOU(A1, Mem{Base: oup}) + MOVOU(Mem{Base: t0, Index: itr2, Scale: 1}.Offset(-16), T0) + PAND(T0, A1) + MOVQ(A1, t0) + PSRLDQ(Imm(8), A1) + MOVQ(A1, t1) + ADDQ(t0, acc0) + ADCQ(t1, acc1) + ADCQ(Imm(1), acc2) + polyMul() + + ADDQ(inl, oup) +} + +func sealSSEFinalize() { + Label("sealSSEFinalize") + Comment("Hash in the buffer lengths") + ADDQ(NewParamAddr("ad_len", 80), acc0) + ADCQ(NewParamAddr("src_len", 56), acc1) + ADCQ(Imm(1), acc2) + polyMul() + + Comment("Final reduce") + MOVQ(acc0, t0) + MOVQ(acc1, t1) + MOVQ(acc2, t2) + SUBQ(I8(-5), acc0) + SBBQ(I8(-1), acc1) + SBBQ(Imm(3), acc2) + CMOVQCS(t0, acc0) + CMOVQCS(t1, acc1) + CMOVQCS(t2, acc2) + + Comment("Add in the \"s\" part of the key") + ADDQ(sStore.Offset(0), acc0) + ADCQ(sStore.Offset(8), acc1) + + Comment("Finally store the tag at the end of the message") + MOVQ(acc0, Mem{Base: oup}.Offset(0*8)) + MOVQ(acc1, Mem{Base: oup}.Offset(1*8)) + RET() +} + +// ---------------------------------------------------------------------------- +// ------------------------- AVX2 Code ---------------------------------------- + +func chacha20Poly1305Seal_AVX2() { + Label("chacha20Poly1305Seal_AVX2") + VZEROUPPER() + chacha20Constants := chacha20Constants_DATA() + VMOVDQU(chacha20Constants, AA0) + VBROADCASTI128_16_R8_YMM14() + VBROADCASTI128_32_R8_YMM12() + VBROADCASTI128_48_R8_YMM4() + avx2InitMask := avx2InitMask_DATA() + VPADDD(avx2InitMask, DD0, DD0) + + Comment("Special optimizations, for very short buffers") + CMPQ(inl, U32(192)) + JBE(LabelRef("seal192AVX2")) + CMPQ(inl, U32(320)) + JBE(LabelRef("seal320AVX2")) + + Comment("For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream") + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(AA0, AA3) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(BB0, BB3) + VMOVDQA(BB0, state1StoreAVX2) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(CC0, CC3) + VMOVDQA(CC0, state2StoreAVX2) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(DD0, ctr0StoreAVX2) + VPADDD(avx2IncMask, DD1, DD2) + VMOVDQA(DD1, ctr1StoreAVX2) + VPADDD(avx2IncMask, DD2, DD3) + VMOVDQA(DD2, ctr2StoreAVX2) + VMOVDQA(DD3, ctr3StoreAVX2) + MOVQ(U32(10), itr2) +} + +func sealAVX2IntroLoop() { + Label("sealAVX2IntroLoop") + VMOVDQA(CC3, tmpStoreAVX2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3) + chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3) + chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA(tmpStoreAVX2, CC3) + VMOVDQA(CC1, tmpStoreAVX2) + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA(tmpStoreAVX2, CC1) + + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(12), DD2, DD2, DD2) + VPALIGNR(Imm(4), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(12), DD3, DD3, DD3) + + VMOVDQA(CC3, tmpStoreAVX2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3) + chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3) + chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA(tmpStoreAVX2, CC3) + VMOVDQA(CC1, tmpStoreAVX2) + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA(tmpStoreAVX2, CC1) + + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(4), DD2, DD2, DD2) + VPALIGNR(Imm(12), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(4), DD3, DD3, DD3) + DECQ(itr2) + JNE(LabelRef("sealAVX2IntroLoop")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(chacha20Constants, AA3, AA3) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state1StoreAVX2, BB3, BB3) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(state2StoreAVX2, CC3, CC3) + VPADDD(ctr0StoreAVX2, DD0, DD0) + VPADDD(ctr1StoreAVX2, DD1, DD1) + VPADDD(ctr2StoreAVX2, DD2, DD2) + VPADDD(ctr3StoreAVX2, DD3, DD3) + + VPERM2I128(Imm(0x13), CC0, DD0, CC0) + VPERM2I128(Imm(0x02), AA0, BB0, DD0) + VPERM2I128(Imm(0x13), AA0, BB0, AA0) + + Comment("Clamp and store poly key") + polyClampMask := polyClampMask_DATA() + VPAND(polyClampMask, DD0, DD0) + VMOVDQA(DD0, rsStoreAVX2) + + Comment("Hash AD") + MOVQ(NewParamAddr("ad_len", 80), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) + + Comment("Can store at least 320 bytes") + VPXOR(Mem{Base: inp}.Offset(0*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(1*32), CC0, CC0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(1*32)) + + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + VPXOR(Mem{Base: inp}.Offset(2*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(3*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(4*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(5*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(3*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(5*32)) + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + VPXOR(Mem{Base: inp}.Offset(6*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(7*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(8*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(9*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(7*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(8*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(9*32)) + + MOVQ(U32(320), itr1) + SUBQ(U32(320), inl) + LEAQ(Mem{Base: inp}.Offset(320), inp) + + VPERM2I128(Imm(0x02), AA3, BB3, AA0) + VPERM2I128(Imm(0x02), CC3, DD3, BB0) + VPERM2I128(Imm(0x13), AA3, BB3, CC0) + VPERM2I128(Imm(0x13), CC3, DD3, DD0) + CMPQ(inl, Imm(128)) + JBE(LabelRef("sealAVX2SealHash")) + + VPXOR(Mem{Base: inp}.Offset(0*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(1*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(2*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(3*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(10*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(11*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(12*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(13*32)) + SUBQ(Imm(128), inl) + LEAQ(Mem{Base: inp}.Offset(128), inp) + + MOVQ(U32(8), itr1) + MOVQ(U32(2), itr2) + + CMPQ(inl, Imm(128)) + JBE(LabelRef("sealAVX2Tail128")) + CMPQ(inl, U32(256)) + JBE(LabelRef("sealAVX2Tail256")) + CMPQ(inl, U32(384)) + JBE(LabelRef("sealAVX2Tail384")) + CMPQ(inl, U32(512)) + JBE(LabelRef("sealAVX2Tail512")) + + Comment("We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop") + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(AA0, AA3) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(BB0, BB3) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(CC0, CC3) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VPADDD(avx2IncMask, DD2, DD3) + VMOVDQA(DD0, ctr0StoreAVX2) + VMOVDQA(DD1, ctr1StoreAVX2) + VMOVDQA(DD2, ctr2StoreAVX2) + VMOVDQA(DD3, ctr3StoreAVX2) + + VMOVDQA(CC3, tmpStoreAVX2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3) + chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3) + chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA(tmpStoreAVX2, CC3) + VMOVDQA(CC1, tmpStoreAVX2) + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA(tmpStoreAVX2, CC1) + + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(12), DD2, DD2, DD2) + VPALIGNR(Imm(4), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(12), DD3, DD3, DD3) + + VMOVDQA(CC3, tmpStoreAVX2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3) + chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3) + chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA(tmpStoreAVX2, CC3) + VMOVDQA(CC1, tmpStoreAVX2) + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA(tmpStoreAVX2, CC1) + + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(4), DD2, DD2, DD2) + VPALIGNR(Imm(12), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(4), DD3, DD3, DD3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol16 := rol16_DATA() + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + + SUBQ(Imm(16), oup) // Adjust the pointer + MOVQ(U32(9), itr1) + JMP(LabelRef("sealAVX2InternalLoopStart")) +} + +// Load state, increment counter blocks, store the incremented counters +func sealAVX2MainLoop() { + Label("sealAVX2MainLoop") + chacha20Constants := chacha20Constants_DATA() + VMOVDQU(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(AA0, AA3) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(BB0, BB3) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(CC0, CC3) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VPADDD(avx2IncMask, DD2, DD3) + VMOVDQA(DD0, ctr0StoreAVX2) + VMOVDQA(DD1, ctr1StoreAVX2) + VMOVDQA(DD2, ctr2StoreAVX2) + VMOVDQA(DD3, ctr3StoreAVX2) + MOVQ(U32(10), itr1) +} + +func sealAVX2InternalLoop() { + Label("sealAVX2InternalLoop") + polyAdd(Mem{Base: oup}.Offset(0 * 8)) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + polyMulStage1_AVX2() + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol16 := rol16_DATA() + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + polyMulStage2_AVX2() + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + polyMulStage3_AVX2() + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulReduceStage() +} + +func sealAVX2InternalLoopStart() { + Label("sealAVX2InternalLoopStart") + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol8 := rol8_DATA() + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + polyAdd(Mem{Base: oup}.Offset(2 * 8)) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + polyMulStage1_AVX2() + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulStage2_AVX2() + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(4), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + VPALIGNR(Imm(12), DD3, DD3, DD3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + polyMulStage3_AVX2() + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol16 := rol16_DATA() + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + polyMulReduceStage() + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + polyAdd(Mem{Base: oup}.Offset(4 * 8)) + LEAQ(Mem{Base: oup}.Offset(6*8), oup) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulStage1_AVX2() + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + polyMulStage2_AVX2() + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + polyMulStage3_AVX2() + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyMulReduceStage() + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(12), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + VPALIGNR(Imm(4), DD3, DD3, DD3) + DECQ(itr1) + JNE(LabelRef("sealAVX2InternalLoop")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(chacha20Constants, AA3, AA3) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state1StoreAVX2, BB3, BB3) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(state2StoreAVX2, CC3, CC3) + VPADDD(ctr0StoreAVX2, DD0, DD0) + VPADDD(ctr1StoreAVX2, DD1, DD1) + VPADDD(ctr2StoreAVX2, DD2, DD2) + VPADDD(ctr3StoreAVX2, DD3, DD3) + VMOVDQA(CC3, tmpStoreAVX2) + + Comment("We only hashed 480 of the 512 bytes available - hash the remaining 32 here") + polyAdd(Mem{Base: oup}.Offset(0 * 8)) + polyMulAVX2() + LEAQ(Mem{Base: oup}.Offset(4*8), oup) + VPERM2I128(Imm(0x02), AA0, BB0, CC3) + VPERM2I128(Imm(0x13), AA0, BB0, BB0) + VPERM2I128(Imm(0x02), CC0, DD0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, CC0) + VPXOR(Mem{Base: inp}.Offset(0*32), CC3, CC3) + VPXOR(Mem{Base: inp}.Offset(1*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(2*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(3*32), CC0, CC0) + VMOVDQU(CC3, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(AA0, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(3*32)) + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + VPXOR(Mem{Base: inp}.Offset(4*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(5*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(6*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(7*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(5*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(7*32)) + + Comment("and here") + polyAdd(Mem{Base: oup}.Offset(-2 * 8)) + polyMulAVX2() + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + VPXOR(Mem{Base: inp}.Offset(8*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(9*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(10*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(11*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(8*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(9*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(10*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(11*32)) + VPERM2I128(Imm(0x02), AA3, BB3, AA0) + VPERM2I128(Imm(0x02), tmpStoreAVX2, DD3, BB0) + VPERM2I128(Imm(0x13), AA3, BB3, CC0) + VPERM2I128(Imm(0x13), tmpStoreAVX2, DD3, DD0) + VPXOR(Mem{Base: inp}.Offset(12*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(13*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(14*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(15*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(12*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(13*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(14*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(15*32)) + LEAQ(Mem{Base: inp}.Offset(32*16), inp) + SUBQ(U32(32*16), inl) + CMPQ(inl, U32(512)) + JG(LabelRef("sealAVX2MainLoop")) + + Comment("Tail can only hash 480 bytes") + polyAdd(Mem{Base: oup}.Offset(0 * 8)) + polyMulAVX2() + polyAdd(Mem{Base: oup}.Offset(2 * 8)) + polyMulAVX2() + LEAQ(Mem{Base: oup}.Offset(32), oup) + + MOVQ(U32(10), itr1) + MOVQ(U32(0), itr2) + CMPQ(inl, Imm(128)) + JBE(LabelRef("sealAVX2Tail128")) + CMPQ(inl, U32(256)) + JBE(LabelRef("sealAVX2Tail256")) + CMPQ(inl, U32(384)) + JBE(LabelRef("sealAVX2Tail384")) + JMP(LabelRef("sealAVX2Tail512")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 193 bytes + +// For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks +func seal192AVX2() { + Label("seal192AVX2") + VMOVDQA(AA0, AA1) + VMOVDQA(BB0, BB1) + VMOVDQA(CC0, CC1) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(AA0, AA2) + VMOVDQA(BB0, BB2) + VMOVDQA(CC0, CC2) + VMOVDQA(DD0, DD2) + VMOVDQA(DD1, TT3) + MOVQ(U32(10), itr2) +} + +func sealAVX2192InnerCipherLoop() { + Label("sealAVX2192InnerCipherLoop") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + DECQ(itr2) + JNE(LabelRef("sealAVX2192InnerCipherLoop")) + VPADDD(AA2, AA0, AA0) + VPADDD(AA2, AA1, AA1) + VPADDD(BB2, BB0, BB0) + VPADDD(BB2, BB1, BB1) + VPADDD(CC2, CC0, CC0) + VPADDD(CC2, CC1, CC1) + VPADDD(DD2, DD0, DD0) + VPADDD(TT3, DD1, DD1) + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + + Comment("Clamp and store poly key") + polyClampMask := polyClampMask_DATA() + VPAND(polyClampMask, TT0, TT0) + VMOVDQA(TT0, rsStoreAVX2) + + Comment("Stream for up to 192 bytes") + VPERM2I128(Imm(0x13), AA0, BB0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, BB0) + VPERM2I128(Imm(0x02), AA1, BB1, CC0) + VPERM2I128(Imm(0x02), CC1, DD1, DD0) + VPERM2I128(Imm(0x13), AA1, BB1, AA1) + VPERM2I128(Imm(0x13), CC1, DD1, BB1) +} + +func sealAVX2ShortSeal() { + Label("sealAVX2ShortSeal") + Comment("Hash aad") + MOVQ(NewParamAddr("ad_len", 80), itr2) + CALL(LabelRef("polyHashADInternal<>(SB)")) + XORQ(itr1, itr1) +} + +func sealAVX2SealHash() { + Label("sealAVX2SealHash") + Comment("itr1 holds the number of bytes encrypted but not yet hashed") + CMPQ(itr1, Imm(16)) + JB(LabelRef("sealAVX2ShortSealLoop")) + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + SUBQ(Imm(16), itr1) + ADDQ(Imm(16), oup) + JMP(LabelRef("sealAVX2SealHash")) +} + +func sealAVX2ShortSealLoop() { + Label("sealAVX2ShortSealLoop") + CMPQ(inl, Imm(32)) + JB(LabelRef("sealAVX2ShortTail32")) + SUBQ(Imm(32), inl) + + Comment("Load for encryption") + VPXOR(Mem{Base: inp}, AA0, AA0) + VMOVDQU(AA0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*32), inp) + + Comment("Now can hash") + polyAdd(Mem{Base: oup}.Offset(0 * 8)) + polyMulAVX2() + polyAdd(Mem{Base: oup}.Offset(2 * 8)) + polyMulAVX2() + LEAQ(Mem{Base: oup}.Offset(1*32), oup) + + Comment("Shift stream left") + VMOVDQA(BB0, AA0) + VMOVDQA(CC0, BB0) + VMOVDQA(DD0, CC0) + VMOVDQA(AA1, DD0) + VMOVDQA(BB1, AA1) + VMOVDQA(CC1, BB1) + VMOVDQA(DD1, CC1) + VMOVDQA(AA2, DD1) + VMOVDQA(BB2, AA2) + JMP(LabelRef("sealAVX2ShortSealLoop")) +} + +func sealAVX2ShortTail32() { + Label("sealAVX2ShortTail32") + CMPQ(inl, Imm(16)) + VMOVDQA(A0, A1) + JB(LabelRef("sealAVX2ShortDone")) + + SUBQ(Imm(16), inl) + + Comment("Load for encryption") + VPXOR(Mem{Base: inp}, A0, T0) + VMOVDQU(T0, Mem{Base: oup}) + LEAQ(Mem{Base: inp}.Offset(1*16), inp) + + Comment("Hash") + polyAdd(Mem{Base: oup}.Offset(0 * 8)) + polyMulAVX2() + LEAQ(Mem{Base: oup}.Offset(1*16), oup) + VPERM2I128(Imm(0x11), AA0, AA0, AA0) + VMOVDQA(A0, A1) +} + +func sealAVX2ShortDone() { + Label("sealAVX2ShortDone") + VZEROUPPER() + JMP(LabelRef("sealSSETail")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 321 bytes + +// For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks +func seal320AVX2() { + Label("seal320AVX2") + VMOVDQA(AA0, AA1) + VMOVDQA(BB0, BB1) + VMOVDQA(CC0, CC1) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(AA0, AA2) + VMOVDQA(BB0, BB2) + VMOVDQA(CC0, CC2) + VPADDD(avx2IncMask, DD1, DD2) + VMOVDQA(BB0, TT1) + VMOVDQA(CC0, TT2) + VMOVDQA(DD0, TT3) + MOVQ(U32(10), itr2) +} + +func sealAVX2320InnerCipherLoop() { + Label("sealAVX2320InnerCipherLoop") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + DECQ(itr2) + JNE(LabelRef("sealAVX2320InnerCipherLoop")) + + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, TT0) + VPADDD(TT0, AA0, AA0) + VPADDD(TT0, AA1, AA1) + VPADDD(TT0, AA2, AA2) + VPADDD(TT1, BB0, BB0) + VPADDD(TT1, BB1, BB1) + VPADDD(TT1, BB2, BB2) + VPADDD(TT2, CC0, CC0) + VPADDD(TT2, CC1, CC1) + VPADDD(TT2, CC2, CC2) + avx2IncMask := avx2IncMask_DATA() + VMOVDQA(avx2IncMask, TT0) + VPADDD(TT3, DD0, DD0) + VPADDD(TT0, TT3, TT3) + VPADDD(TT3, DD1, DD1) + VPADDD(TT0, TT3, TT3) + VPADDD(TT3, DD2, DD2) + + Comment("Clamp and store poly key") + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + polyClampMask := polyClampMask_DATA() + VPAND(polyClampMask, TT0, TT0) + VMOVDQA(TT0, rsStoreAVX2) + + Comment("Stream for up to 320 bytes") + VPERM2I128(Imm(0x13), AA0, BB0, AA0) + VPERM2I128(Imm(0x13), CC0, DD0, BB0) + VPERM2I128(Imm(0x02), AA1, BB1, CC0) + VPERM2I128(Imm(0x02), CC1, DD1, DD0) + VPERM2I128(Imm(0x13), AA1, BB1, AA1) + VPERM2I128(Imm(0x13), CC1, DD1, BB1) + VPERM2I128(Imm(0x02), AA2, BB2, CC1) + VPERM2I128(Imm(0x02), CC2, DD2, DD1) + VPERM2I128(Imm(0x13), AA2, BB2, AA2) + VPERM2I128(Imm(0x13), CC2, DD2, BB2) + JMP(LabelRef("sealAVX2ShortSeal")) +} + +// Need to decrypt up to 128 bytes - prepare two blocks: +// - If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed. +// - If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed. +func sealAVX2Tail128() { + Label("sealAVX2Tail128") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VMOVDQA(DD0, DD1) +} + +func sealAVX2Tail128LoopA() { + Label("sealAVX2Tail128LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +func sealAVX2Tail128LoopB() { + Label("sealAVX2Tail128LoopB") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(12), DD0, DD0, DD0) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + polyAdd(Mem{Base: oup}.Offset(16)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(32), oup) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(4), DD0, DD0, DD0) + DECQ(itr1) + JG(LabelRef("sealAVX2Tail128LoopA")) + DECQ(itr2) + JGE(LabelRef("sealAVX2Tail128LoopB")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA1) + VPADDD(state1StoreAVX2, BB0, BB1) + VPADDD(state2StoreAVX2, CC0, CC1) + VPADDD(DD1, DD0, DD1) + + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + JMP(LabelRef("sealAVX2ShortSealLoop")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 256 bytes of ciphertext + +// Need to decrypt up to 256 bytes - prepare two blocks +// - If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed +// - If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed +func sealAVX2Tail256() { + Label("sealAVX2Tail256") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(chacha20Constants, AA1) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(state1StoreAVX2, BB1) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(state2StoreAVX2, CC1) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VMOVDQA(DD0, TT1) + VMOVDQA(DD1, TT2) +} + +func sealAVX2Tail256LoopA() { + Label("sealAVX2Tail256LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +// LIne 2493 +func sealAVX2Tail256LoopB() { + Label("sealAVX2Tail256LoopB") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + polyAdd(Mem{Base: oup}.Offset(16)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(32), oup) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + DECQ(itr1) + JG(LabelRef("sealAVX2Tail256LoopA")) + DECQ(itr2) + JGE(LabelRef("sealAVX2Tail256LoopB")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(TT1, DD0, DD0) + VPADDD(TT2, DD1, DD1) + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + VPERM2I128(Imm(0x02), CC0, DD0, TT1) + VPERM2I128(Imm(0x13), AA0, BB0, TT2) + VPERM2I128(Imm(0x13), CC0, DD0, TT3) + VPXOR(Mem{Base: inp}.Offset(0*32), TT0, TT0) + VPXOR(Mem{Base: inp}.Offset(1*32), TT1, TT1) + VPXOR(Mem{Base: inp}.Offset(2*32), TT2, TT2) + VPXOR(Mem{Base: inp}.Offset(3*32), TT3, TT3) + VMOVDQU(TT0, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(TT1, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(TT2, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(TT3, Mem{Base: oup}.Offset(3*32)) + MOVQ(U32(128), itr1) + LEAQ(Mem{Base: inp}.Offset(128), inp) + SUBQ(Imm(128), inl) + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + + JMP(LabelRef("sealAVX2SealHash")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 384 bytes of ciphertext + +// Need to decrypt up to 384 bytes - prepare two blocks +// - If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed +// - If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed +func sealAVX2Tail384() { + Label("sealAVX2Tail384") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VMOVDQA(DD0, TT1) + VMOVDQA(DD1, TT2) + VMOVDQA(DD2, TT3) +} + +func sealAVX2Tail384LoopA() { + Label("sealAVX2Tail384LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +func sealAVX2Tail384LoopB() { + Label("sealAVX2Tail384LoopB") + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + polyAdd(Mem{Base: oup}.Offset(16)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(32), oup) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + DECQ(itr1) + JG(LabelRef("sealAVX2Tail384LoopA")) + DECQ(itr2) + JGE(LabelRef("sealAVX2Tail384LoopB")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(TT1, DD0, DD0) + VPADDD(TT2, DD1, DD1) + VPADDD(TT3, DD2, DD2) + VPERM2I128(Imm(0x02), AA0, BB0, TT0) + VPERM2I128(Imm(0x02), CC0, DD0, TT1) + VPERM2I128(Imm(0x13), AA0, BB0, TT2) + VPERM2I128(Imm(0x13), CC0, DD0, TT3) + VPXOR(Mem{Base: inp}.Offset(0*32), TT0, TT0) + VPXOR(Mem{Base: inp}.Offset(1*32), TT1, TT1) + VPXOR(Mem{Base: inp}.Offset(2*32), TT2, TT2) + VPXOR(Mem{Base: inp}.Offset(3*32), TT3, TT3) + VMOVDQU(TT0, Mem{Base: oup}.Offset(0*32)) + VMOVDQU(TT1, Mem{Base: oup}.Offset(1*32)) + VMOVDQU(TT2, Mem{Base: oup}.Offset(2*32)) + VMOVDQU(TT3, Mem{Base: oup}.Offset(3*32)) + VPERM2I128(Imm(0x02), AA1, BB1, TT0) + VPERM2I128(Imm(0x02), CC1, DD1, TT1) + VPERM2I128(Imm(0x13), AA1, BB1, TT2) + VPERM2I128(Imm(0x13), CC1, DD1, TT3) + VPXOR(Mem{Base: inp}.Offset(4*32), TT0, TT0) + VPXOR(Mem{Base: inp}.Offset(5*32), TT1, TT1) + VPXOR(Mem{Base: inp}.Offset(6*32), TT2, TT2) + VPXOR(Mem{Base: inp}.Offset(7*32), TT3, TT3) + VMOVDQU(TT0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(TT1, Mem{Base: oup}.Offset(5*32)) + VMOVDQU(TT2, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(TT3, Mem{Base: oup}.Offset(7*32)) + MOVQ(U32(256), itr1) + LEAQ(Mem{Base: inp}.Offset(256), inp) + SUBQ(U32(256), inl) + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + + JMP(LabelRef("sealAVX2SealHash")) +} + +// ---------------------------------------------------------------------------- +// Special optimization for the last 512 bytes of ciphertext + +// Need to decrypt up to 512 bytes - prepare two blocks +// - If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed +// - If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed +func sealAVX2Tail512() { + Label("sealAVX2Tail512") + chacha20Constants := chacha20Constants_DATA() + VMOVDQA(chacha20Constants, AA0) + VMOVDQA(AA0, AA1) + VMOVDQA(AA0, AA2) + VMOVDQA(AA0, AA3) + VMOVDQA(state1StoreAVX2, BB0) + VMOVDQA(BB0, BB1) + VMOVDQA(BB0, BB2) + VMOVDQA(BB0, BB3) + VMOVDQA(state2StoreAVX2, CC0) + VMOVDQA(CC0, CC1) + VMOVDQA(CC0, CC2) + VMOVDQA(CC0, CC3) + VMOVDQA(ctr3StoreAVX2, DD0) + avx2IncMask := avx2IncMask_DATA() + VPADDD(avx2IncMask, DD0, DD0) + VPADDD(avx2IncMask, DD0, DD1) + VPADDD(avx2IncMask, DD1, DD2) + VPADDD(avx2IncMask, DD2, DD3) + VMOVDQA(DD0, ctr0StoreAVX2) + VMOVDQA(DD1, ctr1StoreAVX2) + VMOVDQA(DD2, ctr2StoreAVX2) + VMOVDQA(DD3, ctr3StoreAVX2) +} + +func sealAVX2Tail512LoopA() { + Label("sealAVX2Tail512LoopA") + polyAdd(Mem{Base: oup}.Offset(0)) + polyMul() + LEAQ(Mem{Base: oup}.Offset(16), oup) +} + +func sealAVX2Tail512LoopB() { + Label("sealAVX2Tail512LoopB") + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol16 := rol16_DATA() + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + polyAdd(Mem{Base: oup}.Offset(0 * 8)) + polyMulAVX2() + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + rol8 := rol8_DATA() + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + VPALIGNR(Imm(4), BB0, BB0, BB0) + VPALIGNR(Imm(4), BB1, BB1, BB1) + VPALIGNR(Imm(4), BB2, BB2, BB2) + VPALIGNR(Imm(4), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(12), DD0, DD0, DD0) + VPALIGNR(Imm(12), DD1, DD1, DD1) + VPALIGNR(Imm(12), DD2, DD2, DD2) + VPALIGNR(Imm(12), DD3, DD3, DD3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + VPSHUFB(rol16, DD0, DD0) + VPSHUFB(rol16, DD1, DD1) + VPSHUFB(rol16, DD2, DD2) + VPSHUFB(rol16, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + polyAdd(Mem{Base: oup}.Offset(2 * 8)) + polyMulAVX2() + LEAQ(Mem{Base: oup}.Offset(4*8), oup) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(12), BB0, CC3) + VPSRLD(Imm(20), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(12), BB1, CC3) + VPSRLD(Imm(20), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(12), BB2, CC3) + VPSRLD(Imm(20), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(12), BB3, CC3) + VPSRLD(Imm(20), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + VPADDD(BB0, AA0, AA0) + VPADDD(BB1, AA1, AA1) + VPADDD(BB2, AA2, AA2) + VPADDD(BB3, AA3, AA3) + VPXOR(AA0, DD0, DD0) + VPXOR(AA1, DD1, DD1) + VPXOR(AA2, DD2, DD2) + VPXOR(AA3, DD3, DD3) + VPSHUFB(rol8, DD0, DD0) + VPSHUFB(rol8, DD1, DD1) + VPSHUFB(rol8, DD2, DD2) + VPSHUFB(rol8, DD3, DD3) + VPADDD(DD0, CC0, CC0) + VPADDD(DD1, CC1, CC1) + VPADDD(DD2, CC2, CC2) + VPADDD(DD3, CC3, CC3) + VPXOR(CC0, BB0, BB0) + VPXOR(CC1, BB1, BB1) + VPXOR(CC2, BB2, BB2) + VPXOR(CC3, BB3, BB3) + VMOVDQA(CC3, tmpStoreAVX2) + VPSLLD(Imm(7), BB0, CC3) + VPSRLD(Imm(25), BB0, BB0) + VPXOR(CC3, BB0, BB0) + VPSLLD(Imm(7), BB1, CC3) + VPSRLD(Imm(25), BB1, BB1) + VPXOR(CC3, BB1, BB1) + VPSLLD(Imm(7), BB2, CC3) + VPSRLD(Imm(25), BB2, BB2) + VPXOR(CC3, BB2, BB2) + VPSLLD(Imm(7), BB3, CC3) + VPSRLD(Imm(25), BB3, BB3) + VPXOR(CC3, BB3, BB3) + VMOVDQA(tmpStoreAVX2, CC3) + VPALIGNR(Imm(12), BB0, BB0, BB0) + VPALIGNR(Imm(12), BB1, BB1, BB1) + VPALIGNR(Imm(12), BB2, BB2, BB2) + VPALIGNR(Imm(12), BB3, BB3, BB3) + VPALIGNR(Imm(8), CC0, CC0, CC0) + VPALIGNR(Imm(8), CC1, CC1, CC1) + VPALIGNR(Imm(8), CC2, CC2, CC2) + VPALIGNR(Imm(8), CC3, CC3, CC3) + VPALIGNR(Imm(4), DD0, DD0, DD0) + VPALIGNR(Imm(4), DD1, DD1, DD1) + VPALIGNR(Imm(4), DD2, DD2, DD2) + VPALIGNR(Imm(4), DD3, DD3, DD3) + + DECQ(itr1) + JG(LabelRef("sealAVX2Tail512LoopA")) + DECQ(itr2) + JGE(LabelRef("sealAVX2Tail512LoopB")) + + chacha20Constants := chacha20Constants_DATA() + VPADDD(chacha20Constants, AA0, AA0) + VPADDD(chacha20Constants, AA1, AA1) + VPADDD(chacha20Constants, AA2, AA2) + VPADDD(chacha20Constants, AA3, AA3) + VPADDD(state1StoreAVX2, BB0, BB0) + VPADDD(state1StoreAVX2, BB1, BB1) + VPADDD(state1StoreAVX2, BB2, BB2) + VPADDD(state1StoreAVX2, BB3, BB3) + VPADDD(state2StoreAVX2, CC0, CC0) + VPADDD(state2StoreAVX2, CC1, CC1) + VPADDD(state2StoreAVX2, CC2, CC2) + VPADDD(state2StoreAVX2, CC3, CC3) + VPADDD(ctr0StoreAVX2, DD0, DD0) + VPADDD(ctr1StoreAVX2, DD1, DD1) + VPADDD(ctr2StoreAVX2, DD2, DD2) + VPADDD(ctr3StoreAVX2, DD3, DD3) + VMOVDQA(CC3, tmpStoreAVX2) + VPERM2I128(Imm(0x02), AA0, BB0, CC3) + VPXOR(Mem{Base: inp}.Offset(0*32), CC3, CC3) + VMOVDQU(CC3, Mem{Base: oup}.Offset(0*32)) + VPERM2I128(Imm(0x02), CC0, DD0, CC3) + VPXOR(Mem{Base: inp}.Offset(1*32), CC3, CC3) + VMOVDQU(CC3, Mem{Base: oup}.Offset(1*32)) + VPERM2I128(Imm(0x13), AA0, BB0, CC3) + VPXOR(Mem{Base: inp}.Offset(2*32), CC3, CC3) + VMOVDQU(CC3, Mem{Base: oup}.Offset(2*32)) + VPERM2I128(Imm(0x13), CC0, DD0, CC3) + VPXOR(Mem{Base: inp}.Offset(3*32), CC3, CC3) + VMOVDQU(CC3, Mem{Base: oup}.Offset(3*32)) + + VPERM2I128(Imm(0x02), AA1, BB1, AA0) + VPERM2I128(Imm(0x02), CC1, DD1, BB0) + VPERM2I128(Imm(0x13), AA1, BB1, CC0) + VPERM2I128(Imm(0x13), CC1, DD1, DD0) + VPXOR(Mem{Base: inp}.Offset(4*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(5*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(6*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(7*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(4*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(5*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(6*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(7*32)) + + VPERM2I128(Imm(0x02), AA2, BB2, AA0) + VPERM2I128(Imm(0x02), CC2, DD2, BB0) + VPERM2I128(Imm(0x13), AA2, BB2, CC0) + VPERM2I128(Imm(0x13), CC2, DD2, DD0) + VPXOR(Mem{Base: inp}.Offset(8*32), AA0, AA0) + VPXOR(Mem{Base: inp}.Offset(9*32), BB0, BB0) + VPXOR(Mem{Base: inp}.Offset(10*32), CC0, CC0) + VPXOR(Mem{Base: inp}.Offset(11*32), DD0, DD0) + VMOVDQU(AA0, Mem{Base: oup}.Offset(8*32)) + VMOVDQU(BB0, Mem{Base: oup}.Offset(9*32)) + VMOVDQU(CC0, Mem{Base: oup}.Offset(10*32)) + VMOVDQU(DD0, Mem{Base: oup}.Offset(11*32)) + + MOVQ(U32(384), itr1) + LEAQ(Mem{Base: inp}.Offset(384), inp) + SUBQ(U32(384), inl) + VPERM2I128(Imm(0x02), AA3, BB3, AA0) + VPERM2I128(Imm(0x02), tmpStoreAVX2, DD3, BB0) + VPERM2I128(Imm(0x13), AA3, BB3, CC0) + VPERM2I128(Imm(0x13), tmpStoreAVX2, DD3, DD0) + + JMP(LabelRef("sealAVX2SealHash")) +} + +// ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATA SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~## + +var ( + // Pointers for memoizing DATA section symbols + chacha20Constants_DATA_ptr, + rol16_DATA_ptr, + rol8_DATA_ptr, + sseIncMask_DATA_ptr, + avx2IncMask_DATA_ptr, + avx2InitMask_DATA_ptr, + polyClampMask_DATA_ptr, + andMask_DATA_ptr *Mem +) + +var nothingUpMySleeve = [8]uint32{ + 0x61707865, + 0x3320646e, + 0x79622d32, + 0x6b206574, + 0x61707865, + 0x3320646e, + 0x79622d32, + 0x6b206574, +} + +// ChaCha20 constants +func chacha20Constants_DATA() Mem { + if chacha20Constants_DATA_ptr != nil { + return *chacha20Constants_DATA_ptr + } + + chacha20Constants := GLOBL(ThatPeskyUnicodeDot+"chacha20Constants", NOPTR|RODATA) + chacha20Constants_DATA_ptr = &chacha20Constants + for i, v := range nothingUpMySleeve { + DATA(i*4, U32(v)) + } + return chacha20Constants +} + +var rol16Consts = [4]uint64{ + 0x0504070601000302, + 0x0D0C0F0E09080B0A, + 0x0504070601000302, + 0x0D0C0F0E09080B0A, +} + +// <<< 16 with PSHUFB +func rol16_DATA() Mem { + if rol16_DATA_ptr != nil { + return *rol16_DATA_ptr + } + + rol16 := GLOBL(ThatPeskyUnicodeDot+"rol16", NOPTR|RODATA) + rol16_DATA_ptr = &rol16 + for i, v := range rol16Consts { + DATA(i*8, U64(v)) + } + return rol16 +} + +var rol8Consts = [4]uint64{ + 0x0605040702010003, + 0x0E0D0C0F0A09080B, + 0x0605040702010003, + 0x0E0D0C0F0A09080B, +} + +// <<< 8 with PSHUFB +func rol8_DATA() Mem { + if rol8_DATA_ptr != nil { + return *rol8_DATA_ptr + } + + rol8 := GLOBL(ThatPeskyUnicodeDot+"rol8", NOPTR|RODATA) + rol8_DATA_ptr = &rol8 + for i, v := range rol8Consts { + DATA(i*8, U64(v)) + } + return rol8 +} + +var avx2InitMaskConsts = [4]uint64{ + 0x0, + 0x0, + 0x1, + 0x0, +} + +func avx2InitMask_DATA() Mem { + if avx2InitMask_DATA_ptr != nil { + return *avx2InitMask_DATA_ptr + } + + avx2InitMask := GLOBL(ThatPeskyUnicodeDot+"avx2InitMask", NOPTR|RODATA) + avx2InitMask_DATA_ptr = &avx2InitMask + for i, v := range avx2InitMaskConsts { + DATA(i*8, U64(v)) + } + return avx2InitMask +} + +var avx2IncMaskConsts = [4]uint64{ + 0x2, + 0x0, + 0x2, + 0x0, +} + +func avx2IncMask_DATA() Mem { + if avx2IncMask_DATA_ptr != nil { + return *avx2IncMask_DATA_ptr + } + + avx2IncMask := GLOBL(ThatPeskyUnicodeDot+"avx2IncMask", NOPTR|RODATA) + avx2IncMask_DATA_ptr = &avx2IncMask + for i, v := range avx2IncMaskConsts { + DATA(i*8, U64(v)) + } + return avx2IncMask +} + +var polyClampMaskConsts = [4]uint64{ + 0x0FFFFFFC0FFFFFFF, + 0x0FFFFFFC0FFFFFFC, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, +} + +// Poly1305 key clamp +func polyClampMask_DATA() Mem { + if polyClampMask_DATA_ptr != nil { + return *polyClampMask_DATA_ptr + } + + polyClampMask := GLOBL(ThatPeskyUnicodeDot+"polyClampMask", NOPTR|RODATA) + polyClampMask_DATA_ptr = &polyClampMask + for i, v := range polyClampMaskConsts { + DATA(i*8, U64(v)) + } + return polyClampMask +} + +var sseIncMaskConsts = [2]uint64{ + 0x1, + 0x0, +} + +func sseIncMask_DATA() Mem { + if sseIncMask_DATA_ptr != nil { + return *sseIncMask_DATA_ptr + } + + sseIncMask := GLOBL(ThatPeskyUnicodeDot+"sseIncMask", NOPTR|RODATA) + sseIncMask_DATA_ptr = &sseIncMask + for i, v := range sseIncMaskConsts { + DATA(i*8, U64(v)) + } + return sseIncMask +} + +var andMaskConsts = [30]uint64{ + 0x00000000000000ff, + 0x0000000000000000, + 0x000000000000ffff, + 0x0000000000000000, + 0x0000000000ffffff, + 0x0000000000000000, + 0x00000000ffffffff, + 0x0000000000000000, + 0x000000ffffffffff, + 0x0000000000000000, + 0x0000ffffffffffff, + 0x0000000000000000, + 0x00ffffffffffffff, + 0x0000000000000000, + 0xffffffffffffffff, + 0x0000000000000000, + 0xffffffffffffffff, + 0x00000000000000ff, + 0xffffffffffffffff, + 0x000000000000ffff, + 0xffffffffffffffff, + 0x0000000000ffffff, + 0xffffffffffffffff, + 0x00000000ffffffff, + 0xffffffffffffffff, + 0x000000ffffffffff, + 0xffffffffffffffff, + 0x0000ffffffffffff, + 0xffffffffffffffff, + 0x00ffffffffffffff, +} + +func andMask_DATA() Mem { + if andMask_DATA_ptr != nil { + return *andMask_DATA_ptr + } + + andMask := GLOBL(ThatPeskyUnicodeDot+"andMask", NOPTR|RODATA) + andMask_DATA_ptr = &andMask + for i, v := range andMaskConsts { + DATA(i*8, U64(v)) + } + return andMask +} + +// removePeskyUnicodeDot strips the dot from the relevant TEXT directives such that they +// can exist as internal assembly functions +// +// Avo v0.6.0 does not support the generation of internal assembly functions. Go's unicode +// dot tells the compiler to link a TEXT symbol to a function in the current Go package +// (or another package if specified). Avo unconditionally prepends the unicode dot to all +// TEXT symbols, making it impossible to emit an internal function without this hack. +// +// There is a pending PR to add internal functions to Avo: +// https://github.com/mmcloughlin/avo/pull/443 +// +// If merged it should allow the usage of InternalFunction("NAME") for the specified functions +func removePeskyUnicodeDot(internalFunctions []string, target string) { + bytes, err := os.ReadFile(target) + if err != nil { + panic(err) + } + + content := string(bytes) + + for _, from := range internalFunctions { + to := strings.ReplaceAll(from, ThatPeskyUnicodeDot, "") + content = strings.ReplaceAll(content, from, to) + } + + err = os.WriteFile(target, []byte(content), 0644) + if err != nil { + panic(err) + } +} diff --git a/chacha20poly1305/_asm/go.mod b/chacha20poly1305/_asm/go.mod new file mode 100644 index 0000000000..23b7bc2c1a --- /dev/null +++ b/chacha20poly1305/_asm/go.mod @@ -0,0 +1,15 @@ +module chacha20poly1305/_asm + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/chacha20poly1305/_asm/go.sum b/chacha20poly1305/_asm/go.sum new file mode 100644 index 0000000000..39dd154050 --- /dev/null +++ b/chacha20poly1305/_asm/go.sum @@ -0,0 +1,12 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/chacha20poly1305/chacha20poly1305.go b/chacha20poly1305/chacha20poly1305.go index bbb86efef5..8cf5d8112e 100644 --- a/chacha20poly1305/chacha20poly1305.go +++ b/chacha20poly1305/chacha20poly1305.go @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539, -// and its extended nonce variant XChaCha20-Poly1305. -package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" +// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its +// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and +// draft-irtf-cfrg-xchacha-01. +package chacha20poly1305 import ( "crypto/cipher" - "encoding/binary" "errors" ) @@ -26,10 +26,14 @@ const ( // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 // variant of this AEAD, in bytes. NonceSizeX = 24 + + // Overhead is the size of the Poly1305 authentication tag, and the + // difference between a ciphertext length and its plaintext. + Overhead = 16 ) type chacha20poly1305 struct { - key [8]uint32 + key [KeySize]byte } // New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. @@ -38,14 +42,7 @@ func New(key []byte) (cipher.AEAD, error) { return nil, errors.New("chacha20poly1305: bad key length") } ret := new(chacha20poly1305) - ret.key[0] = binary.LittleEndian.Uint32(key[0:4]) - ret.key[1] = binary.LittleEndian.Uint32(key[4:8]) - ret.key[2] = binary.LittleEndian.Uint32(key[8:12]) - ret.key[3] = binary.LittleEndian.Uint32(key[12:16]) - ret.key[4] = binary.LittleEndian.Uint32(key[16:20]) - ret.key[5] = binary.LittleEndian.Uint32(key[20:24]) - ret.key[6] = binary.LittleEndian.Uint32(key[24:28]) - ret.key[7] = binary.LittleEndian.Uint32(key[28:32]) + copy(ret.key[:], key) return ret, nil } @@ -54,7 +51,7 @@ func (c *chacha20poly1305) NonceSize() int { } func (c *chacha20poly1305) Overhead() int { - return 16 + return Overhead } func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { diff --git a/chacha20poly1305/chacha20poly1305_amd64.go b/chacha20poly1305/chacha20poly1305_amd64.go index 2aa4fd89db..b850e772e1 100644 --- a/chacha20poly1305/chacha20poly1305_amd64.go +++ b/chacha20poly1305/chacha20poly1305_amd64.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.7,amd64,!gccgo,!appengine +//go:build gc && !purego package chacha20poly1305 import ( "encoding/binary" - "golang.org/x/crypto/internal/subtle" + "golang.org/x/crypto/internal/alias" "golang.org/x/sys/cpu" ) @@ -25,23 +25,23 @@ var ( // setupState writes a ChaCha20 input matrix to state. See // https://tools.ietf.org/html/rfc7539#section-2.3. -func setupState(state *[16]uint32, key *[8]uint32, nonce []byte) { +func setupState(state *[16]uint32, key *[32]byte, nonce []byte) { state[0] = 0x61707865 state[1] = 0x3320646e state[2] = 0x79622d32 state[3] = 0x6b206574 - state[4] = key[0] - state[5] = key[1] - state[6] = key[2] - state[7] = key[3] - state[8] = key[4] - state[9] = key[5] - state[10] = key[6] - state[11] = key[7] + state[4] = binary.LittleEndian.Uint32(key[0:4]) + state[5] = binary.LittleEndian.Uint32(key[4:8]) + state[6] = binary.LittleEndian.Uint32(key[8:12]) + state[7] = binary.LittleEndian.Uint32(key[12:16]) + state[8] = binary.LittleEndian.Uint32(key[16:20]) + state[9] = binary.LittleEndian.Uint32(key[20:24]) + state[10] = binary.LittleEndian.Uint32(key[24:28]) + state[11] = binary.LittleEndian.Uint32(key[28:32]) state[12] = 0 - state[13] = binary.LittleEndian.Uint32(nonce[:4]) + state[13] = binary.LittleEndian.Uint32(nonce[0:4]) state[14] = binary.LittleEndian.Uint32(nonce[4:8]) state[15] = binary.LittleEndian.Uint32(nonce[8:12]) } @@ -55,8 +55,11 @@ func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) [] setupState(&state, &c.key, nonce) ret, out := sliceForAppend(dst, len(plaintext)+16) - if subtle.InexactOverlap(out, plaintext) { - panic("chacha20poly1305: invalid buffer overlap") + if alias.InexactOverlap(out, plaintext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") } chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData) return ret @@ -72,8 +75,11 @@ func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ( ciphertext = ciphertext[:len(ciphertext)-16] ret, out := sliceForAppend(dst, len(ciphertext)) - if subtle.InexactOverlap(out, ciphertext) { - panic("chacha20poly1305: invalid buffer overlap") + if alias.InexactOverlap(out, ciphertext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") } if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) { for i := range out { diff --git a/chacha20poly1305/chacha20poly1305_amd64.s b/chacha20poly1305/chacha20poly1305_amd64.s index 9dd5d7a979..fd5ee845f9 100644 --- a/chacha20poly1305/chacha20poly1305_amd64.s +++ b/chacha20poly1305/chacha20poly1305_amd64.s @@ -1,2695 +1,9762 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run chacha20poly1305_amd64_asm.go -out ../chacha20poly1305_amd64.s -pkg chacha20poly1305. DO NOT EDIT. -// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. - -// +build go1.7,amd64,!gccgo,!appengine +//go:build gc && !purego #include "textflag.h" -// General register allocation -#define oup DI -#define inp SI -#define inl BX -#define adp CX // free to reuse, after we hash the additional data -#define keyp R8 // free to reuse, when we copy the key to stack -#define itr2 R9 // general iterator -#define itr1 CX // general iterator -#define acc0 R10 -#define acc1 R11 -#define acc2 R12 -#define t0 R13 -#define t1 R14 -#define t2 R15 -#define t3 R8 -// Register and stack allocation for the SSE code -#define rStore (0*16)(BP) -#define sStore (1*16)(BP) -#define state1Store (2*16)(BP) -#define state2Store (3*16)(BP) -#define tmpStore (4*16)(BP) -#define ctr0Store (5*16)(BP) -#define ctr1Store (6*16)(BP) -#define ctr2Store (7*16)(BP) -#define ctr3Store (8*16)(BP) -#define A0 X0 -#define A1 X1 -#define A2 X2 -#define B0 X3 -#define B1 X4 -#define B2 X5 -#define C0 X6 -#define C1 X7 -#define C2 X8 -#define D0 X9 -#define D1 X10 -#define D2 X11 -#define T0 X12 -#define T1 X13 -#define T2 X14 -#define T3 X15 -#define A3 T0 -#define B3 T1 -#define C3 T2 -#define D3 T3 -// Register and stack allocation for the AVX2 code -#define rsStoreAVX2 (0*32)(BP) -#define state1StoreAVX2 (1*32)(BP) -#define state2StoreAVX2 (2*32)(BP) -#define ctr0StoreAVX2 (3*32)(BP) -#define ctr1StoreAVX2 (4*32)(BP) -#define ctr2StoreAVX2 (5*32)(BP) -#define ctr3StoreAVX2 (6*32)(BP) -#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack -#define AA0 Y0 -#define AA1 Y5 -#define AA2 Y6 -#define AA3 Y7 -#define BB0 Y14 -#define BB1 Y9 -#define BB2 Y10 -#define BB3 Y11 -#define CC0 Y12 -#define CC1 Y13 -#define CC2 Y8 -#define CC3 Y15 -#define DD0 Y4 -#define DD1 Y1 -#define DD2 Y2 -#define DD3 Y3 -#define TT0 DD3 -#define TT1 AA3 -#define TT2 BB3 -#define TT3 CC3 -// ChaCha20 constants -DATA ·chacha20Constants<>+0x00(SB)/4, $0x61707865 -DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e -DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32 -DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574 -DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865 -DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e -DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32 -DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574 -// <<< 16 with PSHUFB -DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302 -DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302 -DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A -// <<< 8 with PSHUFB -DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003 -DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B -DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003 -DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B - -DATA ·avx2InitMask<>+0x00(SB)/8, $0x0 -DATA ·avx2InitMask<>+0x08(SB)/8, $0x0 -DATA ·avx2InitMask<>+0x10(SB)/8, $0x1 -DATA ·avx2InitMask<>+0x18(SB)/8, $0x0 - -DATA ·avx2IncMask<>+0x00(SB)/8, $0x2 -DATA ·avx2IncMask<>+0x08(SB)/8, $0x0 -DATA ·avx2IncMask<>+0x10(SB)/8, $0x2 -DATA ·avx2IncMask<>+0x18(SB)/8, $0x0 -// Poly1305 key clamp -DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF -DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF - -DATA ·sseIncMask<>+0x00(SB)/8, $0x1 -DATA ·sseIncMask<>+0x08(SB)/8, $0x0 -// To load/store the last < 16 bytes in a buffer -DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff -DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff -DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff -DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff -DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff -DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff -DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff -DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff -DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff -DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff -DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff -DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff -DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff -DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff - -GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32 -GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32 -GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32 -GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16 -GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32 -GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32 -GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32 -GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240 -// No PALIGNR in Go ASM yet (but VPALIGNR is present). -#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3 -#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4 -#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5 -#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13 -#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6 -#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7 -#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8 -#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14 -#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9 -#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10 -#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11 -#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15 -#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3 -#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4 -#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5 -#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13 -#define shiftC0Right shiftC0Left -#define shiftC1Right shiftC1Left -#define shiftC2Right shiftC2Left -#define shiftC3Right shiftC3Left -#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9 -#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10 -#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11 -#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15 -// Some macros -#define chachaQR(A, B, C, D, T) \ - PADDD B, A; PXOR A, D; PSHUFB ·rol16<>(SB), D \ - PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \ - PADDD B, A; PXOR A, D; PSHUFB ·rol8<>(SB), D \ - PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B - -#define chachaQR_AVX2(A, B, C, D, T) \ - VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol16<>(SB), D, D \ - VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \ - VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol8<>(SB), D, D \ - VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B - -#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2 -#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2 -#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX -#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3 -#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t3, t2; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2 - -#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2 -#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3 -#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3 - -#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage -#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage -// ---------------------------------------------------------------------------- + +// func polyHashADInternal<>() TEXT polyHashADInternal<>(SB), NOSPLIT, $0 - // adp points to beginning of additional data - // itr2 holds ad length - XORQ acc0, acc0 - XORQ acc1, acc1 - XORQ acc2, acc2 - CMPQ itr2, $13 - JNE hashADLoop - -openFastTLSAD: - // Special treatment for the TLS case of 13 bytes - MOVQ (adp), acc0 - MOVQ 5(adp), acc1 - SHRQ $24, acc1 - MOVQ $1, acc2 - polyMul + // Hack: Must declare #define macros inside of a function due to Avo constraints + // ROL rotates the uint32s in register R left by N bits, using temporary T. + #define ROL(N, R, T) \ + MOVO R, T; \ + PSLLL $(N), T; \ + PSRLL $(32-(N)), R; \ + PXOR T, R + + // ROL8 rotates the uint32s in register R left by 8, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL8(R, T) PSHUFB ·rol8<>(SB), R + #else + #define ROL8(R, T) ROL(8, R, T) + #endif + + // ROL16 rotates the uint32s in register R left by 16, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL16(R, T) PSHUFB ·rol16<>(SB), R + #else + #define ROL16(R, T) ROL(16, R, T) + #endif + XORQ R10, R10 + XORQ R11, R11 + XORQ R12, R12 + CMPQ R9, $0x0d + JNE hashADLoop + MOVQ (CX), R10 + MOVQ 5(CX), R11 + SHRQ $0x18, R11 + MOVQ $0x00000001, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 RET hashADLoop: // Hash in 16 byte chunks - CMPQ itr2, $16 - JB hashADTail - polyAdd(0(adp)) - LEAQ (1*16)(adp), adp - SUBQ $16, itr2 - polyMul - JMP hashADLoop + CMPQ R9, $0x10 + JB hashADTail + ADDQ (CX), R10 + ADCQ 8(CX), R11 + ADCQ $0x01, R12 + LEAQ 16(CX), CX + SUBQ $0x10, R9 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + JMP hashADLoop hashADTail: - CMPQ itr2, $0 + CMPQ R9, $0x00 JE hashADDone // Hash last < 16 byte tail - XORQ t0, t0 - XORQ t1, t1 - XORQ t2, t2 - ADDQ itr2, adp + XORQ R13, R13 + XORQ R14, R14 + XORQ R15, R15 + ADDQ R9, CX hashADTailLoop: - SHLQ $8, t0, t1 - SHLQ $8, t0 - MOVB -1(adp), t2 - XORQ t2, t0 - DECQ adp - DECQ itr2 - JNE hashADTailLoop - -hashADTailFinish: - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul - - // Finished AD + SHLQ $0x08, R13, R14 + SHLQ $0x08, R13 + MOVB -1(CX), R15 + XORQ R15, R13 + DECQ CX + DECQ R9 + JNE hashADTailLoop + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + hashADDone: RET -// ---------------------------------------------------------------------------- -// func chacha20Poly1305Open(dst, key, src, ad []byte) bool -TEXT ·chacha20Poly1305Open(SB), 0, $288-97 +// func chacha20Poly1305Open(dst []byte, key []uint32, src []byte, ad []byte) bool +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Open(SB), $288-97 // For aligned stack access MOVQ SP, BP - ADDQ $32, BP + ADDQ $0x20, BP ANDQ $-32, BP - MOVQ dst+0(FP), oup - MOVQ key+24(FP), keyp - MOVQ src+48(FP), inp - MOVQ src_len+56(FP), inl - MOVQ ad+72(FP), adp + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX // Check for AVX2 support - CMPB ·useAVX2(SB), $1 + CMPB ·useAVX2+0(SB), $0x01 JE chacha20Poly1305Open_AVX2 // Special optimization, for very short buffers - CMPQ inl, $128 - JBE openSSE128 // About 16% faster + CMPQ BX, $0x80 + JBE openSSE128 // For long buffers, prepare the poly key first - MOVOU ·chacha20Constants<>(SB), A0 - MOVOU (1*16)(keyp), B0 - MOVOU (2*16)(keyp), C0 - MOVOU (3*16)(keyp), D0 - MOVO D0, T1 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X9, X13 // Store state on stack for future use - MOVO B0, state1Store - MOVO C0, state2Store - MOVO D0, ctr3Store - MOVQ $10, itr2 + MOVO X3, 32(BP) + MOVO X6, 48(BP) + MOVO X9, 128(BP) + MOVQ $0x0000000a, R9 openSSEPreparePolyKey: - chachaQR(A0, B0, C0, D0, T0) - shiftB0Left; shiftC0Left; shiftD0Left - chachaQR(A0, B0, C0, D0, T0) - shiftB0Right; shiftC0Right; shiftD0Right - DECQ itr2 - JNE openSSEPreparePolyKey + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + DECQ R9 + JNE openSSEPreparePolyKey // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded - PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0 + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 // Clamp and store the key - PAND ·polyClampMask<>(SB), A0 - MOVO A0, rStore; MOVO B0, sStore + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) // Hash AAD - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) openSSEMainLoop: - CMPQ inl, $256 + CMPQ BX, $0x00000100 JB openSSEMainLoopDone // Load state, increment counter blocks - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) - // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16 - MOVQ $4, itr1 - MOVQ inp, itr2 + // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash + // 2 blocks, and for the remaining 4 only 1 block - for a total of 16 + MOVQ $0x00000004, CX + MOVQ SI, R9 openSSEInternalLoop: - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyAdd(0(itr2)) - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - polyMulStage1 - polyMulStage2 - LEAQ (2*8)(itr2), itr2 - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - polyMulStage3 - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyMulReduceStage - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - DECQ itr1 - JGE openSSEInternalLoop - - polyAdd(0(itr2)) - polyMul - LEAQ (2*8)(itr2), itr2 - - CMPQ itr1, $-6 - JG openSSEInternalLoop + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(R9), R9 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ CX + JGE openSSEInternalLoop + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + CMPQ CX, $-6 + JG openSSEInternalLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 // Load - xor - store - MOVO D3, tmpStore - MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup) - MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup) - MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup) - MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup) - MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup) - MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup) - MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup) - MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup) - MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup) - MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup) - MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup) - MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup) - MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup) - MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup) - MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup) - MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup) - LEAQ 256(inp), inp - LEAQ 256(oup), oup - SUBQ $256, inl + MOVO X15, 64(BP) + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU X0, (DI) + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU X3, 16(DI) + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU X6, 32(DI) + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X9, 48(DI) + MOVOU 64(SI), X9 + PXOR X9, X1 + MOVOU X1, 64(DI) + MOVOU 80(SI), X9 + PXOR X9, X4 + MOVOU X4, 80(DI) + MOVOU 96(SI), X9 + PXOR X9, X7 + MOVOU X7, 96(DI) + MOVOU 112(SI), X9 + PXOR X9, X10 + MOVOU X10, 112(DI) + MOVOU 128(SI), X9 + PXOR X9, X2 + MOVOU X2, 128(DI) + MOVOU 144(SI), X9 + PXOR X9, X5 + MOVOU X5, 144(DI) + MOVOU 160(SI), X9 + PXOR X9, X8 + MOVOU X8, 160(DI) + MOVOU 176(SI), X9 + PXOR X9, X11 + MOVOU X11, 176(DI) + MOVOU 192(SI), X9 + PXOR X9, X12 + MOVOU X12, 192(DI) + MOVOU 208(SI), X9 + PXOR X9, X13 + MOVOU X13, 208(DI) + MOVOU 224(SI), X9 + PXOR X9, X14 + MOVOU X14, 224(DI) + MOVOU 240(SI), X9 + PXOR 64(BP), X9 + MOVOU X9, 240(DI) + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX JMP openSSEMainLoop openSSEMainLoopDone: // Handle the various tail sizes efficiently - TESTQ inl, inl + TESTQ BX, BX JE openSSEFinalize - CMPQ inl, $64 + CMPQ BX, $0x40 JBE openSSETail64 - CMPQ inl, $128 + CMPQ BX, $0x80 JBE openSSETail128 - CMPQ inl, $192 + CMPQ BX, $0xc0 JBE openSSETail192 JMP openSSETail256 openSSEFinalize: // Hash in the PT, AAD lengths - ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2 - polyMul + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Final reduce - MOVQ acc0, t0 - MOVQ acc1, t1 - MOVQ acc2, t2 - SUBQ $-5, acc0 - SBBQ $-1, acc1 - SBBQ $3, acc2 - CMOVQCS t0, acc0 - CMOVQCS t1, acc1 - CMOVQCS t2, acc2 + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 // Add in the "s" part of the key - ADDQ 0+sStore, acc0 - ADCQ 8+sStore, acc1 + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 // Finally, constant time compare to the tag at the end of the message XORQ AX, AX - MOVQ $1, DX - XORQ (0*8)(inp), acc0 - XORQ (1*8)(inp), acc1 - ORQ acc1, acc0 + MOVQ $0x00000001, DX + XORQ (SI), R10 + XORQ 8(SI), R11 + ORQ R11, R10 CMOVQEQ DX, AX // Return true iff tags are equal MOVB AX, ret+96(FP) RET -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 129 bytes openSSE128: - // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks - MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 - MOVQ $10, itr2 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 openSSE128InnerCipherLoop: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftB1Left; shiftB2Left - shiftC0Left; shiftC1Left; shiftC2Left - shiftD0Left; shiftD1Left; shiftD2Left - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftB1Right; shiftB2Right - shiftC0Right; shiftC1Right; shiftC2Right - shiftD0Right; shiftD1Right; shiftD2Right - DECQ itr2 - JNE openSSE128InnerCipherLoop + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE openSSE128InnerCipherLoop // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 - PADDL T2, C1; PADDL T2, C2 - PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 // Clamp and store the key - PAND ·polyClampMask<>(SB), A0 - MOVOU A0, rStore; MOVOU B0, sStore + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) // Hash - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) openSSE128Open: - CMPQ inl, $16 + CMPQ BX, $0x10 JB openSSETail16 - SUBQ $16, inl + SUBQ $0x10, BX // Load for hashing - polyAdd(0(inp)) + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 // Load for decryption - MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup - polyMul + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Shift the stream "left" - MOVO B1, A1 - MOVO C1, B1 - MOVO D1, C1 - MOVO A2, D1 - MOVO B2, A2 - MOVO C2, B2 - MOVO D2, C2 + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 JMP openSSE128Open openSSETail16: - TESTQ inl, inl + TESTQ BX, BX JE openSSEFinalize // We can safely load the CT from the end, because it is padded with the MAC - MOVQ inl, itr2 - SHLQ $4, itr2 - LEAQ ·andMask<>(SB), t0 - MOVOU (inp), T0 - ADDQ inl, inp - PAND -16(t0)(itr2*1), T0 - MOVO T0, 0+tmpStore - MOVQ T0, t0 - MOVQ 8+tmpStore, t1 - PXOR A1, T0 + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVOU (SI), X12 + ADDQ BX, SI + PAND -16(R13)(R9*1), X12 + MOVO X12, 64(BP) + MOVQ X12, R13 + MOVQ 72(BP), R14 + PXOR X1, X12 // We can only store one byte at a time, since plaintext can be shorter than 16 bytes openSSETail16Store: - MOVQ T0, t3 - MOVB t3, (oup) - PSRLDQ $1, T0 - INCQ oup - DECQ inl + MOVQ X12, R8 + MOVB R8, (DI) + PSRLDQ $0x01, X12 + INCQ DI + DECQ BX JNE openSSETail16Store - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 JMP openSSEFinalize -// ---------------------------------------------------------------------------- -// Special optimization for the last 64 bytes of ciphertext openSSETail64: - // Need to decrypt up to 64 bytes - prepare single block - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store - XORQ itr2, itr2 - MOVQ inl, itr1 - CMPQ itr1, $16 - JB openSSETail64LoopB + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + XORQ R9, R9 + MOVQ BX, CX + CMPQ CX, $0x10 + JB openSSETail64LoopB openSSETail64LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMul - SUBQ $16, itr1 + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX openSSETail64LoopB: - ADDQ $16, itr2 - chachaQR(A0, B0, C0, D0, T0) - shiftB0Left; shiftC0Left; shiftD0Left - chachaQR(A0, B0, C0, D0, T0) - shiftB0Right; shiftC0Right; shiftD0Right - - CMPQ itr1, $16 - JAE openSSETail64LoopA - - CMPQ itr2, $160 - JNE openSSETail64LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0 + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + CMPQ CX, $0x10 + JAE openSSETail64LoopA + CMPQ R9, $0xa0 + JNE openSSETail64LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 + PADDL 48(BP), X6 + PADDL 80(BP), X9 openSSETail64DecLoop: - CMPQ inl, $16 + CMPQ BX, $0x10 JB openSSETail64DecLoopDone - SUBQ $16, inl - MOVOU (inp), T0 - PXOR T0, A0 - MOVOU A0, (oup) - LEAQ 16(inp), inp - LEAQ 16(oup), oup - MOVO B0, A0 - MOVO C0, B0 - MOVO D0, C0 + SUBQ $0x10, BX + MOVOU (SI), X12 + PXOR X12, X0 + MOVOU X0, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVO X3, X0 + MOVO X6, X3 + MOVO X9, X6 JMP openSSETail64DecLoop openSSETail64DecLoopDone: - MOVO A0, A1 + MOVO X0, X1 JMP openSSETail16 -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of ciphertext openSSETail128: - // Need to decrypt up to 128 bytes - prepare two blocks - MOVO ·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr0Store - MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr1Store - XORQ itr2, itr2 - MOVQ inl, itr1 - ANDQ $-16, itr1 + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 96(BP) + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX openSSETail128LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMul + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openSSETail128LoopB: - ADDQ $16, itr2 - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - - CMPQ itr2, itr1 - JB openSSETail128LoopA - - CMPQ itr2, $160 - JNE openSSETail128LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 - PADDL state1Store, B0; PADDL state1Store, B1 - PADDL state2Store, C0; PADDL state2Store, C1 - PADDL ctr1Store, D0; PADDL ctr0Store, D1 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 - MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) - - SUBQ $64, inl - LEAQ 64(inp), inp - LEAQ 64(oup), oup - JMP openSSETail64DecLoop - -// ---------------------------------------------------------------------------- -// Special optimization for the last 192 bytes of ciphertext + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + CMPQ R9, CX + JB openSSETail128LoopA + CMPQ R9, $0xa0 + JNE openSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 96(BP), X9 + PADDL 80(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + SUBQ $0x40, BX + LEAQ 64(SI), SI + LEAQ 64(DI), DI + JMP openSSETail64DecLoop + openSSETail192: - // Need to decrypt up to 192 bytes - prepare three blocks - MOVO ·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr0Store - MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store - MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr2Store - - MOVQ inl, itr1 - MOVQ $160, itr2 - CMPQ itr1, $160 - CMOVQGT itr2, itr1 - ANDQ $-16, itr1 - XORQ itr2, itr2 + MOVO ·chacha20Constants<>+0(SB), X2 + MOVO 32(BP), X5 + MOVO 48(BP), X8 + MOVO 128(BP), X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 80(BP) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 112(BP) + MOVQ BX, CX + MOVQ $0x000000a0, R9 + CMPQ CX, $0xa0 + CMOVQGT R9, CX + ANDQ $-16, CX + XORQ R9, R9 openSSLTail192LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMul + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openSSLTail192LoopB: - ADDQ $16, itr2 - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - shiftB2Left; shiftC2Left; shiftD2Left - - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - shiftB2Right; shiftC2Right; shiftD2Right - - CMPQ itr2, itr1 - JB openSSLTail192LoopA - - CMPQ itr2, $160 - JNE openSSLTail192LoopB - - CMPQ inl, $176 - JB openSSLTail192Store - - polyAdd(160(inp)) - polyMul - - CMPQ inl, $192 - JB openSSLTail192Store - - polyAdd(176(inp)) - polyMul + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + CMPQ R9, CX + JB openSSLTail192LoopA + CMPQ R9, $0xa0 + JNE openSSLTail192LoopB + CMPQ BX, $0xb0 + JB openSSLTail192Store + ADDQ 160(SI), R10 + ADCQ 168(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + CMPQ BX, $0xc0 + JB openSSLTail192Store + ADDQ 176(SI), R10 + ADCQ 184(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openSSLTail192Store: - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 - PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 - PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2 - MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup) - - MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 - PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - - SUBQ $128, inl - LEAQ 128(inp), inp - LEAQ 128(oup), oup - JMP openSSETail64DecLoop - -// ---------------------------------------------------------------------------- -// Special optimization for the last 256 bytes of ciphertext + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 112(BP), X9 + PADDL 96(BP), X10 + PADDL 80(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X2 + PXOR X13, X5 + PXOR X14, X8 + PXOR X15, X11 + MOVOU X2, (DI) + MOVOU X5, 16(DI) + MOVOU X8, 32(DI) + MOVOU X11, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + LEAQ 128(DI), DI + JMP openSSETail64DecLoop + openSSETail256: - // Need to decrypt up to 256 bytes - prepare four blocks - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store - XORQ itr2, itr2 + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + XORQ R9, R9 openSSETail256Loop: - // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication - polyAdd(0(inp)(itr2*1)) - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - polyMulStage1 - polyMulStage2 - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyMulStage3 - polyMulReduceStage - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - ADDQ $2*8, itr2 - CMPQ itr2, $160 - JB openSSETail256Loop - MOVQ inl, itr1 - ANDQ $-16, itr1 + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + ADDQ $0x10, R9 + CMPQ R9, $0xa0 + JB openSSETail256Loop + MOVQ BX, CX + ANDQ $-16, CX openSSETail256HashLoop: - polyAdd(0(inp)(itr2*1)) - polyMul - ADDQ $2*8, itr2 - CMPQ itr2, itr1 - JB openSSETail256HashLoop + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, R9 + CMPQ R9, CX + JB openSSETail256HashLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 - MOVO D3, tmpStore + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) // Load - xor - store - MOVOU (0*16)(inp), D3; PXOR D3, A0 - MOVOU (1*16)(inp), D3; PXOR D3, B0 - MOVOU (2*16)(inp), D3; PXOR D3, C0 - MOVOU (3*16)(inp), D3; PXOR D3, D0 - MOVOU A0, (0*16)(oup) - MOVOU B0, (1*16)(oup) - MOVOU C0, (2*16)(oup) - MOVOU D0, (3*16)(oup) - MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 - PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 - PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 - MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) - LEAQ 192(inp), inp - LEAQ 192(oup), oup - SUBQ $192, inl - MOVO A3, A0 - MOVO B3, B0 - MOVO C3, C0 - MOVO tmpStore, D0 - - JMP openSSETail64DecLoop - -// ---------------------------------------------------------------------------- -// ------------------------- AVX2 Code ---------------------------------------- + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + LEAQ 192(SI), SI + LEAQ 192(DI), DI + SUBQ $0xc0, BX + MOVO X12, X0 + MOVO X13, X3 + MOVO X14, X6 + MOVO 64(BP), X9 + JMP openSSETail64DecLoop + chacha20Poly1305Open_AVX2: VZEROUPPER - VMOVDQU ·chacha20Constants<>(SB), AA0 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 - BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 - VPADDD ·avx2InitMask<>(SB), DD0, DD0 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 // Special optimization, for very short buffers - CMPQ inl, $192 + CMPQ BX, $0xc0 JBE openAVX2192 - CMPQ inl, $320 + CMPQ BX, $0x00000140 JBE openAVX2320 // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream - VMOVDQA BB0, state1StoreAVX2 - VMOVDQA CC0, state2StoreAVX2 - VMOVDQA DD0, ctr3StoreAVX2 - MOVQ $10, itr2 + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, 64(BP) + VMOVDQA Y4, 192(BP) + MOVQ $0x0000000a, R9 openAVX2PreparePolyKey: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 - DECQ itr2 - JNE openAVX2PreparePolyKey - - VPADDD ·chacha20Constants<>(SB), AA0, AA0 - VPADDD state1StoreAVX2, BB0, BB0 - VPADDD state2StoreAVX2, CC0, CC0 - VPADDD ctr3StoreAVX2, DD0, DD0 - - VPERM2I128 $0x02, AA0, BB0, TT0 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ R9 + JNE openAVX2PreparePolyKey + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD 32(BP), Y14, Y14 + VPADDD 64(BP), Y12, Y12 + VPADDD 192(BP), Y4, Y4 + VPERM2I128 $0x02, Y0, Y14, Y3 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for the first 64 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 // Hash AD + first 64 bytes - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ itr1, itr1 + XORQ CX, CX openAVX2InitialHash64: - polyAdd(0(inp)(itr1*1)) - polyMulAVX2 - ADDQ $16, itr1 - CMPQ itr1, $64 - JNE openAVX2InitialHash64 + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, CX + CMPQ CX, $0x40 + JNE openAVX2InitialHash64 // Decrypt the first 64 bytes - VPXOR (0*32)(inp), AA0, AA0 - VPXOR (1*32)(inp), BB0, BB0 - VMOVDQU AA0, (0*32)(oup) - VMOVDQU BB0, (1*32)(oup) - LEAQ (2*32)(inp), inp - LEAQ (2*32)(oup), oup - SUBQ $64, inl + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VMOVDQU Y0, (DI) + VMOVDQU Y14, 32(DI) + LEAQ 64(SI), SI + LEAQ 64(DI), DI + SUBQ $0x40, BX openAVX2MainLoop: - CMPQ inl, $512 + CMPQ BX, $0x00000200 JB openAVX2MainLoopDone // Load state, increment counter blocks, store the incremented counters - VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - XORQ itr1, itr1 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX openAVX2InternalLoop: - // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications - // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext - polyAdd(0*8(inp)(itr1*1)) - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage1_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulStage2_AVX2 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyMulStage3_AVX2 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - polyAdd(2*8(inp)(itr1*1)) - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage1_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage2_AVX2 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage3_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulReduceStage - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(4*8(inp)(itr1*1)) - LEAQ (6*8)(itr1), itr1 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage1_AVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - polyMulStage2_AVX2 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage3_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - CMPQ itr1, $480 + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(SI)(CX*1), R10 + ADCQ 24(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(SI)(CX*1), R10 + ADCQ 40(SI)(CX*1), R11 + ADCQ $0x01, R12 + LEAQ 48(CX), CX + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + CMPQ CX, $0x000001e0 JNE openAVX2InternalLoop - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) // We only hashed 480 of the 512 bytes available - hash the remaining 32 here - polyAdd(480(inp)) - polyMulAVX2 - VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 - VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 - VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + ADDQ 480(SI), R10 + ADCQ 488(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) // and here - polyAdd(496(inp)) - polyMulAVX2 - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 - VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) - LEAQ (32*16)(inp), inp - LEAQ (32*16)(oup), oup - SUBQ $(32*16), inl + ADDQ 496(SI), R10 + ADCQ 504(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + LEAQ 512(DI), DI + SUBQ $0x00000200, BX JMP openAVX2MainLoop openAVX2MainLoopDone: // Handle the various tail sizes efficiently - TESTQ inl, inl + TESTQ BX, BX JE openSSEFinalize - CMPQ inl, $128 + CMPQ BX, $0x80 JBE openAVX2Tail128 - CMPQ inl, $256 + CMPQ BX, $0x00000100 JBE openAVX2Tail256 - CMPQ inl, $384 + CMPQ BX, $0x00000180 JBE openAVX2Tail384 JMP openAVX2Tail512 -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 193 bytes openAVX2192: - // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks - VMOVDQA AA0, AA1 - VMOVDQA BB0, BB1 - VMOVDQA CC0, CC1 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2 - VMOVDQA BB0, BB2 - VMOVDQA CC0, CC2 - VMOVDQA DD0, DD2 - VMOVDQA DD1, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 openAVX2192InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 JNE openAVX2192InnerCipherLoop - VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 - VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 - VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 - VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, TT0 + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 192 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 openAVX2ShortOpen: // Hash - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) openAVX2ShortOpenLoop: - CMPQ inl, $32 + CMPQ BX, $0x20 JB openAVX2ShortTail32 - SUBQ $32, inl + SUBQ $0x20, BX // Load for hashing - polyAdd(0*8(inp)) - polyMulAVX2 - polyAdd(2*8(inp)) - polyMulAVX2 + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Load for decryption - VPXOR (inp), AA0, AA0 - VMOVDQU AA0, (oup) - LEAQ (1*32)(inp), inp - LEAQ (1*32)(oup), oup + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI // Shift stream left - VMOVDQA BB0, AA0 - VMOVDQA CC0, BB0 - VMOVDQA DD0, CC0 - VMOVDQA AA1, DD0 - VMOVDQA BB1, AA1 - VMOVDQA CC1, BB1 - VMOVDQA DD1, CC1 - VMOVDQA AA2, DD1 - VMOVDQA BB2, AA2 + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 JMP openAVX2ShortOpenLoop openAVX2ShortTail32: - CMPQ inl, $16 - VMOVDQA A0, A1 + CMPQ BX, $0x10 + VMOVDQA X0, X1 JB openAVX2ShortDone - - SUBQ $16, inl + SUBQ $0x10, BX // Load for hashing - polyAdd(0*8(inp)) - polyMulAVX2 + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Load for decryption - VPXOR (inp), A0, T0 - VMOVDQU T0, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup - VPERM2I128 $0x11, AA0, AA0, AA0 - VMOVDQA A0, A1 + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 openAVX2ShortDone: VZEROUPPER JMP openSSETail16 -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 321 bytes openAVX2320: - // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks - VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 openAVX2320InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ R9 JNE openAVX2320InnerCipherLoop - - VMOVDQA ·chacha20Constants<>(SB), TT0 - VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 - VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 - VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 - VMOVDQA ·avx2IncMask<>(SB), TT0 - VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD2, DD2 + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 // Clamp and store poly key - VPERM2I128 $0x02, AA0, BB0, TT0 - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 320 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 - VPERM2I128 $0x02, AA2, BB2, CC1 - VPERM2I128 $0x02, CC2, DD2, DD1 - VPERM2I128 $0x13, AA2, BB2, AA2 - VPERM2I128 $0x13, CC2, DD2, BB2 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 JMP openAVX2ShortOpen -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of ciphertext openAVX2Tail128: // Need to decrypt up to 128 bytes - prepare two blocks - VMOVDQA ·chacha20Constants<>(SB), AA1 - VMOVDQA state1StoreAVX2, BB1 - VMOVDQA state2StoreAVX2, CC1 - VMOVDQA ctr3StoreAVX2, DD1 - VPADDD ·avx2IncMask<>(SB), DD1, DD1 - VMOVDQA DD1, DD0 - - XORQ itr2, itr2 - MOVQ inl, itr1 - ANDQ $-16, itr1 - TESTQ itr1, itr1 - JE openAVX2Tail128LoopB + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y1 + VMOVDQA Y1, Y4 + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX + TESTQ CX, CX + JE openAVX2Tail128LoopB openAVX2Tail128LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMulAVX2 + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openAVX2Tail128LoopB: - ADDQ $16, itr2 - chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD1, DD1, DD1 - CMPQ itr2, itr1 - JB openAVX2Tail128LoopA - CMPQ itr2, $160 - JNE openAVX2Tail128LoopB - - VPADDD ·chacha20Constants<>(SB), AA1, AA1 - VPADDD state1StoreAVX2, BB1, BB1 - VPADDD state2StoreAVX2, CC1, CC1 - VPADDD DD0, DD1, DD1 - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + ADDQ $0x10, R9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX + JB openAVX2Tail128LoopA + CMPQ R9, $0xa0 + JNE openAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y13, Y13 + VPADDD Y4, Y1, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 openAVX2TailLoop: - CMPQ inl, $32 + CMPQ BX, $0x20 JB openAVX2Tail - SUBQ $32, inl + SUBQ $0x20, BX // Load for decryption - VPXOR (inp), AA0, AA0 - VMOVDQU AA0, (oup) - LEAQ (1*32)(inp), inp - LEAQ (1*32)(oup), oup - VMOVDQA BB0, AA0 - VMOVDQA CC0, BB0 - VMOVDQA DD0, CC0 + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 JMP openAVX2TailLoop openAVX2Tail: - CMPQ inl, $16 - VMOVDQA A0, A1 + CMPQ BX, $0x10 + VMOVDQA X0, X1 JB openAVX2TailDone - SUBQ $16, inl + SUBQ $0x10, BX // Load for decryption - VPXOR (inp), A0, T0 - VMOVDQU T0, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup - VPERM2I128 $0x11, AA0, AA0, AA0 - VMOVDQA A0, A1 + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 openAVX2TailDone: VZEROUPPER JMP openSSETail16 -// ---------------------------------------------------------------------------- -// Special optimization for the last 256 bytes of ciphertext openAVX2Tail256: - // Need to decrypt up to 256 bytes - prepare four blocks - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA DD0, TT1 - VMOVDQA DD1, TT2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 // Compute the number of iterations that will hash data - MOVQ inl, tmpStoreAVX2 - MOVQ inl, itr1 - SUBQ $128, itr1 - SHRQ $4, itr1 - MOVQ $10, itr2 - CMPQ itr1, $10 - CMOVQGT itr2, itr1 - MOVQ inp, inl - XORQ itr2, itr2 + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x80, CX + SHRQ $0x04, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 openAVX2Tail256LoopA: - polyAdd(0(inl)) - polyMulAVX2 - LEAQ 16(inl), inl + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX - // Perform ChaCha rounds, while hashing the remaining input openAVX2Tail256LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - INCQ itr2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - CMPQ itr2, itr1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX JB openAVX2Tail256LoopA + CMPQ R9, $0x0a + JNE openAVX2Tail256LoopB + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX - CMPQ itr2, $10 - JNE openAVX2Tail256LoopB - - MOVQ inl, itr2 - SUBQ inp, inl - MOVQ inl, itr1 - MOVQ tmpStoreAVX2, inl - - // Hash the remainder of data (if any) openAVX2Tail256Hash: - ADDQ $16, itr1 - CMPQ itr1, inl - JGT openAVX2Tail256HashEnd - polyAdd (0(itr2)) - polyMulAVX2 - LEAQ 16(itr2), itr2 - JMP openAVX2Tail256Hash - -// Store 128 bytes safely, then go to store loop + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail256HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail256Hash + openAVX2Tail256HashEnd: - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 - VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2 - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - - VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2 - VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup) - LEAQ (4*32)(inp), inp - LEAQ (4*32)(oup), oup - SUBQ $4*32, inl - - JMP openAVX2TailLoop - -// ---------------------------------------------------------------------------- -// Special optimization for the last 384 bytes of ciphertext + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y6 + VPERM2I128 $0x02, Y12, Y4, Y10 + VPERM2I128 $0x13, Y0, Y14, Y8 + VPERM2I128 $0x13, Y12, Y4, Y2 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR (SI), Y6, Y6 + VPXOR 32(SI), Y10, Y10 + VPXOR 64(SI), Y8, Y8 + VPXOR 96(SI), Y2, Y2 + VMOVDQU Y6, (DI) + VMOVDQU Y10, 32(DI) + VMOVDQU Y8, 64(DI) + VMOVDQU Y2, 96(DI) + LEAQ 128(SI), SI + LEAQ 128(DI), DI + SUBQ $0x80, BX + JMP openAVX2TailLoop + openAVX2Tail384: // Need to decrypt up to 384 bytes - prepare six blocks - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA DD0, ctr0StoreAVX2 - VMOVDQA DD1, ctr1StoreAVX2 - VMOVDQA DD2, ctr2StoreAVX2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) // Compute the number of iterations that will hash two blocks of data - MOVQ inl, tmpStoreAVX2 - MOVQ inl, itr1 - SUBQ $256, itr1 - SHRQ $4, itr1 - ADDQ $6, itr1 - MOVQ $10, itr2 - CMPQ itr1, $10 - CMOVQGT itr2, itr1 - MOVQ inp, inl - XORQ itr2, itr2 - - // Perform ChaCha rounds, while hashing the remaining input + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x00000100, CX + SHRQ $0x04, CX + ADDQ $0x06, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 + openAVX2Tail384LoopB: - polyAdd(0(inl)) - polyMulAVX2 - LEAQ 16(inl), inl + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX openAVX2Tail384LoopA: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - polyAdd(0(inl)) - polyMulAVX2 - LEAQ 16(inl), inl - INCQ itr2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - - CMPQ itr2, itr1 - JB openAVX2Tail384LoopB - - CMPQ itr2, $10 - JNE openAVX2Tail384LoopA - - MOVQ inl, itr2 - SUBQ inp, inl - MOVQ inl, itr1 - MOVQ tmpStoreAVX2, inl + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + CMPQ R9, CX + JB openAVX2Tail384LoopB + CMPQ R9, $0x0a + JNE openAVX2Tail384LoopA + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX openAVX2Tail384Hash: - ADDQ $16, itr1 - CMPQ itr1, inl - JGT openAVX2Tail384HashEnd - polyAdd(0(itr2)) - polyMulAVX2 - LEAQ 16(itr2), itr2 - JMP openAVX2Tail384Hash - -// Store 256 bytes safely, then go to store loop + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail384HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail384Hash + openAVX2Tail384HashEnd: - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2 - VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3 - VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 - VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3 - VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 - VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - LEAQ (8*32)(inp), inp - LEAQ (8*32)(oup), oup - SUBQ $8*32, inl + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX JMP openAVX2TailLoop -// ---------------------------------------------------------------------------- -// Special optimization for the last 512 bytes of ciphertext openAVX2Tail512: - VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - XORQ itr1, itr1 - MOVQ inp, itr2 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX + MOVQ SI, R9 openAVX2Tail512LoopB: - polyAdd(0(itr2)) - polyMulAVX2 - LEAQ (2*8)(itr2), itr2 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 openAVX2Tail512LoopA: - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyAdd(0*8(itr2)) - polyMulAVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(2*8(itr2)) - polyMulAVX2 - LEAQ (4*8)(itr2), itr2 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - INCQ itr1 - CMPQ itr1, $4 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(R9), R10 + ADCQ 24(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(R9), R9 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + INCQ CX + CMPQ CX, $0x04 JLT openAVX2Tail512LoopB - - CMPQ itr1, $10 - JNE openAVX2Tail512LoopA - - MOVQ inl, itr1 - SUBQ $384, itr1 - ANDQ $-16, itr1 + CMPQ CX, $0x0a + JNE openAVX2Tail512LoopA + MOVQ BX, CX + SUBQ $0x00000180, CX + ANDQ $-16, CX openAVX2Tail512HashLoop: - TESTQ itr1, itr1 + TESTQ CX, CX JE openAVX2Tail512HashEnd - polyAdd(0(itr2)) - polyMulAVX2 - LEAQ 16(itr2), itr2 - SUBQ $16, itr1 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + SUBQ $0x10, CX JMP openAVX2Tail512HashLoop openAVX2Tail512HashEnd: - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 - VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 - VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 - VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - - LEAQ (12*32)(inp), inp - LEAQ (12*32)(oup), oup - SUBQ $12*32, inl - - JMP openAVX2TailLoop - -// ---------------------------------------------------------------------------- -// ---------------------------------------------------------------------------- -// func chacha20Poly1305Seal(dst, key, src, ad []byte) -TEXT ·chacha20Poly1305Seal(SB), 0, $288-96 - // For aligned stack access + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + LEAQ 384(SI), SI + LEAQ 384(DI), DI + SUBQ $0x00000180, BX + JMP openAVX2TailLoop + +DATA ·chacha20Constants<>+0(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+4(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+8(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+12(SB)/4, $0x6b206574 +DATA ·chacha20Constants<>+16(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+20(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+24(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+28(SB)/4, $0x6b206574 +GLOBL ·chacha20Constants<>(SB), RODATA|NOPTR, $32 + +DATA ·polyClampMask<>+0(SB)/8, $0x0ffffffc0fffffff +DATA ·polyClampMask<>+8(SB)/8, $0x0ffffffc0ffffffc +DATA ·polyClampMask<>+16(SB)/8, $0xffffffffffffffff +DATA ·polyClampMask<>+24(SB)/8, $0xffffffffffffffff +GLOBL ·polyClampMask<>(SB), RODATA|NOPTR, $32 + +DATA ·sseIncMask<>+0(SB)/8, $0x0000000000000001 +DATA ·sseIncMask<>+8(SB)/8, $0x0000000000000000 +GLOBL ·sseIncMask<>(SB), RODATA|NOPTR, $16 + +DATA ·andMask<>+0(SB)/8, $0x00000000000000ff +DATA ·andMask<>+8(SB)/8, $0x0000000000000000 +DATA ·andMask<>+16(SB)/8, $0x000000000000ffff +DATA ·andMask<>+24(SB)/8, $0x0000000000000000 +DATA ·andMask<>+32(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+40(SB)/8, $0x0000000000000000 +DATA ·andMask<>+48(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+56(SB)/8, $0x0000000000000000 +DATA ·andMask<>+64(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+72(SB)/8, $0x0000000000000000 +DATA ·andMask<>+80(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+88(SB)/8, $0x0000000000000000 +DATA ·andMask<>+96(SB)/8, $0x00ffffffffffffff +DATA ·andMask<>+104(SB)/8, $0x0000000000000000 +DATA ·andMask<>+112(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+120(SB)/8, $0x0000000000000000 +DATA ·andMask<>+128(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+136(SB)/8, $0x00000000000000ff +DATA ·andMask<>+144(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+152(SB)/8, $0x000000000000ffff +DATA ·andMask<>+160(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+168(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+176(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+184(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+192(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+200(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+208(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+216(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+224(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+232(SB)/8, $0x00ffffffffffffff +GLOBL ·andMask<>(SB), RODATA|NOPTR, $240 + +DATA ·avx2InitMask<>+0(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+16(SB)/8, $0x0000000000000001 +DATA ·avx2InitMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2InitMask<>(SB), RODATA|NOPTR, $32 + +DATA ·rol16<>+0(SB)/8, $0x0504070601000302 +DATA ·rol16<>+8(SB)/8, $0x0d0c0f0e09080b0a +DATA ·rol16<>+16(SB)/8, $0x0504070601000302 +DATA ·rol16<>+24(SB)/8, $0x0d0c0f0e09080b0a +GLOBL ·rol16<>(SB), RODATA|NOPTR, $32 + +DATA ·rol8<>+0(SB)/8, $0x0605040702010003 +DATA ·rol8<>+8(SB)/8, $0x0e0d0c0f0a09080b +DATA ·rol8<>+16(SB)/8, $0x0605040702010003 +DATA ·rol8<>+24(SB)/8, $0x0e0d0c0f0a09080b +GLOBL ·rol8<>(SB), RODATA|NOPTR, $32 + +DATA ·avx2IncMask<>+0(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2IncMask<>+16(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2IncMask<>(SB), RODATA|NOPTR, $32 + +// func chacha20Poly1305Seal(dst []byte, key []uint32, src []byte, ad []byte) +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Seal(SB), $288-96 MOVQ SP, BP - ADDQ $32, BP + ADDQ $0x20, BP ANDQ $-32, BP - MOVQ dst+0(FP), oup - MOVQ key+24(FP), keyp - MOVQ src+48(FP), inp - MOVQ src_len+56(FP), inl - MOVQ ad+72(FP), adp - - CMPB ·useAVX2(SB), $1 + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX + CMPB ·useAVX2+0(SB), $0x01 JE chacha20Poly1305Seal_AVX2 // Special optimization, for very short buffers - CMPQ inl, $128 - JBE sealSSE128 // About 15% faster + CMPQ BX, $0x80 + JBE sealSSE128 // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration - MOVOU ·chacha20Constants<>(SB), A0 - MOVOU (1*16)(keyp), B0 - MOVOU (2*16)(keyp), C0 - MOVOU (3*16)(keyp), D0 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 // Store state on stack for future use - MOVO B0, state1Store - MOVO C0, state2Store + MOVO X3, 32(BP) + MOVO X6, 48(BP) // Load state, increment counter blocks - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store - MOVQ $10, itr2 + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + MOVQ $0x0000000a, R9 sealSSEIntroLoop: - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - DECQ itr2 - JNE sealSSEIntroLoop + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JNE sealSSEIntroLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 // Clamp and store the key - PAND ·polyClampMask<>(SB), A0 - MOVO A0, rStore - MOVO B0, sStore + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) // Hash AAD - MOVQ ad_len+80(FP), itr2 - CALL polyHashADInternal<>(SB) - - MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 - PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 - MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) - MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 - PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 - MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup) - - MOVQ $128, itr1 - SUBQ $128, inl - LEAQ 128(inp), inp - - MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1 - - CMPQ inl, $64 - JBE sealSSE128SealHash - - MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 - PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 - MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup) - - ADDQ $64, itr1 - SUBQ $64, inl - LEAQ 64(inp), inp - - MOVQ $2, itr1 - MOVQ $8, itr2 - - CMPQ inl, $64 - JBE sealSSETail64 - CMPQ inl, $128 - JBE sealSSETail128 - CMPQ inl, $192 - JBE sealSSETail192 + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 64(DI) + MOVOU X5, 80(DI) + MOVOU X8, 96(DI) + MOVOU X11, 112(DI) + MOVQ $0x00000080, CX + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 + JBE sealSSE128SealHash + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 128(DI) + MOVOU X13, 144(DI) + MOVOU X14, 160(DI) + MOVOU X15, 176(DI) + ADDQ $0x40, CX + SUBQ $0x40, BX + LEAQ 64(SI), SI + MOVQ $0x00000002, CX + MOVQ $0x00000008, R9 + CMPQ BX, $0x40 + JBE sealSSETail64 + CMPQ BX, $0x80 + JBE sealSSETail128 + CMPQ BX, $0xc0 + JBE sealSSETail192 sealSSEMainLoop: // Load state, increment counter blocks - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) sealSSEInnerLoop: - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyAdd(0(oup)) - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - polyMulStage1 - polyMulStage2 - LEAQ (2*8)(oup), oup - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - polyMulStage3 - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyMulReduceStage - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - DECQ itr2 - JGE sealSSEInnerLoop - polyAdd(0(oup)) - polyMul - LEAQ (2*8)(oup), oup - DECQ itr1 - JG sealSSEInnerLoop + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(DI), DI + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JGE sealSSEInnerLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSEInnerLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 - MOVO D3, tmpStore + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) // Load - xor - store - MOVOU (0*16)(inp), D3; PXOR D3, A0 - MOVOU (1*16)(inp), D3; PXOR D3, B0 - MOVOU (2*16)(inp), D3; PXOR D3, C0 - MOVOU (3*16)(inp), D3; PXOR D3, D0 - MOVOU A0, (0*16)(oup) - MOVOU B0, (1*16)(oup) - MOVOU C0, (2*16)(oup) - MOVOU D0, (3*16)(oup) - MOVO tmpStore, D3 - - MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 - PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 - PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 - MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) - ADDQ $192, inp - MOVQ $192, itr1 - SUBQ $192, inl - MOVO A3, A1 - MOVO B3, B1 - MOVO C3, C1 - MOVO D3, D1 - CMPQ inl, $64 + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVO 64(BP), X15 + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + ADDQ $0xc0, SI + MOVQ $0x000000c0, CX + SUBQ $0xc0, BX + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 JBE sealSSE128SealHash - MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 - PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 - MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup) - LEAQ 64(inp), inp - SUBQ $64, inl - MOVQ $6, itr1 - MOVQ $4, itr2 - CMPQ inl, $192 + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 192(DI) + MOVOU X13, 208(DI) + MOVOU X14, 224(DI) + MOVOU X15, 240(DI) + LEAQ 64(SI), SI + SUBQ $0x40, BX + MOVQ $0x00000006, CX + MOVQ $0x00000004, R9 + CMPQ BX, $0xc0 JG sealSSEMainLoop - - MOVQ inl, itr1 - TESTQ inl, inl + MOVQ BX, CX + TESTQ BX, BX JE sealSSE128SealHash - MOVQ $6, itr1 - CMPQ inl, $64 + MOVQ $0x00000006, CX + CMPQ BX, $0x40 JBE sealSSETail64 - CMPQ inl, $128 + CMPQ BX, $0x80 JBE sealSSETail128 JMP sealSSETail192 -// ---------------------------------------------------------------------------- -// Special optimization for the last 64 bytes of plaintext sealSSETail64: - // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes - MOVO ·chacha20Constants<>(SB), A1 - MOVO state1Store, B1 - MOVO state2Store, C1 - MOVO ctr3Store, D1 - PADDL ·sseIncMask<>(SB), D1 - MOVO D1, ctr0Store + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) sealSSETail64LoopA: - // Perform ChaCha rounds, while hashing the previously encrypted ciphertext - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealSSETail64LoopB: - chachaQR(A1, B1, C1, D1, T1) - shiftB1Left; shiftC1Left; shiftD1Left - chachaQR(A1, B1, C1, D1, T1) - shiftB1Right; shiftC1Right; shiftD1Right - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup - - DECQ itr1 - JG sealSSETail64LoopA - - DECQ itr2 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSETail64LoopA + DECQ R9 JGE sealSSETail64LoopB - PADDL ·chacha20Constants<>(SB), A1 - PADDL state1Store, B1 - PADDL state2Store, C1 - PADDL ctr0Store, D1 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X4 + PADDL 48(BP), X7 + PADDL 80(BP), X10 + JMP sealSSE128Seal - JMP sealSSE128Seal - -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of plaintext sealSSETail128: - // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) sealSSETail128LoopA: - // Perform ChaCha rounds, while hashing the previously encrypted ciphertext - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealSSETail128LoopB: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - - DECQ itr1 - JG sealSSETail128LoopA - - DECQ itr2 - JGE sealSSETail128LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 - PADDL state1Store, B0; PADDL state1Store, B1 - PADDL state2Store, C0; PADDL state2Store, C1 - PADDL ctr0Store, D0; PADDL ctr1Store, D1 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 - MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) - - MOVQ $64, itr1 - LEAQ 64(inp), inp - SUBQ $64, inl - - JMP sealSSE128SealHash - -// ---------------------------------------------------------------------------- -// Special optimization for the last 192 bytes of plaintext + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + DECQ CX + JG sealSSETail128LoopA + DECQ R9 + JGE sealSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVQ $0x00000040, CX + LEAQ 64(SI), SI + SUBQ $0x40, BX + JMP sealSSE128SealHash + sealSSETail192: - // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr2Store + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 112(BP) sealSSETail192LoopA: - // Perform ChaCha rounds, while hashing the previously encrypted ciphertext - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealSSETail192LoopB: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - shiftB2Left; shiftC2Left; shiftD2Left - - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup - - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - shiftB2Right; shiftC2Right; shiftD2Right - - DECQ itr1 - JG sealSSETail192LoopA - - DECQ itr2 - JGE sealSSETail192LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 - PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 - PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 - MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) - MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 - PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - - MOVO A2, A1 - MOVO B2, B1 - MOVO C2, C1 - MOVO D2, D1 - MOVQ $128, itr1 - LEAQ 128(inp), inp - SUBQ $128, inl - - JMP sealSSE128SealHash - -// ---------------------------------------------------------------------------- -// Special seal optimization for buffers smaller than 129 bytes + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ CX + JG sealSSETail192LoopA + DECQ R9 + JGE sealSSETail192LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + PADDL 112(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + JMP sealSSE128SealHash + sealSSE128: - // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks - MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 - MOVQ $10, itr2 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 sealSSE128InnerCipherLoop: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftB1Left; shiftB2Left - shiftC0Left; shiftC1Left; shiftC2Left - shiftD0Left; shiftD1Left; shiftD2Left - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftB1Right; shiftB2Right - shiftC0Right; shiftC1Right; shiftC2Right - shiftD0Right; shiftD1Right; shiftD2Right - DECQ itr2 - JNE sealSSE128InnerCipherLoop + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE sealSSE128InnerCipherLoop // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 - PADDL T2, C1; PADDL T2, C2 - PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 - PAND ·polyClampMask<>(SB), A0 - MOVOU A0, rStore - MOVOU B0, sStore + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) // Hash - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ itr1, itr1 + XORQ CX, CX sealSSE128SealHash: - // itr1 holds the number of bytes encrypted but not yet hashed - CMPQ itr1, $16 - JB sealSSE128Seal - polyAdd(0(oup)) - polyMul - - SUBQ $16, itr1 - ADDQ $16, oup - - JMP sealSSE128SealHash + CMPQ CX, $0x10 + JB sealSSE128Seal + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + ADDQ $0x10, DI + JMP sealSSE128SealHash sealSSE128Seal: - CMPQ inl, $16 + CMPQ BX, $0x10 JB sealSSETail - SUBQ $16, inl + SUBQ $0x10, BX // Load for decryption - MOVOU (inp), T0 - PXOR T0, A1 - MOVOU A1, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI // Extract for hashing - MOVQ A1, t0 - PSRLDQ $8, A1 - MOVQ A1, t1 - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Shift the stream "left" - MOVO B1, A1 - MOVO C1, B1 - MOVO D1, C1 - MOVO A2, D1 - MOVO B2, A2 - MOVO C2, B2 - MOVO D2, C2 + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 JMP sealSSE128Seal sealSSETail: - TESTQ inl, inl + TESTQ BX, BX JE sealSSEFinalize // We can only load the PT one byte at a time to avoid read after end of buffer - MOVQ inl, itr2 - SHLQ $4, itr2 - LEAQ ·andMask<>(SB), t0 - MOVQ inl, itr1 - LEAQ -1(inp)(inl*1), inp - XORQ t2, t2 - XORQ t3, t3 + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVQ BX, CX + LEAQ -1(SI)(BX*1), SI + XORQ R15, R15 + XORQ R8, R8 XORQ AX, AX sealSSETailLoadLoop: - SHLQ $8, t2, t3 - SHLQ $8, t2 - MOVB (inp), AX - XORQ AX, t2 - LEAQ -1(inp), inp - DECQ itr1 + SHLQ $0x08, R15, R8 + SHLQ $0x08, R15 + MOVB (SI), AX + XORQ AX, R15 + LEAQ -1(SI), SI + DECQ CX JNE sealSSETailLoadLoop - MOVQ t2, 0+tmpStore - MOVQ t3, 8+tmpStore - PXOR 0+tmpStore, A1 - MOVOU A1, (oup) - MOVOU -16(t0)(itr2*1), T0 - PAND T0, A1 - MOVQ A1, t0 - PSRLDQ $8, A1 - MOVQ A1, t1 - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul - - ADDQ inl, oup + MOVQ R15, 64(BP) + MOVQ R8, 72(BP) + PXOR 64(BP), X1 + MOVOU X1, (DI) + MOVOU -16(R13)(R9*1), X12 + PAND X12, X1 + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ BX, DI sealSSEFinalize: // Hash in the buffer lengths - ADDQ ad_len+80(FP), acc0 - ADCQ src_len+56(FP), acc1 - ADCQ $1, acc2 - polyMul + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Final reduce - MOVQ acc0, t0 - MOVQ acc1, t1 - MOVQ acc2, t2 - SUBQ $-5, acc0 - SBBQ $-1, acc1 - SBBQ $3, acc2 - CMOVQCS t0, acc0 - CMOVQCS t1, acc1 - CMOVQCS t2, acc2 + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 // Add in the "s" part of the key - ADDQ 0+sStore, acc0 - ADCQ 8+sStore, acc1 + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 // Finally store the tag at the end of the message - MOVQ acc0, (0*8)(oup) - MOVQ acc1, (1*8)(oup) + MOVQ R10, (DI) + MOVQ R11, 8(DI) RET -// ---------------------------------------------------------------------------- -// ------------------------- AVX2 Code ---------------------------------------- chacha20Poly1305Seal_AVX2: VZEROUPPER - VMOVDQU ·chacha20Constants<>(SB), AA0 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 - BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 - VPADDD ·avx2InitMask<>(SB), DD0, DD0 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 // Special optimizations, for very short buffers - CMPQ inl, $192 - JBE seal192AVX2 // 33% faster - CMPQ inl, $320 - JBE seal320AVX2 // 17% faster + CMPQ BX, $0x000000c0 + JBE seal192AVX2 + CMPQ BX, $0x00000140 + JBE seal320AVX2 // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream - VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2 - VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2 - VPADDD ·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2 - VPADDD ·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2 - VPADDD ·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2 - VMOVDQA DD3, ctr3StoreAVX2 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA Y12, 64(BP) + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, 96(BP) + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y1, 128(BP) + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + MOVQ $0x0000000a, R9 sealAVX2IntroLoop: - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 - VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 - VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 - VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 - - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 - VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 - VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 - VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 - DECQ itr2 - JNE sealAVX2IntroLoop - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - - VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127 - VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key - VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y3, Y3, Y3 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ R9 + JNE sealAVX2IntroLoop + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPERM2I128 $0x02, Y0, Y14, Y4 + VPERM2I128 $0x13, Y0, Y14, Y0 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), DD0, DD0 - VMOVDQA DD0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y4, Y4 + VMOVDQA Y4, (BP) // Hash AD - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) // Can store at least 320 bytes - VPXOR (0*32)(inp), AA0, AA0 - VPXOR (1*32)(inp), CC0, CC0 - VMOVDQU AA0, (0*32)(oup) - VMOVDQU CC0, (1*32)(oup) - - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0 - VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup) - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0 - VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup) - - MOVQ $320, itr1 - SUBQ $320, inl - LEAQ 320(inp), inp - - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0 - CMPQ inl, $128 + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y12, Y12 + VMOVDQU Y0, (DI) + VMOVDQU Y12, 32(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 64(SI), Y0, Y0 + VPXOR 96(SI), Y14, Y14 + VPXOR 128(SI), Y12, Y12 + VPXOR 160(SI), Y4, Y4 + VMOVDQU Y0, 64(DI) + VMOVDQU Y14, 96(DI) + VMOVDQU Y12, 128(DI) + VMOVDQU Y4, 160(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 192(SI), Y0, Y0 + VPXOR 224(SI), Y14, Y14 + VPXOR 256(SI), Y12, Y12 + VPXOR 288(SI), Y4, Y4 + VMOVDQU Y0, 192(DI) + VMOVDQU Y14, 224(DI) + VMOVDQU Y12, 256(DI) + VMOVDQU Y4, 288(DI) + MOVQ $0x00000140, CX + SUBQ $0x00000140, BX + LEAQ 320(SI), SI + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, Y15, Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, Y15, Y3, Y4 + CMPQ BX, $0x80 JBE sealAVX2SealHash - - VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0 - VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup) - SUBQ $128, inl - LEAQ 128(inp), inp - - MOVQ $8, itr1 - MOVQ $2, itr2 - - CMPQ inl, $128 - JBE sealAVX2Tail128 - CMPQ inl, $256 - JBE sealAVX2Tail256 - CMPQ inl, $384 - JBE sealAVX2Tail384 - CMPQ inl, $512 - JBE sealAVX2Tail512 + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VPXOR 64(SI), Y12, Y12 + VPXOR 96(SI), Y4, Y4 + VMOVDQU Y0, 320(DI) + VMOVDQU Y14, 352(DI) + VMOVDQU Y12, 384(DI) + VMOVDQU Y4, 416(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVQ $0x00000008, CX + MOVQ $0x00000002, R9 + CMPQ BX, $0x80 + JBE sealAVX2Tail128 + CMPQ BX, $0x00000100 + JBE sealAVX2Tail256 + CMPQ BX, $0x00000180 + JBE sealAVX2Tail384 + CMPQ BX, $0x00000200 + JBE sealAVX2Tail512 // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 - VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 - VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 - VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 - - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 - VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 - VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 - VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - - SUBQ $16, oup // Adjust the pointer - MOVQ $9, itr1 - JMP sealAVX2InternalLoopStart + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y3, Y3, Y3 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + SUBQ $0x10, DI + MOVQ $0x00000009, CX + JMP sealAVX2InternalLoopStart sealAVX2MainLoop: - // Load state, increment counter blocks, store the incremented counters - VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - MOVQ $10, itr1 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + MOVQ $0x0000000a, CX sealAVX2InternalLoop: - polyAdd(0*8(oup)) - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage1_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulStage2_AVX2 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyMulStage3_AVX2 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 sealAVX2InternalLoopStart: - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - polyAdd(2*8(oup)) - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage1_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage2_AVX2 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage3_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulReduceStage - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(4*8(oup)) - LEAQ (6*8)(oup), oup - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage1_AVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - polyMulStage2_AVX2 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage3_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - DECQ itr1 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(DI), R10 + ADCQ 40(DI), R11 + ADCQ $0x01, R12 + LEAQ 48(DI), DI + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ CX JNE sealAVX2InternalLoop - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) // We only hashed 480 of the 512 bytes available - hash the remaining 32 here - polyAdd(0*8(oup)) - polyMulAVX2 - LEAQ (4*8)(oup), oup - VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 - VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 - VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) // and here - polyAdd(-2*8(oup)) - polyMulAVX2 - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 - VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) - LEAQ (32*16)(inp), inp - SUBQ $(32*16), inl - CMPQ inl, $512 + ADDQ -16(DI), R10 + ADCQ -8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + SUBQ $0x00000200, BX + CMPQ BX, $0x00000200 JG sealAVX2MainLoop // Tail can only hash 480 bytes - polyAdd(0*8(oup)) - polyMulAVX2 - polyAdd(2*8(oup)) - polyMulAVX2 - LEAQ 32(oup), oup - - MOVQ $10, itr1 - MOVQ $0, itr2 - CMPQ inl, $128 - JBE sealAVX2Tail128 - CMPQ inl, $256 - JBE sealAVX2Tail256 - CMPQ inl, $384 - JBE sealAVX2Tail384 - JMP sealAVX2Tail512 - -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 193 bytes + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + MOVQ $0x0000000a, CX + MOVQ $0x00000000, R9 + CMPQ BX, $0x80 + JBE sealAVX2Tail128 + CMPQ BX, $0x00000100 + JBE sealAVX2Tail256 + CMPQ BX, $0x00000180 + JBE sealAVX2Tail384 + JMP sealAVX2Tail512 + seal192AVX2: - // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks - VMOVDQA AA0, AA1 - VMOVDQA BB0, BB1 - VMOVDQA CC0, CC1 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2 - VMOVDQA BB0, BB2 - VMOVDQA CC0, CC2 - VMOVDQA DD0, DD2 - VMOVDQA DD1, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 sealAVX2192InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 JNE sealAVX2192InnerCipherLoop - VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 - VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 - VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 - VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, TT0 + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 192 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 sealAVX2ShortSeal: // Hash aad - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ itr1, itr1 + XORQ CX, CX sealAVX2SealHash: // itr1 holds the number of bytes encrypted but not yet hashed - CMPQ itr1, $16 - JB sealAVX2ShortSealLoop - polyAdd(0(oup)) - polyMul - SUBQ $16, itr1 - ADDQ $16, oup - JMP sealAVX2SealHash + CMPQ CX, $0x10 + JB sealAVX2ShortSealLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + ADDQ $0x10, DI + JMP sealAVX2SealHash sealAVX2ShortSealLoop: - CMPQ inl, $32 + CMPQ BX, $0x20 JB sealAVX2ShortTail32 - SUBQ $32, inl + SUBQ $0x20, BX // Load for encryption - VPXOR (inp), AA0, AA0 - VMOVDQU AA0, (oup) - LEAQ (1*32)(inp), inp + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI // Now can hash - polyAdd(0*8(oup)) - polyMulAVX2 - polyAdd(2*8(oup)) - polyMulAVX2 - LEAQ (1*32)(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI // Shift stream left - VMOVDQA BB0, AA0 - VMOVDQA CC0, BB0 - VMOVDQA DD0, CC0 - VMOVDQA AA1, DD0 - VMOVDQA BB1, AA1 - VMOVDQA CC1, BB1 - VMOVDQA DD1, CC1 - VMOVDQA AA2, DD1 - VMOVDQA BB2, AA2 + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 JMP sealAVX2ShortSealLoop sealAVX2ShortTail32: - CMPQ inl, $16 - VMOVDQA A0, A1 + CMPQ BX, $0x10 + VMOVDQA X0, X1 JB sealAVX2ShortDone - - SUBQ $16, inl + SUBQ $0x10, BX // Load for encryption - VPXOR (inp), A0, T0 - VMOVDQU T0, (oup) - LEAQ (1*16)(inp), inp + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI // Hash - polyAdd(0*8(oup)) - polyMulAVX2 - LEAQ (1*16)(oup), oup - VPERM2I128 $0x11, AA0, AA0, AA0 - VMOVDQA A0, A1 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 sealAVX2ShortDone: VZEROUPPER JMP sealSSETail -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 321 bytes seal320AVX2: - // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks - VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 sealAVX2320InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ R9 JNE sealAVX2320InnerCipherLoop - - VMOVDQA ·chacha20Constants<>(SB), TT0 - VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 - VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 - VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 - VMOVDQA ·avx2IncMask<>(SB), TT0 - VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD2, DD2 + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 // Clamp and store poly key - VPERM2I128 $0x02, AA0, BB0, TT0 - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 320 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 - VPERM2I128 $0x02, AA2, BB2, CC1 - VPERM2I128 $0x02, CC2, DD2, DD1 - VPERM2I128 $0x13, AA2, BB2, AA2 - VPERM2I128 $0x13, CC2, DD2, BB2 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 JMP sealAVX2ShortSeal -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of ciphertext sealAVX2Tail128: - // Need to decrypt up to 128 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0 - VMOVDQA state1StoreAVX2, BB0 - VMOVDQA state2StoreAVX2, CC0 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VMOVDQA DD0, DD1 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA 32(BP), Y14 + VMOVDQA 64(BP), Y12 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VMOVDQA Y4, Y1 sealAVX2Tail128LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail128LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - polyAdd(0(oup)) - polyMul - VPALIGNR $4, BB0, BB0, BB0 - VPALIGNR $8, CC0, CC0, CC0 - VPALIGNR $12, DD0, DD0, DD0 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - polyAdd(16(oup)) - polyMul - LEAQ 32(oup), oup - VPALIGNR $12, BB0, BB0, BB0 - VPALIGNR $8, CC0, CC0, CC0 - VPALIGNR $4, DD0, DD0, DD0 - DECQ itr1 - JG sealAVX2Tail128LoopA - DECQ itr2 - JGE sealAVX2Tail128LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA1 - VPADDD state1StoreAVX2, BB0, BB1 - VPADDD state2StoreAVX2, CC0, CC1 - VPADDD DD1, DD0, DD1 - - VPERM2I128 $0x02, AA1, BB1, AA0 - VPERM2I128 $0x02, CC1, DD1, BB0 - VPERM2I128 $0x13, AA1, BB1, CC0 - VPERM2I128 $0x13, CC1, DD1, DD0 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ CX + JG sealAVX2Tail128LoopA + DECQ R9 + JGE sealAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y5 + VPADDD 32(BP), Y14, Y9 + VPADDD 64(BP), Y12, Y13 + VPADDD Y1, Y4, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 JMP sealAVX2ShortSealLoop -// ---------------------------------------------------------------------------- -// Special optimization for the last 256 bytes of ciphertext sealAVX2Tail256: - // Need to decrypt up to 256 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA ·chacha20Constants<>(SB), AA1 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA DD0, TT1 - VMOVDQA DD1, TT2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 sealAVX2Tail256LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail256LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - polyAdd(0(oup)) - polyMul - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - polyAdd(16(oup)) - polyMul - LEAQ 32(oup), oup - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - DECQ itr1 - JG sealAVX2Tail256LoopA - DECQ itr2 - JGE sealAVX2Tail256LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 - VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, TT0 - VPERM2I128 $0x02, CC0, DD0, TT1 - VPERM2I128 $0x13, AA0, BB0, TT2 - VPERM2I128 $0x13, CC0, DD0, TT3 - VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 - VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) - MOVQ $128, itr1 - LEAQ 128(inp), inp - SUBQ $128, inl - VPERM2I128 $0x02, AA1, BB1, AA0 - VPERM2I128 $0x02, CC1, DD1, BB0 - VPERM2I128 $0x13, AA1, BB1, CC0 - VPERM2I128 $0x13, CC1, DD1, DD0 - - JMP sealAVX2SealHash - -// ---------------------------------------------------------------------------- -// Special optimization for the last 384 bytes of ciphertext + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ CX + JG sealAVX2Tail256LoopA + DECQ R9 + JGE sealAVX2Tail256LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + JMP sealAVX2SealHash + sealAVX2Tail384: - // Need to decrypt up to 384 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 + VMOVDQA Y2, Y15 sealAVX2Tail384LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail384LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - polyAdd(0(oup)) - polyMul - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - polyAdd(16(oup)) - polyMul - LEAQ 32(oup), oup - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - DECQ itr1 - JG sealAVX2Tail384LoopA - DECQ itr2 - JGE sealAVX2Tail384LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 - VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2 - VPERM2I128 $0x02, AA0, BB0, TT0 - VPERM2I128 $0x02, CC0, DD0, TT1 - VPERM2I128 $0x13, AA0, BB0, TT2 - VPERM2I128 $0x13, CC0, DD0, TT3 - VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 - VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, TT0 - VPERM2I128 $0x02, CC1, DD1, TT1 - VPERM2I128 $0x13, AA1, BB1, TT2 - VPERM2I128 $0x13, CC1, DD1, TT3 - VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 - VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) - MOVQ $256, itr1 - LEAQ 256(inp), inp - SUBQ $256, inl - VPERM2I128 $0x02, AA2, BB2, AA0 - VPERM2I128 $0x02, CC2, DD2, BB0 - VPERM2I128 $0x13, AA2, BB2, CC0 - VPERM2I128 $0x13, CC2, DD2, DD0 - - JMP sealAVX2SealHash - -// ---------------------------------------------------------------------------- -// Special optimization for the last 512 bytes of ciphertext + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ CX + JG sealAVX2Tail384LoopA + DECQ R9 + JGE sealAVX2Tail384LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPADDD Y15, Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + MOVQ $0x00000100, CX + LEAQ 256(SI), SI + SUBQ $0x00000100, BX + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + JMP sealAVX2SealHash + sealAVX2Tail512: - // Need to decrypt up to 512 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) sealAVX2Tail512LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail512LoopB: - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyAdd(0*8(oup)) - polyMulAVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(2*8(oup)) - polyMulAVX2 - LEAQ (4*8)(oup), oup - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - - DECQ itr1 - JG sealAVX2Tail512LoopA - DECQ itr2 - JGE sealAVX2Tail512LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 - VPERM2I128 $0x02, AA0, BB0, CC3 - VPXOR (0*32)(inp), CC3, CC3 - VMOVDQU CC3, (0*32)(oup) - VPERM2I128 $0x02, CC0, DD0, CC3 - VPXOR (1*32)(inp), CC3, CC3 - VMOVDQU CC3, (1*32)(oup) - VPERM2I128 $0x13, AA0, BB0, CC3 - VPXOR (2*32)(inp), CC3, CC3 - VMOVDQU CC3, (2*32)(oup) - VPERM2I128 $0x13, CC0, DD0, CC3 - VPXOR (3*32)(inp), CC3, CC3 - VMOVDQU CC3, (3*32)(oup) - - VPERM2I128 $0x02, AA1, BB1, AA0 - VPERM2I128 $0x02, CC1, DD1, BB0 - VPERM2I128 $0x13, AA1, BB1, CC0 - VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) - - VPERM2I128 $0x02, AA2, BB2, AA0 - VPERM2I128 $0x02, CC2, DD2, BB0 - VPERM2I128 $0x13, AA2, BB2, CC0 - VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - - MOVQ $384, itr1 - LEAQ 384(inp), inp - SUBQ $384, inl - VPERM2I128 $0x02, AA3, BB3, AA0 - VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0 - VPERM2I128 $0x13, AA3, BB3, CC0 - VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - - JMP sealAVX2SealHash + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ CX + JG sealAVX2Tail512LoopA + DECQ R9 + JGE sealAVX2Tail512LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPXOR (SI), Y15, Y15 + VMOVDQU Y15, (DI) + VPERM2I128 $0x02, Y12, Y4, Y15 + VPXOR 32(SI), Y15, Y15 + VMOVDQU Y15, 32(DI) + VPERM2I128 $0x13, Y0, Y14, Y15 + VPXOR 64(SI), Y15, Y15 + VMOVDQU Y15, 64(DI) + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + MOVQ $0x00000180, CX + LEAQ 384(SI), SI + SUBQ $0x00000180, BX + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + JMP sealAVX2SealHash diff --git a/chacha20poly1305/chacha20poly1305_generic.go b/chacha20poly1305/chacha20poly1305_generic.go index c27971216c..2ecc840fca 100644 --- a/chacha20poly1305/chacha20poly1305_generic.go +++ b/chacha20poly1305/chacha20poly1305_generic.go @@ -7,69 +7,75 @@ package chacha20poly1305 import ( "encoding/binary" - "golang.org/x/crypto/internal/chacha20" - "golang.org/x/crypto/internal/subtle" - "golang.org/x/crypto/poly1305" + "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/alias" + "golang.org/x/crypto/internal/poly1305" ) -func roundTo16(n int) int { - return 16 * ((n + 15) / 16) +func writeWithPadding(p *poly1305.MAC, b []byte) { + p.Write(b) + if rem := len(b) % 16; rem != 0 { + var buf [16]byte + padLen := 16 - rem + p.Write(buf[:padLen]) + } +} + +func writeUint64(p *poly1305.MAC, n int) { + var buf [8]byte + binary.LittleEndian.PutUint64(buf[:], uint64(n)) + p.Write(buf[:]) } func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) - if subtle.InexactOverlap(out, plaintext) { - panic("chacha20poly1305: invalid buffer overlap") + ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] + if alias.InexactOverlap(out, plaintext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") } var polyKey [32]byte - s := chacha20.New(c.key, [3]uint32{ - binary.LittleEndian.Uint32(nonce[0:4]), - binary.LittleEndian.Uint32(nonce[4:8]), - binary.LittleEndian.Uint32(nonce[8:12]), - }) + s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) s.XORKeyStream(polyKey[:], polyKey[:]) - s.Advance() // skip the next 32 bytes - s.XORKeyStream(out, plaintext) - - polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8) - copy(polyInput, additionalData) - copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)]) - binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) - binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext))) + s.SetCounter(1) // set the counter to 1, skipping 32 bytes + s.XORKeyStream(ciphertext, plaintext) - var tag [poly1305.TagSize]byte - poly1305.Sum(&tag, polyInput, &polyKey) - copy(out[len(plaintext):], tag[:]) + p := poly1305.New(&polyKey) + writeWithPadding(p, additionalData) + writeWithPadding(p, ciphertext) + writeUint64(p, len(additionalData)) + writeUint64(p, len(plaintext)) + p.Sum(tag[:0]) return ret } func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { - var tag [poly1305.TagSize]byte - copy(tag[:], ciphertext[len(ciphertext)-16:]) + tag := ciphertext[len(ciphertext)-16:] ciphertext = ciphertext[:len(ciphertext)-16] var polyKey [32]byte - s := chacha20.New(c.key, [3]uint32{ - binary.LittleEndian.Uint32(nonce[0:4]), - binary.LittleEndian.Uint32(nonce[4:8]), - binary.LittleEndian.Uint32(nonce[8:12]), - }) + s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) s.XORKeyStream(polyKey[:], polyKey[:]) - s.Advance() // skip the next 32 bytes + s.SetCounter(1) // set the counter to 1, skipping 32 bytes - polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8) - copy(polyInput, additionalData) - copy(polyInput[roundTo16(len(additionalData)):], ciphertext) - binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) - binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext))) + p := poly1305.New(&polyKey) + writeWithPadding(p, additionalData) + writeWithPadding(p, ciphertext) + writeUint64(p, len(additionalData)) + writeUint64(p, len(ciphertext)) ret, out := sliceForAppend(dst, len(ciphertext)) - if subtle.InexactOverlap(out, ciphertext) { - panic("chacha20poly1305: invalid buffer overlap") + if alias.InexactOverlap(out, ciphertext) { + panic("chacha20poly1305: invalid buffer overlap of output and input") + } + if alias.AnyOverlap(out, additionalData) { + panic("chacha20poly1305: invalid buffer overlap of output and additional data") } - if !poly1305.Verify(&tag, polyInput, &polyKey) { + if !p.Verify(tag) { for i := range out { out[i] = 0 } diff --git a/chacha20poly1305/chacha20poly1305_noasm.go b/chacha20poly1305/chacha20poly1305_noasm.go index 4c2eb703c3..34e6ab1df8 100644 --- a/chacha20poly1305/chacha20poly1305_noasm.go +++ b/chacha20poly1305/chacha20poly1305_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 !go1.7 gccgo appengine +//go:build !amd64 || !gc || purego package chacha20poly1305 diff --git a/chacha20poly1305/chacha20poly1305_test.go b/chacha20poly1305/chacha20poly1305_test.go index a23af5df72..b38970d177 100644 --- a/chacha20poly1305/chacha20poly1305_test.go +++ b/chacha20poly1305/chacha20poly1305_test.go @@ -10,7 +10,6 @@ import ( cryptorand "crypto/rand" "encoding/hex" "fmt" - "log" mathrand "math/rand" "strconv" "testing" @@ -154,7 +153,7 @@ func TestRandom(t *testing.T) { t.Run("X", func(t *testing.T) { f(t, NonceSizeX) }) } -func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) { +func benchmarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) { b.ReportAllocs() b.SetBytes(int64(len(buf))) @@ -177,7 +176,7 @@ func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) { } } -func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) { +func benchmarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) { b.ReportAllocs() b.SetBytes(int64(len(buf))) @@ -205,51 +204,65 @@ func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) { func BenchmarkChacha20Poly1305(b *testing.B) { for _, length := range []int{64, 1350, 8 * 1024} { b.Run("Open-"+strconv.Itoa(length), func(b *testing.B) { - benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSize) + benchmarkChaCha20Poly1305Open(b, make([]byte, length), NonceSize) }) b.Run("Seal-"+strconv.Itoa(length), func(b *testing.B) { - benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSize) + benchmarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSize) }) b.Run("Open-"+strconv.Itoa(length)+"-X", func(b *testing.B) { - benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSizeX) + benchmarkChaCha20Poly1305Open(b, make([]byte, length), NonceSizeX) }) b.Run("Seal-"+strconv.Itoa(length)+"-X", func(b *testing.B) { - benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSizeX) + benchmarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSizeX) }) } } -var key = make([]byte, KeySize) - func ExampleNewX() { + // key should be randomly generated or derived from a function like Argon2. + key := make([]byte, KeySize) + if _, err := cryptorand.Read(key); err != nil { + panic(err) + } + aead, err := NewX(key) if err != nil { - log.Fatalln("Failed to instantiate XChaCha20-Poly1305:", err) + panic(err) } - for _, msg := range []string{ - "Attack at dawn.", - "The eagle has landed.", - "Gophers, gophers, gophers everywhere!", - } { - // Encryption. - nonce := make([]byte, NonceSizeX) + // Encryption. + var encryptedMsg []byte + { + msg := []byte("Gophers, gophers, gophers everywhere!") + + // Select a random nonce, and leave capacity for the ciphertext. + nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead()) if _, err := cryptorand.Read(nonce); err != nil { panic(err) } - ciphertext := aead.Seal(nil, nonce, []byte(msg), nil) - // Decryption. + // Encrypt the message and append the ciphertext to the nonce. + encryptedMsg = aead.Seal(nonce, nonce, msg, nil) + } + + // Decryption. + { + if len(encryptedMsg) < aead.NonceSize() { + panic("ciphertext too short") + } + + // Split nonce and ciphertext. + nonce, ciphertext := encryptedMsg[:aead.NonceSize()], encryptedMsg[aead.NonceSize():] + + // Decrypt the message and check it wasn't tampered with. plaintext, err := aead.Open(nil, nonce, ciphertext, nil) if err != nil { - log.Fatalln("Failed to decrypt or authenticate message:", err) + panic(err) } fmt.Printf("%s\n", plaintext) } - // Output: Attack at dawn. - // The eagle has landed. - // Gophers, gophers, gophers everywhere! + // Output: Gophers, gophers, gophers everywhere! } diff --git a/chacha20poly1305/chacha20poly1305_vectors_test.go b/chacha20poly1305/chacha20poly1305_vectors_test.go index fa3607e8ab..76823d13e6 100644 --- a/chacha20poly1305/chacha20poly1305_vectors_test.go +++ b/chacha20poly1305/chacha20poly1305_vectors_test.go @@ -15,11 +15,12 @@ var chacha20Poly1305Tests = []struct { "a0784d7a4716f3feb4f64e7f4b39bf04", }, { + // https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-01#appendix-A.3.1 "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", "50515253c0c1c2c3c4c5c6c7", "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", - "070000004041424344454647", - "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691", + "404142434445464748494a4b4c4d4e4f5051525354555657", + "bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52ec0875924c1c7987947deafd8780acf49", }, { "1400000cebccee3bf561b292340fec60", diff --git a/chacha20poly1305/xchacha20poly1305.go b/chacha20poly1305/xchacha20poly1305.go index a02fa57192..1cebfe946f 100644 --- a/chacha20poly1305/xchacha20poly1305.go +++ b/chacha20poly1305/xchacha20poly1305.go @@ -6,14 +6,13 @@ package chacha20poly1305 import ( "crypto/cipher" - "encoding/binary" "errors" - "golang.org/x/crypto/internal/chacha20" + "golang.org/x/crypto/chacha20" ) type xchacha20poly1305 struct { - key [8]uint32 + key [KeySize]byte } // NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. @@ -27,14 +26,7 @@ func NewX(key []byte) (cipher.AEAD, error) { return nil, errors.New("chacha20poly1305: bad key length") } ret := new(xchacha20poly1305) - ret.key[0] = binary.LittleEndian.Uint32(key[0:4]) - ret.key[1] = binary.LittleEndian.Uint32(key[4:8]) - ret.key[2] = binary.LittleEndian.Uint32(key[8:12]) - ret.key[3] = binary.LittleEndian.Uint32(key[12:16]) - ret.key[4] = binary.LittleEndian.Uint32(key[16:20]) - ret.key[5] = binary.LittleEndian.Uint32(key[20:24]) - ret.key[6] = binary.LittleEndian.Uint32(key[24:28]) - ret.key[7] = binary.LittleEndian.Uint32(key[28:32]) + copy(ret.key[:], key) return ret, nil } @@ -43,7 +35,7 @@ func (*xchacha20poly1305) NonceSize() int { } func (*xchacha20poly1305) Overhead() int { - return 16 + return Overhead } func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { @@ -60,15 +52,10 @@ func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) [ panic("chacha20poly1305: plaintext too large") } - hNonce := [4]uint32{ - binary.LittleEndian.Uint32(nonce[0:4]), - binary.LittleEndian.Uint32(nonce[4:8]), - binary.LittleEndian.Uint32(nonce[8:12]), - binary.LittleEndian.Uint32(nonce[12:16]), - } - c := &chacha20poly1305{ - key: chacha20.HChaCha20(&x.key, &hNonce), - } + c := new(chacha20poly1305) + hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) + copy(c.key[:], hKey) + // The first 4 bytes of the final nonce are unused counter space. cNonce := make([]byte, NonceSize) copy(cNonce[4:12], nonce[16:24]) @@ -87,15 +74,10 @@ func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) panic("chacha20poly1305: ciphertext too large") } - hNonce := [4]uint32{ - binary.LittleEndian.Uint32(nonce[0:4]), - binary.LittleEndian.Uint32(nonce[4:8]), - binary.LittleEndian.Uint32(nonce[8:12]), - binary.LittleEndian.Uint32(nonce[12:16]), - } - c := &chacha20poly1305{ - key: chacha20.HChaCha20(&x.key, &hNonce), - } + c := new(chacha20poly1305) + hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) + copy(c.key[:], hKey) + // The first 4 bytes of the final nonce are unused counter space. cNonce := make([]byte, NonceSize) copy(cNonce[4:12], nonce[16:24]) diff --git a/cryptobyte/asn1.go b/cryptobyte/asn1.go index 528b9bff67..d25979d9f5 100644 --- a/cryptobyte/asn1.go +++ b/cryptobyte/asn1.go @@ -81,7 +81,7 @@ func (b *Builder) AddASN1BigInt(n *big.Int) { for i := range bytes { bytes[i] ^= 0xff } - if bytes[0]&0x80 == 0 { + if len(bytes) == 0 || bytes[0]&0x80 == 0 { c.add(0xff) } c.add(bytes...) @@ -117,6 +117,19 @@ func (b *Builder) AddASN1GeneralizedTime(t time.Time) { }) } +// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. +func (b *Builder) AddASN1UTCTime(t time.Time) { + b.AddASN1(asn1.UTCTime, func(c *Builder) { + // As utilized by the X.509 profile, UTCTime can only + // represent the years 1950 through 2049. + if t.Year() < 1950 || t.Year() >= 2050 { + b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) + return + } + c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) + }) +} + // AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not // support BIT STRINGs that are not a whole number of bytes. func (b *Builder) AddASN1BitString(data []byte) { @@ -221,7 +234,7 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { // Identifiers with the low five bits set indicate high-tag-number format // (two or more octets), which we don't support. if tag&0x1f == 0x1f { - b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) + b.err = fmt.Errorf("cryptobyte: high-tag number identifier octets not supported: 0x%x", tag) return } b.AddUint8(uint8(tag)) @@ -230,12 +243,12 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { // String -// ReadASN1Boolean decodes an ASN.1 INTEGER and converts it to a boolean +// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean // representation into out and advances. It reports whether the read // was successful. func (s *String) ReadASN1Boolean(out *bool) bool { var bytes String - if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 { + if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { return false } @@ -251,36 +264,35 @@ func (s *String) ReadASN1Boolean(out *bool) bool { return true } -var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem() - // ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does -// not point to an integer or to a big.Int, it panics. It reports whether the -// read was successful. +// not point to an integer, to a big.Int, or to a []byte it panics. Only +// positive and zero values can be decoded into []byte, and they are returned as +// big-endian binary values that share memory with s. Positive values will have +// no leading zeroes, and zero will be returned as a single zero byte. +// ReadASN1Integer reports whether the read was successful. func (s *String) ReadASN1Integer(out interface{}) bool { - if reflect.TypeOf(out).Kind() != reflect.Ptr { - panic("out is not a pointer") - } - switch reflect.ValueOf(out).Elem().Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch out := out.(type) { + case *int, *int8, *int16, *int32, *int64: var i int64 if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { return false } reflect.ValueOf(out).Elem().SetInt(i) return true - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + case *uint, *uint8, *uint16, *uint32, *uint64: var u uint64 if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { return false } reflect.ValueOf(out).Elem().SetUint(u) return true - case reflect.Struct: - if reflect.TypeOf(out).Elem() == bigIntType { - return s.readASN1BigInt(out.(*big.Int)) - } + case *big.Int: + return s.readASN1BigInt(out) + case *[]byte: + return s.readASN1Bytes(out) + default: + panic("out does not point to an integer type") } - panic("out does not point to an integer type") } func checkASN1Integer(bytes []byte) bool { @@ -320,6 +332,21 @@ func (s *String) readASN1BigInt(out *big.Int) bool { return true } +func (s *String) readASN1Bytes(out *[]byte) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { + return false + } + if bytes[0]&0x80 == 0x80 { + return false + } + for len(bytes) > 1 && bytes[0] == 0 { + bytes = bytes[1:] + } + *out = bytes + return true +} + func (s *String) readASN1Int64(out *int64) bool { var bytes String if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { @@ -394,11 +421,24 @@ func (s *String) ReadASN1Enum(out *int) bool { func (s *String) readBase128Int(out *int) bool { ret := 0 for i := 0; len(*s) > 0; i++ { - if i == 4 { + if i == 5 { + return false + } + // Avoid overflowing int on a 32-bit platform. + // We don't want different behavior based on the architecture. + if ret >= 1<<(31-7) { return false } ret <<= 7 b := s.read(1)[0] + + // ITU-T X.690, section 8.19.2: + // The subidentifier shall be encoded in the fewest possible octets, + // that is, the leading octet of the subidentifier shall not have the value 0x80. + if i == 0 && b == 0x80 { + return false + } + ret |= int(b & 0x7f) if b&0x80 == 0 { *out = ret @@ -466,15 +506,55 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { return true } +const defaultUTCTimeFormatStr = "060102150405Z0700" + +// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. +// It reports whether the read was successful. +func (s *String) ReadASN1UTCTime(out *time.Time) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.UTCTime) { + return false + } + t := string(bytes) + + formatStr := defaultUTCTimeFormatStr + var err error + res, err := time.Parse(formatStr, t) + if err != nil { + // Fallback to minute precision if we can't parse second + // precision. If we are following X.509 or X.690 we shouldn't + // support this, but we do. + formatStr = "0601021504Z0700" + res, err = time.Parse(formatStr, t) + } + if err != nil { + return false + } + + if serialized := res.Format(formatStr); serialized != t { + return false + } + + if res.Year() >= 2050 { + // UTCTime interprets the low order digits 50-99 as 1950-99. + // This only applies to its use in the X.509 profile. + // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + res = res.AddDate(-100, 0, 0) + } + *out = res + return true +} + // ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. // It reports whether the read was successful. func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { var bytes String - if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { + if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || + len(bytes)*8/8 != len(bytes) { return false } - paddingBits := uint8(bytes[0]) + paddingBits := bytes[0] bytes = bytes[1:] if paddingBits > 7 || len(bytes) == 0 && paddingBits != 0 || @@ -487,7 +567,7 @@ func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { return true } -// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is +// ReadASN1BitStringAsBytes decodes an ASN.1 BIT STRING into out and advances. It is // an error if the BIT STRING is not a whole number of bytes. It reports // whether the read was successful. func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { @@ -496,7 +576,7 @@ func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool { return false } - paddingBits := uint8(bytes[0]) + paddingBits := bytes[0] if paddingBits != 0 { return false } @@ -596,34 +676,27 @@ func (s *String) SkipOptionalASN1(tag asn1.Tag) bool { return s.ReadASN1(&unused, tag) } -// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER -// explicitly tagged with tag into out and advances. If no element with a -// matching tag is present, it writes defaultValue into out instead. If out -// does not point to an integer or to a big.Int, it panics. It reports -// whether the read was successful. +// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly +// tagged with tag into out and advances. If no element with a matching tag is +// present, it writes defaultValue into out instead. Otherwise, it behaves like +// ReadASN1Integer. func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool { - if reflect.TypeOf(out).Kind() != reflect.Ptr { - panic("out is not a pointer") - } var present bool var i String if !s.ReadOptionalASN1(&i, &present, tag) { return false } if !present { - switch reflect.ValueOf(out).Elem().Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + switch out.(type) { + case *int, *int8, *int16, *int32, *int64, + *uint, *uint8, *uint16, *uint32, *uint64, *[]byte: reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue)) - case reflect.Struct: - if reflect.TypeOf(out).Elem() != bigIntType { - panic("invalid integer type") - } - if reflect.TypeOf(defaultValue).Kind() != reflect.Ptr || - reflect.TypeOf(defaultValue).Elem() != bigIntType { + case *big.Int: + if defaultValue, ok := defaultValue.(*big.Int); ok { + out.(*big.Int).Set(defaultValue) + } else { panic("out points to big.Int, but defaultValue does not") } - out.(*big.Int).Set(defaultValue.(*big.Int)) default: panic("invalid integer type") } @@ -660,13 +733,14 @@ func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag return true } -// ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or, -// if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue. -// It reports whether the operation was successful. -func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool { +// ReadOptionalASN1Boolean attempts to read an optional ASN.1 BOOLEAN +// explicitly tagged with tag into out and advances. If no element with a +// matching tag is present, it sets "out" to defaultValue instead. It reports +// whether the read was successful. +func (s *String) ReadOptionalASN1Boolean(out *bool, tag asn1.Tag, defaultValue bool) bool { var present bool var child String - if !s.ReadOptionalASN1(&child, &present, asn1.BOOLEAN) { + if !s.ReadOptionalASN1(&child, &present, tag) { return false } @@ -675,7 +749,7 @@ func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool { return true } - return s.ReadASN1Boolean(out) + return child.ReadASN1Boolean(out) } func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool { @@ -740,7 +814,7 @@ func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool { length = headerLen + len32 } - if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) { + if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { return false } if skipHeader && !out.Skip(int(headerLen)) { diff --git a/cryptobyte/asn1/asn1.go b/cryptobyte/asn1/asn1.go index cda8e3edfd..90ef6a241d 100644 --- a/cryptobyte/asn1/asn1.go +++ b/cryptobyte/asn1/asn1.go @@ -4,7 +4,7 @@ // Package asn1 contains supporting types for parsing and building ASN.1 // messages with the cryptobyte package. -package asn1 // import "golang.org/x/crypto/cryptobyte/asn1" +package asn1 // Tag represents an ASN.1 identifier octet, consisting of a tag number // (indicating a type) and class (such as context-specific or constructed). diff --git a/cryptobyte/asn1_test.go b/cryptobyte/asn1_test.go index 9f6c952a34..93760b06e9 100644 --- a/cryptobyte/asn1_test.go +++ b/cryptobyte/asn1_test.go @@ -31,6 +31,10 @@ var readASN1TestData = []readASN1Test{ {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil}, {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil}, {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil}, + {"2**31 - 1 length", []byte{0x30, 0x84, 0x7f, 0xff, 0xff, 0xff}, 0x30, false, nil}, + {"2**32 - 1 length", []byte{0x30, 0x84, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, + {"2**63 - 1 length", []byte{0x30, 0x88, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, + {"2**64 - 1 length", []byte{0x30, 0x88, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, } func TestReadASN1(t *testing.T) { @@ -111,6 +115,28 @@ func TestReadASN1OptionalInteger(t *testing.T) { } } +const defaultBool = false + +var optionalBoolTestData = []readASN1Test{ + {"empty", []byte{}, 0xa0, true, false}, + {"invalid", []byte{0xa1, 0x3, 0x1, 0x2, 0x7f}, 0xa1, false, defaultBool}, + {"missing", []byte{0xa1, 0x3, 0x1, 0x1, 0x7f}, 0xa0, true, defaultBool}, + {"present", []byte{0xa1, 0x3, 0x1, 0x1, 0xff}, 0xa1, true, true}, +} + +func TestReadASN1OptionalBoolean(t *testing.T) { + for _, test := range optionalBoolTestData { + t.Run(test.name, func(t *testing.T) { + in := String(test.in) + var out bool + ok := in.ReadOptionalASN1Boolean(&out, test.tag, defaultBool) + if ok != test.ok || ok && out != test.out.(bool) { + t.Errorf("in.ReadOptionalASN1Boolean() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) + } + }) + } +} + func TestReadASN1IntegerSigned(t *testing.T) { testData64 := []struct { in []byte @@ -150,6 +176,32 @@ func TestReadASN1IntegerSigned(t *testing.T) { } }) + // Repeat the same cases, reading into a []byte. + t.Run("bytes", func(t *testing.T) { + for i, test := range testData64 { + in := String(test.in) + var out []byte + ok := in.ReadASN1Integer(&out) + if test.out < 0 { + if ok { + t.Errorf("#%d: in.ReadASN1Integer(%d) = %v, want false", i, test.out, ok) + } + continue + } + if !ok { + t.Errorf("#%d: in.ReadASN1Integer() = %v, want true", i, ok) + continue + } + n := new(big.Int).SetBytes(out).Int64() + if n != test.out { + t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %x, want %d", i, ok, out, test.out) + } + if out[0] == 0 && len(out) > 1 { + t.Errorf("#%d: in.ReadASN1Integer() = %v; out = %x, has leading zeroes", i, ok, out) + } + } + }) + // Repeat with the implicit-tagging functions t.Run("WithTag", func(t *testing.T) { for i, test := range testData64 { @@ -243,6 +295,10 @@ func TestASN1ObjectIdentifier(t *testing.T) { {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}}, {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, + {[]byte{6, 7, 85, 0x02, 0x85, 0xc7, 0xcc, 0xfb, 0x01}, true, []int{2, 5, 2, 1492336001}}, + {[]byte{6, 7, 0x55, 0x02, 0x87, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 2147483647}}, // 2**31-1 + {[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**31 + {[]byte{6, 3, 85, 0x80, 0x02}, false, []int{}}, // leading 0x80 octet } for i, test := range testData { @@ -307,6 +363,37 @@ func TestReadASN1GeneralizedTime(t *testing.T) { } } +func TestReadASN1UTCTime(t *testing.T) { + testData := []struct { + in string + ok bool + out time.Time + }{ + {"000102030405Z", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"500102030405Z", true, time.Date(1950, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"490102030405Z", true, time.Date(2049, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"990102030405Z", true, time.Date(1999, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"250102030405Z", true, time.Date(2025, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"750102030405Z", true, time.Date(1975, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"000102030405+0905", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.FixedZone("", 9*60*60+5*60))}, + {"000102030405-0905", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.FixedZone("", -9*60*60-5*60))}, + {"0001020304Z", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.UTC)}, + {"5001020304Z", true, time.Date(1950, 01, 02, 03, 04, 00, 0, time.UTC)}, + {"0001020304+0905", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.FixedZone("", 9*60*60+5*60))}, + {"0001020304-0905", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.FixedZone("", -9*60*60-5*60))}, + {"000102030405Z0700", false, time.Time{}}, + {"000102030405", false, time.Time{}}, + } + for i, test := range testData { + in := String(append([]byte{byte(asn1.UTCTime), byte(len(test.in))}, test.in...)) + var out time.Time + ok := in.ReadASN1UTCTime(&out) + if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) { + t.Errorf("#%d: in.ReadASN1UTCTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out) + } + } +} + func TestReadASN1BitString(t *testing.T) { testData := []struct { in []byte @@ -331,3 +418,40 @@ func TestReadASN1BitString(t *testing.T) { } } } + +func TestAddASN1BigInt(t *testing.T) { + x := big.NewInt(-1) + var b Builder + b.AddASN1BigInt(x) + got, err := b.Bytes() + if err != nil { + t.Fatalf("unexpected error adding -1: %v", err) + } + s := String(got) + var y big.Int + ok := s.ReadASN1Integer(&y) + if !ok || x.Cmp(&y) != 0 { + t.Errorf("unexpected bytes %v, want %v", &y, x) + } +} + +func TestReadASN1Boolean(t *testing.T) { + testData := []struct { + in []byte + ok bool + out bool + }{ + {[]byte{}, false, false}, + {[]byte{0x01, 0x01, 0x00}, true, false}, + {[]byte{0x01, 0x01, 0xff}, true, true}, + {[]byte{0x01, 0x01, 0x01}, false, false}, + } + for i, test := range testData { + in := String(test.in) + var out bool + ok := in.ReadASN1Boolean(&out) + if ok != test.ok || ok && (out != test.out) { + t.Errorf("#%d: in.ReadASN1Boolean() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) + } + } +} diff --git a/cryptobyte/builder.go b/cryptobyte/builder.go index ca7b1db5ce..cf254f5f1e 100644 --- a/cryptobyte/builder.go +++ b/cryptobyte/builder.go @@ -95,6 +95,16 @@ func (b *Builder) AddUint32(v uint32) { b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) } +// AddUint48 appends a big-endian, 48-bit value to the byte string. +func (b *Builder) AddUint48(v uint64) { + b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +// AddUint64 appends a big-endian, 64-bit value to the byte string. +func (b *Builder) AddUint64(v uint64) { + b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + // AddBytes appends a sequence of bytes to the byte string. func (b *Builder) AddBytes(v []byte) { b.add(v...) @@ -106,13 +116,13 @@ func (b *Builder) AddBytes(v []byte) { // supplied to them. The child builder passed to the continuation can be used // to build the content of the length-prefixed sequence. For example: // -// parent := cryptobyte.NewBuilder() -// parent.AddUint8LengthPrefixed(func (child *Builder) { -// child.AddUint8(42) -// child.AddUint8LengthPrefixed(func (grandchild *Builder) { -// grandchild.AddUint8(5) -// }) -// }) +// parent := cryptobyte.NewBuilder() +// parent.AddUint8LengthPrefixed(func (child *Builder) { +// child.AddUint8(42) +// child.AddUint8LengthPrefixed(func (grandchild *Builder) { +// grandchild.AddUint8(5) +// }) +// }) // // It is an error to write more bytes to the child than allowed by the reserved // length prefix. After the continuation returns, the child must be considered @@ -298,9 +308,9 @@ func (b *Builder) add(bytes ...byte) { b.result = append(b.result, bytes...) } -// Unwrite rolls back n bytes written directly to the Builder. An attempt by a -// child builder passed to a continuation to unwrite bytes from its parent will -// panic. +// Unwrite rolls back non-negative n bytes written directly to the Builder. +// An attempt by a child builder passed to a continuation to unwrite bytes +// from its parent will panic. func (b *Builder) Unwrite(n int) { if b.err != nil { return @@ -312,6 +322,9 @@ func (b *Builder) Unwrite(n int) { if length < 0 { panic("cryptobyte: internal error") } + if n < 0 { + panic("cryptobyte: attempted to unwrite negative number of bytes") + } if n > length { panic("cryptobyte: attempted to unwrite more than was written") } diff --git a/cryptobyte/cryptobyte_test.go b/cryptobyte/cryptobyte_test.go index fb63709148..9b55d52e32 100644 --- a/cryptobyte/cryptobyte_test.go +++ b/cryptobyte/cryptobyte_test.go @@ -141,7 +141,7 @@ func TestUint24(t *testing.T) { var s String = b.BytesOrPanic() var v uint32 if !s.ReadUint24(&v) { - t.Error("ReadUint8() = false, want true") + t.Error("ReadUint24() = false, want true") } if v != 0xfffefd { t.Errorf("v = %d, want fffefd", v) @@ -169,7 +169,7 @@ func TestUint32(t *testing.T) { var s String = b.BytesOrPanic() var v uint32 if !s.ReadUint32(&v) { - t.Error("ReadUint8() = false, want true") + t.Error("ReadUint32() = false, want true") } if v != 0xfffefdfc { t.Errorf("v = %x, want fffefdfc", v) @@ -179,6 +179,47 @@ func TestUint32(t *testing.T) { } } +func TestUint48(t *testing.T) { + var b Builder + var u uint64 = 0xfefcff3cfdfc + b.AddUint48(u) + if err := builderBytesEq(&b, 254, 252, 255, 60, 253, 252); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var v uint64 + if !s.ReadUint48(&v) { + t.Error("ReadUint48() = false, want true") + } + if v != u { + t.Errorf("v = %x, want %x", v, u) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUint64(t *testing.T) { + var b Builder + b.AddUint64(0xf2fefefcff3cfdfc) + if err := builderBytesEq(&b, 242, 254, 254, 252, 255, 60, 253, 252); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var v uint64 + if !s.ReadUint64(&v) { + t.Error("ReadUint64() = false, want true") + } + if v != 0xf2fefefcff3cfdfc { + t.Errorf("v = %x, want f2fefefcff3cfdfc", v) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + func TestUMultiple(t *testing.T) { var b Builder b.AddUint8(23) diff --git a/cryptobyte/string.go b/cryptobyte/string.go index 39bf98aeea..4b0f8097f9 100644 --- a/cryptobyte/string.go +++ b/cryptobyte/string.go @@ -15,7 +15,7 @@ // // See the documentation and examples for the Builder and String types to get // started. -package cryptobyte // import "golang.org/x/crypto/cryptobyte" +package cryptobyte // String represents a string of bytes. It provides methods for parsing // fixed-length and length-prefixed values from it. @@ -24,7 +24,7 @@ type String []byte // read advances a String by n bytes and returns them. If less than n bytes // remain, it returns nil. func (s *String) read(n int) []byte { - if len(*s) < n { + if len(*s) < n || n < 0 { return nil } v := (*s)[:n] @@ -81,6 +81,28 @@ func (s *String) ReadUint32(out *uint32) bool { return true } +// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint48(out *uint64) bool { + v := s.read(6) + if v == nil { + return false + } + *out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5]) + return true +} + +// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it. +// It reports whether the read was successful. +func (s *String) ReadUint64(out *uint64) bool { + v := s.read(8) + if v == nil { + return false + } + *out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7]) + return true +} + func (s *String) readUnsigned(out *uint32, length int) bool { v := s.read(length) if v == nil { @@ -105,11 +127,6 @@ func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { length = length << 8 length = length | uint32(b) } - if int(length) < 0 { - // This currently cannot overflow because we read uint24 at most, but check - // anyway in case that changes in the future. - return false - } v := s.read(int(length)) if v == nil { return false diff --git a/curve25519/const_amd64.h b/curve25519/const_amd64.h deleted file mode 100644 index b3f74162f6..0000000000 --- a/curve25519/const_amd64.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -#define REDMASK51 0x0007FFFFFFFFFFFF diff --git a/curve25519/const_amd64.s b/curve25519/const_amd64.s deleted file mode 100644 index ee7b4bd5f8..0000000000 --- a/curve25519/const_amd64.s +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -// These constants cannot be encoded in non-MOVQ immediates. -// We access them directly from memory instead. - -DATA ·_121666_213(SB)/8, $996687872 -GLOBL ·_121666_213(SB), 8, $8 - -DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA -GLOBL ·_2P0(SB), 8, $8 - -DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE -GLOBL ·_2P1234(SB), 8, $8 diff --git a/curve25519/cswap_amd64.s b/curve25519/cswap_amd64.s deleted file mode 100644 index cd793a5b5f..0000000000 --- a/curve25519/cswap_amd64.s +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -// func cswap(inout *[4][5]uint64, v uint64) -TEXT ·cswap(SB),7,$0 - MOVQ inout+0(FP),DI - MOVQ v+8(FP),SI - - SUBQ $1, SI - NOTQ SI - MOVQ SI, X15 - PSHUFD $0x44, X15, X15 - - MOVOU 0(DI), X0 - MOVOU 16(DI), X2 - MOVOU 32(DI), X4 - MOVOU 48(DI), X6 - MOVOU 64(DI), X8 - MOVOU 80(DI), X1 - MOVOU 96(DI), X3 - MOVOU 112(DI), X5 - MOVOU 128(DI), X7 - MOVOU 144(DI), X9 - - MOVO X1, X10 - MOVO X3, X11 - MOVO X5, X12 - MOVO X7, X13 - MOVO X9, X14 - - PXOR X0, X10 - PXOR X2, X11 - PXOR X4, X12 - PXOR X6, X13 - PXOR X8, X14 - PAND X15, X10 - PAND X15, X11 - PAND X15, X12 - PAND X15, X13 - PAND X15, X14 - PXOR X10, X0 - PXOR X10, X1 - PXOR X11, X2 - PXOR X11, X3 - PXOR X12, X4 - PXOR X12, X5 - PXOR X13, X6 - PXOR X13, X7 - PXOR X14, X8 - PXOR X14, X9 - - MOVOU X0, 0(DI) - MOVOU X2, 16(DI) - MOVOU X4, 32(DI) - MOVOU X6, 48(DI) - MOVOU X8, 64(DI) - MOVOU X1, 80(DI) - MOVOU X3, 96(DI) - MOVOU X5, 112(DI) - MOVOU X7, 128(DI) - MOVOU X9, 144(DI) - RET diff --git a/curve25519/curve25519.go b/curve25519/curve25519.go index 75f24babb6..048faef3a5 100644 --- a/curve25519/curve25519.go +++ b/curve25519/curve25519.go @@ -1,834 +1,93 @@ -// Copyright 2013 The Go Authors. All rights reserved. +// Copyright 2019 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. -// We have an implementation in amd64 assembly so this code is only run on -// non-amd64 platforms. The amd64 assembly does not support gccgo. -// +build !amd64 gccgo appengine - +// Package curve25519 provides an implementation of the X25519 function, which +// performs scalar multiplication on the elliptic curve known as Curve25519 +// according to [RFC 7748]. +// +// The curve25519 package is a wrapper for the X25519 implementation in the +// crypto/ecdh package. It is [frozen] and is not accepting new features. +// +// [RFC 7748]: https://datatracker.ietf.org/doc/html/rfc7748 +// [frozen]: https://go.dev/wiki/Frozen package curve25519 -import ( - "encoding/binary" -) - -// This code is a port of the public domain, "ref10" implementation of -// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. - -// fieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type fieldElement [10]int32 +import "crypto/ecdh" -func feZero(fe *fieldElement) { - for i := range fe { - fe[i] = 0 - } -} - -func feOne(fe *fieldElement) { - feZero(fe) - fe[0] = 1 -} - -func feAdd(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] + b[i] - } -} - -func feSub(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] - b[i] - } -} - -func feCopy(dst, src *fieldElement) { - for i := range dst { - dst[i] = src[i] - } -} - -// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. +// ScalarMult sets dst to the product scalar * point. // -// Preconditions: b in {0,1}. -func feCSwap(f, g *fieldElement, b int32) { - b = -b - for i := range f { - t := b & (f[i] ^ g[i]) - f[i] ^= t - g[i] ^= t +// Deprecated: when provided a low-order point, ScalarMult will set dst to all +// zeroes, irrespective of the scalar. Instead, use the X25519 function, which +// will return an error. +func ScalarMult(dst, scalar, point *[32]byte) { + if _, err := x25519(dst, scalar[:], point[:]); err != nil { + // The only error condition for x25519 when the inputs are 32 bytes long + // is if the output would have been the all-zero value. + for i := range dst { + dst[i] = 0 + } } } -// load3 reads a 24-bit, little-endian value from in. -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -// load4 reads a 32-bit, little-endian value from in. -func load4(in []byte) int64 { - return int64(binary.LittleEndian.Uint32(in)) -} - -func feFromBytes(dst *fieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 0x7fffff) << 2 - - var carry [10]int64 - carry[9] = (h9 + 1<<24) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + 1<<24) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + 1<<24) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + 1<<24) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + 1<<24) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + 1<<25) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + 1<<25) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + 1<<25) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + 1<<25) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + 1<<25) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - dst[0] = int32(h0) - dst[1] = int32(h1) - dst[2] = int32(h2) - dst[3] = int32(h3) - dst[4] = int32(h4) - dst[5] = int32(h5) - dst[6] = int32(h6) - dst[7] = int32(h7) - dst[8] = int32(h8) - dst[9] = int32(h9) -} - -// feToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) -} - -// feMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: +// ScalarBaseMult sets dst to the product scalar * base where base is the +// standard generator. // -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. -// -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs can squeeze carries into int32. -func feMul(h, f, g *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - g0 := g[0] - g1 := g[1] - g2 := g[2] - g3 := g[3] - g4 := g[4] - g5 := g[5] - g6 := g[6] - g7 := g[7] - g8 := g[8] - g9 := g[9] - g1_19 := 19 * g1 // 1.4*2^29 - g2_19 := 19 * g2 // 1.4*2^30; still ok - g3_19 := 19 * g3 - g4_19 := 19 * g4 - g5_19 := 19 * g5 - g6_19 := 19 * g6 - g7_19 := 19 * g7 - g8_19 := 19 * g8 - g9_19 := 19 * g9 - f1_2 := 2 * f1 - f3_2 := 2 * f3 - f5_2 := 2 * f5 - f7_2 := 2 * f7 - f9_2 := 2 * f9 - f0g0 := int64(f0) * int64(g0) - f0g1 := int64(f0) * int64(g1) - f0g2 := int64(f0) * int64(g2) - f0g3 := int64(f0) * int64(g3) - f0g4 := int64(f0) * int64(g4) - f0g5 := int64(f0) * int64(g5) - f0g6 := int64(f0) * int64(g6) - f0g7 := int64(f0) * int64(g7) - f0g8 := int64(f0) * int64(g8) - f0g9 := int64(f0) * int64(g9) - f1g0 := int64(f1) * int64(g0) - f1g1_2 := int64(f1_2) * int64(g1) - f1g2 := int64(f1) * int64(g2) - f1g3_2 := int64(f1_2) * int64(g3) - f1g4 := int64(f1) * int64(g4) - f1g5_2 := int64(f1_2) * int64(g5) - f1g6 := int64(f1) * int64(g6) - f1g7_2 := int64(f1_2) * int64(g7) - f1g8 := int64(f1) * int64(g8) - f1g9_38 := int64(f1_2) * int64(g9_19) - f2g0 := int64(f2) * int64(g0) - f2g1 := int64(f2) * int64(g1) - f2g2 := int64(f2) * int64(g2) - f2g3 := int64(f2) * int64(g3) - f2g4 := int64(f2) * int64(g4) - f2g5 := int64(f2) * int64(g5) - f2g6 := int64(f2) * int64(g6) - f2g7 := int64(f2) * int64(g7) - f2g8_19 := int64(f2) * int64(g8_19) - f2g9_19 := int64(f2) * int64(g9_19) - f3g0 := int64(f3) * int64(g0) - f3g1_2 := int64(f3_2) * int64(g1) - f3g2 := int64(f3) * int64(g2) - f3g3_2 := int64(f3_2) * int64(g3) - f3g4 := int64(f3) * int64(g4) - f3g5_2 := int64(f3_2) * int64(g5) - f3g6 := int64(f3) * int64(g6) - f3g7_38 := int64(f3_2) * int64(g7_19) - f3g8_19 := int64(f3) * int64(g8_19) - f3g9_38 := int64(f3_2) * int64(g9_19) - f4g0 := int64(f4) * int64(g0) - f4g1 := int64(f4) * int64(g1) - f4g2 := int64(f4) * int64(g2) - f4g3 := int64(f4) * int64(g3) - f4g4 := int64(f4) * int64(g4) - f4g5 := int64(f4) * int64(g5) - f4g6_19 := int64(f4) * int64(g6_19) - f4g7_19 := int64(f4) * int64(g7_19) - f4g8_19 := int64(f4) * int64(g8_19) - f4g9_19 := int64(f4) * int64(g9_19) - f5g0 := int64(f5) * int64(g0) - f5g1_2 := int64(f5_2) * int64(g1) - f5g2 := int64(f5) * int64(g2) - f5g3_2 := int64(f5_2) * int64(g3) - f5g4 := int64(f5) * int64(g4) - f5g5_38 := int64(f5_2) * int64(g5_19) - f5g6_19 := int64(f5) * int64(g6_19) - f5g7_38 := int64(f5_2) * int64(g7_19) - f5g8_19 := int64(f5) * int64(g8_19) - f5g9_38 := int64(f5_2) * int64(g9_19) - f6g0 := int64(f6) * int64(g0) - f6g1 := int64(f6) * int64(g1) - f6g2 := int64(f6) * int64(g2) - f6g3 := int64(f6) * int64(g3) - f6g4_19 := int64(f6) * int64(g4_19) - f6g5_19 := int64(f6) * int64(g5_19) - f6g6_19 := int64(f6) * int64(g6_19) - f6g7_19 := int64(f6) * int64(g7_19) - f6g8_19 := int64(f6) * int64(g8_19) - f6g9_19 := int64(f6) * int64(g9_19) - f7g0 := int64(f7) * int64(g0) - f7g1_2 := int64(f7_2) * int64(g1) - f7g2 := int64(f7) * int64(g2) - f7g3_38 := int64(f7_2) * int64(g3_19) - f7g4_19 := int64(f7) * int64(g4_19) - f7g5_38 := int64(f7_2) * int64(g5_19) - f7g6_19 := int64(f7) * int64(g6_19) - f7g7_38 := int64(f7_2) * int64(g7_19) - f7g8_19 := int64(f7) * int64(g8_19) - f7g9_38 := int64(f7_2) * int64(g9_19) - f8g0 := int64(f8) * int64(g0) - f8g1 := int64(f8) * int64(g1) - f8g2_19 := int64(f8) * int64(g2_19) - f8g3_19 := int64(f8) * int64(g3_19) - f8g4_19 := int64(f8) * int64(g4_19) - f8g5_19 := int64(f8) * int64(g5_19) - f8g6_19 := int64(f8) * int64(g6_19) - f8g7_19 := int64(f8) * int64(g7_19) - f8g8_19 := int64(f8) * int64(g8_19) - f8g9_19 := int64(f8) * int64(g9_19) - f9g0 := int64(f9) * int64(g0) - f9g1_38 := int64(f9_2) * int64(g1_19) - f9g2_19 := int64(f9) * int64(g2_19) - f9g3_38 := int64(f9_2) * int64(g3_19) - f9g4_19 := int64(f9) * int64(g4_19) - f9g5_38 := int64(f9_2) * int64(g5_19) - f9g6_19 := int64(f9) * int64(g6_19) - f9g7_38 := int64(f9_2) * int64(g7_19) - f9g8_19 := int64(f9) * int64(g8_19) - f9g9_38 := int64(f9_2) * int64(g9_19) - h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 - h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 - h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 - h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 - h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 - h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 - h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 - h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 - h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 - h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 - var carry [10]int64 - - // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - // |h0| <= 2^25 - // |h4| <= 2^25 - // |h1| <= 1.51*2^58 - // |h5| <= 1.51*2^58 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - // |h1| <= 2^24; from now on fits into int32 - // |h5| <= 2^24; from now on fits into int32 - // |h2| <= 1.21*2^59 - // |h6| <= 1.21*2^59 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - // |h2| <= 2^25; from now on fits into int32 unchanged - // |h6| <= 2^25; from now on fits into int32 unchanged - // |h3| <= 1.51*2^58 - // |h7| <= 1.51*2^58 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - // |h3| <= 2^24; from now on fits into int32 unchanged - // |h7| <= 2^24; from now on fits into int32 unchanged - // |h4| <= 1.52*2^33 - // |h8| <= 1.52*2^33 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - // |h4| <= 2^25; from now on fits into int32 unchanged - // |h8| <= 2^25; from now on fits into int32 unchanged - // |h5| <= 1.01*2^24 - // |h9| <= 1.51*2^58 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - // |h9| <= 2^24; from now on fits into int32 unchanged - // |h0| <= 1.8*2^37 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - // |h0| <= 2^25; from now on fits into int32 unchanged - // |h1| <= 1.01*2^24 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) +// It is recommended to use the X25519 function with Basepoint instead, as +// copying into fixed size arrays can lead to unexpected bugs. +func ScalarBaseMult(dst, scalar *[32]byte) { + curve := ecdh.X25519() + priv, err := curve.NewPrivateKey(scalar[:]) + if err != nil { + panic("curve25519: " + err.Error()) + } + copy(dst[:], priv.PublicKey().Bytes()) } -// feSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feSquare(h, f *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - f0_2 := 2 * f0 - f1_2 := 2 * f1 - f2_2 := 2 * f2 - f3_2 := 2 * f3 - f4_2 := 2 * f4 - f5_2 := 2 * f5 - f6_2 := 2 * f6 - f7_2 := 2 * f7 - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - f0f0 := int64(f0) * int64(f0) - f0f1_2 := int64(f0_2) * int64(f1) - f0f2_2 := int64(f0_2) * int64(f2) - f0f3_2 := int64(f0_2) * int64(f3) - f0f4_2 := int64(f0_2) * int64(f4) - f0f5_2 := int64(f0_2) * int64(f5) - f0f6_2 := int64(f0_2) * int64(f6) - f0f7_2 := int64(f0_2) * int64(f7) - f0f8_2 := int64(f0_2) * int64(f8) - f0f9_2 := int64(f0_2) * int64(f9) - f1f1_2 := int64(f1_2) * int64(f1) - f1f2_2 := int64(f1_2) * int64(f2) - f1f3_4 := int64(f1_2) * int64(f3_2) - f1f4_2 := int64(f1_2) * int64(f4) - f1f5_4 := int64(f1_2) * int64(f5_2) - f1f6_2 := int64(f1_2) * int64(f6) - f1f7_4 := int64(f1_2) * int64(f7_2) - f1f8_2 := int64(f1_2) * int64(f8) - f1f9_76 := int64(f1_2) * int64(f9_38) - f2f2 := int64(f2) * int64(f2) - f2f3_2 := int64(f2_2) * int64(f3) - f2f4_2 := int64(f2_2) * int64(f4) - f2f5_2 := int64(f2_2) * int64(f5) - f2f6_2 := int64(f2_2) * int64(f6) - f2f7_2 := int64(f2_2) * int64(f7) - f2f8_38 := int64(f2_2) * int64(f8_19) - f2f9_38 := int64(f2) * int64(f9_38) - f3f3_2 := int64(f3_2) * int64(f3) - f3f4_2 := int64(f3_2) * int64(f4) - f3f5_4 := int64(f3_2) * int64(f5_2) - f3f6_2 := int64(f3_2) * int64(f6) - f3f7_76 := int64(f3_2) * int64(f7_38) - f3f8_38 := int64(f3_2) * int64(f8_19) - f3f9_76 := int64(f3_2) * int64(f9_38) - f4f4 := int64(f4) * int64(f4) - f4f5_2 := int64(f4_2) * int64(f5) - f4f6_38 := int64(f4_2) * int64(f6_19) - f4f7_38 := int64(f4) * int64(f7_38) - f4f8_38 := int64(f4_2) * int64(f8_19) - f4f9_38 := int64(f4) * int64(f9_38) - f5f5_38 := int64(f5) * int64(f5_38) - f5f6_38 := int64(f5_2) * int64(f6_19) - f5f7_76 := int64(f5_2) * int64(f7_38) - f5f8_38 := int64(f5_2) * int64(f8_19) - f5f9_76 := int64(f5_2) * int64(f9_38) - f6f6_19 := int64(f6) * int64(f6_19) - f6f7_38 := int64(f6) * int64(f7_38) - f6f8_38 := int64(f6_2) * int64(f8_19) - f6f9_38 := int64(f6) * int64(f9_38) - f7f7_38 := int64(f7) * int64(f7_38) - f7f8_38 := int64(f7_2) * int64(f8_19) - f7f9_76 := int64(f7_2) * int64(f9_38) - f8f8_19 := int64(f8) * int64(f8_19) - f8f9_38 := int64(f8) * int64(f9_38) - f9f9_38 := int64(f9) * int64(f9_38) - h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 - h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 - h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 - h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 - h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 - h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 - h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 - h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 - h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 - h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 - var carry [10]int64 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 +const ( + // ScalarSize is the size of the scalar input to X25519. + ScalarSize = 32 + // PointSize is the size of the point input to X25519. + PointSize = 32 +) - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 +// Basepoint is the canonical Curve25519 generator. +var Basepoint []byte - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 +var basePoint = [32]byte{9} - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} +func init() { Basepoint = basePoint[:] } -// feMul121666 calculates h = f * 121666. Can overlap h with f. +// X25519 returns the result of the scalar multiplication (scalar * point), +// according to RFC 7748, Section 5. scalar, point and the return value are +// slices of 32 bytes. // -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +// scalar can be generated at random, for example with crypto/rand. point should +// be either Basepoint or the output of another X25519 call. // -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feMul121666(h, f *fieldElement) { - h0 := int64(f[0]) * 121666 - h1 := int64(f[1]) * 121666 - h2 := int64(f[2]) * 121666 - h3 := int64(f[3]) * 121666 - h4 := int64(f[4]) * 121666 - h5 := int64(f[5]) * 121666 - h6 := int64(f[6]) * 121666 - h7 := int64(f[7]) * 121666 - h8 := int64(f[8]) * 121666 - h9 := int64(f[9]) * 121666 - var carry [10]int64 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) +// If point is Basepoint (but not if it's a different slice with the same +// contents) a precomputed implementation might be used for performance. +func X25519(scalar, point []byte) ([]byte, error) { + // Outline the body of function, to let the allocation be inlined in the + // caller, and possibly avoid escaping to the heap. + var dst [32]byte + return x25519(&dst, scalar, point) } -// feInvert sets out = z^-1. -func feInvert(out, z *fieldElement) { - var t0, t1, t2, t3 fieldElement - var i int - - feSquare(&t0, z) - for i = 1; i < 1; i++ { - feSquare(&t0, &t0) - } - feSquare(&t1, &t0) - for i = 1; i < 2; i++ { - feSquare(&t1, &t1) - } - feMul(&t1, z, &t1) - feMul(&t0, &t0, &t1) - feSquare(&t2, &t0) - for i = 1; i < 1; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t1, &t2) - feSquare(&t2, &t1) - for i = 1; i < 5; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 20; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) +func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { + curve := ecdh.X25519() + pub, err := curve.NewPublicKey(point) + if err != nil { + return nil, err } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) + priv, err := curve.NewPrivateKey(scalar) + if err != nil { + return nil, err } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 100; i++ { - feSquare(&t3, &t3) + out, err := priv.ECDH(pub) + if err != nil { + return nil, err } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t1, &t1) - for i = 1; i < 5; i++ { - feSquare(&t1, &t1) - } - feMul(out, &t1, &t0) -} - -func scalarMult(out, in, base *[32]byte) { - var e [32]byte - - copy(e[:], in[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement - feFromBytes(&x1, base) - feOne(&x2) - feCopy(&x3, &x1) - feOne(&z3) - - swap := int32(0) - for pos := 254; pos >= 0; pos-- { - b := e[pos/8] >> uint(pos&7) - b &= 1 - swap ^= int32(b) - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - swap = int32(b) - - feSub(&tmp0, &x3, &z3) - feSub(&tmp1, &x2, &z2) - feAdd(&x2, &x2, &z2) - feAdd(&z2, &x3, &z3) - feMul(&z3, &tmp0, &x2) - feMul(&z2, &z2, &tmp1) - feSquare(&tmp0, &tmp1) - feSquare(&tmp1, &x2) - feAdd(&x3, &z3, &z2) - feSub(&z2, &z3, &z2) - feMul(&x2, &tmp1, &tmp0) - feSub(&tmp1, &tmp1, &tmp0) - feSquare(&z2, &z2) - feMul121666(&z3, &tmp1) - feSquare(&x3, &x3) - feAdd(&tmp0, &tmp0, &z3) - feMul(&z3, &x1, &z2) - feMul(&z2, &tmp1, &tmp0) - } - - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - - feInvert(&z2, &z2) - feMul(&x2, &x2, &z2) - feToBytes(out, &x2) + copy(dst[:], out) + return dst[:], nil } diff --git a/curve25519/curve25519_test.go b/curve25519/curve25519_test.go index 56ef73bcc6..e2b338b5ec 100644 --- a/curve25519/curve25519_test.go +++ b/curve25519/curve25519_test.go @@ -2,38 +2,70 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package curve25519 +package curve25519_test import ( "bytes" "crypto/rand" - "fmt" + "encoding/hex" "testing" + + "golang.org/x/crypto/curve25519" ) const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" -func TestBaseScalarMult(t *testing.T) { - var a, b [32]byte - in := &a - out := &b - a[0] = 1 +func TestX25519Basepoint(t *testing.T) { + x := make([]byte, 32) + x[0] = 1 for i := 0; i < 200; i++ { - ScalarBaseMult(out, in) - in, out = out, in + var err error + x, err = curve25519.X25519(x, curve25519.Basepoint) + if err != nil { + t.Fatal(err) + } } - result := fmt.Sprintf("%x", in[:]) + result := hex.EncodeToString(x) if result != expectedHex { t.Errorf("incorrect result: got %s, want %s", result, expectedHex) } } +func TestLowOrderPoints(t *testing.T) { + scalar := make([]byte, curve25519.ScalarSize) + if _, err := rand.Read(scalar); err != nil { + t.Fatal(err) + } + for i, p := range lowOrderPoints { + out, err := curve25519.X25519(scalar, p) + if err == nil { + t.Errorf("%d: expected error, got nil", i) + } + if out != nil { + t.Errorf("%d: expected nil output, got %x", i, out) + } + } +} + func TestTestVectors(t *testing.T) { + t.Run("Legacy", func(t *testing.T) { testTestVectors(t, curve25519.ScalarMult) }) + t.Run("X25519", func(t *testing.T) { + testTestVectors(t, func(dst, scalar, point *[32]byte) { + out, err := curve25519.X25519(scalar[:], point[:]) + if err != nil { + t.Fatal(err) + } + copy(dst[:], out) + }) + }) +} + +func testTestVectors(t *testing.T, scalarMult func(dst, scalar, point *[32]byte)) { for _, tv := range testVectors { var got [32]byte - ScalarMult(&got, &tv.In, &tv.Base) + scalarMult(&got, &tv.In, &tv.Base) if !bytes.Equal(got[:], tv.Expect[:]) { t.Logf(" in = %x", tv.In) t.Logf(" base = %x", tv.Base) @@ -58,22 +90,53 @@ func TestHighBitIgnored(t *testing.T) { var hi0, hi1 [32]byte u[31] &= 0x7f - ScalarMult(&hi0, &s, &u) + curve25519.ScalarMult(&hi0, &s, &u) u[31] |= 0x80 - ScalarMult(&hi1, &s, &u) + curve25519.ScalarMult(&hi1, &s, &u) if !bytes.Equal(hi0[:], hi1[:]) { t.Errorf("high bit of group point should not affect result") } } -func BenchmarkScalarBaseMult(b *testing.B) { - var in, out [32]byte - in[0] = 1 +var benchmarkSink byte + +func BenchmarkX25519Basepoint(b *testing.B) { + scalar := make([]byte, curve25519.ScalarSize) + if _, err := rand.Read(scalar); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + out, err := curve25519.X25519(scalar, curve25519.Basepoint) + if err != nil { + b.Fatal(err) + } + benchmarkSink ^= out[0] + } +} + +func BenchmarkX25519(b *testing.B) { + scalar := make([]byte, curve25519.ScalarSize) + if _, err := rand.Read(scalar); err != nil { + b.Fatal(err) + } + point, err := curve25519.X25519(scalar, curve25519.Basepoint) + if err != nil { + b.Fatal(err) + } + if _, err := rand.Read(scalar); err != nil { + b.Fatal(err) + } - b.SetBytes(32) + b.ResetTimer() for i := 0; i < b.N; i++ { - ScalarBaseMult(&out, &in) + out, err := curve25519.X25519(scalar, point) + if err != nil { + b.Fatal(err) + } + benchmarkSink ^= out[0] } } diff --git a/curve25519/doc.go b/curve25519/doc.go deleted file mode 100644 index da9b10d9c1..0000000000 --- a/curve25519/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package curve25519 provides an implementation of scalar multiplication on -// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html -package curve25519 // import "golang.org/x/crypto/curve25519" - -// basePoint is the x coordinate of the generator of the curve. -var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -// ScalarMult sets dst to the product in*base where dst and base are the x -// coordinates of group points and all values are in little-endian form. -func ScalarMult(dst, in, base *[32]byte) { - scalarMult(dst, in, base) -} - -// ScalarBaseMult sets dst to the product in*base where dst and base are the x -// coordinates of group points, base is the standard generator and all values -// are in little-endian form. -func ScalarBaseMult(dst, in *[32]byte) { - ScalarMult(dst, in, &basePoint) -} diff --git a/curve25519/freeze_amd64.s b/curve25519/freeze_amd64.s deleted file mode 100644 index 390816106e..0000000000 --- a/curve25519/freeze_amd64.s +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func freeze(inout *[5]uint64) -TEXT ·freeze(SB),7,$0-8 - MOVQ inout+0(FP), DI - - MOVQ 0(DI),SI - MOVQ 8(DI),DX - MOVQ 16(DI),CX - MOVQ 24(DI),R8 - MOVQ 32(DI),R9 - MOVQ $REDMASK51,AX - MOVQ AX,R10 - SUBQ $18,R10 - MOVQ $3,R11 -REDUCELOOP: - MOVQ SI,R12 - SHRQ $51,R12 - ANDQ AX,SI - ADDQ R12,DX - MOVQ DX,R12 - SHRQ $51,R12 - ANDQ AX,DX - ADDQ R12,CX - MOVQ CX,R12 - SHRQ $51,R12 - ANDQ AX,CX - ADDQ R12,R8 - MOVQ R8,R12 - SHRQ $51,R12 - ANDQ AX,R8 - ADDQ R12,R9 - MOVQ R9,R12 - SHRQ $51,R12 - ANDQ AX,R9 - IMUL3Q $19,R12,R12 - ADDQ R12,SI - SUBQ $1,R11 - JA REDUCELOOP - MOVQ $1,R12 - CMPQ R10,SI - CMOVQLT R11,R12 - CMPQ AX,DX - CMOVQNE R11,R12 - CMPQ AX,CX - CMOVQNE R11,R12 - CMPQ AX,R8 - CMOVQNE R11,R12 - CMPQ AX,R9 - CMOVQNE R11,R12 - NEGQ R12 - ANDQ R12,AX - ANDQ R12,R10 - SUBQ R10,SI - SUBQ AX,DX - SUBQ AX,CX - SUBQ AX,R8 - SUBQ AX,R9 - MOVQ SI,0(DI) - MOVQ DX,8(DI) - MOVQ CX,16(DI) - MOVQ R8,24(DI) - MOVQ R9,32(DI) - RET diff --git a/curve25519/ladderstep_amd64.s b/curve25519/ladderstep_amd64.s deleted file mode 100644 index e0ac30c70f..0000000000 --- a/curve25519/ladderstep_amd64.s +++ /dev/null @@ -1,1377 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func ladderstep(inout *[5][5]uint64) -TEXT ·ladderstep(SB),0,$296-8 - MOVQ inout+0(FP),DI - - MOVQ 40(DI),SI - MOVQ 48(DI),DX - MOVQ 56(DI),CX - MOVQ 64(DI),R8 - MOVQ 72(DI),R9 - MOVQ SI,AX - MOVQ DX,R10 - MOVQ CX,R11 - MOVQ R8,R12 - MOVQ R9,R13 - ADDQ ·_2P0(SB),AX - ADDQ ·_2P1234(SB),R10 - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 80(DI),SI - ADDQ 88(DI),DX - ADDQ 96(DI),CX - ADDQ 104(DI),R8 - ADDQ 112(DI),R9 - SUBQ 80(DI),AX - SUBQ 88(DI),R10 - SUBQ 96(DI),R11 - SUBQ 104(DI),R12 - SUBQ 112(DI),R13 - MOVQ SI,0(SP) - MOVQ DX,8(SP) - MOVQ CX,16(SP) - MOVQ R8,24(SP) - MOVQ R9,32(SP) - MOVQ AX,40(SP) - MOVQ R10,48(SP) - MOVQ R11,56(SP) - MOVQ R12,64(SP) - MOVQ R13,72(SP) - MOVQ 40(SP),AX - MULQ 40(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 48(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 56(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 64(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 72(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 48(SP),AX - MULQ 48(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 48(SP),AX - SHLQ $1,AX - MULQ 56(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 48(SP),AX - SHLQ $1,AX - MULQ 64(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 48(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 56(SP),AX - MULQ 56(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 56(SP),DX - IMUL3Q $38,DX,AX - MULQ 64(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 56(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 64(SP),DX - IMUL3Q $19,DX,AX - MULQ 64(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 64(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 72(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,80(SP) - MOVQ R8,88(SP) - MOVQ R9,96(SP) - MOVQ AX,104(SP) - MOVQ R10,112(SP) - MOVQ 0(SP),AX - MULQ 0(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 8(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 16(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 24(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 32(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 8(SP),AX - MULQ 8(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - SHLQ $1,AX - MULQ 16(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - SHLQ $1,AX - MULQ 24(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 16(SP),AX - MULQ 16(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SP),DX - IMUL3Q $38,DX,AX - MULQ 24(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 16(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 24(SP),DX - IMUL3Q $19,DX,AX - MULQ 24(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 24(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 32(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,120(SP) - MOVQ R8,128(SP) - MOVQ R9,136(SP) - MOVQ AX,144(SP) - MOVQ R10,152(SP) - MOVQ SI,SI - MOVQ R8,DX - MOVQ R9,CX - MOVQ AX,R8 - MOVQ R10,R9 - ADDQ ·_2P0(SB),SI - ADDQ ·_2P1234(SB),DX - ADDQ ·_2P1234(SB),CX - ADDQ ·_2P1234(SB),R8 - ADDQ ·_2P1234(SB),R9 - SUBQ 80(SP),SI - SUBQ 88(SP),DX - SUBQ 96(SP),CX - SUBQ 104(SP),R8 - SUBQ 112(SP),R9 - MOVQ SI,160(SP) - MOVQ DX,168(SP) - MOVQ CX,176(SP) - MOVQ R8,184(SP) - MOVQ R9,192(SP) - MOVQ 120(DI),SI - MOVQ 128(DI),DX - MOVQ 136(DI),CX - MOVQ 144(DI),R8 - MOVQ 152(DI),R9 - MOVQ SI,AX - MOVQ DX,R10 - MOVQ CX,R11 - MOVQ R8,R12 - MOVQ R9,R13 - ADDQ ·_2P0(SB),AX - ADDQ ·_2P1234(SB),R10 - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 160(DI),SI - ADDQ 168(DI),DX - ADDQ 176(DI),CX - ADDQ 184(DI),R8 - ADDQ 192(DI),R9 - SUBQ 160(DI),AX - SUBQ 168(DI),R10 - SUBQ 176(DI),R11 - SUBQ 184(DI),R12 - SUBQ 192(DI),R13 - MOVQ SI,200(SP) - MOVQ DX,208(SP) - MOVQ CX,216(SP) - MOVQ R8,224(SP) - MOVQ R9,232(SP) - MOVQ AX,240(SP) - MOVQ R10,248(SP) - MOVQ R11,256(SP) - MOVQ R12,264(SP) - MOVQ R13,272(SP) - MOVQ 224(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,280(SP) - MULQ 56(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 232(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,288(SP) - MULQ 48(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 200(SP),AX - MULQ 40(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 200(SP),AX - MULQ 48(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 200(SP),AX - MULQ 56(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 200(SP),AX - MULQ 64(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 200(SP),AX - MULQ 72(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 208(SP),AX - MULQ 40(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 208(SP),AX - MULQ 48(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 208(SP),AX - MULQ 56(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 208(SP),AX - MULQ 64(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 208(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 216(SP),AX - MULQ 40(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 216(SP),AX - MULQ 48(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 216(SP),AX - MULQ 56(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 216(SP),DX - IMUL3Q $19,DX,AX - MULQ 64(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 216(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 224(SP),AX - MULQ 40(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 224(SP),AX - MULQ 48(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 280(SP),AX - MULQ 64(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 280(SP),AX - MULQ 72(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 232(SP),AX - MULQ 40(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 288(SP),AX - MULQ 56(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 288(SP),AX - MULQ 64(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 288(SP),AX - MULQ 72(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,40(SP) - MOVQ R8,48(SP) - MOVQ R9,56(SP) - MOVQ AX,64(SP) - MOVQ R10,72(SP) - MOVQ 264(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,200(SP) - MULQ 16(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 272(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,208(SP) - MULQ 8(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 240(SP),AX - MULQ 0(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 240(SP),AX - MULQ 8(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 240(SP),AX - MULQ 16(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 240(SP),AX - MULQ 24(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 240(SP),AX - MULQ 32(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 248(SP),AX - MULQ 0(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 248(SP),AX - MULQ 8(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 248(SP),AX - MULQ 16(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 248(SP),AX - MULQ 24(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 248(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 256(SP),AX - MULQ 0(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 256(SP),AX - MULQ 8(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 256(SP),AX - MULQ 16(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 256(SP),DX - IMUL3Q $19,DX,AX - MULQ 24(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 256(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 264(SP),AX - MULQ 0(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 264(SP),AX - MULQ 8(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 200(SP),AX - MULQ 24(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 200(SP),AX - MULQ 32(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 272(SP),AX - MULQ 0(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 208(SP),AX - MULQ 16(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 208(SP),AX - MULQ 24(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 208(SP),AX - MULQ 32(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,DX - MOVQ R8,CX - MOVQ R9,R11 - MOVQ AX,R12 - MOVQ R10,R13 - ADDQ ·_2P0(SB),DX - ADDQ ·_2P1234(SB),CX - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 40(SP),SI - ADDQ 48(SP),R8 - ADDQ 56(SP),R9 - ADDQ 64(SP),AX - ADDQ 72(SP),R10 - SUBQ 40(SP),DX - SUBQ 48(SP),CX - SUBQ 56(SP),R11 - SUBQ 64(SP),R12 - SUBQ 72(SP),R13 - MOVQ SI,120(DI) - MOVQ R8,128(DI) - MOVQ R9,136(DI) - MOVQ AX,144(DI) - MOVQ R10,152(DI) - MOVQ DX,160(DI) - MOVQ CX,168(DI) - MOVQ R11,176(DI) - MOVQ R12,184(DI) - MOVQ R13,192(DI) - MOVQ 120(DI),AX - MULQ 120(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 128(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 136(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 144(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 152(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 128(DI),AX - MULQ 128(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 128(DI),AX - SHLQ $1,AX - MULQ 136(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 128(DI),AX - SHLQ $1,AX - MULQ 144(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 128(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(DI),AX - MULQ 136(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 136(DI),DX - IMUL3Q $38,DX,AX - MULQ 144(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(DI),DX - IMUL3Q $19,DX,AX - MULQ 144(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 152(DI),DX - IMUL3Q $19,DX,AX - MULQ 152(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,120(DI) - MOVQ R8,128(DI) - MOVQ R9,136(DI) - MOVQ AX,144(DI) - MOVQ R10,152(DI) - MOVQ 160(DI),AX - MULQ 160(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 168(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 176(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 184(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 192(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 168(DI),AX - MULQ 168(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 168(DI),AX - SHLQ $1,AX - MULQ 176(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 168(DI),AX - SHLQ $1,AX - MULQ 184(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 168(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),AX - MULQ 176(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 176(DI),DX - IMUL3Q $38,DX,AX - MULQ 184(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),DX - IMUL3Q $19,DX,AX - MULQ 184(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 192(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,160(DI) - MOVQ R8,168(DI) - MOVQ R9,176(DI) - MOVQ AX,184(DI) - MOVQ R10,192(DI) - MOVQ 184(DI),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 16(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 192(DI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 160(DI),AX - MULQ 0(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 160(DI),AX - MULQ 8(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 160(DI),AX - MULQ 16(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 160(DI),AX - MULQ 24(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 160(DI),AX - MULQ 32(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 168(DI),AX - MULQ 0(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 168(DI),AX - MULQ 8(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 168(DI),AX - MULQ 16(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 168(DI),AX - MULQ 24(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 168(DI),DX - IMUL3Q $19,DX,AX - MULQ 32(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),AX - MULQ 0(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 176(DI),AX - MULQ 8(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 176(DI),AX - MULQ 16(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 176(DI),DX - IMUL3Q $19,DX,AX - MULQ 24(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),DX - IMUL3Q $19,DX,AX - MULQ 32(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),AX - MULQ 0(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 184(DI),AX - MULQ 8(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 24(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 32(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 192(DI),AX - MULQ 0(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 16(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 24(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 32(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,160(DI) - MOVQ R8,168(DI) - MOVQ R9,176(DI) - MOVQ AX,184(DI) - MOVQ R10,192(DI) - MOVQ 144(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 96(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 152(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 88(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 120(SP),AX - MULQ 80(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 120(SP),AX - MULQ 88(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 120(SP),AX - MULQ 96(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 120(SP),AX - MULQ 104(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 120(SP),AX - MULQ 112(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 128(SP),AX - MULQ 80(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 128(SP),AX - MULQ 88(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 128(SP),AX - MULQ 96(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 128(SP),AX - MULQ 104(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 128(SP),DX - IMUL3Q $19,DX,AX - MULQ 112(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(SP),AX - MULQ 80(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 136(SP),AX - MULQ 88(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 136(SP),AX - MULQ 96(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 136(SP),DX - IMUL3Q $19,DX,AX - MULQ 104(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(SP),DX - IMUL3Q $19,DX,AX - MULQ 112(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(SP),AX - MULQ 80(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 144(SP),AX - MULQ 88(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 104(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 112(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 152(SP),AX - MULQ 80(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 96(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 104(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 112(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,40(DI) - MOVQ R8,48(DI) - MOVQ R9,56(DI) - MOVQ AX,64(DI) - MOVQ R10,72(DI) - MOVQ 160(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - MOVQ AX,SI - MOVQ DX,CX - MOVQ 168(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,CX - MOVQ DX,R8 - MOVQ 176(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R8 - MOVQ DX,R9 - MOVQ 184(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R9 - MOVQ DX,R10 - MOVQ 192(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R10 - IMUL3Q $19,DX,DX - ADDQ DX,SI - ADDQ 80(SP),SI - ADDQ 88(SP),CX - ADDQ 96(SP),R8 - ADDQ 104(SP),R9 - ADDQ 112(SP),R10 - MOVQ SI,80(DI) - MOVQ CX,88(DI) - MOVQ R8,96(DI) - MOVQ R9,104(DI) - MOVQ R10,112(DI) - MOVQ 104(DI),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 176(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 112(DI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 168(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 80(DI),AX - MULQ 160(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 80(DI),AX - MULQ 168(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 80(DI),AX - MULQ 176(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 80(DI),AX - MULQ 184(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 80(DI),AX - MULQ 192(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 88(DI),AX - MULQ 160(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 88(DI),AX - MULQ 168(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 88(DI),AX - MULQ 176(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 88(DI),AX - MULQ 184(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 88(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 96(DI),AX - MULQ 160(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 96(DI),AX - MULQ 168(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 96(DI),AX - MULQ 176(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 96(DI),DX - IMUL3Q $19,DX,AX - MULQ 184(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 96(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 104(DI),AX - MULQ 160(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 104(DI),AX - MULQ 168(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 184(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 192(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 112(DI),AX - MULQ 160(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 176(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 184(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 192(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,80(DI) - MOVQ R8,88(DI) - MOVQ R9,96(DI) - MOVQ AX,104(DI) - MOVQ R10,112(DI) - RET diff --git a/curve25519/mont25519_amd64.go b/curve25519/mont25519_amd64.go deleted file mode 100644 index 5822bd5338..0000000000 --- a/curve25519/mont25519_amd64.go +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -package curve25519 - -// These functions are implemented in the .s files. The names of the functions -// in the rest of the file are also taken from the SUPERCOP sources to help -// people following along. - -//go:noescape - -func cswap(inout *[5]uint64, v uint64) - -//go:noescape - -func ladderstep(inout *[5][5]uint64) - -//go:noescape - -func freeze(inout *[5]uint64) - -//go:noescape - -func mul(dest, a, b *[5]uint64) - -//go:noescape - -func square(out, in *[5]uint64) - -// mladder uses a Montgomery ladder to calculate (xr/zr) *= s. -func mladder(xr, zr *[5]uint64, s *[32]byte) { - var work [5][5]uint64 - - work[0] = *xr - setint(&work[1], 1) - setint(&work[2], 0) - work[3] = *xr - setint(&work[4], 1) - - j := uint(6) - var prevbit byte - - for i := 31; i >= 0; i-- { - for j < 8 { - bit := ((*s)[i] >> j) & 1 - swap := bit ^ prevbit - prevbit = bit - cswap(&work[1], uint64(swap)) - ladderstep(&work) - j-- - } - j = 7 - } - - *xr = work[1] - *zr = work[2] -} - -func scalarMult(out, in, base *[32]byte) { - var e [32]byte - copy(e[:], (*in)[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var t, z [5]uint64 - unpack(&t, base) - mladder(&t, &z, &e) - invert(&z, &z) - mul(&t, &t, &z) - pack(out, &t) -} - -func setint(r *[5]uint64, v uint64) { - r[0] = v - r[1] = 0 - r[2] = 0 - r[3] = 0 - r[4] = 0 -} - -// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian -// order. -func unpack(r *[5]uint64, x *[32]byte) { - r[0] = uint64(x[0]) | - uint64(x[1])<<8 | - uint64(x[2])<<16 | - uint64(x[3])<<24 | - uint64(x[4])<<32 | - uint64(x[5])<<40 | - uint64(x[6]&7)<<48 - - r[1] = uint64(x[6])>>3 | - uint64(x[7])<<5 | - uint64(x[8])<<13 | - uint64(x[9])<<21 | - uint64(x[10])<<29 | - uint64(x[11])<<37 | - uint64(x[12]&63)<<45 - - r[2] = uint64(x[12])>>6 | - uint64(x[13])<<2 | - uint64(x[14])<<10 | - uint64(x[15])<<18 | - uint64(x[16])<<26 | - uint64(x[17])<<34 | - uint64(x[18])<<42 | - uint64(x[19]&1)<<50 - - r[3] = uint64(x[19])>>1 | - uint64(x[20])<<7 | - uint64(x[21])<<15 | - uint64(x[22])<<23 | - uint64(x[23])<<31 | - uint64(x[24])<<39 | - uint64(x[25]&15)<<47 - - r[4] = uint64(x[25])>>4 | - uint64(x[26])<<4 | - uint64(x[27])<<12 | - uint64(x[28])<<20 | - uint64(x[29])<<28 | - uint64(x[30])<<36 | - uint64(x[31]&127)<<44 -} - -// pack sets out = x where out is the usual, little-endian form of the 5, -// 51-bit limbs in x. -func pack(out *[32]byte, x *[5]uint64) { - t := *x - freeze(&t) - - out[0] = byte(t[0]) - out[1] = byte(t[0] >> 8) - out[2] = byte(t[0] >> 16) - out[3] = byte(t[0] >> 24) - out[4] = byte(t[0] >> 32) - out[5] = byte(t[0] >> 40) - out[6] = byte(t[0] >> 48) - - out[6] ^= byte(t[1]<<3) & 0xf8 - out[7] = byte(t[1] >> 5) - out[8] = byte(t[1] >> 13) - out[9] = byte(t[1] >> 21) - out[10] = byte(t[1] >> 29) - out[11] = byte(t[1] >> 37) - out[12] = byte(t[1] >> 45) - - out[12] ^= byte(t[2]<<6) & 0xc0 - out[13] = byte(t[2] >> 2) - out[14] = byte(t[2] >> 10) - out[15] = byte(t[2] >> 18) - out[16] = byte(t[2] >> 26) - out[17] = byte(t[2] >> 34) - out[18] = byte(t[2] >> 42) - out[19] = byte(t[2] >> 50) - - out[19] ^= byte(t[3]<<1) & 0xfe - out[20] = byte(t[3] >> 7) - out[21] = byte(t[3] >> 15) - out[22] = byte(t[3] >> 23) - out[23] = byte(t[3] >> 31) - out[24] = byte(t[3] >> 39) - out[25] = byte(t[3] >> 47) - - out[25] ^= byte(t[4]<<4) & 0xf0 - out[26] = byte(t[4] >> 4) - out[27] = byte(t[4] >> 12) - out[28] = byte(t[4] >> 20) - out[29] = byte(t[4] >> 28) - out[30] = byte(t[4] >> 36) - out[31] = byte(t[4] >> 44) -} - -// invert calculates r = x^-1 mod p using Fermat's little theorem. -func invert(r *[5]uint64, x *[5]uint64) { - var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 - - square(&z2, x) /* 2 */ - square(&t, &z2) /* 4 */ - square(&t, &t) /* 8 */ - mul(&z9, &t, x) /* 9 */ - mul(&z11, &z9, &z2) /* 11 */ - square(&t, &z11) /* 22 */ - mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ - - square(&t, &z2_5_0) /* 2^6 - 2^1 */ - for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ - square(&t, &t) - } - mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ - - square(&t, &z2_10_0) /* 2^11 - 2^1 */ - for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ - square(&t, &t) - } - mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ - - square(&t, &z2_20_0) /* 2^21 - 2^1 */ - for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ - square(&t, &t) - } - mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ - - square(&t, &t) /* 2^41 - 2^1 */ - for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ - square(&t, &t) - } - mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ - - square(&t, &z2_50_0) /* 2^51 - 2^1 */ - for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ - square(&t, &t) - } - mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ - - square(&t, &z2_100_0) /* 2^101 - 2^1 */ - for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ - square(&t, &t) - } - mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ - - square(&t, &t) /* 2^201 - 2^1 */ - for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ - square(&t, &t) - } - mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ - - square(&t, &t) /* 2^251 - 2^1 */ - square(&t, &t) /* 2^252 - 2^2 */ - square(&t, &t) /* 2^253 - 2^3 */ - - square(&t, &t) /* 2^254 - 2^4 */ - - square(&t, &t) /* 2^255 - 2^5 */ - mul(r, &t, &z11) /* 2^255 - 21 */ -} diff --git a/curve25519/mul_amd64.s b/curve25519/mul_amd64.s deleted file mode 100644 index 1f76d1a3f5..0000000000 --- a/curve25519/mul_amd64.s +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func mul(dest, a, b *[5]uint64) -TEXT ·mul(SB),0,$16-24 - MOVQ dest+0(FP), DI - MOVQ a+8(FP), SI - MOVQ b+16(FP), DX - - MOVQ DX,CX - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,0(SP) - MULQ 16(CX) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 0(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 8(CX) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SI),AX - MULQ 16(CX) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SI),AX - MULQ 24(CX) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 0(SI),AX - MULQ 32(CX) - MOVQ AX,BX - MOVQ DX,BP - MOVQ 8(SI),AX - MULQ 0(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SI),AX - MULQ 8(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SI),AX - MULQ 16(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SI),AX - MULQ 24(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),AX - MULQ 0(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 16(SI),AX - MULQ 8(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SI),AX - MULQ 16(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 24(SI),AX - MULQ 0(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 24(SI),AX - MULQ 8(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 0(SP),AX - MULQ 24(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 0(SP),AX - MULQ 32(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 32(SI),AX - MULQ 0(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SP),AX - MULQ 16(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 24(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - MULQ 32(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ $REDMASK51,SI - SHLQ $13,R8,R9 - ANDQ SI,R8 - SHLQ $13,R10,R11 - ANDQ SI,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ SI,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ SI,R14 - ADDQ R13,R14 - SHLQ $13,BX,BP - ANDQ SI,BX - ADDQ R15,BX - IMUL3Q $19,BP,DX - ADDQ DX,R8 - MOVQ R8,DX - SHRQ $51,DX - ADDQ R10,DX - MOVQ DX,CX - SHRQ $51,DX - ANDQ SI,R8 - ADDQ R12,DX - MOVQ DX,R9 - SHRQ $51,DX - ANDQ SI,CX - ADDQ R14,DX - MOVQ DX,AX - SHRQ $51,DX - ANDQ SI,R9 - ADDQ BX,DX - MOVQ DX,R10 - SHRQ $51,DX - ANDQ SI,AX - IMUL3Q $19,DX,DX - ADDQ DX,R8 - ANDQ SI,R10 - MOVQ R8,0(DI) - MOVQ CX,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/curve25519/square_amd64.s b/curve25519/square_amd64.s deleted file mode 100644 index 07511a45af..0000000000 --- a/curve25519/square_amd64.s +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,!gccgo,!appengine - -#include "const_amd64.h" - -// func square(out, in *[5]uint64) -TEXT ·square(SB),7,$0-16 - MOVQ out+0(FP), DI - MOVQ in+8(FP), SI - - MOVQ 0(SI),AX - MULQ 0(SI) - MOVQ AX,CX - MOVQ DX,R8 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 8(SI) - MOVQ AX,R9 - MOVQ DX,R10 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 16(SI) - MOVQ AX,R11 - MOVQ DX,R12 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 24(SI) - MOVQ AX,R13 - MOVQ DX,R14 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 32(SI) - MOVQ AX,R15 - MOVQ DX,BX - MOVQ 8(SI),AX - MULQ 8(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 16(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 24(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 8(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),AX - MULQ 16(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 24(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ $REDMASK51,SI - SHLQ $13,CX,R8 - ANDQ SI,CX - SHLQ $13,R9,R10 - ANDQ SI,R9 - ADDQ R8,R9 - SHLQ $13,R11,R12 - ANDQ SI,R11 - ADDQ R10,R11 - SHLQ $13,R13,R14 - ANDQ SI,R13 - ADDQ R12,R13 - SHLQ $13,R15,BX - ANDQ SI,R15 - ADDQ R14,R15 - IMUL3Q $19,BX,DX - ADDQ DX,CX - MOVQ CX,DX - SHRQ $51,DX - ADDQ R9,DX - ANDQ SI,CX - MOVQ DX,R8 - SHRQ $51,DX - ADDQ R11,DX - ANDQ SI,R8 - MOVQ DX,R9 - SHRQ $51,DX - ADDQ R13,DX - ANDQ SI,R9 - MOVQ DX,AX - SHRQ $51,DX - ADDQ R15,DX - ANDQ SI,AX - MOVQ DX,R10 - SHRQ $51,DX - IMUL3Q $19,DX,DX - ADDQ DX,CX - ANDQ SI,R10 - MOVQ CX,0(DI) - MOVQ R8,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/curve25519/testvectors_test.go b/curve25519/vectors_test.go similarity index 86% rename from curve25519/testvectors_test.go rename to curve25519/vectors_test.go index 79b7a092e9..f4c0a1414f 100644 --- a/curve25519/testvectors_test.go +++ b/curve25519/vectors_test.go @@ -2,7 +2,19 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package curve25519 +package curve25519_test + +// lowOrderPoints from libsodium. +// https://github.com/jedisct1/libsodium/blob/65621a1059a37d/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L11-L70 +var lowOrderPoints = [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00}, + {0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57}, + {0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, + {0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, + {0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, +} // testVectors generated with BoringSSL. var testVectors = []struct { diff --git a/ed25519/ed25519.go b/ed25519/ed25519.go index c7f8c7e64e..df453dcce0 100644 --- a/ed25519/ed25519.go +++ b/ed25519/ed25519.go @@ -1,35 +1,25 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2019 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. -// In Go 1.13, the ed25519 package was promoted to the standard library as -// crypto/ed25519, and this package became a wrapper for the standard library one. -// -// +build !go1.13 - -// Package ed25519 implements the Ed25519 signature algorithm. See -// https://ed25519.cr.yp.to/. +// Package ed25519 implements the Ed25519 signature algorithm. // // 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]. However, unlike RFC 8032's formulation, this package's private key // 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”. +// +// The ed25519 package is a wrapper for the Ed25519 implementation in the +// crypto/ed25519 package. It is [frozen] and is not accepting new features. +// +// [RFC 8032]: https://datatracker.ietf.org/doc/html/rfc8032 +// [frozen]: https://go.dev/wiki/Frozen package ed25519 -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - import ( - "bytes" - "crypto" - cryptorand "crypto/rand" - "crypto/sha512" - "errors" + "crypto/ed25519" "io" - "strconv" - - "golang.org/x/crypto/ed25519/internal/edwards25519" ) const ( @@ -44,57 +34,21 @@ const ( ) // PublicKey is the type of Ed25519 public keys. -type PublicKey []byte +// +// This type is an alias for crypto/ed25519's PublicKey type. +// See the crypto/ed25519 package for the methods on this type. +type PublicKey = ed25519.PublicKey // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -type PrivateKey []byte - -// Public returns the PublicKey corresponding to priv. -func (priv PrivateKey) Public() crypto.PublicKey { - publicKey := make([]byte, PublicKeySize) - copy(publicKey, priv[32:]) - 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. -// Ed25519 performs two passes over messages to be signed and therefore cannot -// handle pre-hashed messages. Thus opts.HashFunc() must return zero to -// indicate the message hasn't been hashed. This can be achieved by passing -// crypto.Hash(0) as the value for opts. -func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { - if opts.HashFunc() != crypto.Hash(0) { - return nil, errors.New("ed25519: cannot sign hashed message") - } - - return Sign(priv, message), nil -} +// +// This type is an alias for crypto/ed25519's PrivateKey type. +// See the crypto/ed25519 package for the methods on this type. +type PrivateKey = ed25519.PrivateKey // GenerateKey generates a public/private key pair using entropy from rand. // If rand is nil, crypto/rand.Reader will be used. func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - if rand == nil { - rand = cryptorand.Reader - } - - seed := make([]byte, SeedSize) - if _, err := io.ReadFull(rand, seed); err != nil { - return nil, nil, err - } - - privateKey := NewKeyFromSeed(seed) - publicKey := make([]byte, PublicKeySize) - copy(publicKey, privateKey[32:]) - - return publicKey, privateKey, nil + return ed25519.GenerateKey(rand) } // NewKeyFromSeed calculates a private key from a seed. It will panic if @@ -102,121 +56,17 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { // 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[31] &= 127 - digest[31] |= 64 - - var A edwards25519.ExtendedGroupElement - var hBytes [32]byte - copy(hBytes[:], digest[:]) - edwards25519.GeScalarMultBase(&A, &hBytes) - var publicKeyBytes [32]byte - A.ToBytes(&publicKeyBytes) - - privateKey := make([]byte, PrivateKeySize) - copy(privateKey, seed) - copy(privateKey[32:], publicKeyBytes[:]) - - return privateKey + return ed25519.NewKeyFromSeed(seed) } // Sign signs the message with privateKey and returns a signature. It will // panic if len(privateKey) is not PrivateKeySize. func Sign(privateKey PrivateKey, message []byte) []byte { - if l := len(privateKey); l != PrivateKeySize { - panic("ed25519: bad private key length: " + strconv.Itoa(l)) - } - - h := sha512.New() - h.Write(privateKey[:32]) - - var digest1, messageDigest, hramDigest [64]byte - var expandedSecretKey [32]byte - h.Sum(digest1[:0]) - copy(expandedSecretKey[:], digest1[:]) - expandedSecretKey[0] &= 248 - expandedSecretKey[31] &= 63 - expandedSecretKey[31] |= 64 - - h.Reset() - h.Write(digest1[32:]) - h.Write(message) - h.Sum(messageDigest[:0]) - - var messageDigestReduced [32]byte - edwards25519.ScReduce(&messageDigestReduced, &messageDigest) - var R edwards25519.ExtendedGroupElement - edwards25519.GeScalarMultBase(&R, &messageDigestReduced) - - var encodedR [32]byte - R.ToBytes(&encodedR) - - h.Reset() - h.Write(encodedR[:]) - h.Write(privateKey[32:]) - h.Write(message) - h.Sum(hramDigest[:0]) - var hramDigestReduced [32]byte - edwards25519.ScReduce(&hramDigestReduced, &hramDigest) - - var s [32]byte - edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) - - signature := make([]byte, SignatureSize) - copy(signature[:], encodedR[:]) - copy(signature[32:], s[:]) - - return signature + return ed25519.Sign(privateKey, message) } // Verify reports whether sig is a valid signature of message by publicKey. It // will panic if len(publicKey) is not PublicKeySize. func Verify(publicKey PublicKey, message, sig []byte) bool { - if l := len(publicKey); l != PublicKeySize { - panic("ed25519: bad public key length: " + strconv.Itoa(l)) - } - - if len(sig) != SignatureSize || sig[63]&224 != 0 { - return false - } - - var A edwards25519.ExtendedGroupElement - var publicKeyBytes [32]byte - copy(publicKeyBytes[:], publicKey) - if !A.FromBytes(&publicKeyBytes) { - return false - } - edwards25519.FeNeg(&A.X, &A.X) - edwards25519.FeNeg(&A.T, &A.T) - - h := sha512.New() - h.Write(sig[:32]) - h.Write(publicKey[:]) - h.Write(message) - var digest [64]byte - h.Sum(digest[:0]) - - var hReduced [32]byte - edwards25519.ScReduce(&hReduced, &digest) - - var R edwards25519.ProjectiveGroupElement - var s [32]byte - copy(s[:], sig[32:]) - - // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in - // the range [0, order) in order to prevent signature malleability. - if !edwards25519.ScMinimal(&s) { - return false - } - - edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) - - var checkR [32]byte - R.ToBytes(&checkR) - return bytes.Equal(sig[:32], checkR[:]) + return ed25519.Verify(publicKey, message, sig) } diff --git a/ed25519/ed25519_go113.go b/ed25519/ed25519_go113.go deleted file mode 100644 index d1448d8d22..0000000000 --- a/ed25519/ed25519_go113.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019 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 go1.13 - -// Package ed25519 implements the Ed25519 signature algorithm. See -// https://ed25519.cr.yp.to/. -// -// These functions are also compatible with the “Ed25519” function defined in -// RFC 8032. However, unlike RFC 8032's formulation, this package's private key -// 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”. -// -// Beginning with Go 1.13, the functionality of this package was moved to the -// standard library as crypto/ed25519. This package only acts as a compatibility -// wrapper. -package ed25519 - -import ( - "crypto/ed25519" - "io" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys as used in this package. - PublicKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - 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. -// -// This type is an alias for crypto/ed25519's PublicKey type. -// See the crypto/ed25519 package for the methods on this type. -type PublicKey = ed25519.PublicKey - -// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -// -// This type is an alias for crypto/ed25519's PrivateKey type. -// See the crypto/ed25519 package for the methods on this type. -type PrivateKey = ed25519.PrivateKey - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - return ed25519.GenerateKey(rand) -} - -// 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 { - return ed25519.NewKeyFromSeed(seed) -} - -// Sign signs the message with privateKey and returns a signature. It will -// panic if len(privateKey) is not PrivateKeySize. -func Sign(privateKey PrivateKey, message []byte) []byte { - return ed25519.Sign(privateKey, message) -} - -// Verify reports whether sig is a valid signature of message by publicKey. It -// will panic if len(publicKey) is not PublicKeySize. -func Verify(publicKey PublicKey, message, sig []byte) bool { - return ed25519.Verify(publicKey, message, sig) -} diff --git a/ed25519/ed25519_test.go b/ed25519/ed25519_test.go index 13187cd94a..ab433ba02b 100644 --- a/ed25519/ed25519_test.go +++ b/ed25519/ed25519_test.go @@ -1,221 +1,22 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2019 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 ed25519_test import ( - "bufio" - "bytes" - "compress/gzip" - "crypto" - "crypto/rand" - "encoding/hex" - "os" - "strings" + ed25519std "crypto/ed25519" "testing" "golang.org/x/crypto/ed25519" - "golang.org/x/crypto/ed25519/internal/edwards25519" ) -type zeroReader struct{} - -func (zeroReader) Read(buf []byte) (int, error) { - for i := range buf { - buf[i] = 0 - } - return len(buf), nil -} - -func TestUnmarshalMarshal(t *testing.T) { - pub, _, _ := ed25519.GenerateKey(rand.Reader) - - var A edwards25519.ExtendedGroupElement - var pubBytes [32]byte - copy(pubBytes[:], pub) - if !A.FromBytes(&pubBytes) { - t.Fatalf("ExtendedGroupElement.FromBytes failed") - } - - var pub2 [32]byte - A.ToBytes(&pub2) - - if pubBytes != pub2 { - t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2) - } -} - -func TestSignVerify(t *testing.T) { - var zero zeroReader - public, private, _ := ed25519.GenerateKey(zero) +func TestTypeAlias(t *testing.T) { + public, private, _ := ed25519std.GenerateKey(nil) message := []byte("test message") sig := ed25519.Sign(private, message) if !ed25519.Verify(public, message, sig) { t.Errorf("valid signature rejected") } - - wrongMessage := []byte("wrong message") - if ed25519.Verify(public, wrongMessage, sig) { - t.Errorf("signature of different message accepted") - } -} - -func TestCryptoSigner(t *testing.T) { - var zero zeroReader - public, private, _ := ed25519.GenerateKey(zero) - - signer := crypto.Signer(private) - - publicInterface := signer.Public() - public2, ok := publicInterface.(ed25519.PublicKey) - if !ok { - t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) - } - - if !bytes.Equal(public, public2) { - t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2) - } - - message := []byte("message") - var noHash crypto.Hash - signature, err := signer.Sign(zero, message, noHash) - if err != nil { - t.Fatalf("error from Sign(): %s", err) - } - - if !ed25519.Verify(public, message, signature) { - t.Errorf("Verify failed on signature from Sign()") - } -} - -func TestGolden(t *testing.T) { - // sign.input.gz is a selection of test cases from - // https://ed25519.cr.yp.to/python/sign.input - testDataZ, err := os.Open("testdata/sign.input.gz") - if err != nil { - t.Fatal(err) - } - defer testDataZ.Close() - testData, err := gzip.NewReader(testDataZ) - if err != nil { - t.Fatal(err) - } - defer testData.Close() - - scanner := bufio.NewScanner(testData) - lineNo := 0 - - for scanner.Scan() { - lineNo++ - - line := scanner.Text() - parts := strings.Split(line, ":") - if len(parts) != 5 { - t.Fatalf("bad number of parts on line %d", lineNo) - } - - privBytes, _ := hex.DecodeString(parts[0]) - pubKey, _ := hex.DecodeString(parts[1]) - msg, _ := hex.DecodeString(parts[2]) - sig, _ := hex.DecodeString(parts[3]) - // The signatures in the test vectors also include the message - // at the end, but we just want R and S. - sig = sig[:ed25519.SignatureSize] - - if l := len(pubKey); l != ed25519.PublicKeySize { - t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) - } - - var priv [ed25519.PrivateKeySize]byte - copy(priv[:], privBytes) - copy(priv[32:], pubKey) - - sig2 := ed25519.Sign(priv[:], msg) - if !bytes.Equal(sig, sig2[:]) { - t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) - } - - if !ed25519.Verify(pubKey, msg, sig2) { - t.Errorf("signature failed to verify on line %d", lineNo) - } - - priv2 := ed25519.NewKeyFromSeed(priv[:32]) - if !bytes.Equal(priv[:], priv2) { - t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) - } - - if pubKey2 := priv2.Public().(ed25519.PublicKey); !bytes.Equal(pubKey, pubKey2) { - t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) - } - - if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) { - t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed) - } - } - - if err := scanner.Err(); err != nil { - t.Fatalf("error reading test data: %s", err) - } -} - -func TestMalleability(t *testing.T) { - // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test - // that s be in [0, order). This prevents someone from adding a multiple of - // order to s and obtaining a second valid signature for the same message. - msg := []byte{0x54, 0x65, 0x73, 0x74} - sig := []byte{ - 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, - 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, - 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, - 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, - 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, - 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, - } - publicKey := []byte{ - 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, - 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, - 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, - } - - if ed25519.Verify(publicKey, msg, sig) { - t.Fatal("non-canonical signature accepted") - } -} - -func BenchmarkKeyGeneration(b *testing.B) { - var zero zeroReader - for i := 0; i < b.N; i++ { - if _, _, err := ed25519.GenerateKey(zero); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkSigning(b *testing.B) { - var zero zeroReader - _, priv, err := ed25519.GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - b.ResetTimer() - for i := 0; i < b.N; i++ { - ed25519.Sign(priv, message) - } -} - -func BenchmarkVerification(b *testing.B) { - var zero zeroReader - pub, priv, err := ed25519.GenerateKey(zero) - if err != nil { - b.Fatal(err) - } - message := []byte("Hello, world!") - signature := ed25519.Sign(priv, message) - b.ResetTimer() - for i := 0; i < b.N; i++ { - ed25519.Verify(pub, message, signature) - } } diff --git a/ed25519/go113_test.go b/ed25519/go113_test.go deleted file mode 100644 index 76edde07c2..0000000000 --- a/ed25519/go113_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 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 go1.13 - -package ed25519_test - -import ( - ed25519std "crypto/ed25519" - "golang.org/x/crypto/ed25519" - "testing" -) - -func TestTypeAlias(t *testing.T) { - var zero zeroReader - public, private, _ := ed25519std.GenerateKey(zero) - - message := []byte("test message") - sig := ed25519.Sign(private, message) - if !ed25519.Verify(public, message, sig) { - t.Errorf("valid signature rejected") - } -} diff --git a/ed25519/internal/edwards25519/const.go b/ed25519/internal/edwards25519/const.go deleted file mode 100644 index e39f086c1d..0000000000 --- a/ed25519/internal/edwards25519/const.go +++ /dev/null @@ -1,1422 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -// These values are from the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -// d is a constant in the Edwards curve equation. -var d = FieldElement{ - -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, -} - -// d2 is 2*d. -var d2 = FieldElement{ - -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, -} - -// SqrtM1 is the square-root of -1 in the field. -var SqrtM1 = FieldElement{ - -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, -} - -// A is a constant in the Montgomery-form of curve25519. -var A = FieldElement{ - 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -// bi contains precomputed multiples of the base-point. See the Ed25519 paper -// for a discussion about how these values are used. -var bi = [8]PreComputedGroupElement{ - { - FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, - }, - { - FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, - }, - { - FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, - }, - { - FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, - }, - { - FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, - FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, - FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}, - }, - { - FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, - FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, - FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}, - }, - { - FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, - FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, - FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}, - }, - { - FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, - FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, - FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}, - }, -} - -// base contains precomputed multiples of the base-point. See the Ed25519 paper -// for a discussion about how these values are used. -var base = [32][8]PreComputedGroupElement{ - { - { - FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, - }, - { - FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, - FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, - FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}, - }, - { - FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, - }, - { - FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, - FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, - FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}, - }, - { - FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, - }, - { - FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, - FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, - FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}, - }, - { - FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, - }, - { - FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, - FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, - FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}, - }, - }, - { - { - FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, - FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, - FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}, - }, - { - FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, - FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, - FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}, - }, - { - FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, - FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, - FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}, - }, - { - FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, - FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, - FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}, - }, - { - FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, - FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, - FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}, - }, - { - FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, - FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, - FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}, - }, - { - FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, - FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, - FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}, - }, - { - FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, - FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, - FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}, - }, - }, - { - { - FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, - FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, - FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}, - }, - { - FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, - FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, - FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}, - }, - { - FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, - FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, - FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}, - }, - { - FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, - FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, - FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}, - }, - { - FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, - FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, - FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}, - }, - { - FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, - FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, - FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}, - }, - { - FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, - FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, - FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}, - }, - { - FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, - FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, - FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}, - }, - }, - { - { - FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, - FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, - FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}, - }, - { - FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, - FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, - FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}, - }, - { - FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, - FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, - FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}, - }, - { - FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, - FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, - FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}, - }, - { - FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, - FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, - FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}, - }, - { - FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, - FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, - FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}, - }, - { - FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, - FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, - FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}, - }, - { - FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, - FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, - FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}, - }, - }, - { - { - FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, - FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, - FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}, - }, - { - FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, - FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, - FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}, - }, - { - FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, - FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, - FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}, - }, - { - FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, - FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, - FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}, - }, - { - FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, - FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, - FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}, - }, - { - FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, - FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, - FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}, - }, - { - FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, - FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, - FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}, - }, - { - FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, - FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, - FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}, - }, - }, - { - { - FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, - FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, - FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}, - }, - { - FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, - FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, - FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}, - }, - { - FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, - FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, - FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}, - }, - { - FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, - FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, - FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}, - }, - { - FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, - FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, - FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}, - }, - { - FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, - FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, - FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}, - }, - { - FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, - FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, - FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}, - }, - { - FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, - FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, - FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}, - }, - }, - { - { - FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, - FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, - FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}, - }, - { - FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, - FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, - FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}, - }, - { - FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, - FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, - FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}, - }, - { - FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, - FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, - FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}, - }, - { - FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, - FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, - FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}, - }, - { - FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, - FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, - FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}, - }, - { - FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, - FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, - FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}, - }, - { - FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, - FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, - FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}, - }, - }, - { - { - FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, - FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, - FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}, - }, - { - FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, - FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, - FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}, - }, - { - FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, - FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, - FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}, - }, - { - FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, - FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, - FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}, - }, - { - FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, - FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, - FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}, - }, - { - FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, - FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, - FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}, - }, - { - FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, - FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, - FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}, - }, - { - FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, - FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, - FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}, - }, - }, - { - { - FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, - FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, - FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}, - }, - { - FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, - FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, - FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}, - }, - { - FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, - FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, - FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}, - }, - { - FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, - FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, - FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}, - }, - { - FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, - FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, - FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}, - }, - { - FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, - FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, - FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}, - }, - { - FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, - FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, - FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}, - }, - { - FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, - FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, - FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}, - }, - }, - { - { - FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, - FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, - FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}, - }, - { - FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, - FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, - FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}, - }, - { - FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, - FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, - FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}, - }, - { - FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, - FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, - FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}, - }, - { - FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, - FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, - FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}, - }, - { - FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, - FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, - FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}, - }, - { - FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, - FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, - FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}, - }, - { - FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, - FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, - FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}, - }, - }, - { - { - FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, - FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, - FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}, - }, - { - FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, - FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, - FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}, - }, - { - FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, - FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, - FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}, - }, - { - FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, - FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, - FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}, - }, - { - FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, - FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, - FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}, - }, - { - FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, - FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, - FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}, - }, - { - FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, - FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, - FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}, - }, - { - FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, - FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, - FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}, - }, - }, - { - { - FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, - FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, - FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}, - }, - { - FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, - FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, - FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}, - }, - { - FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, - FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, - FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}, - }, - { - FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, - FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, - FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}, - }, - { - FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, - FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, - FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}, - }, - { - FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, - FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, - FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}, - }, - { - FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, - FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, - FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}, - }, - { - FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, - FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, - FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}, - }, - }, - { - { - FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, - FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, - FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}, - }, - { - FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, - FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, - FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}, - }, - { - FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, - FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, - FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}, - }, - { - FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, - FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, - FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}, - }, - { - FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, - FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, - FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}, - }, - { - FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, - FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, - FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}, - }, - { - FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, - FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, - FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}, - }, - { - FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, - FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, - FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}, - }, - }, - { - { - FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, - FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, - FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}, - }, - { - FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, - FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, - FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}, - }, - { - FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, - FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, - FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}, - }, - { - FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, - FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, - FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}, - }, - { - FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, - FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, - FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}, - }, - { - FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, - FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, - FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}, - }, - { - FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, - FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, - FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}, - }, - { - FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, - FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, - FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}, - }, - }, - { - { - FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, - FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, - FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}, - }, - { - FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, - FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, - FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}, - }, - { - FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, - FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, - FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}, - }, - { - FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, - FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, - FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}, - }, - { - FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, - FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, - FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}, - }, - { - FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, - FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, - FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}, - }, - { - FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, - FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, - FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}, - }, - { - FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, - FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, - FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}, - }, - }, - { - { - FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, - FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, - FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}, - }, - { - FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, - FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, - FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}, - }, - { - FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, - FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, - FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}, - }, - { - FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, - FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, - FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}, - }, - { - FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, - FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, - FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}, - }, - { - FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, - FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, - FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}, - }, - { - FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, - FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, - FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}, - }, - { - FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, - FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, - FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}, - }, - }, - { - { - FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, - FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, - FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}, - }, - { - FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, - FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, - FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}, - }, - { - FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, - FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, - FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}, - }, - { - FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, - FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, - FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}, - }, - { - FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, - FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, - FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}, - }, - { - FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, - FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, - FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}, - }, - { - FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, - FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, - FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}, - }, - { - FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, - FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, - FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}, - }, - }, - { - { - FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, - FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, - FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}, - }, - { - FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, - FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, - FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}, - }, - { - FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, - FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, - FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}, - }, - { - FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, - FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, - FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}, - }, - { - FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, - FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, - FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}, - }, - { - FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, - FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, - FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}, - }, - { - FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, - FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, - FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}, - }, - { - FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, - FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, - FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}, - }, - }, - { - { - FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, - FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, - FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}, - }, - { - FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, - FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, - FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}, - }, - { - FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, - FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, - FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}, - }, - { - FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, - FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, - FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}, - }, - { - FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, - FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, - FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}, - }, - { - FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, - FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, - FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}, - }, - { - FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, - FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, - FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}, - }, - { - FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, - FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, - FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}, - }, - }, - { - { - FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, - FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, - FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}, - }, - { - FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, - FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, - FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}, - }, - { - FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, - FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, - FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}, - }, - { - FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, - FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, - FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}, - }, - { - FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, - FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, - FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}, - }, - { - FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, - FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, - FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}, - }, - { - FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, - FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, - FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}, - }, - { - FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, - FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, - FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}, - }, - }, - { - { - FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, - FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, - FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}, - }, - { - FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, - FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, - FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}, - }, - { - FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, - FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, - FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}, - }, - { - FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, - FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, - FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}, - }, - { - FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, - FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, - FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}, - }, - { - FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, - FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, - FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}, - }, - { - FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, - FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, - FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}, - }, - { - FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, - FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, - FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}, - }, - }, - { - { - FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, - FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, - FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}, - }, - { - FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, - FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, - FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}, - }, - { - FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, - FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, - FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}, - }, - { - FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, - FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, - FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}, - }, - { - FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, - FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, - FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}, - }, - { - FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, - FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, - FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}, - }, - { - FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, - FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, - FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}, - }, - { - FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, - FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, - FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}, - }, - }, - { - { - FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, - FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, - FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}, - }, - { - FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, - FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, - FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}, - }, - { - FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, - FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, - FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}, - }, - { - FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, - FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, - FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}, - }, - { - FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, - FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, - FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}, - }, - { - FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, - FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, - FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}, - }, - { - FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, - FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, - FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}, - }, - { - FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, - FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, - FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}, - }, - }, - { - { - FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, - FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, - FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}, - }, - { - FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, - FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, - FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}, - }, - { - FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, - FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, - FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}, - }, - { - FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, - FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, - FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}, - }, - { - FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, - FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, - FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}, - }, - { - FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, - FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, - FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}, - }, - { - FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, - FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, - FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}, - }, - { - FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, - FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, - FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}, - }, - }, - { - { - FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, - FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, - FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}, - }, - { - FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, - FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, - FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}, - }, - { - FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, - FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, - FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}, - }, - { - FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, - FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, - FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}, - }, - { - FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, - FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, - FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}, - }, - { - FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, - FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, - FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}, - }, - { - FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, - FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, - FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}, - }, - { - FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, - FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, - FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}, - }, - }, - { - { - FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, - FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, - FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}, - }, - { - FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, - FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, - FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}, - }, - { - FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, - FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, - FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}, - }, - { - FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, - FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, - FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}, - }, - { - FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, - FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, - FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}, - }, - { - FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, - FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, - FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}, - }, - { - FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, - FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, - FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}, - }, - { - FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, - FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, - FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}, - }, - }, - { - { - FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, - FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, - FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}, - }, - { - FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, - FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, - FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}, - }, - { - FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, - FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, - FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}, - }, - { - FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, - FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, - FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}, - }, - { - FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, - FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, - FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}, - }, - { - FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, - FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, - FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}, - }, - { - FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, - FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, - FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}, - }, - { - FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, - FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, - FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}, - }, - }, - { - { - FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, - FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, - FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}, - }, - { - FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, - FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, - FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}, - }, - { - FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, - FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, - FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}, - }, - { - FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, - FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, - FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}, - }, - { - FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, - FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, - FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}, - }, - { - FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, - FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, - FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}, - }, - { - FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, - FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, - FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}, - }, - { - FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, - FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, - FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}, - }, - }, - { - { - FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, - FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, - FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}, - }, - { - FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, - FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, - FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}, - }, - { - FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, - FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, - FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}, - }, - { - FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, - FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, - FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}, - }, - { - FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, - FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, - FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}, - }, - { - FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, - FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, - FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}, - }, - { - FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, - FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, - FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}, - }, - { - FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, - FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, - FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}, - }, - }, - { - { - FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, - FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, - FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}, - }, - { - FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, - FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, - FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}, - }, - { - FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, - FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, - FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}, - }, - { - FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, - FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, - FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}, - }, - { - FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, - FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, - FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}, - }, - { - FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, - FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, - FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}, - }, - { - FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, - FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, - FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}, - }, - { - FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, - FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, - FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}, - }, - }, - { - { - FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, - FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, - FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}, - }, - { - FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, - FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, - FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}, - }, - { - FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, - FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, - FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}, - }, - { - FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, - FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, - FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}, - }, - { - FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, - FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, - FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}, - }, - { - FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, - FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, - FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}, - }, - { - FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, - FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, - FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}, - }, - { - FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, - FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, - FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}, - }, - }, - { - { - FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, - FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, - FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}, - }, - { - FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, - FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, - FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}, - }, - { - FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, - FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, - FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}, - }, - { - FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, - FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, - FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}, - }, - { - FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, - FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, - FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}, - }, - { - FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, - FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, - FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}, - }, - { - FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, - FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, - FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}, - }, - { - FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, - FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, - FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}, - }, - }, -} diff --git a/ed25519/internal/edwards25519/edwards25519.go b/ed25519/internal/edwards25519/edwards25519.go deleted file mode 100644 index fd03c252af..0000000000 --- a/ed25519/internal/edwards25519/edwards25519.go +++ /dev/null @@ -1,1793 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import "encoding/binary" - -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -// FieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type FieldElement [10]int32 - -var zero FieldElement - -func FeZero(fe *FieldElement) { - copy(fe[:], zero[:]) -} - -func FeOne(fe *FieldElement) { - FeZero(fe) - fe[0] = 1 -} - -func FeAdd(dst, a, b *FieldElement) { - dst[0] = a[0] + b[0] - dst[1] = a[1] + b[1] - dst[2] = a[2] + b[2] - dst[3] = a[3] + b[3] - dst[4] = a[4] + b[4] - dst[5] = a[5] + b[5] - dst[6] = a[6] + b[6] - dst[7] = a[7] + b[7] - dst[8] = a[8] + b[8] - dst[9] = a[9] + b[9] -} - -func FeSub(dst, a, b *FieldElement) { - dst[0] = a[0] - b[0] - dst[1] = a[1] - b[1] - dst[2] = a[2] - b[2] - dst[3] = a[3] - b[3] - dst[4] = a[4] - b[4] - dst[5] = a[5] - b[5] - dst[6] = a[6] - b[6] - dst[7] = a[7] - b[7] - dst[8] = a[8] - b[8] - dst[9] = a[9] - b[9] -} - -func FeCopy(dst, src *FieldElement) { - copy(dst[:], src[:]) -} - -// Replace (f,g) with (g,g) if b == 1; -// replace (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -func FeCMove(f, g *FieldElement, b int32) { - b = -b - f[0] ^= b & (f[0] ^ g[0]) - f[1] ^= b & (f[1] ^ g[1]) - f[2] ^= b & (f[2] ^ g[2]) - f[3] ^= b & (f[3] ^ g[3]) - f[4] ^= b & (f[4] ^ g[4]) - f[5] ^= b & (f[5] ^ g[5]) - f[6] ^= b & (f[6] ^ g[6]) - f[7] ^= b & (f[7] ^ g[7]) - f[8] ^= b & (f[8] ^ g[8]) - f[9] ^= b & (f[9] ^ g[9]) -} - -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -func load4(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - r |= int64(in[3]) << 24 - return r -} - -func FeFromBytes(dst *FieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 8388607) << 2 - - FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -// FeToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) -} - -func FeIsNegative(f *FieldElement) byte { - var s [32]byte - FeToBytes(&s, f) - return s[0] & 1 -} - -func FeIsNonZero(f *FieldElement) int32 { - var s [32]byte - FeToBytes(&s, f) - var x uint8 - for _, b := range s { - x |= b - } - x |= x >> 4 - x |= x >> 2 - x |= x >> 1 - return int32(x & 1) -} - -// FeNeg sets h = -f -// -// Preconditions: -// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func FeNeg(h, f *FieldElement) { - h[0] = -f[0] - h[1] = -f[1] - h[2] = -f[2] - h[3] = -f[3] - h[4] = -f[4] - h[5] = -f[5] - h[6] = -f[6] - h[7] = -f[7] - h[8] = -f[8] - h[9] = -f[9] -} - -func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { - var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64 - - /* - |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - */ - - c0 = (h0 + (1 << 25)) >> 26 - h1 += c0 - h0 -= c0 << 26 - c4 = (h4 + (1 << 25)) >> 26 - h5 += c4 - h4 -= c4 << 26 - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.51*2^58 */ - /* |h5| <= 1.51*2^58 */ - - c1 = (h1 + (1 << 24)) >> 25 - h2 += c1 - h1 -= c1 << 25 - c5 = (h5 + (1 << 24)) >> 25 - h6 += c5 - h5 -= c5 << 25 - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.21*2^59 */ - /* |h6| <= 1.21*2^59 */ - - c2 = (h2 + (1 << 25)) >> 26 - h3 += c2 - h2 -= c2 << 26 - c6 = (h6 + (1 << 25)) >> 26 - h7 += c6 - h6 -= c6 << 26 - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.51*2^58 */ - /* |h7| <= 1.51*2^58 */ - - c3 = (h3 + (1 << 24)) >> 25 - h4 += c3 - h3 -= c3 << 25 - c7 = (h7 + (1 << 24)) >> 25 - h8 += c7 - h7 -= c7 << 25 - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.52*2^33 */ - /* |h8| <= 1.52*2^33 */ - - c4 = (h4 + (1 << 25)) >> 26 - h5 += c4 - h4 -= c4 << 26 - c8 = (h8 + (1 << 25)) >> 26 - h9 += c8 - h8 -= c8 << 26 - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.51*2^58 */ - - c9 = (h9 + (1 << 24)) >> 25 - h0 += c9 * 19 - h9 -= c9 << 25 - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.8*2^37 */ - - c0 = (h0 + (1 << 25)) >> 26 - h1 += c0 - h0 -= c0 << 26 - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// FeMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: -// -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. -// -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs, can squeeze carries into int32. -func FeMul(h, f, g *FieldElement) { - f0 := int64(f[0]) - f1 := int64(f[1]) - f2 := int64(f[2]) - f3 := int64(f[3]) - f4 := int64(f[4]) - f5 := int64(f[5]) - f6 := int64(f[6]) - f7 := int64(f[7]) - f8 := int64(f[8]) - f9 := int64(f[9]) - - f1_2 := int64(2 * f[1]) - f3_2 := int64(2 * f[3]) - f5_2 := int64(2 * f[5]) - f7_2 := int64(2 * f[7]) - f9_2 := int64(2 * f[9]) - - g0 := int64(g[0]) - g1 := int64(g[1]) - g2 := int64(g[2]) - g3 := int64(g[3]) - g4 := int64(g[4]) - g5 := int64(g[5]) - g6 := int64(g[6]) - g7 := int64(g[7]) - g8 := int64(g[8]) - g9 := int64(g[9]) - - g1_19 := int64(19 * g[1]) /* 1.4*2^29 */ - g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */ - g3_19 := int64(19 * g[3]) - g4_19 := int64(19 * g[4]) - g5_19 := int64(19 * g[5]) - g6_19 := int64(19 * g[6]) - g7_19 := int64(19 * g[7]) - g8_19 := int64(19 * g[8]) - g9_19 := int64(19 * g[9]) - - h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19 - h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19 - h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19 - h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19 - h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19 - h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19 - h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19 - h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19 - h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19 - h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0 - - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { - f0 := int64(f[0]) - f1 := int64(f[1]) - f2 := int64(f[2]) - f3 := int64(f[3]) - f4 := int64(f[4]) - f5 := int64(f[5]) - f6 := int64(f[6]) - f7 := int64(f[7]) - f8 := int64(f[8]) - f9 := int64(f[9]) - f0_2 := int64(2 * f[0]) - f1_2 := int64(2 * f[1]) - f2_2 := int64(2 * f[2]) - f3_2 := int64(2 * f[3]) - f4_2 := int64(2 * f[4]) - f5_2 := int64(2 * f[5]) - f6_2 := int64(2 * f[6]) - f7_2 := int64(2 * f[7]) - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - - h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 - h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 - h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 - h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 - h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 - h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 - h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 - h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 - h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 - h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 - - return -} - -// FeSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func FeSquare(h, f *FieldElement) { - h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -// FeSquare2 sets h = 2 * f * f -// -// Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -// See fe_mul.c for discussion of implementation strategy. -func FeSquare2(h, f *FieldElement) { - h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) - - h0 += h0 - h1 += h1 - h2 += h2 - h3 += h3 - h4 += h4 - h5 += h5 - h6 += h6 - h7 += h7 - h8 += h8 - h9 += h9 - - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} - -func FeInvert(out, z *FieldElement) { - var t0, t1, t2, t3 FieldElement - var i int - - FeSquare(&t0, z) // 2^1 - FeSquare(&t1, &t0) // 2^2 - for i = 1; i < 2; i++ { // 2^3 - FeSquare(&t1, &t1) - } - FeMul(&t1, z, &t1) // 2^3 + 2^0 - FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0 - FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1 - FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0 - FeSquare(&t2, &t1) // 5,4,3,2,1 - for i = 1; i < 5; i++ { // 9,8,7,6,5 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0 - FeSquare(&t2, &t1) // 10..1 - for i = 1; i < 10; i++ { // 19..10 - FeSquare(&t2, &t2) - } - FeMul(&t2, &t2, &t1) // 19..0 - FeSquare(&t3, &t2) // 20..1 - for i = 1; i < 20; i++ { // 39..20 - FeSquare(&t3, &t3) - } - FeMul(&t2, &t3, &t2) // 39..0 - FeSquare(&t2, &t2) // 40..1 - for i = 1; i < 10; i++ { // 49..10 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 49..0 - FeSquare(&t2, &t1) // 50..1 - for i = 1; i < 50; i++ { // 99..50 - FeSquare(&t2, &t2) - } - FeMul(&t2, &t2, &t1) // 99..0 - FeSquare(&t3, &t2) // 100..1 - for i = 1; i < 100; i++ { // 199..100 - FeSquare(&t3, &t3) - } - FeMul(&t2, &t3, &t2) // 199..0 - FeSquare(&t2, &t2) // 200..1 - for i = 1; i < 50; i++ { // 249..50 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 249..0 - FeSquare(&t1, &t1) // 250..1 - for i = 1; i < 5; i++ { // 254..5 - FeSquare(&t1, &t1) - } - FeMul(out, &t1, &t0) // 254..5,3,1,0 -} - -func fePow22523(out, z *FieldElement) { - var t0, t1, t2 FieldElement - var i int - - FeSquare(&t0, z) - for i = 1; i < 1; i++ { - FeSquare(&t0, &t0) - } - FeSquare(&t1, &t0) - for i = 1; i < 2; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, z, &t1) - FeMul(&t0, &t0, &t1) - FeSquare(&t0, &t0) - for i = 1; i < 1; i++ { - FeSquare(&t0, &t0) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 5; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 10; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, &t1, &t0) - FeSquare(&t2, &t1) - for i = 1; i < 20; i++ { - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) - FeSquare(&t1, &t1) - for i = 1; i < 10; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 50; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, &t1, &t0) - FeSquare(&t2, &t1) - for i = 1; i < 100; i++ { - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) - FeSquare(&t1, &t1) - for i = 1; i < 50; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t0, &t0) - for i = 1; i < 2; i++ { - FeSquare(&t0, &t0) - } - FeMul(out, &t0, z) -} - -// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 * -// y^2 where d = -121665/121666. -// -// Several representations are used: -// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z -// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT -// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T -// PreComputedGroupElement: (y+x,y-x,2dxy) - -type ProjectiveGroupElement struct { - X, Y, Z FieldElement -} - -type ExtendedGroupElement struct { - X, Y, Z, T FieldElement -} - -type CompletedGroupElement struct { - X, Y, Z, T FieldElement -} - -type PreComputedGroupElement struct { - yPlusX, yMinusX, xy2d FieldElement -} - -type CachedGroupElement struct { - yPlusX, yMinusX, Z, T2d FieldElement -} - -func (p *ProjectiveGroupElement) Zero() { - FeZero(&p.X) - FeOne(&p.Y) - FeOne(&p.Z) -} - -func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) { - var t0 FieldElement - - FeSquare(&r.X, &p.X) - FeSquare(&r.Z, &p.Y) - FeSquare2(&r.T, &p.Z) - FeAdd(&r.Y, &p.X, &p.Y) - FeSquare(&t0, &r.Y) - FeAdd(&r.Y, &r.Z, &r.X) - FeSub(&r.Z, &r.Z, &r.X) - FeSub(&r.X, &t0, &r.Y) - FeSub(&r.T, &r.T, &r.Z) -} - -func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) { - var recip, x, y FieldElement - - FeInvert(&recip, &p.Z) - FeMul(&x, &p.X, &recip) - FeMul(&y, &p.Y, &recip) - FeToBytes(s, &y) - s[31] ^= FeIsNegative(&x) << 7 -} - -func (p *ExtendedGroupElement) Zero() { - FeZero(&p.X) - FeOne(&p.Y) - FeOne(&p.Z) - FeZero(&p.T) -} - -func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) { - var q ProjectiveGroupElement - p.ToProjective(&q) - q.Double(r) -} - -func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) { - FeAdd(&r.yPlusX, &p.Y, &p.X) - FeSub(&r.yMinusX, &p.Y, &p.X) - FeCopy(&r.Z, &p.Z) - FeMul(&r.T2d, &p.T, &d2) -} - -func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) { - FeCopy(&r.X, &p.X) - FeCopy(&r.Y, &p.Y) - FeCopy(&r.Z, &p.Z) -} - -func (p *ExtendedGroupElement) ToBytes(s *[32]byte) { - var recip, x, y FieldElement - - FeInvert(&recip, &p.Z) - FeMul(&x, &p.X, &recip) - FeMul(&y, &p.Y, &recip) - FeToBytes(s, &y) - s[31] ^= FeIsNegative(&x) << 7 -} - -func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool { - var u, v, v3, vxx, check FieldElement - - FeFromBytes(&p.Y, s) - FeOne(&p.Z) - FeSquare(&u, &p.Y) - FeMul(&v, &u, &d) - FeSub(&u, &u, &p.Z) // y = y^2-1 - FeAdd(&v, &v, &p.Z) // v = dy^2+1 - - FeSquare(&v3, &v) - FeMul(&v3, &v3, &v) // v3 = v^3 - FeSquare(&p.X, &v3) - FeMul(&p.X, &p.X, &v) - FeMul(&p.X, &p.X, &u) // x = uv^7 - - fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8) - FeMul(&p.X, &p.X, &v3) - FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8) - - var tmpX, tmp2 [32]byte - - FeSquare(&vxx, &p.X) - FeMul(&vxx, &vxx, &v) - FeSub(&check, &vxx, &u) // vx^2-u - if FeIsNonZero(&check) == 1 { - FeAdd(&check, &vxx, &u) // vx^2+u - if FeIsNonZero(&check) == 1 { - return false - } - FeMul(&p.X, &p.X, &SqrtM1) - - FeToBytes(&tmpX, &p.X) - for i, v := range tmpX { - tmp2[31-i] = v - } - } - - if FeIsNegative(&p.X) != (s[31] >> 7) { - FeNeg(&p.X, &p.X) - } - - FeMul(&p.T, &p.X, &p.Y) - return true -} - -func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) { - FeMul(&r.X, &p.X, &p.T) - FeMul(&r.Y, &p.Y, &p.Z) - FeMul(&r.Z, &p.Z, &p.T) -} - -func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) { - FeMul(&r.X, &p.X, &p.T) - FeMul(&r.Y, &p.Y, &p.Z) - FeMul(&r.Z, &p.Z, &p.T) - FeMul(&r.T, &p.X, &p.Y) -} - -func (p *PreComputedGroupElement) Zero() { - FeOne(&p.yPlusX) - FeOne(&p.yMinusX) - FeZero(&p.xy2d) -} - -func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yPlusX) - FeMul(&r.Y, &r.Y, &q.yMinusX) - FeMul(&r.T, &q.T2d, &p.T) - FeMul(&r.X, &p.Z, &q.Z) - FeAdd(&t0, &r.X, &r.X) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeAdd(&r.Z, &t0, &r.T) - FeSub(&r.T, &t0, &r.T) -} - -func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yMinusX) - FeMul(&r.Y, &r.Y, &q.yPlusX) - FeMul(&r.T, &q.T2d, &p.T) - FeMul(&r.X, &p.Z, &q.Z) - FeAdd(&t0, &r.X, &r.X) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeSub(&r.Z, &t0, &r.T) - FeAdd(&r.T, &t0, &r.T) -} - -func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yPlusX) - FeMul(&r.Y, &r.Y, &q.yMinusX) - FeMul(&r.T, &q.xy2d, &p.T) - FeAdd(&t0, &p.Z, &p.Z) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeAdd(&r.Z, &t0, &r.T) - FeSub(&r.T, &t0, &r.T) -} - -func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yMinusX) - FeMul(&r.Y, &r.Y, &q.yPlusX) - FeMul(&r.T, &q.xy2d, &p.T) - FeAdd(&t0, &p.Z, &p.Z) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeSub(&r.Z, &t0, &r.T) - FeAdd(&r.T, &t0, &r.T) -} - -func slide(r *[256]int8, a *[32]byte) { - for i := range r { - r[i] = int8(1 & (a[i>>3] >> uint(i&7))) - } - - for i := range r { - if r[i] != 0 { - for b := 1; b <= 6 && i+b < 256; b++ { - if r[i+b] != 0 { - if r[i]+(r[i+b]<= -15 { - r[i] -= r[i+b] << uint(b) - for k := i + b; k < 256; k++ { - if r[k] == 0 { - r[k] = 1 - break - } - r[k] = 0 - } - } else { - break - } - } - } - } - } -} - -// GeDoubleScalarMultVartime sets r = a*A + b*B -// where a = a[0]+256*a[1]+...+256^31 a[31]. -// and b = b[0]+256*b[1]+...+256^31 b[31]. -// B is the Ed25519 base point (x,4/5) with x positive. -func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) { - var aSlide, bSlide [256]int8 - var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A - var t CompletedGroupElement - var u, A2 ExtendedGroupElement - var i int - - slide(&aSlide, a) - slide(&bSlide, b) - - A.ToCached(&Ai[0]) - A.Double(&t) - t.ToExtended(&A2) - - for i := 0; i < 7; i++ { - geAdd(&t, &A2, &Ai[i]) - t.ToExtended(&u) - u.ToCached(&Ai[i+1]) - } - - r.Zero() - - for i = 255; i >= 0; i-- { - if aSlide[i] != 0 || bSlide[i] != 0 { - break - } - } - - for ; i >= 0; i-- { - r.Double(&t) - - if aSlide[i] > 0 { - t.ToExtended(&u) - geAdd(&t, &u, &Ai[aSlide[i]/2]) - } else if aSlide[i] < 0 { - t.ToExtended(&u) - geSub(&t, &u, &Ai[(-aSlide[i])/2]) - } - - if bSlide[i] > 0 { - t.ToExtended(&u) - geMixedAdd(&t, &u, &bi[bSlide[i]/2]) - } else if bSlide[i] < 0 { - t.ToExtended(&u) - geMixedSub(&t, &u, &bi[(-bSlide[i])/2]) - } - - t.ToProjective(r) - } -} - -// equal returns 1 if b == c and 0 otherwise, assuming that b and c are -// non-negative. -func equal(b, c int32) int32 { - x := uint32(b ^ c) - x-- - return int32(x >> 31) -} - -// negative returns 1 if b < 0 and 0 otherwise. -func negative(b int32) int32 { - return (b >> 31) & 1 -} - -func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) { - FeCMove(&t.yPlusX, &u.yPlusX, b) - FeCMove(&t.yMinusX, &u.yMinusX, b) - FeCMove(&t.xy2d, &u.xy2d, b) -} - -func selectPoint(t *PreComputedGroupElement, pos int32, b int32) { - var minusT PreComputedGroupElement - bNegative := negative(b) - bAbs := b - (((-bNegative) & b) << 1) - - t.Zero() - for i := int32(0); i < 8; i++ { - PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1)) - } - FeCopy(&minusT.yPlusX, &t.yMinusX) - FeCopy(&minusT.yMinusX, &t.yPlusX) - FeNeg(&minusT.xy2d, &t.xy2d) - PreComputedGroupElementCMove(t, &minusT, bNegative) -} - -// GeScalarMultBase computes h = a*B, where -// a = a[0]+256*a[1]+...+256^31 a[31] -// B is the Ed25519 base point (x,4/5) with x positive. -// -// Preconditions: -// a[31] <= 127 -func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) { - var e [64]int8 - - for i, v := range a { - e[2*i] = int8(v & 15) - e[2*i+1] = int8((v >> 4) & 15) - } - - // each e[i] is between 0 and 15 and e[63] is between 0 and 7. - - carry := int8(0) - for i := 0; i < 63; i++ { - e[i] += carry - carry = (e[i] + 8) >> 4 - e[i] -= carry << 4 - } - e[63] += carry - // each e[i] is between -8 and 8. - - h.Zero() - var t PreComputedGroupElement - var r CompletedGroupElement - for i := int32(1); i < 64; i += 2 { - selectPoint(&t, i/2, int32(e[i])) - geMixedAdd(&r, h, &t) - r.ToExtended(h) - } - - var s ProjectiveGroupElement - - h.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToExtended(h) - - for i := int32(0); i < 64; i += 2 { - selectPoint(&t, i/2, int32(e[i])) - geMixedAdd(&r, h, &t) - r.ToExtended(h) - } -} - -// The scalars are GF(2^252 + 27742317777372353535851937790883648493). - -// Input: -// a[0]+256*a[1]+...+256^31*a[31] = a -// b[0]+256*b[1]+...+256^31*b[31] = b -// c[0]+256*c[1]+...+256^31*c[31] = c -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func ScMulAdd(s, a, b, c *[32]byte) { - a0 := 2097151 & load3(a[:]) - a1 := 2097151 & (load4(a[2:]) >> 5) - a2 := 2097151 & (load3(a[5:]) >> 2) - a3 := 2097151 & (load4(a[7:]) >> 7) - a4 := 2097151 & (load4(a[10:]) >> 4) - a5 := 2097151 & (load3(a[13:]) >> 1) - a6 := 2097151 & (load4(a[15:]) >> 6) - a7 := 2097151 & (load3(a[18:]) >> 3) - a8 := 2097151 & load3(a[21:]) - a9 := 2097151 & (load4(a[23:]) >> 5) - a10 := 2097151 & (load3(a[26:]) >> 2) - a11 := (load4(a[28:]) >> 7) - b0 := 2097151 & load3(b[:]) - b1 := 2097151 & (load4(b[2:]) >> 5) - b2 := 2097151 & (load3(b[5:]) >> 2) - b3 := 2097151 & (load4(b[7:]) >> 7) - b4 := 2097151 & (load4(b[10:]) >> 4) - b5 := 2097151 & (load3(b[13:]) >> 1) - b6 := 2097151 & (load4(b[15:]) >> 6) - b7 := 2097151 & (load3(b[18:]) >> 3) - b8 := 2097151 & load3(b[21:]) - b9 := 2097151 & (load4(b[23:]) >> 5) - b10 := 2097151 & (load3(b[26:]) >> 2) - b11 := (load4(b[28:]) >> 7) - c0 := 2097151 & load3(c[:]) - c1 := 2097151 & (load4(c[2:]) >> 5) - c2 := 2097151 & (load3(c[5:]) >> 2) - c3 := 2097151 & (load4(c[7:]) >> 7) - c4 := 2097151 & (load4(c[10:]) >> 4) - c5 := 2097151 & (load3(c[13:]) >> 1) - c6 := 2097151 & (load4(c[15:]) >> 6) - c7 := 2097151 & (load3(c[18:]) >> 3) - c8 := 2097151 & load3(c[21:]) - c9 := 2097151 & (load4(c[23:]) >> 5) - c10 := 2097151 & (load3(c[26:]) >> 2) - c11 := (load4(c[28:]) >> 7) - var carry [23]int64 - - s0 := c0 + a0*b0 - s1 := c1 + a0*b1 + a1*b0 - s2 := c2 + a0*b2 + a1*b1 + a2*b0 - s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 - s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 - s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 - s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 - s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 - s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 - s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 - s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 - s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 - s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 - s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 - s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 - s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 - s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 - s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 - s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 - s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 - s20 := a9*b11 + a10*b10 + a11*b9 - s21 := a10*b11 + a11*b10 - s22 := a11 * b11 - s23 := int64(0) - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - carry[18] = (s18 + (1 << 20)) >> 21 - s19 += carry[18] - s18 -= carry[18] << 21 - carry[20] = (s20 + (1 << 20)) >> 21 - s21 += carry[20] - s20 -= carry[20] << 21 - carry[22] = (s22 + (1 << 20)) >> 21 - s23 += carry[22] - s22 -= carry[22] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - carry[17] = (s17 + (1 << 20)) >> 21 - s18 += carry[17] - s17 -= carry[17] << 21 - carry[19] = (s19 + (1 << 20)) >> 21 - s20 += carry[19] - s19 -= carry[19] << 21 - carry[21] = (s21 + (1 << 20)) >> 21 - s22 += carry[21] - s21 -= carry[21] << 21 - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - s[0] = byte(s0 >> 0) - s[1] = byte(s0 >> 8) - s[2] = byte((s0 >> 16) | (s1 << 5)) - s[3] = byte(s1 >> 3) - s[4] = byte(s1 >> 11) - s[5] = byte((s1 >> 19) | (s2 << 2)) - s[6] = byte(s2 >> 6) - s[7] = byte((s2 >> 14) | (s3 << 7)) - s[8] = byte(s3 >> 1) - s[9] = byte(s3 >> 9) - s[10] = byte((s3 >> 17) | (s4 << 4)) - s[11] = byte(s4 >> 4) - s[12] = byte(s4 >> 12) - s[13] = byte((s4 >> 20) | (s5 << 1)) - s[14] = byte(s5 >> 7) - s[15] = byte((s5 >> 15) | (s6 << 6)) - s[16] = byte(s6 >> 2) - s[17] = byte(s6 >> 10) - s[18] = byte((s6 >> 18) | (s7 << 3)) - s[19] = byte(s7 >> 5) - s[20] = byte(s7 >> 13) - s[21] = byte(s8 >> 0) - s[22] = byte(s8 >> 8) - s[23] = byte((s8 >> 16) | (s9 << 5)) - s[24] = byte(s9 >> 3) - s[25] = byte(s9 >> 11) - s[26] = byte((s9 >> 19) | (s10 << 2)) - s[27] = byte(s10 >> 6) - s[28] = byte((s10 >> 14) | (s11 << 7)) - s[29] = byte(s11 >> 1) - s[30] = byte(s11 >> 9) - s[31] = byte(s11 >> 17) -} - -// Input: -// s[0]+256*s[1]+...+256^63*s[63] = s -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = s mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func ScReduce(out *[32]byte, s *[64]byte) { - s0 := 2097151 & load3(s[:]) - s1 := 2097151 & (load4(s[2:]) >> 5) - s2 := 2097151 & (load3(s[5:]) >> 2) - s3 := 2097151 & (load4(s[7:]) >> 7) - s4 := 2097151 & (load4(s[10:]) >> 4) - s5 := 2097151 & (load3(s[13:]) >> 1) - s6 := 2097151 & (load4(s[15:]) >> 6) - s7 := 2097151 & (load3(s[18:]) >> 3) - s8 := 2097151 & load3(s[21:]) - s9 := 2097151 & (load4(s[23:]) >> 5) - s10 := 2097151 & (load3(s[26:]) >> 2) - s11 := 2097151 & (load4(s[28:]) >> 7) - s12 := 2097151 & (load4(s[31:]) >> 4) - s13 := 2097151 & (load3(s[34:]) >> 1) - s14 := 2097151 & (load4(s[36:]) >> 6) - s15 := 2097151 & (load3(s[39:]) >> 3) - s16 := 2097151 & load3(s[42:]) - s17 := 2097151 & (load4(s[44:]) >> 5) - s18 := 2097151 & (load3(s[47:]) >> 2) - s19 := 2097151 & (load4(s[49:]) >> 7) - s20 := 2097151 & (load4(s[52:]) >> 4) - s21 := 2097151 & (load3(s[55:]) >> 1) - s22 := 2097151 & (load4(s[57:]) >> 6) - s23 := (load4(s[60:]) >> 3) - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - var carry [17]int64 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - out[0] = byte(s0 >> 0) - out[1] = byte(s0 >> 8) - out[2] = byte((s0 >> 16) | (s1 << 5)) - out[3] = byte(s1 >> 3) - out[4] = byte(s1 >> 11) - out[5] = byte((s1 >> 19) | (s2 << 2)) - out[6] = byte(s2 >> 6) - out[7] = byte((s2 >> 14) | (s3 << 7)) - out[8] = byte(s3 >> 1) - out[9] = byte(s3 >> 9) - out[10] = byte((s3 >> 17) | (s4 << 4)) - out[11] = byte(s4 >> 4) - out[12] = byte(s4 >> 12) - out[13] = byte((s4 >> 20) | (s5 << 1)) - out[14] = byte(s5 >> 7) - out[15] = byte((s5 >> 15) | (s6 << 6)) - out[16] = byte(s6 >> 2) - out[17] = byte(s6 >> 10) - out[18] = byte((s6 >> 18) | (s7 << 3)) - out[19] = byte(s7 >> 5) - out[20] = byte(s7 >> 13) - out[21] = byte(s8 >> 0) - out[22] = byte(s8 >> 8) - out[23] = byte((s8 >> 16) | (s9 << 5)) - out[24] = byte(s9 >> 3) - out[25] = byte(s9 >> 11) - out[26] = byte((s9 >> 19) | (s10 << 2)) - out[27] = byte(s10 >> 6) - out[28] = byte((s10 >> 14) | (s11 << 7)) - out[29] = byte(s11 >> 1) - out[30] = byte(s11 >> 9) - out[31] = byte(s11 >> 17) -} - -// order is the order of Curve25519 in little-endian form. -var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} - -// ScMinimal returns true if the given scalar is less than the order of the -// curve. -func ScMinimal(scalar *[32]byte) bool { - for i := 3; ; i-- { - v := binary.LittleEndian.Uint64(scalar[i*8:]) - if v > order[i] { - return false - } else if v < order[i] { - break - } else if i == 0 { - return false - } - } - - return true -} diff --git a/ed25519/testdata/sign.input.gz b/ed25519/testdata/sign.input.gz deleted file mode 100644 index 41030690c0..0000000000 Binary files a/ed25519/testdata/sign.input.gz and /dev/null differ diff --git a/go.mod b/go.mod index c4af3ec414..f331951a16 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,11 @@ module golang.org/x/crypto +go 1.24.0 + require ( - golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 - golang.org/x/sys v0.0.0-20190412213103-97732733099d + golang.org/x/net v0.45.0 // tagx:ignore + golang.org/x/sys v0.37.0 + golang.org/x/term v0.36.0 ) + +require golang.org/x/text v0.30.0 // indirect diff --git a/go.sum b/go.sum index 44da498250..6d9f239e86 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= diff --git a/hkdf/hkdf.go b/hkdf/hkdf.go index dda3f143be..3bee66294e 100644 --- a/hkdf/hkdf.go +++ b/hkdf/hkdf.go @@ -8,7 +8,7 @@ // HKDF is a cryptographic key derivation function (KDF) with the goal of // expanding limited input keying material into one or more cryptographically // strong secret keys. -package hkdf // import "golang.org/x/crypto/hkdf" +package hkdf import ( "crypto/hmac" @@ -56,7 +56,9 @@ func (f *hkdf) Read(p []byte) (int, error) { // Fill the rest of the buffer for len(p) > 0 { - f.expander.Reset() + if f.counter > 1 { + f.expander.Reset() + } f.expander.Write(f.prev) f.expander.Write(f.info) f.expander.Write([]byte{f.counter}) diff --git a/internal/subtle/aliasing.go b/internal/alias/alias.go similarity index 82% rename from internal/subtle/aliasing.go rename to internal/alias/alias.go index f38797bfa1..551ff0c353 100644 --- a/internal/subtle/aliasing.go +++ b/internal/alias/alias.go @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !appengine +//go:build !purego -// Package subtle implements functions that are often useful in cryptographic -// code but require careful thought to use correctly. -package subtle // import "golang.org/x/crypto/internal/subtle" +// Package alias implements memory aliasing tests. +package alias import "unsafe" diff --git a/internal/subtle/aliasing_appengine.go b/internal/alias/alias_purego.go similarity index 84% rename from internal/subtle/aliasing_appengine.go rename to internal/alias/alias_purego.go index 0cc4a8a642..6fe61b5c6e 100644 --- a/internal/subtle/aliasing_appengine.go +++ b/internal/alias/alias_purego.go @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build appengine +//go:build purego -// Package subtle implements functions that are often useful in cryptographic -// code but require careful thought to use correctly. -package subtle // import "golang.org/x/crypto/internal/subtle" +// Package alias implements memory aliasing tests. +package alias // This is the Google App Engine standard variant based on reflect // because the unsafe package and cgo are disallowed. diff --git a/internal/subtle/aliasing_test.go b/internal/alias/alias_test.go similarity index 88% rename from internal/subtle/aliasing_test.go rename to internal/alias/alias_test.go index a5b62ff740..a68fb33667 100644 --- a/internal/subtle/aliasing_test.go +++ b/internal/alias/alias_test.go @@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package subtle_test +package alias -import ( - "testing" - - "golang.org/x/crypto/internal/subtle" -) +import "testing" var a, b [100]byte @@ -32,11 +28,11 @@ var aliasingTests = []struct { } func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { - any := subtle.AnyOverlap(x, y) + any := AnyOverlap(x, y) if any != anyOverlap { t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) } - inexact := subtle.InexactOverlap(x, y) + inexact := InexactOverlap(x, y) if inexact != inexactOverlap { t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) } diff --git a/internal/chacha20/asm_ppc64le.s b/internal/chacha20/asm_ppc64le.s deleted file mode 100644 index cde3fc989b..0000000000 --- a/internal/chacha20/asm_ppc64le.s +++ /dev/null @@ -1,668 +0,0 @@ -// Copyright 2019 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. - -// Based on CRYPTOGAMS code with the following comment: -// # ==================================================================== -// # Written by Andy Polyakov for the OpenSSL -// # project. The module is, however, dual licensed under OpenSSL and -// # CRYPTOGAMS licenses depending on where you obtain it. For further -// # details see http://www.openssl.org/~appro/cryptogams/. -// # ==================================================================== - -// Original code can be found at the link below: -// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91e5c39ca79126a4a876d5d8ff - -// There are some differences between CRYPTOGAMS code and this one. The round -// loop for "_int" isn't the same as the original. Some adjustments were -// necessary because there are less vector registers available. For example, some -// X variables (r12, r13, r14, and r15) share the same register used by the -// counter. The original code uses ctr to name the counter. Here we use CNT -// because golang uses CTR as the counter register name. - -// +build ppc64le,!gccgo,!appengine - -#include "textflag.h" - -#define OUT R3 -#define INP R4 -#define LEN R5 -#define KEY R6 -#define CNT R7 - -#define TEMP R8 - -#define X0 R11 -#define X1 R12 -#define X2 R14 -#define X3 R15 -#define X4 R16 -#define X5 R17 -#define X6 R18 -#define X7 R19 -#define X8 R20 -#define X9 R21 -#define X10 R22 -#define X11 R23 -#define X12 R24 -#define X13 R25 -#define X14 R26 -#define X15 R27 - -#define CON0 X0 -#define CON1 X1 -#define CON2 X2 -#define CON3 X3 - -#define KEY0 X4 -#define KEY1 X5 -#define KEY2 X6 -#define KEY3 X7 -#define KEY4 X8 -#define KEY5 X9 -#define KEY6 X10 -#define KEY7 X11 - -#define CNT0 X12 -#define CNT1 X13 -#define CNT2 X14 -#define CNT3 X15 - -#define TMP0 R9 -#define TMP1 R10 -#define TMP2 R28 -#define TMP3 R29 - -#define CONSTS R8 - -#define A0 V0 -#define B0 V1 -#define C0 V2 -#define D0 V3 -#define A1 V4 -#define B1 V5 -#define C1 V6 -#define D1 V7 -#define A2 V8 -#define B2 V9 -#define C2 V10 -#define D2 V11 -#define T0 V12 -#define T1 V13 -#define T2 V14 - -#define K0 V15 -#define K1 V16 -#define K2 V17 -#define K3 V18 -#define K4 V19 -#define K5 V20 - -#define FOUR V21 -#define SIXTEEN V22 -#define TWENTY4 V23 -#define TWENTY V24 -#define TWELVE V25 -#define TWENTY5 V26 -#define SEVEN V27 - -#define INPPERM V28 -#define OUTPERM V29 -#define OUTMASK V30 - -#define DD0 V31 -#define DD1 SEVEN -#define DD2 T0 -#define DD3 T1 -#define DD4 T2 - -DATA ·consts+0x00(SB)/8, $0x3320646e61707865 -DATA ·consts+0x08(SB)/8, $0x6b20657479622d32 -DATA ·consts+0x10(SB)/8, $0x0000000000000001 -DATA ·consts+0x18(SB)/8, $0x0000000000000000 -DATA ·consts+0x20(SB)/8, $0x0000000000000004 -DATA ·consts+0x28(SB)/8, $0x0000000000000000 -DATA ·consts+0x30(SB)/8, $0x0a0b08090e0f0c0d -DATA ·consts+0x38(SB)/8, $0x0203000106070405 -DATA ·consts+0x40(SB)/8, $0x090a0b080d0e0f0c -DATA ·consts+0x48(SB)/8, $0x0102030005060704 -GLOBL ·consts(SB), RODATA, $80 - -//func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[32]byte, counter *[16]byte) -TEXT ·chaCha20_ctr32_vmx(SB),NOSPLIT|NOFRAME,$0 - // Load the arguments inside the registers - MOVD out+0(FP), OUT - MOVD inp+8(FP), INP - MOVD len+16(FP), LEN - MOVD key+24(FP), KEY - MOVD counter+32(FP), CNT - - MOVD $·consts(SB), CONSTS // point to consts addr - - MOVD $16, X0 - MOVD $32, X1 - MOVD $48, X2 - MOVD $64, X3 - MOVD $31, X4 - MOVD $15, X5 - - // Load key - LVX (KEY)(R0), K1 - LVSR (KEY)(R0), T0 - LVX (KEY)(X0), K2 - LVX (KEY)(X4), DD0 - - // Load counter - LVX (CNT)(R0), K3 - LVSR (CNT)(R0), T1 - LVX (CNT)(X5), DD1 - - // Load constants - LVX (CONSTS)(R0), K0 - LVX (CONSTS)(X0), K5 - LVX (CONSTS)(X1), FOUR - LVX (CONSTS)(X2), SIXTEEN - LVX (CONSTS)(X3), TWENTY4 - - // Align key and counter - VPERM K2, K1, T0, K1 - VPERM DD0, K2, T0, K2 - VPERM DD1, K3, T1, K3 - - // Load counter to GPR - MOVWZ 0(CNT), CNT0 - MOVWZ 4(CNT), CNT1 - MOVWZ 8(CNT), CNT2 - MOVWZ 12(CNT), CNT3 - - // Adjust vectors for the initial state - VADDUWM K3, K5, K3 - VADDUWM K3, K5, K4 - VADDUWM K4, K5, K5 - - // Synthesized constants - VSPLTISW $-12, TWENTY - VSPLTISW $12, TWELVE - VSPLTISW $-7, TWENTY5 - - VXOR T0, T0, T0 - VSPLTISW $-1, OUTMASK - LVSR (INP)(R0), INPPERM - LVSL (OUT)(R0), OUTPERM - VPERM OUTMASK, T0, OUTPERM, OUTMASK - -loop_outer_vmx: - // Load constant - MOVD $0x61707865, CON0 - MOVD $0x3320646e, CON1 - MOVD $0x79622d32, CON2 - MOVD $0x6b206574, CON3 - - VOR K0, K0, A0 - VOR K0, K0, A1 - VOR K0, K0, A2 - VOR K1, K1, B0 - - MOVD $10, TEMP - - // Load key to GPR - MOVWZ 0(KEY), X4 - MOVWZ 4(KEY), X5 - MOVWZ 8(KEY), X6 - MOVWZ 12(KEY), X7 - VOR K1, K1, B1 - VOR K1, K1, B2 - MOVWZ 16(KEY), X8 - MOVWZ 0(CNT), X12 - MOVWZ 20(KEY), X9 - MOVWZ 4(CNT), X13 - VOR K2, K2, C0 - VOR K2, K2, C1 - MOVWZ 24(KEY), X10 - MOVWZ 8(CNT), X14 - VOR K2, K2, C2 - VOR K3, K3, D0 - MOVWZ 28(KEY), X11 - MOVWZ 12(CNT), X15 - VOR K4, K4, D1 - VOR K5, K5, D2 - - MOVD X4, TMP0 - MOVD X5, TMP1 - MOVD X6, TMP2 - MOVD X7, TMP3 - VSPLTISW $7, SEVEN - - MOVD TEMP, CTR - -loop_vmx: - // CRYPTOGAMS uses a macro to create a loop using perl. This isn't possible - // using assembly macros. Therefore, the macro expansion result was used - // in order to maintain the algorithm efficiency. - // This loop generates three keystream blocks using VMX instructions and, - // in parallel, one keystream block using scalar instructions. - ADD X4, X0, X0 - ADD X5, X1, X1 - VADDUWM A0, B0, A0 - VADDUWM A1, B1, A1 - ADD X6, X2, X2 - ADD X7, X3, X3 - VADDUWM A2, B2, A2 - VXOR D0, A0, D0 - XOR X0, X12, X12 - XOR X1, X13, X13 - VXOR D1, A1, D1 - VXOR D2, A2, D2 - XOR X2, X14, X14 - XOR X3, X15, X15 - VPERM D0, D0, SIXTEEN, D0 - VPERM D1, D1, SIXTEEN, D1 - ROTLW $16, X12, X12 - ROTLW $16, X13, X13 - VPERM D2, D2, SIXTEEN, D2 - VADDUWM C0, D0, C0 - ROTLW $16, X14, X14 - ROTLW $16, X15, X15 - VADDUWM C1, D1, C1 - VADDUWM C2, D2, C2 - ADD X12, X8, X8 - ADD X13, X9, X9 - VXOR B0, C0, T0 - VXOR B1, C1, T1 - ADD X14, X10, X10 - ADD X15, X11, X11 - VXOR B2, C2, T2 - VRLW T0, TWELVE, B0 - XOR X8, X4, X4 - XOR X9, X5, X5 - VRLW T1, TWELVE, B1 - VRLW T2, TWELVE, B2 - XOR X10, X6, X6 - XOR X11, X7, X7 - VADDUWM A0, B0, A0 - VADDUWM A1, B1, A1 - ROTLW $12, X4, X4 - ROTLW $12, X5, X5 - VADDUWM A2, B2, A2 - VXOR D0, A0, D0 - ROTLW $12, X6, X6 - ROTLW $12, X7, X7 - VXOR D1, A1, D1 - VXOR D2, A2, D2 - ADD X4, X0, X0 - ADD X5, X1, X1 - VPERM D0, D0, TWENTY4, D0 - VPERM D1, D1, TWENTY4, D1 - ADD X6, X2, X2 - ADD X7, X3, X3 - VPERM D2, D2, TWENTY4, D2 - VADDUWM C0, D0, C0 - XOR X0, X12, X12 - XOR X1, X13, X13 - VADDUWM C1, D1, C1 - VADDUWM C2, D2, C2 - XOR X2, X14, X14 - XOR X3, X15, X15 - VXOR B0, C0, T0 - VXOR B1, C1, T1 - ROTLW $8, X12, X12 - ROTLW $8, X13, X13 - VXOR B2, C2, T2 - VRLW T0, SEVEN, B0 - ROTLW $8, X14, X14 - ROTLW $8, X15, X15 - VRLW T1, SEVEN, B1 - VRLW T2, SEVEN, B2 - ADD X12, X8, X8 - ADD X13, X9, X9 - VSLDOI $8, C0, C0, C0 - VSLDOI $8, C1, C1, C1 - ADD X14, X10, X10 - ADD X15, X11, X11 - VSLDOI $8, C2, C2, C2 - VSLDOI $12, B0, B0, B0 - XOR X8, X4, X4 - XOR X9, X5, X5 - VSLDOI $12, B1, B1, B1 - VSLDOI $12, B2, B2, B2 - XOR X10, X6, X6 - XOR X11, X7, X7 - VSLDOI $4, D0, D0, D0 - VSLDOI $4, D1, D1, D1 - ROTLW $7, X4, X4 - ROTLW $7, X5, X5 - VSLDOI $4, D2, D2, D2 - VADDUWM A0, B0, A0 - ROTLW $7, X6, X6 - ROTLW $7, X7, X7 - VADDUWM A1, B1, A1 - VADDUWM A2, B2, A2 - ADD X5, X0, X0 - ADD X6, X1, X1 - VXOR D0, A0, D0 - VXOR D1, A1, D1 - ADD X7, X2, X2 - ADD X4, X3, X3 - VXOR D2, A2, D2 - VPERM D0, D0, SIXTEEN, D0 - XOR X0, X15, X15 - XOR X1, X12, X12 - VPERM D1, D1, SIXTEEN, D1 - VPERM D2, D2, SIXTEEN, D2 - XOR X2, X13, X13 - XOR X3, X14, X14 - VADDUWM C0, D0, C0 - VADDUWM C1, D1, C1 - ROTLW $16, X15, X15 - ROTLW $16, X12, X12 - VADDUWM C2, D2, C2 - VXOR B0, C0, T0 - ROTLW $16, X13, X13 - ROTLW $16, X14, X14 - VXOR B1, C1, T1 - VXOR B2, C2, T2 - ADD X15, X10, X10 - ADD X12, X11, X11 - VRLW T0, TWELVE, B0 - VRLW T1, TWELVE, B1 - ADD X13, X8, X8 - ADD X14, X9, X9 - VRLW T2, TWELVE, B2 - VADDUWM A0, B0, A0 - XOR X10, X5, X5 - XOR X11, X6, X6 - VADDUWM A1, B1, A1 - VADDUWM A2, B2, A2 - XOR X8, X7, X7 - XOR X9, X4, X4 - VXOR D0, A0, D0 - VXOR D1, A1, D1 - ROTLW $12, X5, X5 - ROTLW $12, X6, X6 - VXOR D2, A2, D2 - VPERM D0, D0, TWENTY4, D0 - ROTLW $12, X7, X7 - ROTLW $12, X4, X4 - VPERM D1, D1, TWENTY4, D1 - VPERM D2, D2, TWENTY4, D2 - ADD X5, X0, X0 - ADD X6, X1, X1 - VADDUWM C0, D0, C0 - VADDUWM C1, D1, C1 - ADD X7, X2, X2 - ADD X4, X3, X3 - VADDUWM C2, D2, C2 - VXOR B0, C0, T0 - XOR X0, X15, X15 - XOR X1, X12, X12 - VXOR B1, C1, T1 - VXOR B2, C2, T2 - XOR X2, X13, X13 - XOR X3, X14, X14 - VRLW T0, SEVEN, B0 - VRLW T1, SEVEN, B1 - ROTLW $8, X15, X15 - ROTLW $8, X12, X12 - VRLW T2, SEVEN, B2 - VSLDOI $8, C0, C0, C0 - ROTLW $8, X13, X13 - ROTLW $8, X14, X14 - VSLDOI $8, C1, C1, C1 - VSLDOI $8, C2, C2, C2 - ADD X15, X10, X10 - ADD X12, X11, X11 - VSLDOI $4, B0, B0, B0 - VSLDOI $4, B1, B1, B1 - ADD X13, X8, X8 - ADD X14, X9, X9 - VSLDOI $4, B2, B2, B2 - VSLDOI $12, D0, D0, D0 - XOR X10, X5, X5 - XOR X11, X6, X6 - VSLDOI $12, D1, D1, D1 - VSLDOI $12, D2, D2, D2 - XOR X8, X7, X7 - XOR X9, X4, X4 - ROTLW $7, X5, X5 - ROTLW $7, X6, X6 - ROTLW $7, X7, X7 - ROTLW $7, X4, X4 - BC 0x10, 0, loop_vmx - - SUB $256, LEN, LEN - - // Accumulate key block - ADD $0x61707865, X0, X0 - ADD $0x3320646e, X1, X1 - ADD $0x79622d32, X2, X2 - ADD $0x6b206574, X3, X3 - ADD TMP0, X4, X4 - ADD TMP1, X5, X5 - ADD TMP2, X6, X6 - ADD TMP3, X7, X7 - MOVWZ 16(KEY), TMP0 - MOVWZ 20(KEY), TMP1 - MOVWZ 24(KEY), TMP2 - MOVWZ 28(KEY), TMP3 - ADD TMP0, X8, X8 - ADD TMP1, X9, X9 - ADD TMP2, X10, X10 - ADD TMP3, X11, X11 - - MOVWZ 12(CNT), TMP0 - MOVWZ 8(CNT), TMP1 - MOVWZ 4(CNT), TMP2 - MOVWZ 0(CNT), TEMP - ADD TMP0, X15, X15 - ADD TMP1, X14, X14 - ADD TMP2, X13, X13 - ADD TEMP, X12, X12 - - // Accumulate key block - VADDUWM A0, K0, A0 - VADDUWM A1, K0, A1 - VADDUWM A2, K0, A2 - VADDUWM B0, K1, B0 - VADDUWM B1, K1, B1 - VADDUWM B2, K1, B2 - VADDUWM C0, K2, C0 - VADDUWM C1, K2, C1 - VADDUWM C2, K2, C2 - VADDUWM D0, K3, D0 - VADDUWM D1, K4, D1 - VADDUWM D2, K5, D2 - - // Increment counter - ADD $4, TEMP, TEMP - MOVW TEMP, 0(CNT) - - VADDUWM K3, FOUR, K3 - VADDUWM K4, FOUR, K4 - VADDUWM K5, FOUR, K5 - - // XOR the input slice (INP) with the keystream, which is stored in GPRs (X0-X3). - - // Load input (aligned or not) - MOVWZ 0(INP), TMP0 - MOVWZ 4(INP), TMP1 - MOVWZ 8(INP), TMP2 - MOVWZ 12(INP), TMP3 - - // XOR with input - XOR TMP0, X0, X0 - XOR TMP1, X1, X1 - XOR TMP2, X2, X2 - XOR TMP3, X3, X3 - MOVWZ 16(INP), TMP0 - MOVWZ 20(INP), TMP1 - MOVWZ 24(INP), TMP2 - MOVWZ 28(INP), TMP3 - XOR TMP0, X4, X4 - XOR TMP1, X5, X5 - XOR TMP2, X6, X6 - XOR TMP3, X7, X7 - MOVWZ 32(INP), TMP0 - MOVWZ 36(INP), TMP1 - MOVWZ 40(INP), TMP2 - MOVWZ 44(INP), TMP3 - XOR TMP0, X8, X8 - XOR TMP1, X9, X9 - XOR TMP2, X10, X10 - XOR TMP3, X11, X11 - MOVWZ 48(INP), TMP0 - MOVWZ 52(INP), TMP1 - MOVWZ 56(INP), TMP2 - MOVWZ 60(INP), TMP3 - XOR TMP0, X12, X12 - XOR TMP1, X13, X13 - XOR TMP2, X14, X14 - XOR TMP3, X15, X15 - - // Store output (aligned or not) - MOVW X0, 0(OUT) - MOVW X1, 4(OUT) - MOVW X2, 8(OUT) - MOVW X3, 12(OUT) - - ADD $64, INP, INP // INP points to the end of the slice for the alignment code below - - MOVW X4, 16(OUT) - MOVD $16, TMP0 - MOVW X5, 20(OUT) - MOVD $32, TMP1 - MOVW X6, 24(OUT) - MOVD $48, TMP2 - MOVW X7, 28(OUT) - MOVD $64, TMP3 - MOVW X8, 32(OUT) - MOVW X9, 36(OUT) - MOVW X10, 40(OUT) - MOVW X11, 44(OUT) - MOVW X12, 48(OUT) - MOVW X13, 52(OUT) - MOVW X14, 56(OUT) - MOVW X15, 60(OUT) - ADD $64, OUT, OUT - - // Load input - LVX (INP)(R0), DD0 - LVX (INP)(TMP0), DD1 - LVX (INP)(TMP1), DD2 - LVX (INP)(TMP2), DD3 - LVX (INP)(TMP3), DD4 - ADD $64, INP, INP - - VPERM DD1, DD0, INPPERM, DD0 // Align input - VPERM DD2, DD1, INPPERM, DD1 - VPERM DD3, DD2, INPPERM, DD2 - VPERM DD4, DD3, INPPERM, DD3 - VXOR A0, DD0, A0 // XOR with input - VXOR B0, DD1, B0 - LVX (INP)(TMP0), DD1 // Keep loading input - VXOR C0, DD2, C0 - LVX (INP)(TMP1), DD2 - VXOR D0, DD3, D0 - LVX (INP)(TMP2), DD3 - LVX (INP)(TMP3), DD0 - ADD $64, INP, INP - MOVD $63, TMP3 // 63 is not a typo - VPERM A0, A0, OUTPERM, A0 - VPERM B0, B0, OUTPERM, B0 - VPERM C0, C0, OUTPERM, C0 - VPERM D0, D0, OUTPERM, D0 - - VPERM DD1, DD4, INPPERM, DD4 // Align input - VPERM DD2, DD1, INPPERM, DD1 - VPERM DD3, DD2, INPPERM, DD2 - VPERM DD0, DD3, INPPERM, DD3 - VXOR A1, DD4, A1 - VXOR B1, DD1, B1 - LVX (INP)(TMP0), DD1 // Keep loading - VXOR C1, DD2, C1 - LVX (INP)(TMP1), DD2 - VXOR D1, DD3, D1 - LVX (INP)(TMP2), DD3 - - // Note that the LVX address is always rounded down to the nearest 16-byte - // boundary, and that it always points to at most 15 bytes beyond the end of - // the slice, so we cannot cross a page boundary. - LVX (INP)(TMP3), DD4 // Redundant in aligned case. - ADD $64, INP, INP - VPERM A1, A1, OUTPERM, A1 // Pre-misalign output - VPERM B1, B1, OUTPERM, B1 - VPERM C1, C1, OUTPERM, C1 - VPERM D1, D1, OUTPERM, D1 - - VPERM DD1, DD0, INPPERM, DD0 // Align Input - VPERM DD2, DD1, INPPERM, DD1 - VPERM DD3, DD2, INPPERM, DD2 - VPERM DD4, DD3, INPPERM, DD3 - VXOR A2, DD0, A2 - VXOR B2, DD1, B2 - VXOR C2, DD2, C2 - VXOR D2, DD3, D2 - VPERM A2, A2, OUTPERM, A2 - VPERM B2, B2, OUTPERM, B2 - VPERM C2, C2, OUTPERM, C2 - VPERM D2, D2, OUTPERM, D2 - - ANDCC $15, OUT, X1 // Is out aligned? - MOVD OUT, X0 - - VSEL A0, B0, OUTMASK, DD0 // Collect pre-misaligned output - VSEL B0, C0, OUTMASK, DD1 - VSEL C0, D0, OUTMASK, DD2 - VSEL D0, A1, OUTMASK, DD3 - VSEL A1, B1, OUTMASK, B0 - VSEL B1, C1, OUTMASK, C0 - VSEL C1, D1, OUTMASK, D0 - VSEL D1, A2, OUTMASK, A1 - VSEL A2, B2, OUTMASK, B1 - VSEL B2, C2, OUTMASK, C1 - VSEL C2, D2, OUTMASK, D1 - - STVX DD0, (OUT+TMP0) - STVX DD1, (OUT+TMP1) - STVX DD2, (OUT+TMP2) - ADD $64, OUT, OUT - STVX DD3, (OUT+R0) - STVX B0, (OUT+TMP0) - STVX C0, (OUT+TMP1) - STVX D0, (OUT+TMP2) - ADD $64, OUT, OUT - STVX A1, (OUT+R0) - STVX B1, (OUT+TMP0) - STVX C1, (OUT+TMP1) - STVX D1, (OUT+TMP2) - ADD $64, OUT, OUT - - BEQ aligned_vmx - - SUB X1, OUT, X2 // in misaligned case edges - MOVD $0, X3 // are written byte-by-byte - -unaligned_tail_vmx: - STVEBX D2, (X2+X3) - ADD $1, X3, X3 - CMPW X3, X1 - BNE unaligned_tail_vmx - SUB X1, X0, X2 - -unaligned_head_vmx: - STVEBX A0, (X2+X1) - CMPW X1, $15 - ADD $1, X1, X1 - BNE unaligned_head_vmx - - CMPU LEN, $255 // done with 256-byte block yet? - BGT loop_outer_vmx - - JMP done_vmx - -aligned_vmx: - STVX A0, (X0+R0) - CMPU LEN, $255 // done with 256-byte block yet? - BGT loop_outer_vmx - -done_vmx: - RET diff --git a/internal/chacha20/chacha_arm64.go b/internal/chacha20/chacha_arm64.go deleted file mode 100644 index ad74e23aef..0000000000 --- a/internal/chacha20/chacha_arm64.go +++ /dev/null @@ -1,31 +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 go1.11 -// +build !gccgo - -package chacha20 - -const ( - haveAsm = true - bufSize = 256 -) - -//go:noescape -func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) - -func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { - - if len(src) >= bufSize { - xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) - } - - if len(src)%bufSize != 0 { - i := len(src) - len(src)%bufSize - c.buf = [bufSize]byte{} - copy(c.buf[:], src[i:]) - xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter) - c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize]) - } -} diff --git a/internal/chacha20/chacha_generic.go b/internal/chacha20/chacha_generic.go deleted file mode 100644 index 6570847f5e..0000000000 --- a/internal/chacha20/chacha_generic.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ChaCha20 implements the core ChaCha20 function as specified -// in https://tools.ietf.org/html/rfc7539#section-2.3. -package chacha20 - -import ( - "crypto/cipher" - "encoding/binary" - - "golang.org/x/crypto/internal/subtle" -) - -// assert that *Cipher implements cipher.Stream -var _ cipher.Stream = (*Cipher)(nil) - -// Cipher is a stateful instance of ChaCha20 using a particular key -// and nonce. A *Cipher implements the cipher.Stream interface. -type Cipher struct { - key [8]uint32 - counter uint32 // incremented after each block - nonce [3]uint32 - buf [bufSize]byte // buffer for unused keystream bytes - len int // number of unused keystream bytes at end of buf -} - -// New creates a new ChaCha20 stream cipher with the given key and nonce. -// The initial counter value is set to 0. -func New(key [8]uint32, nonce [3]uint32) *Cipher { - return &Cipher{key: key, nonce: nonce} -} - -// ChaCha20 constants spelling "expand 32-byte k" -const ( - j0 uint32 = 0x61707865 - j1 uint32 = 0x3320646e - j2 uint32 = 0x79622d32 - j3 uint32 = 0x6b206574 -) - -func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { - a += b - d ^= a - d = (d << 16) | (d >> 16) - c += d - b ^= c - b = (b << 12) | (b >> 20) - a += b - d ^= a - d = (d << 8) | (d >> 24) - c += d - b ^= c - b = (b << 7) | (b >> 25) - return a, b, c, d -} - -// XORKeyStream XORs each byte in the given slice with a byte from the -// cipher's key stream. Dst and src must overlap entirely or not at all. -// -// If len(dst) < len(src), XORKeyStream will panic. It is acceptable -// to pass a dst bigger than src, and in that case, XORKeyStream will -// only update dst[:len(src)] and will not touch the rest of dst. -// -// Multiple calls to XORKeyStream behave as if the concatenation of -// the src buffers was passed in a single run. That is, Cipher -// maintains state and does not reset at each XORKeyStream call. -func (s *Cipher) XORKeyStream(dst, src []byte) { - if len(dst) < len(src) { - panic("chacha20: output smaller than input") - } - if subtle.InexactOverlap(dst[:len(src)], src) { - panic("chacha20: invalid buffer overlap") - } - - // xor src with buffered keystream first - if s.len != 0 { - buf := s.buf[len(s.buf)-s.len:] - if len(src) < len(buf) { - buf = buf[:len(src)] - } - td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint - for i, b := range buf { - td[i] = ts[i] ^ b - } - s.len -= len(buf) - if s.len != 0 { - return - } - s.buf = [len(s.buf)]byte{} // zero the empty buffer - src = src[len(buf):] - dst = dst[len(buf):] - } - - if len(src) == 0 { - return - } - if haveAsm { - if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 { - panic("chacha20: counter overflow") - } - s.xorKeyStreamAsm(dst, src) - return - } - - // set up a 64-byte buffer to pad out the final block if needed - // (hoisted out of the main loop to avoid spills) - rem := len(src) % 64 // length of final block - fin := len(src) - rem // index of final block - if rem > 0 { - copy(s.buf[len(s.buf)-64:], src[fin:]) - } - - // pre-calculate most of the first round - s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0]) - s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1]) - s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2]) - - n := len(src) - src, dst = src[:n:n], dst[:n:n] // BCE hint - for i := 0; i < n; i += 64 { - // calculate the remainder of the first round - s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter) - - // execute the second round - x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15) - x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12) - x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13) - x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14) - - // execute the remaining 18 rounds - for i := 0; i < 9; i++ { - x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) - x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) - x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) - x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) - - x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) - x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) - x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) - x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) - } - - x0 += j0 - x1 += j1 - x2 += j2 - x3 += j3 - - x4 += s.key[0] - x5 += s.key[1] - x6 += s.key[2] - x7 += s.key[3] - x8 += s.key[4] - x9 += s.key[5] - x10 += s.key[6] - x11 += s.key[7] - - x12 += s.counter - x13 += s.nonce[0] - x14 += s.nonce[1] - x15 += s.nonce[2] - - // increment the counter - s.counter += 1 - if s.counter == 0 { - panic("chacha20: counter overflow") - } - - // pad to 64 bytes if needed - in, out := src[i:], dst[i:] - if i == fin { - // src[fin:] has already been copied into s.buf before - // the main loop - in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:] - } - in, out = in[:64], out[:64] // BCE hint - - // XOR the key stream with the source and write out the result - xor(out[0:], in[0:], x0) - xor(out[4:], in[4:], x1) - xor(out[8:], in[8:], x2) - xor(out[12:], in[12:], x3) - xor(out[16:], in[16:], x4) - xor(out[20:], in[20:], x5) - xor(out[24:], in[24:], x6) - xor(out[28:], in[28:], x7) - xor(out[32:], in[32:], x8) - xor(out[36:], in[36:], x9) - xor(out[40:], in[40:], x10) - xor(out[44:], in[44:], x11) - xor(out[48:], in[48:], x12) - xor(out[52:], in[52:], x13) - xor(out[56:], in[56:], x14) - xor(out[60:], in[60:], x15) - } - // copy any trailing bytes out of the buffer and into dst - if rem != 0 { - s.len = 64 - rem - copy(dst[fin:], s.buf[len(s.buf)-64:]) - } -} - -// Advance discards bytes in the key stream until the next 64 byte block -// boundary is reached and updates the counter accordingly. If the key -// stream is already at a block boundary no bytes will be discarded and -// the counter will be unchanged. -func (s *Cipher) Advance() { - s.len -= s.len % 64 - if s.len == 0 { - s.buf = [len(s.buf)]byte{} - } -} - -// XORKeyStream crypts bytes from in to out using the given key and counters. -// In and out must overlap entirely or not at all. Counter contains the raw -// ChaCha20 counter bytes (i.e. block counter followed by nonce). -func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { - s := Cipher{ - key: [8]uint32{ - binary.LittleEndian.Uint32(key[0:4]), - binary.LittleEndian.Uint32(key[4:8]), - binary.LittleEndian.Uint32(key[8:12]), - binary.LittleEndian.Uint32(key[12:16]), - binary.LittleEndian.Uint32(key[16:20]), - binary.LittleEndian.Uint32(key[20:24]), - binary.LittleEndian.Uint32(key[24:28]), - binary.LittleEndian.Uint32(key[28:32]), - }, - nonce: [3]uint32{ - binary.LittleEndian.Uint32(counter[4:8]), - binary.LittleEndian.Uint32(counter[8:12]), - binary.LittleEndian.Uint32(counter[12:16]), - }, - counter: binary.LittleEndian.Uint32(counter[0:4]), - } - s.XORKeyStream(out, in) -} - -// HChaCha20 uses the ChaCha20 core to generate a derived key from a key and a -// nonce. It should only be used as part of the XChaCha20 construction. -func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 { - x0, x1, x2, x3 := j0, j1, j2, j3 - x4, x5, x6, x7 := key[0], key[1], key[2], key[3] - x8, x9, x10, x11 := key[4], key[5], key[6], key[7] - x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3] - - for i := 0; i < 10; i++ { - x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) - x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) - x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) - x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) - - x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) - x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) - x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) - x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) - } - - var out [8]uint32 - out[0], out[1], out[2], out[3] = x0, x1, x2, x3 - out[4], out[5], out[6], out[7] = x12, x13, x14, x15 - return out -} diff --git a/internal/chacha20/chacha_noasm.go b/internal/chacha20/chacha_noasm.go deleted file mode 100644 index bf8beba670..0000000000 --- a/internal/chacha20/chacha_noasm.go +++ /dev/null @@ -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 !ppc64le,!arm64,!s390x arm64,!go1.11 gccgo appengine - -package chacha20 - -const ( - bufSize = 64 - haveAsm = false -) - -func (*Cipher) xorKeyStreamAsm(dst, src []byte) { - panic("not implemented") -} diff --git a/internal/chacha20/chacha_ppc64le.go b/internal/chacha20/chacha_ppc64le.go deleted file mode 100644 index 638cb5e5de..0000000000 --- a/internal/chacha20/chacha_ppc64le.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2019 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 ppc64le,!gccgo,!appengine - -package chacha20 - -import "encoding/binary" - -const ( - bufSize = 256 - haveAsm = true -) - -//go:noescape -func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[8]uint32, counter *uint32) - -func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { - if len(src) >= bufSize { - chaCha20_ctr32_vmx(&dst[0], &src[0], len(src)-len(src)%bufSize, &c.key, &c.counter) - } - if len(src)%bufSize != 0 { - chaCha20_ctr32_vmx(&c.buf[0], &c.buf[0], bufSize, &c.key, &c.counter) - start := len(src) - len(src)%bufSize - ts, td, tb := src[start:], dst[start:], c.buf[:] - // Unroll loop to XOR 32 bytes per iteration. - for i := 0; i < len(ts)-32; i += 32 { - td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination - s0 := binary.LittleEndian.Uint64(ts[0:8]) - s1 := binary.LittleEndian.Uint64(ts[8:16]) - s2 := binary.LittleEndian.Uint64(ts[16:24]) - s3 := binary.LittleEndian.Uint64(ts[24:32]) - b0 := binary.LittleEndian.Uint64(tb[0:8]) - b1 := binary.LittleEndian.Uint64(tb[8:16]) - b2 := binary.LittleEndian.Uint64(tb[16:24]) - b3 := binary.LittleEndian.Uint64(tb[24:32]) - binary.LittleEndian.PutUint64(td[0:8], s0^b0) - binary.LittleEndian.PutUint64(td[8:16], s1^b1) - binary.LittleEndian.PutUint64(td[16:24], s2^b2) - binary.LittleEndian.PutUint64(td[24:32], s3^b3) - ts, td, tb = ts[32:], td[32:], tb[32:] - } - td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination - for i, v := range ts { - td[i] = tb[i] ^ v - } - c.len = bufSize - (len(src) % bufSize) - - } - -} diff --git a/internal/chacha20/chacha_s390x.go b/internal/chacha20/chacha_s390x.go deleted file mode 100644 index aad645b447..0000000000 --- a/internal/chacha20/chacha_s390x.go +++ /dev/null @@ -1,29 +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 - -import ( - "golang.org/x/sys/cpu" -) - -var haveAsm = cpu.S390X.HasVX - -const bufSize = 256 - -// 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() diff --git a/internal/chacha20/chacha_test.go b/internal/chacha20/chacha_test.go deleted file mode 100644 index 9a7a0994cf..0000000000 --- a/internal/chacha20/chacha_test.go +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package chacha20 - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "math/rand" - "testing" -) - -func TestCore(t *testing.T) { - // This is just a smoke test that checks the example from - // https://tools.ietf.org/html/rfc7539#section-2.3.2. The - // chacha20poly1305 package contains much more extensive tests of this - // code. - var key [32]byte - for i := range key { - key[i] = byte(i) - } - - var input [16]byte - input[0] = 1 - input[7] = 9 - input[11] = 0x4a - - var out [64]byte - XORKeyStream(out[:], out[:], &input, &key) - const expected = "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e" - if result := hex.EncodeToString(out[:]); result != expected { - t.Errorf("wanted %x but got %x", expected, result) - } -} - -// Run the test cases with the input and output in different buffers. -func TestNoOverlap(t *testing.T) { - for _, c := range testVectors { - s := New(c.key, c.nonce) - input, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - output := make([]byte, c.length) - s.XORKeyStream(output, input) - got := hex.EncodeToString(output) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } -} - -// Run the test cases with the input and output overlapping entirely. -func TestOverlap(t *testing.T) { - for _, c := range testVectors { - s := New(c.key, c.nonce) - data, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - s.XORKeyStream(data, data) - got := hex.EncodeToString(data) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } -} - -// Run the test cases with various source and destination offsets. -func TestUnaligned(t *testing.T) { - const max = 8 // max offset (+1) to test - for _, c := range testVectors { - input := make([]byte, c.length+max) - output := make([]byte, c.length+max) - for i := 0; i < max; i++ { // input offsets - for j := 0; j < max; j++ { // output offsets - s := New(c.key, c.nonce) - - input := input[i : i+c.length] - output := output[j : j+c.length] - - data, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - copy(input, data) - s.XORKeyStream(output, input) - got := hex.EncodeToString(output) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } - } - } -} - -// Run the test cases by calling XORKeyStream multiple times. -func TestStep(t *testing.T) { - // wide range of step sizes to try and hit edge cases - steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256} - rnd := rand.New(rand.NewSource(123)) - for _, c := range testVectors { - s := New(c.key, c.nonce) - input, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - output := make([]byte, c.length) - - // step through the buffers - i, step := 0, steps[rnd.Intn(len(steps))] - for i+step < c.length { - s.XORKeyStream(output[i:i+step], input[i:i+step]) - if i+step < c.length && output[i+step] != 0 { - t.Errorf("length=%v, i=%v, step=%v: output overwritten", c.length, i, step) - } - i += step - step = steps[rnd.Intn(len(steps))] - } - // finish the encryption - s.XORKeyStream(output[i:], input[i:]) - - got := hex.EncodeToString(output) - if got != c.output { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output) - } - } -} - -// Test that Advance() discards bytes until a block boundary is hit. -func TestAdvance(t *testing.T) { - for _, c := range testVectors { - for i := 0; i < 63; i++ { - s := New(c.key, c.nonce) - z := New(c.key, c.nonce) - input, err := hex.DecodeString(c.input) - if err != nil { - t.Fatalf("cannot decode input %#v: %v", c.input, err) - } - zeros, discard := make([]byte, 64), make([]byte, 64) - so, zo := make([]byte, c.length), make([]byte, c.length) - for j := 0; j < c.length; j += 64 { - lim := j + i - if lim > c.length { - lim = c.length - } - s.XORKeyStream(so[j:lim], input[j:lim]) - // calling s.Advance() multiple times should have no effect - for k := 0; k < i%3+1; k++ { - s.Advance() - } - z.XORKeyStream(zo[j:lim], input[j:lim]) - if lim < c.length { - end := 64 - i - if c.length-lim < end { - end = c.length - lim - } - z.XORKeyStream(discard[:], zeros[:end]) - } - } - - got := hex.EncodeToString(so) - want := hex.EncodeToString(zo) - if got != want { - t.Errorf("length=%v: got %#v, want %#v", c.length, got, want) - } - } - } -} - -func BenchmarkChaCha20(b *testing.B) { - sizes := []int{32, 63, 64, 256, 1024, 1350, 65536} - for _, size := range sizes { - s := size - b.Run(fmt.Sprint(s), func(b *testing.B) { - k := [32]byte{} - c := [16]byte{} - src := make([]byte, s) - dst := make([]byte, s) - b.SetBytes(int64(s)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - XORKeyStream(dst, src, &c, &k) - } - }) - } -} - -func TestHChaCha20(t *testing.T) { - // See draft-paragon-paseto-rfc-00 §7.2.1. - key := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - nonce := []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27} - expected := []byte{0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, - 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, - 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, - 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, - } - result := HChaCha20(&[8]uint32{ - binary.LittleEndian.Uint32(key[0:4]), - binary.LittleEndian.Uint32(key[4:8]), - binary.LittleEndian.Uint32(key[8:12]), - binary.LittleEndian.Uint32(key[12:16]), - binary.LittleEndian.Uint32(key[16:20]), - binary.LittleEndian.Uint32(key[20:24]), - binary.LittleEndian.Uint32(key[24:28]), - binary.LittleEndian.Uint32(key[28:32]), - }, &[4]uint32{ - binary.LittleEndian.Uint32(nonce[0:4]), - binary.LittleEndian.Uint32(nonce[4:8]), - binary.LittleEndian.Uint32(nonce[8:12]), - binary.LittleEndian.Uint32(nonce[12:16]), - }) - for i := 0; i < 8; i++ { - want := binary.LittleEndian.Uint32(expected[i*4 : (i+1)*4]) - if got := result[i]; got != want { - t.Errorf("word %d incorrect: want 0x%x, got 0x%x", i, want, got) - } - } -} diff --git a/internal/poly1305/_asm/go.mod b/internal/poly1305/_asm/go.mod new file mode 100644 index 0000000000..cabd9519b2 --- /dev/null +++ b/internal/poly1305/_asm/go.mod @@ -0,0 +1,15 @@ +module internal/poly1305/_asm + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/internal/poly1305/_asm/go.sum b/internal/poly1305/_asm/go.sum new file mode 100644 index 0000000000..39dd154050 --- /dev/null +++ b/internal/poly1305/_asm/go.sum @@ -0,0 +1,12 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/internal/poly1305/_asm/sum_amd64_asm.go b/internal/poly1305/_asm/sum_amd64_asm.go new file mode 100644 index 0000000000..a445c68f01 --- /dev/null +++ b/internal/poly1305/_asm/sum_amd64_asm.go @@ -0,0 +1,126 @@ +// Copyright 2024 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 main + +import ( + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/sha3" +) + +//go:generate go run . -out ../sum_amd64.s -pkg poly1305 + +func main() { + Package("golang.org/x/crypto/internal/poly1305") + ConstraintExpr("gc,!purego") + update() + Generate() +} + +func update() { + Implement("update") + + Load(Param("state"), RDI) + MOVQ(NewParamAddr("msg_base", 8), RSI) + MOVQ(NewParamAddr("msg_len", 16), R15) + + MOVQ(Mem{Base: DI}.Offset(0), R8) // h0 + MOVQ(Mem{Base: DI}.Offset(8), R9) // h1 + MOVQ(Mem{Base: DI}.Offset(16), R10) // h2 + MOVQ(Mem{Base: DI}.Offset(24), R11) // r0 + MOVQ(Mem{Base: DI}.Offset(32), R12) // r1 + + CMPQ(R15, Imm(16)) + JB(LabelRef("bytes_between_0_and_15")) + + Label("loop") + POLY1305_ADD(RSI, R8, R9, R10) + + Label("multiply") + POLY1305_MUL(R8, R9, R10, R11, R12, RBX, RCX, R13, R14) + SUBQ(Imm(16), R15) + CMPQ(R15, Imm(16)) + JAE(LabelRef("loop")) + + Label("bytes_between_0_and_15") + TESTQ(R15, R15) + JZ(LabelRef("done")) + MOVQ(U32(1), RBX) + XORQ(RCX, RCX) + XORQ(R13, R13) + ADDQ(R15, RSI) + + Label("flush_buffer") + SHLQ(Imm(8), RBX, RCX) + SHLQ(Imm(8), RBX) + MOVB(Mem{Base: SI}.Offset(-1), R13B) + XORQ(R13, RBX) + DECQ(RSI) + DECQ(R15) + JNZ(LabelRef("flush_buffer")) + + ADDQ(RBX, R8) + ADCQ(RCX, R9) + ADCQ(Imm(0), R10) + MOVQ(U32(16), R15) + JMP(LabelRef("multiply")) + + Label("done") + MOVQ(R8, Mem{Base: DI}.Offset(0)) + MOVQ(R9, Mem{Base: DI}.Offset(8)) + MOVQ(R10, Mem{Base: DI}.Offset(16)) + RET() +} + +func POLY1305_ADD(msg, h0, h1, h2 GPPhysical) { + ADDQ(Mem{Base: msg}.Offset(0), h0) + ADCQ(Mem{Base: msg}.Offset(8), h1) + ADCQ(Imm(1), h2) + LEAQ(Mem{Base: msg}.Offset(16), msg) +} + +func POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3 GPPhysical) { + MOVQ(r0, RAX) + MULQ(h0) + MOVQ(RAX, t0) + MOVQ(RDX, t1) + MOVQ(r0, RAX) + MULQ(h1) + ADDQ(RAX, t1) + ADCQ(Imm(0), RDX) + MOVQ(r0, t2) + IMULQ(h2, t2) + ADDQ(RDX, t2) + + MOVQ(r1, RAX) + MULQ(h0) + ADDQ(RAX, t1) + ADCQ(Imm(0), RDX) + MOVQ(RDX, h0) + MOVQ(r1, t3) + IMULQ(h2, t3) + MOVQ(r1, RAX) + MULQ(h1) + ADDQ(RAX, t2) + ADCQ(RDX, t3) + ADDQ(h0, t2) + ADCQ(Imm(0), t3) + + MOVQ(t0, h0) + MOVQ(t1, h1) + MOVQ(t2, h2) + ANDQ(Imm(3), h2) + MOVQ(t2, t0) + ANDQ(I32(-4), t0) + ADDQ(t0, h0) + ADCQ(t3, h1) + ADCQ(Imm(0), h2) + SHRQ(Imm(2), t3, t2) + SHRQ(Imm(2), t3) + ADDQ(t2, h0) + ADCQ(t3, h1) + ADCQ(Imm(0), h2) +} diff --git a/poly1305/mac_noasm.go b/internal/poly1305/mac_noasm.go similarity index 65% rename from poly1305/mac_noasm.go rename to internal/poly1305/mac_noasm.go index a8dd589ae3..8d99551fee 100644 --- a/poly1305/mac_noasm.go +++ b/internal/poly1305/mac_noasm.go @@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!ppc64le gccgo appengine +//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego package poly1305 type mac struct{ macGeneric } - -func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} } diff --git a/poly1305/poly1305.go b/internal/poly1305/poly1305.go similarity index 75% rename from poly1305/poly1305.go rename to internal/poly1305/poly1305.go index d076a56235..4aaea810a2 100644 --- a/poly1305/poly1305.go +++ b/internal/poly1305/poly1305.go @@ -15,15 +15,23 @@ // used with a fixed key in order to generate one-time keys from an nonce. // However, in this package AES isn't used and the one-time key is specified // directly. -package poly1305 // import "golang.org/x/crypto/poly1305" +package poly1305 import "crypto/subtle" // TagSize is the size, in bytes, of a poly1305 authenticator. const TagSize = 16 -// Verify returns true if mac is a valid authenticator for m with the given -// key. +// 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 *[16]byte, m []byte, key *[32]byte) { + h := New(key) + h.Write(m) + h.Sum(out[:0]) +} + +// Verify returns true if mac is a valid authenticator for m with the given key. func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { var tmp [16]byte Sum(&tmp, m, key) @@ -40,10 +48,9 @@ func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { // two different messages with the same key allows an attacker // to forge messages at will. func New(key *[32]byte) *MAC { - return &MAC{ - mac: newMAC(key), - finalized: false, - } + m := &MAC{} + initialize(key, &m.macState) + return m } // MAC is an io.Writer computing an authentication tag @@ -52,7 +59,7 @@ func New(key *[32]byte) *MAC { // MAC cannot be used like common hash.Hash implementations, // because using a poly1305 key twice breaks its security. // Therefore writing data to a running MAC after calling -// Sum causes it to panic. +// Sum or Verify causes it to panic. type MAC struct { mac // platform-dependent implementation @@ -65,10 +72,10 @@ func (h *MAC) Size() int { return TagSize } // Write adds more data to the running message authentication code. // It never returns an error. // -// It must not be called after the first call of Sum. +// It must not be called after the first call of Sum or Verify. func (h *MAC) Write(p []byte) (n int, err error) { if h.finalized { - panic("poly1305: write to MAC after Sum") + panic("poly1305: write to MAC after Sum or Verify") } return h.mac.Write(p) } @@ -81,3 +88,12 @@ func (h *MAC) Sum(b []byte) []byte { h.finalized = true return append(b, mac[:]...) } + +// Verify returns whether the authenticator of all data written to +// the message authentication code matches the expected value. +func (h *MAC) Verify(expected []byte) bool { + var mac [TagSize]byte + h.mac.Sum(&mac) + h.finalized = true + return subtle.ConstantTimeCompare(expected, mac[:]) == 1 +} diff --git a/poly1305/poly1305_test.go b/internal/poly1305/poly1305_test.go similarity index 66% rename from poly1305/poly1305_test.go rename to internal/poly1305/poly1305_test.go index e35928a0b6..e7ec6d19dd 100644 --- a/poly1305/poly1305_test.go +++ b/internal/poly1305/poly1305_test.go @@ -5,6 +5,8 @@ package poly1305 import ( + "crypto/rand" + "encoding/binary" "encoding/hex" "flag" "testing" @@ -14,9 +16,10 @@ import ( var stressFlag = flag.Bool("stress", false, "run slow stress tests") type test struct { - in string - key string - tag string + in string + key string + tag string + state string } func (t *test) Input() []byte { @@ -47,9 +50,33 @@ func (t *test) Tag() [16]byte { return tag } +func (t *test) InitialState() [3]uint64 { + // state is hex encoded in big-endian byte order + if t.state == "" { + return [3]uint64{0, 0, 0} + } + buf, err := hex.DecodeString(t.state) + if err != nil { + panic(err) + } + if len(buf) != 3*8 { + panic("incorrect state length") + } + return [3]uint64{ + binary.BigEndian.Uint64(buf[16:24]), + binary.BigEndian.Uint64(buf[8:16]), + binary.BigEndian.Uint64(buf[0:8]), + } +} + func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) { var tag [16]byte for i, v := range testData { + // cannot set initial state before calling sum, so skip those tests + if v.InitialState() != [3]uint64{0, 0, 0} { + continue + } + in := v.Input() if unaligned { in = unalignBytes(in) @@ -59,6 +86,30 @@ func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg if tag != v.Tag() { t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:]) } + if !Verify(&tag, in, &key) { + t.Errorf("%d: tag didn't verify", i) + } + // If the key is zero, the tag will always be zero, independent of the input. + if len(in) > 0 && key != [32]byte{} { + in[0] ^= 0xff + if Verify(&tag, in, &key) { + t.Errorf("%d: tag verified after altering the input", i) + } + in[0] ^= 0xff + } + // If the input is empty, the tag only depends on the second half of the key. + if len(in) > 0 { + key[0] ^= 0xff + if Verify(&tag, in, &key) { + t.Errorf("%d: tag verified after altering the key", i) + } + key[0] ^= 0xff + } + tag[0] ^= 0xff + if Verify(&tag, in, &key) { + t.Errorf("%d: tag verified after altering the tag", i) + } + tag[0] ^= 0xff } } @@ -115,8 +166,17 @@ func testWriteGeneric(t *testing.T, unaligned bool) { input = unalignBytes(input) } h := newMACGeneric(&key) - h.Write(input[:len(input)/2]) - h.Write(input[len(input)/2:]) + if s := v.InitialState(); s != [3]uint64{0, 0, 0} { + h.macState.h = s + } + n, err := h.Write(input[:len(input)/3]) + if err != nil || n != len(input[:len(input)/3]) { + t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) + } + n, err = h.Write(input[len(input)/3:]) + if err != nil || n != len(input[len(input)/3:]) { + t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) + } h.Sum(&out) if tag := v.Tag(); out != tag { t.Errorf("%d: expected %x, got %x", i, tag[:], out[:]) @@ -134,12 +194,29 @@ func testWrite(t *testing.T, unaligned bool) { input = unalignBytes(input) } h := New(&key) - h.Write(input[:len(input)/2]) - h.Write(input[len(input)/2:]) + if s := v.InitialState(); s != [3]uint64{0, 0, 0} { + h.macState.h = s + } + n, err := h.Write(input[:len(input)/3]) + if err != nil || n != len(input[:len(input)/3]) { + t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) + } + n, err = h.Write(input[len(input)/3:]) + if err != nil || n != len(input[len(input)/3:]) { + t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) + } h.Sum(out[:0]) - if tag := v.Tag(); out != tag { + tag := v.Tag() + if out != tag { t.Errorf("%d: expected %x, got %x", i, tag[:], out[:]) } + if !h.Verify(tag[:]) { + t.Errorf("%d: Verify failed", i) + } + tag[0] ^= 0xff + if h.Verify(tag[:]) { + t.Errorf("%d: Verify succeeded after modifying the tag", i) + } } } @@ -150,6 +227,7 @@ func benchmarkSum(b *testing.B, size int, unaligned bool) { if unaligned { in = unalignBytes(in) } + rand.Read(in) b.SetBytes(int64(len(in))) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -164,6 +242,7 @@ func benchmarkWrite(b *testing.B, size int, unaligned bool) { if unaligned { in = unalignBytes(in) } + rand.Read(in) b.SetBytes(int64(len(in))) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/internal/poly1305/sum_amd64.s b/internal/poly1305/sum_amd64.s new file mode 100644 index 0000000000..133757384b --- /dev/null +++ b/internal/poly1305/sum_amd64.s @@ -0,0 +1,93 @@ +// Code generated by command: go run sum_amd64_asm.go -out ../sum_amd64.s -pkg poly1305. DO NOT EDIT. + +//go:build gc && !purego + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOVQ state+0(FP), DI + MOVQ msg_base+8(FP), SI + MOVQ msg_len+16(FP), R15 + MOVQ (DI), R8 + MOVQ 8(DI), R9 + MOVQ 16(DI), R10 + MOVQ 24(DI), R11 + MOVQ 32(DI), R12 + CMPQ R15, $0x10 + JB bytes_between_0_and_15 + +loop: + ADDQ (SI), R8 + ADCQ 8(SI), R9 + ADCQ $0x01, R10 + LEAQ 16(SI), SI + +multiply: + MOVQ R11, AX + MULQ R8 + MOVQ AX, BX + MOVQ DX, CX + MOVQ R11, AX + MULQ R9 + ADDQ AX, CX + ADCQ $0x00, DX + MOVQ R11, R13 + IMULQ R10, R13 + ADDQ DX, R13 + MOVQ R12, AX + MULQ R8 + ADDQ AX, CX + ADCQ $0x00, DX + MOVQ DX, R8 + MOVQ R12, R14 + IMULQ R10, R14 + MOVQ R12, AX + MULQ R9 + ADDQ AX, R13 + ADCQ DX, R14 + ADDQ R8, R13 + ADCQ $0x00, R14 + MOVQ BX, R8 + MOVQ CX, R9 + MOVQ R13, R10 + ANDQ $0x03, R10 + MOVQ R13, BX + ANDQ $-4, BX + ADDQ BX, R8 + ADCQ R14, R9 + ADCQ $0x00, R10 + SHRQ $0x02, R14, R13 + SHRQ $0x02, R14 + ADDQ R13, R8 + ADCQ R14, R9 + ADCQ $0x00, R10 + SUBQ $0x10, R15 + CMPQ R15, $0x10 + JAE loop + +bytes_between_0_and_15: + TESTQ R15, R15 + JZ done + MOVQ $0x00000001, BX + XORQ CX, CX + XORQ R13, R13 + ADDQ R15, SI + +flush_buffer: + SHLQ $0x08, BX, CX + SHLQ $0x08, BX + MOVB -1(SI), R13 + XORQ R13, BX + DECQ SI + DECQ R15 + JNZ flush_buffer + ADDQ BX, R8 + ADCQ CX, R9 + ADCQ $0x00, R10 + MOVQ $0x00000010, R15 + JMP multiply + +done: + MOVQ R8, (DI) + MOVQ R9, 8(DI) + MOVQ R10, 16(DI) + RET diff --git a/internal/poly1305/sum_asm.go b/internal/poly1305/sum_asm.go new file mode 100644 index 0000000000..315b84ac39 --- /dev/null +++ b/internal/poly1305/sum_asm.go @@ -0,0 +1,47 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le) + +package poly1305 + +//go:noescape +func update(state *macState, msg []byte) + +// mac is a wrapper for macGeneric that redirects calls that would have gone to +// updateGeneric to update. +// +// Its Write and Sum methods are otherwise identical to the macGeneric ones, but +// using function pointers would carry a major performance cost. +type mac struct{ macGeneric } + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + update(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + update(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +func (h *mac) Sum(out *[16]byte) { + state := h.macState + if h.offset > 0 { + update(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} diff --git a/internal/poly1305/sum_generic.go b/internal/poly1305/sum_generic.go new file mode 100644 index 0000000000..ec2202bd7d --- /dev/null +++ b/internal/poly1305/sum_generic.go @@ -0,0 +1,312 @@ +// 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. + +// This file provides the generic implementation of Sum and MAC. Other files +// might provide optimized assembly implementations of some of this code. + +package poly1305 + +import ( + "encoding/binary" + "math/bits" +) + +// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag +// for a 64 bytes message is approximately +// +// s + m[0:16] * r⁴ + m[16:32] * r³ + m[32:48] * r² + m[48:64] * r mod 2¹³⁰ - 5 +// +// for some secret r and s. It can be computed sequentially like +// +// for len(msg) > 0: +// h += read(msg, 16) +// h *= r +// h %= 2¹³⁰ - 5 +// return h + s +// +// All the complexity is about doing performant constant-time math on numbers +// larger than any available numeric type. + +func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { + h := newMACGeneric(key) + h.Write(msg) + h.Sum(out) +} + +func newMACGeneric(key *[32]byte) macGeneric { + m := macGeneric{} + initialize(key, &m.macState) + return m +} + +// macState holds numbers in saturated 64-bit little-endian limbs. That is, +// the value of [x0, x1, x2] is x[0] + x[1] * 2⁶⁴ + x[2] * 2¹²⁸. +type macState struct { + // h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but + // can grow larger during and after rounds. It must, however, remain below + // 2 * (2¹³⁰ - 5). + h [3]uint64 + // r and s are the private key components. + r [2]uint64 + s [2]uint64 +} + +type macGeneric struct { + macState + + buffer [TagSize]byte + offset int +} + +// Write splits the incoming message into TagSize chunks, and passes them to +// update. It buffers incomplete chunks. +func (h *macGeneric) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < TagSize { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + updateGeneric(&h.macState, h.buffer[:]) + } + if n := len(p) - (len(p) % TagSize); n > 0 { + updateGeneric(&h.macState, p[:n]) + p = p[n:] + } + if len(p) > 0 { + h.offset += copy(h.buffer[h.offset:], p) + } + return nn, nil +} + +// Sum flushes the last incomplete chunk from the buffer, if any, and generates +// the MAC output. It does not modify its state, in order to allow for multiple +// calls to Sum, even if no Write is allowed after Sum. +func (h *macGeneric) Sum(out *[TagSize]byte) { + state := h.macState + if h.offset > 0 { + updateGeneric(&state, h.buffer[:h.offset]) + } + finalize(out, &state.h, &state.s) +} + +// [rMask0, rMask1] is the specified Poly1305 clamping mask in little-endian. It +// clears some bits of the secret coefficient to make it possible to implement +// multiplication more efficiently. +const ( + rMask0 = 0x0FFFFFFC0FFFFFFF + rMask1 = 0x0FFFFFFC0FFFFFFC +) + +// initialize loads the 256-bit key into the two 128-bit secret values r and s. +func initialize(key *[32]byte, m *macState) { + m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 + m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 + m.s[0] = binary.LittleEndian.Uint64(key[16:24]) + m.s[1] = binary.LittleEndian.Uint64(key[24:32]) +} + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +func add128(a, b uint128) uint128 { + lo, c := bits.Add64(a.lo, b.lo, 0) + hi, c := bits.Add64(a.hi, b.hi, c) + if c != 0 { + panic("poly1305: unexpected overflow") + } + return uint128{lo, hi} +} + +func shiftRightBy2(a uint128) uint128 { + a.lo = a.lo>>2 | (a.hi&3)<<62 + a.hi = a.hi >> 2 + return a +} + +// updateGeneric absorbs msg into the state.h accumulator. For each chunk m of +// 128 bits of message, it computes +// +// h₊ = (h + m) * r mod 2¹³⁰ - 5 +// +// If the msg length is not a multiple of TagSize, it assumes the last +// incomplete chunk is the final one. +func updateGeneric(state *macState, msg []byte) { + h0, h1, h2 := state.h[0], state.h[1], state.h[2] + r0, r1 := state.r[0], state.r[1] + + for len(msg) > 0 { + var c uint64 + + // For the first step, h + m, we use a chain of bits.Add64 intrinsics. + // The resulting value of h might exceed 2¹³⁰ - 5, but will be partially + // reduced at the end of the multiplication below. + // + // The spec requires us to set a bit just above the message size, not to + // hide leading zeroes. For full chunks, that's 1 << 128, so we can just + // add 1 to the most significant (2¹²⁸) limb, h2. + if len(msg) >= TagSize { + h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0) + h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c) + h2 += c + 1 + + msg = msg[TagSize:] + } else { + var buf [TagSize]byte + copy(buf[:], msg) + buf[len(msg)] = 1 + + h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0) + h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c) + h2 += c + + msg = nil + } + + // Multiplication of big number limbs is similar to elementary school + // columnar multiplication. Instead of digits, there are 64-bit limbs. + // + // We are multiplying a 3 limbs number, h, by a 2 limbs number, r. + // + // h2 h1 h0 x + // r1 r0 = + // ---------------- + // h2r0 h1r0 h0r0 <-- individual 128-bit products + // + h2r1 h1r1 h0r1 + // ------------------------ + // m3 m2 m1 m0 <-- result in 128-bit overlapping limbs + // ------------------------ + // m3.hi m2.hi m1.hi m0.hi <-- carry propagation + // + m3.lo m2.lo m1.lo m0.lo + // ------------------------------- + // t4 t3 t2 t1 t0 <-- final result in 64-bit limbs + // + // The main difference from pen-and-paper multiplication is that we do + // carry propagation in a separate step, as if we wrote two digit sums + // at first (the 128-bit limbs), and then carried the tens all at once. + + h0r0 := mul64(h0, r0) + h1r0 := mul64(h1, r0) + h2r0 := mul64(h2, r0) + h0r1 := mul64(h0, r1) + h1r1 := mul64(h1, r1) + h2r1 := mul64(h2, r1) + + // Since h2 is known to be at most 7 (5 + 1 + 1), and r0 and r1 have their + // top 4 bits cleared by rMask{0,1}, we know that their product is not going + // to overflow 64 bits, so we can ignore the high part of the products. + // + // This also means that the product doesn't have a fifth limb (t4). + if h2r0.hi != 0 { + panic("poly1305: unexpected overflow") + } + if h2r1.hi != 0 { + panic("poly1305: unexpected overflow") + } + + m0 := h0r0 + m1 := add128(h1r0, h0r1) // These two additions don't overflow thanks again + m2 := add128(h2r0, h1r1) // to the 4 masked bits at the top of r0 and r1. + m3 := h2r1 + + t0 := m0.lo + t1, c := bits.Add64(m1.lo, m0.hi, 0) + t2, c := bits.Add64(m2.lo, m1.hi, c) + t3, _ := bits.Add64(m3.lo, m2.hi, c) + + // Now we have the result as 4 64-bit limbs, and we need to reduce it + // modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do + // a cheap partial reduction according to the reduction identity + // + // c * 2¹³⁰ + n = c * 5 + n mod 2¹³⁰ - 5 + // + // because 2¹³⁰ = 5 mod 2¹³⁰ - 5. Partial reduction since the result is + // likely to be larger than 2¹³⁰ - 5, but still small enough to fit the + // assumptions we make about h in the rest of the code. + // + // See also https://speakerdeck.com/gtank/engineering-prime-numbers?slide=23 + + // We split the final result at the 2¹³⁰ mark into h and cc, the carry. + // Note that the carry bits are effectively shifted left by 2, in other + // words, cc = c * 4 for the c in the reduction identity. + h0, h1, h2 = t0, t1, t2&maskLow2Bits + cc := uint128{t2 & maskNotLow2Bits, t3} + + // To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c. + + h0, c = bits.Add64(h0, cc.lo, 0) + h1, c = bits.Add64(h1, cc.hi, c) + h2 += c + + cc = shiftRightBy2(cc) + + h0, c = bits.Add64(h0, cc.lo, 0) + h1, c = bits.Add64(h1, cc.hi, c) + h2 += c + + // h2 is at most 3 + 1 + 1 = 5, making the whole of h at most + // + // 5 * 2¹²⁸ + (2¹²⁸ - 1) = 6 * 2¹²⁸ - 1 + } + + state.h[0], state.h[1], state.h[2] = h0, h1, h2 +} + +const ( + maskLow2Bits uint64 = 0x0000000000000003 + maskNotLow2Bits uint64 = ^maskLow2Bits +) + +// select64 returns x if v == 1 and y if v == 0, in constant time. +func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y } + +// [p0, p1, p2] is 2¹³⁰ - 5 in little endian order. +const ( + p0 = 0xFFFFFFFFFFFFFFFB + p1 = 0xFFFFFFFFFFFFFFFF + p2 = 0x0000000000000003 +) + +// finalize completes the modular reduction of h and computes +// +// out = h + s mod 2¹²⁸ +func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) { + h0, h1, h2 := h[0], h[1], h[2] + + // After the partial reduction in updateGeneric, h might be more than + // 2¹³⁰ - 5, but will be less than 2 * (2¹³⁰ - 5). To complete the reduction + // in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the + // result if the subtraction underflows, and t otherwise. + + hMinusP0, b := bits.Sub64(h0, p0, 0) + hMinusP1, b := bits.Sub64(h1, p1, b) + _, b = bits.Sub64(h2, p2, b) + + // h = h if h < p else h - p + h0 = select64(b, h0, hMinusP0) + h1 = select64(b, h1, hMinusP1) + + // Finally, we compute the last Poly1305 step + // + // tag = h + s mod 2¹²⁸ + // + // by just doing a wide addition with the 128 low bits of h and discarding + // the overflow. + h0, c := bits.Add64(h0, s[0], 0) + h1, _ = bits.Add64(h1, s[1], c) + + binary.LittleEndian.PutUint64(out[0:8], h0) + binary.LittleEndian.PutUint64(out[8:16], h1) +} diff --git a/internal/poly1305/sum_loong64.s b/internal/poly1305/sum_loong64.s new file mode 100644 index 0000000000..bc8361da40 --- /dev/null +++ b/internal/poly1305/sum_loong64.s @@ -0,0 +1,123 @@ +// Copyright 2025 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. + +//go:build gc && !purego + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOVV state+0(FP), R4 + MOVV msg_base+8(FP), R5 + MOVV msg_len+16(FP), R6 + + MOVV $0x10, R7 + + MOVV (R4), R8 // h0 + MOVV 8(R4), R9 // h1 + MOVV 16(R4), R10 // h2 + MOVV 24(R4), R11 // r0 + MOVV 32(R4), R12 // r1 + + BLT R6, R7, bytes_between_0_and_15 + +loop: + MOVV (R5), R14 // msg[0:8] + MOVV 8(R5), R16 // msg[8:16] + ADDV R14, R8, R8 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow) + ADDV R16, R9, R27 + SGTU R14, R8, R24 // h0.carry + SGTU R9, R27, R28 + ADDV R27, R24, R9 // h1 + SGTU R27, R9, R24 + OR R24, R28, R24 // h1.carry + ADDV $0x01, R24, R24 + ADDV R10, R24, R10 // h2 + + ADDV $16, R5, R5 // msg = msg[16:] + +multiply: + MULV R8, R11, R14 // h0r0.lo + MULHVU R8, R11, R15 // h0r0.hi + MULV R9, R11, R13 // h1r0.lo + MULHVU R9, R11, R16 // h1r0.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MULV R10, R11, R25 + ADDV R16, R25, R25 + MULV R8, R12, R13 // h0r1.lo + MULHVU R8, R12, R16 // h0r1.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MOVV R16, R8 + MULV R10, R12, R26 // h2r1 + MULV R9, R12, R13 // h1r1.lo + MULHVU R9, R12, R16 // h1r1.hi + ADDV R13, R25, R25 + ADDV R16, R26, R27 + SGTU R13, R25, R24 + ADDV R27, R24, R26 + ADDV R8, R25, R25 + SGTU R8, R25, R24 + ADDV R24, R26, R26 + AND $3, R25, R10 + AND $-4, R25, R17 + ADDV R17, R14, R8 + ADDV R26, R15, R27 + SGTU R17, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + SLLV $62, R26, R27 + SRLV $2, R25, R28 + SRLV $2, R26, R26 + OR R27, R28, R25 + ADDV R25, R8, R8 + ADDV R26, R9, R27 + SGTU R25, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + + SUBV $16, R6, R6 + BGE R6, R7, loop + +bytes_between_0_and_15: + BEQ R6, R0, done + MOVV $1, R14 + XOR R15, R15 + ADDV R6, R5, R5 + +flush_buffer: + MOVBU -1(R5), R25 + SRLV $56, R14, R24 + SLLV $8, R15, R28 + SLLV $8, R14, R14 + OR R24, R28, R15 + XOR R25, R14, R14 + SUBV $1, R6, R6 + SUBV $1, R5, R5 + BNE R6, R0, flush_buffer + + ADDV R14, R8, R8 + SGTU R14, R8, R24 + ADDV R15, R9, R27 + SGTU R15, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R10, R24, R10 + + MOVV $16, R6 + JMP multiply + +done: + MOVV R8, (R4) + MOVV R9, 8(R4) + MOVV R10, 16(R4) + RET diff --git a/poly1305/sum_ppc64le.s b/internal/poly1305/sum_ppc64x.s similarity index 62% rename from poly1305/sum_ppc64le.s rename to internal/poly1305/sum_ppc64x.s index 55c7167ec9..6899a1dabc 100644 --- a/poly1305/sum_ppc64le.s +++ b/internal/poly1305/sum_ppc64x.s @@ -2,15 +2,25 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ppc64le,!gccgo,!appengine +//go:build gc && !purego && (ppc64 || ppc64le) #include "textflag.h" // This was ported from the amd64 implementation. +#ifdef GOARCH_ppc64le +#define LE_MOVD MOVD +#define LE_MOVWZ MOVWZ +#define LE_MOVHZ MOVHZ +#else +#define LE_MOVD MOVDBR +#define LE_MOVWZ MOVWBR +#define LE_MOVHZ MOVHBR +#endif + #define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \ - MOVD (msg), t0; \ - MOVD 8(msg), t1; \ + LE_MOVD (msg)( R0), t0; \ + LE_MOVD (msg)(R24), t1; \ MOVD $1, t2; \ ADDC t0, h0, h0; \ ADDE t1, h1, h1; \ @@ -19,15 +29,14 @@ #define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ MULLD r0, h0, t0; \ - MULLD r0, h1, t4; \ MULHDU r0, h0, t1; \ + MULLD r0, h1, t4; \ MULHDU r0, h1, t5; \ ADDC t4, t1, t1; \ MULLD r0, h2, t2; \ - ADDZE t5; \ MULHDU r1, h0, t4; \ MULLD r1, h0, h0; \ - ADD t5, t2, t2; \ + ADDE t5, t2, t2; \ ADDC h0, t1, t1; \ MULLD h2, r1, t3; \ ADDZE t4, h0; \ @@ -37,13 +46,11 @@ ADDE t5, t3, t3; \ ADDC h0, t2, t2; \ MOVD $-4, t4; \ - MOVD t0, h0; \ - MOVD t1, h1; \ ADDZE t3; \ - ANDCC $3, t2, h2; \ - AND t2, t4, t0; \ + RLDICL $0, t2, $62, h2; \ + AND t2, t4, h0; \ ADDC t0, h0, h0; \ - ADDE t3, h1, h1; \ + ADDE t3, t1, h1; \ SLD $62, t3, t4; \ SRD $2, t2; \ ADDZE h2; \ @@ -53,12 +60,7 @@ ADDE t3, h1, h1; \ ADDZE h2 -DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -GLOBL ·poly1305Mask<>(SB), RODATA, $16 - // func update(state *[7]uint64, msg []byte) - TEXT ·update(SB), $0-32 MOVD state+0(FP), R3 MOVD msg_base+8(FP), R4 @@ -70,12 +72,15 @@ TEXT ·update(SB), $0-32 MOVD 24(R3), R11 // r0 MOVD 32(R3), R12 // r1 + MOVD $8, R24 + CMP R5, $16 BLT bytes_between_0_and_15 loop: POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) + PCALIGN $16 multiply: POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) ADD $-16, R5 @@ -83,7 +88,7 @@ multiply: BGE loop bytes_between_0_and_15: - CMP $0, R5 + CMP R5, $0 BEQ done MOVD $0, R16 // h0 MOVD $0, R17 // h1 @@ -97,7 +102,7 @@ flush_buffer: // Greater than 8 -- load the rightmost remaining bytes in msg // and put into R17 (h1) - MOVD (R4)(R21), R17 + LE_MOVD (R4)(R21), R17 MOVD $16, R22 // Find the offset to those bytes @@ -121,9 +126,9 @@ just1: BLT less8 // Exactly 8 - MOVD (R4), R16 + LE_MOVD (R4), R16 - CMP $0, R17 + CMP R17, $0 // Check if we've already set R17; if not // set 1 to indicate end of msg. @@ -136,7 +141,7 @@ less8: MOVD $0, R22 // shift count CMP R5, $4 BLT less4 - MOVWZ (R4), R16 + LE_MOVWZ (R4), R16 ADD $4, R4 ADD $-4, R5 MOVD $32, R22 @@ -144,7 +149,7 @@ less8: less4: CMP R5, $2 BLT less2 - MOVHZ (R4), R21 + LE_MOVHZ (R4), R21 SLD R22, R21, R21 OR R16, R21, R16 ADD $16, R22 @@ -152,7 +157,7 @@ less4: ADD $2, R4 less2: - CMP $0, R5 + CMP R5, $0 BEQ insert1 MOVBZ (R4), R21 SLD R22, R21, R21 @@ -167,12 +172,12 @@ insert1: carry: // Add new values to h0, h1, h2 - ADDC R16, R8 - ADDE R17, R9 - ADDE $0, R10 - MOVD $16, R5 - ADD R5, R4 - BR multiply + ADDC R16, R8 + ADDE R17, R9 + ADDZE R10, R10 + MOVD $16, R5 + ADD R5, R4 + BR multiply done: // Save h0, h1, h2 in state @@ -180,68 +185,3 @@ done: MOVD R9, 8(R3) MOVD R10, 16(R3) RET - -// func initialize(state *[7]uint64, key *[32]byte) -TEXT ·initialize(SB), $0-16 - MOVD state+0(FP), R3 - MOVD key+8(FP), R4 - - // state[0...7] is initialized with zero - // Load key - MOVD 0(R4), R5 - MOVD 8(R4), R6 - MOVD 16(R4), R7 - MOVD 24(R4), R8 - - // Address of key mask - MOVD $·poly1305Mask<>(SB), R9 - - // Save original key in state - MOVD R7, 40(R3) - MOVD R8, 48(R3) - - // Get mask - MOVD (R9), R7 - MOVD 8(R9), R8 - - // And with key - AND R5, R7, R5 - AND R6, R8, R6 - - // Save masked key in state - MOVD R5, 24(R3) - MOVD R6, 32(R3) - RET - -// func finalize(tag *[TagSize]byte, state *[7]uint64) -TEXT ·finalize(SB), $0-16 - MOVD tag+0(FP), R3 - MOVD state+8(FP), R4 - - // Get h0, h1, h2 from state - MOVD 0(R4), R5 - MOVD 8(R4), R6 - MOVD 16(R4), R7 - - // Save h0, h1 - MOVD R5, R8 - MOVD R6, R9 - MOVD $3, R20 - MOVD $-1, R21 - SUBC $-5, R5 - SUBE R21, R6 - SUBE R20, R7 - MOVD $0, R21 - SUBZE R21 - - // Check for carry - CMP $0, R21 - ISEL $2, R5, R8, R5 - ISEL $2, R6, R9, R6 - MOVD 40(R4), R8 - MOVD 48(R4), R9 - ADDC R8, R5 - ADDE R9, R6 - MOVD R5, 0(R3) - MOVD R6, 8(R3) - RET diff --git a/internal/poly1305/sum_s390x.go b/internal/poly1305/sum_s390x.go new file mode 100644 index 0000000000..e1d033a491 --- /dev/null +++ b/internal/poly1305/sum_s390x.go @@ -0,0 +1,76 @@ +// 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. + +//go:build gc && !purego + +package poly1305 + +import ( + "golang.org/x/sys/cpu" +) + +// updateVX 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 updateVX(state *macState, msg []byte) + +// mac is a replacement for macGeneric that uses a larger buffer and redirects +// calls that would have gone to updateGeneric to updateVX if the vector +// facility is installed. +// +// A larger buffer is required for good performance because the vector +// implementation has a higher fixed cost per call than the generic +// implementation. +type mac struct { + macState + + buffer [16 * TagSize]byte // size must be a multiple of block size (16) + offset int +} + +func (h *mac) Write(p []byte) (int, error) { + nn := len(p) + if h.offset > 0 { + n := copy(h.buffer[h.offset:], p) + if h.offset+n < len(h.buffer) { + h.offset += n + return nn, nil + } + p = p[n:] + h.offset = 0 + if cpu.S390X.HasVX { + updateVX(&h.macState, h.buffer[:]) + } else { + updateGeneric(&h.macState, h.buffer[:]) + } + } + + tail := len(p) % len(h.buffer) // number of bytes to copy into buffer + body := len(p) - tail // number of bytes to process now + if body > 0 { + if cpu.S390X.HasVX { + updateVX(&h.macState, p[:body]) + } else { + updateGeneric(&h.macState, p[:body]) + } + } + h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0 + return nn, nil +} + +func (h *mac) Sum(out *[TagSize]byte) { + state := h.macState + remainder := h.buffer[:h.offset] + + // Use the generic implementation if we have 2 or fewer blocks left + // to sum. The vector implementation has a higher startup time. + if cpu.S390X.HasVX && len(remainder) > 2*TagSize { + updateVX(&state, remainder) + } else if len(remainder) > 0 { + updateGeneric(&state, remainder) + } + finalize(out, &state.h, &state.s) +} diff --git a/internal/poly1305/sum_s390x.s b/internal/poly1305/sum_s390x.s new file mode 100644 index 0000000000..0fe3a7c217 --- /dev/null +++ b/internal/poly1305/sum_s390x.s @@ -0,0 +1,503 @@ +// 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. + +//go:build gc && !purego + +#include "textflag.h" + +// This implementation of Poly1305 uses the vector facility (vx) +// to process up to 2 blocks (32 bytes) per iteration using an +// algorithm based on the one described in: +// +// NEON crypto, Daniel J. Bernstein & Peter Schwabe +// https://cryptojedi.org/papers/neoncrypto-20120320.pdf +// +// This algorithm uses 5 26-bit limbs to represent a 130-bit +// value. These limbs are, for the most part, zero extended and +// placed into 64-bit vector register elements. Each vector +// register is 128-bits wide and so holds 2 of these elements. +// Using 26-bit limbs allows us plenty of headroom to accommodate +// accumulations before and after multiplication without +// overflowing either 32-bits (before multiplication) or 64-bits +// (after multiplication). +// +// In order to parallelise the operations required to calculate +// the sum we use two separate accumulators and then sum those +// in an extra final step. For compatibility with the generic +// implementation we perform this summation at the end of every +// updateVX call. +// +// To use two accumulators we must multiply the message blocks +// by r² rather than r. Only the final message block should be +// multiplied by r. +// +// Example: +// +// We want to calculate the sum (h) for a 64 byte message (m): +// +// h = m[0:16]r⁴ + m[16:32]r³ + m[32:48]r² + m[48:64]r +// +// To do this we split the calculation into the even indices +// and odd indices of the message. These form our SIMD 'lanes': +// +// h = m[ 0:16]r⁴ + m[32:48]r² + <- lane 0 +// m[16:32]r³ + m[48:64]r <- lane 1 +// +// To calculate this iteratively we refactor so that both lanes +// are written in terms of r² and r: +// +// h = (m[ 0:16]r² + m[32:48])r² + <- lane 0 +// (m[16:32]r² + m[48:64])r <- lane 1 +// ^ ^ +// | coefficients for second iteration +// coefficients for first iteration +// +// So in this case we would have two iterations. In the first +// both lanes are multiplied by r². In the second only the +// first lane is multiplied by r² and the second lane is +// instead multiplied by r. This gives use the odd and even +// powers of r that we need from the original equation. +// +// Notation: +// +// h - accumulator +// r - key +// m - message +// +// [a, b] - SIMD register holding two 64-bit values +// [a, b, c, d] - SIMD register holding four 32-bit values +// xᵢ[n] - limb n of variable x with bit width i +// +// Limbs are expressed in little endian order, so for 26-bit +// limbs x₂₆[4] will be the most significant limb and x₂₆[0] +// will be the least significant limb. + +// masking constants +#define MOD24 V0 // [0x0000000000ffffff, 0x0000000000ffffff] - mask low 24-bits +#define MOD26 V1 // [0x0000000003ffffff, 0x0000000003ffffff] - mask low 26-bits + +// expansion constants (see EXPAND macro) +#define EX0 V2 +#define EX1 V3 +#define EX2 V4 + +// key (r², r or 1 depending on context) +#define R_0 V5 +#define R_1 V6 +#define R_2 V7 +#define R_3 V8 +#define R_4 V9 + +// precalculated coefficients (5r², 5r or 0 depending on context) +#define R5_1 V10 +#define R5_2 V11 +#define R5_3 V12 +#define R5_4 V13 + +// message block (m) +#define M_0 V14 +#define M_1 V15 +#define M_2 V16 +#define M_3 V17 +#define M_4 V18 + +// accumulator (h) +#define H_0 V19 +#define H_1 V20 +#define H_2 V21 +#define H_3 V22 +#define H_4 V23 + +// temporary registers (for short-lived values) +#define T_0 V24 +#define T_1 V25 +#define T_2 V26 +#define T_3 V27 +#define T_4 V28 + +GLOBL ·constants<>(SB), RODATA, $0x30 +// EX0 +DATA ·constants<>+0x00(SB)/8, $0x0006050403020100 +DATA ·constants<>+0x08(SB)/8, $0x1016151413121110 +// EX1 +DATA ·constants<>+0x10(SB)/8, $0x060c0b0a09080706 +DATA ·constants<>+0x18(SB)/8, $0x161c1b1a19181716 +// EX2 +DATA ·constants<>+0x20(SB)/8, $0x0d0d0d0d0d0f0e0d +DATA ·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d + +// MULTIPLY multiplies each lane of f and g, partially reduced +// modulo 2¹³⁰ - 5. The result, h, consists of partial products +// in each lane that need to be reduced further to produce the +// final result. +// +// h₁₃₀ = (f₁₃₀g₁₃₀) % 2¹³⁰ + (5f₁₃₀g₁₃₀) / 2¹³⁰ +// +// Note that the multiplication by 5 of the high bits is +// achieved by precalculating the multiplication of four of the +// g coefficients by 5. These are g51-g54. +#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, g3, h3 \ + VMLOF f0, g1, h1 \ + VMLOF f0, g4, h4 \ + VMLOF f0, g2, h2 \ + VMLOF f1, g54, T_0 \ + VMLOF f1, g2, T_3 \ + VMLOF f1, g0, T_1 \ + VMLOF f1, g3, T_4 \ + VMLOF f1, g1, T_2 \ + VMALOF f2, g53, h0, h0 \ + VMALOF f2, g1, h3, h3 \ + VMALOF f2, g54, h1, h1 \ + VMALOF f2, g2, h4, h4 \ + VMALOF f2, g0, h2, h2 \ + VMALOF f3, g52, T_0, T_0 \ + VMALOF f3, g0, T_3, T_3 \ + VMALOF f3, g53, T_1, T_1 \ + VMALOF f3, g1, T_4, T_4 \ + VMALOF f3, g54, T_2, T_2 \ + VMALOF f4, g51, h0, h0 \ + VMALOF f4, g54, h3, h3 \ + VMALOF f4, g52, h1, h1 \ + VMALOF f4, g0, h4, h4 \ + VMALOF f4, g53, h2, h2 \ + VAG T_0, h0, h0 \ + VAG T_3, h3, h3 \ + VAG T_1, h1, h1 \ + VAG T_4, h4, h4 \ + VAG T_2, h2, h2 + +// REDUCE performs the following carry operations in four +// stages, as specified in Bernstein & Schwabe: +// +// 1: h₂₆[0]->h₂₆[1] h₂₆[3]->h₂₆[4] +// 2: h₂₆[1]->h₂₆[2] h₂₆[4]->h₂₆[0] +// 3: h₂₆[0]->h₂₆[1] h₂₆[2]->h₂₆[3] +// 4: h₂₆[3]->h₂₆[4] +// +// The result is that all of the limbs are limited to 26-bits +// except for h₂₆[1] and h₂₆[4] which are limited to 27-bits. +// +// Note that although each limb is aligned at 26-bit intervals +// they may contain values that exceed 2²⁶ - 1, hence the need +// to carry the excess bits in each limb. +#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 splits the 128-bit little-endian values in0 and in1 +// into 26-bit big-endian limbs and places the results into +// the first and second lane of d₂₆[0:4] respectively. +// +// The EX0, EX1 and EX2 constants are arrays of byte indices +// for permutation. The permutation both reverses the bytes +// in the input and ensures the bytes are copied into the +// destination limb ready to be shifted into their final +// position. +#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ + VPERM in0, in1, EX0, d0 \ + VPERM in0, in1, EX1, d2 \ + VPERM in0, in1, EX2, d4 \ + VESRLG $26, d0, d1 \ + VESRLG $30, d2, d3 \ + VESRLG $4, d2, d2 \ + VN MOD26, d0, d0 \ // [in0₂₆[0], in1₂₆[0]] + VN MOD26, d3, d3 \ // [in0₂₆[3], in1₂₆[3]] + VN MOD26, d1, d1 \ // [in0₂₆[1], in1₂₆[1]] + VN MOD24, d4, d4 \ // [in0₂₆[4], in1₂₆[4]] + VN MOD26, d2, d2 // [in0₂₆[2], in1₂₆[2]] + +// func updateVX(state *macState, msg []byte) +TEXT ·updateVX(SB), NOSPLIT, $0 + MOVD state+0(FP), R1 + LMG msg+8(FP), R2, R3 // R2=msg_base, R3=msg_len + + // load EX0, EX1 and EX2 + MOVD $·constants<>(SB), R5 + VLM (R5), EX0, EX2 + + // generate masks + VGMG $(64-24), $63, MOD24 // [0x00ffffff, 0x00ffffff] + VGMG $(64-26), $63, MOD26 // [0x03ffffff, 0x03ffffff] + + // load h (accumulator) and r (key) from state + VZERO T_1 // [0, 0] + VL 0(R1), T_0 // [h₆₄[0], h₆₄[1]] + VLEG $0, 16(R1), T_1 // [h₆₄[2], 0] + VL 24(R1), T_2 // [r₆₄[0], r₆₄[1]] + VPDI $0, T_0, T_2, T_3 // [h₆₄[0], r₆₄[0]] + VPDI $5, T_0, T_2, T_4 // [h₆₄[1], r₆₄[1]] + + // unpack h and r into 26-bit limbs + // note: h₆₄[2] may have the low 3 bits set, so h₂₆[4] is a 27-bit value + VN MOD26, T_3, H_0 // [h₂₆[0], r₂₆[0]] + VZERO H_1 // [0, 0] + VZERO H_3 // [0, 0] + VGMG $(64-12-14), $(63-12), T_0 // [0x03fff000, 0x03fff000] - 26-bit mask with low 12 bits masked out + VESLG $24, T_1, T_1 // [h₆₄[2]<<24, 0] + VERIMG $-26&63, T_3, MOD26, H_1 // [h₂₆[1], r₂₆[1]] + VESRLG $+52&63, T_3, H_2 // [h₂₆[2], r₂₆[2]] - low 12 bits only + VERIMG $-14&63, T_4, MOD26, H_3 // [h₂₆[1], r₂₆[1]] + VESRLG $40, T_4, H_4 // [h₂₆[4], r₂₆[4]] - low 24 bits only + VERIMG $+12&63, T_4, T_0, H_2 // [h₂₆[2], r₂₆[2]] - complete + VO T_1, H_4, H_4 // [h₂₆[4], r₂₆[4]] - complete + + // replicate r across all 4 vector elements + VREPF $3, H_0, R_0 // [r₂₆[0], r₂₆[0], r₂₆[0], r₂₆[0]] + VREPF $3, H_1, R_1 // [r₂₆[1], r₂₆[1], r₂₆[1], r₂₆[1]] + VREPF $3, H_2, R_2 // [r₂₆[2], r₂₆[2], r₂₆[2], r₂₆[2]] + VREPF $3, H_3, R_3 // [r₂₆[3], r₂₆[3], r₂₆[3], r₂₆[3]] + VREPF $3, H_4, R_4 // [r₂₆[4], r₂₆[4], r₂₆[4], r₂₆[4]] + + // zero out lane 1 of h + VLEIG $1, $0, H_0 // [h₂₆[0], 0] + VLEIG $1, $0, H_1 // [h₂₆[1], 0] + VLEIG $1, $0, H_2 // [h₂₆[2], 0] + VLEIG $1, $0, H_3 // [h₂₆[3], 0] + VLEIG $1, $0, H_4 // [h₂₆[4], 0] + + // calculate 5r (ignore least significant limb) + VREPIF $5, T_0 + VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r₂₆[1], 5r₂₆[1], 5r₂₆[1]] + VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r₂₆[2], 5r₂₆[2], 5r₂₆[2]] + VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r₂₆[3], 5r₂₆[3], 5r₂₆[3]] + VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r₂₆[4], 5r₂₆[4], 5r₂₆[4]] + + // skip r² calculation if we are only calculating one block + CMPBLE R3, $16, skip + + // calculate r² + MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, M_0, M_1, M_2, M_3, M_4) + REDUCE(M_0, M_1, M_2, M_3, M_4) + VGBM $0x0f0f, T_0 + VERIMG $0, M_0, T_0, R_0 // [r₂₆[0], r²₂₆[0], r₂₆[0], r²₂₆[0]] + VERIMG $0, M_1, T_0, R_1 // [r₂₆[1], r²₂₆[1], r₂₆[1], r²₂₆[1]] + VERIMG $0, M_2, T_0, R_2 // [r₂₆[2], r²₂₆[2], r₂₆[2], r²₂₆[2]] + VERIMG $0, M_3, T_0, R_3 // [r₂₆[3], r²₂₆[3], r₂₆[3], r²₂₆[3]] + VERIMG $0, M_4, T_0, R_4 // [r₂₆[4], r²₂₆[4], r₂₆[4], r²₂₆[4]] + + // calculate 5r² (ignore least significant limb) + VREPIF $5, T_0 + VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r²₂₆[1], 5r₂₆[1], 5r²₂₆[1]] + VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r²₂₆[2], 5r₂₆[2], 5r²₂₆[2]] + VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r²₂₆[3], 5r₂₆[3], 5r²₂₆[3]] + VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r²₂₆[4], 5r₂₆[4], 5r²₂₆[4]] + +loop: + CMPBLE R3, $32, b2 // 2 or fewer blocks remaining, need to change key coefficients + + // load next 2 blocks from message + VLM (R2), T_0, T_1 + + // update message slice + SUB $32, R3 + MOVD $32(R2), R2 + + // unpack message blocks into 26-bit big-endian limbs + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // add 2¹²⁸ to each message block value + VLEIB $4, $1, M_4 + VLEIB $12, $1, M_4 + +multiply: + // accumulate the incoming message + VAG H_0, M_0, M_0 + VAG H_3, M_3, M_3 + VAG H_1, M_1, M_1 + VAG H_4, M_4, M_4 + VAG H_2, M_2, M_2 + + // multiply the accumulator by the key coefficient + MULTIPLY(M_0, M_1, M_2, M_3, M_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) + + // carry and partially reduce the partial products + REDUCE(H_0, H_1, H_2, H_3, H_4) + + CMPBNE R3, $0, loop + +finish: + // sum lane 0 and lane 1 and put the result in lane 1 + VZERO T_0 + VSUMQG H_0, T_0, H_0 + VSUMQG H_3, T_0, H_3 + VSUMQG H_1, T_0, H_1 + VSUMQG H_4, T_0, H_4 + VSUMQG H_2, T_0, H_2 + + // reduce again after summation + // TODO(mundaym): there might be a more efficient way to do this + // now that we only have 1 active lane. For example, we could + // simultaneously pack the values as we reduce them. + REDUCE(H_0, H_1, H_2, H_3, H_4) + + // carry h[1] through to h[4] so that only h[4] can exceed 2²⁶ - 1 + // TODO(mundaym): in testing this final carry was unnecessary. + // Needs a proof before it can be removed though. + 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¹³⁰ - 5) + // Pack each lane in h₂₆[0:4] into h₁₂₈[0:1]. + VESLG $26, H_1, H_1 + VESLG $26, H_3, H_3 + VO H_0, H_1, H_0 + VO H_2, H_3, H_2 + VESLG $4, H_2, H_2 + VLEIB $7, $48, H_1 + VSLB H_1, H_2, H_2 + VO H_0, H_2, H_0 + VLEIB $7, $104, H_1 + VSLB H_1, H_4, H_3 + VO H_3, H_0, H_0 + VLEIB $7, $24, H_1 + VSRLB H_1, H_4, H_1 + + // update state + VSTEG $1, H_0, 0(R1) + VSTEG $0, H_0, 8(R1) + VSTEG $1, H_1, 16(R1) + RET + +b2: // 2 or fewer blocks remaining + CMPBLE R3, $16, b1 + + // Load the 2 remaining blocks (17-32 bytes remaining). + MOVD $-17(R3), R0 // index of final byte to load modulo 16 + VL (R2), T_0 // load full 16 byte block + VLL R0, 16(R2), T_1 // load final (possibly partial) block and pad with zeros to 16 bytes + + // The Poly1305 algorithm requires that a 1 bit be appended to + // each message block. If the final block is less than 16 bytes + // long then it is easiest to insert the 1 before the message + // block is split into 26-bit limbs. If, on the other hand, the + // final message block is 16 bytes long then we append the 1 bit + // after expansion as normal. + MOVBZ $1, R0 + MOVD $-16(R3), R3 // index of byte in last block to insert 1 at (could be 16) + CMPBEQ R3, $16, 2(PC) // skip the insertion if the final block is 16 bytes long + VLVGB R3, R0, T_1 // insert 1 into the byte at index R3 + + // Split both blocks into 26-bit limbs in the appropriate lanes. + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // Append a 1 byte to the end of the second to last block. + VLEIB $4, $1, M_4 + + // Append a 1 byte to the end of the last block only if it is a + // full 16 byte block. + CMPBNE R3, $16, 2(PC) + VLEIB $12, $1, M_4 + + // Finally, set up the coefficients for the final multiplication. + // We have previously saved r and 5r in the 32-bit even indexes + // of the R_[0-4] and R5_[1-4] coefficient registers. + // + // We want lane 0 to be multiplied by r² so that can be kept the + // same. We want lane 1 to be multiplied by r so we need to move + // the saved r value into the 32-bit odd index in lane 1 by + // rotating the 64-bit lane by 32. + VGBM $0x00ff, T_0 // [0, 0xffffffffffffffff] - mask lane 1 only + VERIMG $32, R_0, T_0, R_0 // [_, r²₂₆[0], _, r₂₆[0]] + VERIMG $32, R_1, T_0, R_1 // [_, r²₂₆[1], _, r₂₆[1]] + VERIMG $32, R_2, T_0, R_2 // [_, r²₂₆[2], _, r₂₆[2]] + VERIMG $32, R_3, T_0, R_3 // [_, r²₂₆[3], _, r₂₆[3]] + VERIMG $32, R_4, T_0, R_4 // [_, r²₂₆[4], _, r₂₆[4]] + VERIMG $32, R5_1, T_0, R5_1 // [_, 5r²₂₆[1], _, 5r₂₆[1]] + VERIMG $32, R5_2, T_0, R5_2 // [_, 5r²₂₆[2], _, 5r₂₆[2]] + VERIMG $32, R5_3, T_0, R5_3 // [_, 5r²₂₆[3], _, 5r₂₆[3]] + VERIMG $32, R5_4, T_0, R5_4 // [_, 5r²₂₆[4], _, 5r₂₆[4]] + + MOVD $0, R3 + BR multiply + +skip: + CMPBEQ R3, $0, finish + +b1: // 1 block remaining + + // Load the final block (1-16 bytes). This will be placed into + // lane 0. + MOVD $-1(R3), R0 + VLL R0, (R2), T_0 // pad to 16 bytes with zeros + + // The Poly1305 algorithm requires that a 1 bit be appended to + // each message block. If the final block is less than 16 bytes + // long then it is easiest to insert the 1 before the message + // block is split into 26-bit limbs. If, on the other hand, the + // final message block is 16 bytes long then we append the 1 bit + // after expansion as normal. + MOVBZ $1, R0 + CMPBEQ R3, $16, 2(PC) + VLVGB R3, R0, T_0 + + // Set the message block in lane 1 to the value 0 so that it + // can be accumulated without affecting the final result. + VZERO T_1 + + // Split the final message block into 26-bit limbs in lane 0. + // Lane 1 will be contain 0. + EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) + + // Append a 1 byte to the end of the last block only if it is a + // full 16 byte block. + CMPBNE R3, $16, 2(PC) + VLEIB $4, $1, M_4 + + // We have previously saved r and 5r in the 32-bit even indexes + // of the R_[0-4] and R5_[1-4] coefficient registers. + // + // We want lane 0 to be multiplied by r so we need to move the + // saved r value into the 32-bit odd index in lane 0. We want + // lane 1 to be set to the value 1. This makes multiplication + // a no-op. We do this by setting lane 1 in every register to 0 + // and then just setting the 32-bit index 3 in R_0 to 1. + VZERO T_0 + MOVD $0, R0 + MOVD $0x10111213, R12 + VLVGP R12, R0, T_1 // [_, 0x10111213, _, 0x00000000] + VPERM T_0, R_0, T_1, R_0 // [_, r₂₆[0], _, 0] + VPERM T_0, R_1, T_1, R_1 // [_, r₂₆[1], _, 0] + VPERM T_0, R_2, T_1, R_2 // [_, r₂₆[2], _, 0] + VPERM T_0, R_3, T_1, R_3 // [_, r₂₆[3], _, 0] + VPERM T_0, R_4, T_1, R_4 // [_, r₂₆[4], _, 0] + VPERM T_0, R5_1, T_1, R5_1 // [_, 5r₂₆[1], _, 0] + VPERM T_0, R5_2, T_1, R5_2 // [_, 5r₂₆[2], _, 0] + VPERM T_0, R5_3, T_1, R5_3 // [_, 5r₂₆[3], _, 0] + VPERM T_0, R5_4, T_1, R5_4 // [_, 5r₂₆[4], _, 0] + + // Set the value of lane 1 to be 1. + VLEIF $3, $1, R_0 // [_, r₂₆[0], _, 1] + + MOVD $0, R3 + BR multiply diff --git a/poly1305/vectors_test.go b/internal/poly1305/vectors_test.go similarity index 98% rename from poly1305/vectors_test.go rename to internal/poly1305/vectors_test.go index 18d7ff8e85..4788950f19 100644 --- a/poly1305/vectors_test.go +++ b/internal/poly1305/vectors_test.go @@ -2940,4 +2940,61 @@ var testData = [...]test{ "eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" + "f2c5b0dc5de9f5e55a97791507bc6373db26", }, + + // Override initial state to ensure large h (subject to h < 2(2¹³⁰ - 5)) is + // deserialized from the state correctly. + { + key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + state: "0000000000000007fffffffffffffffffffffffffffffff5", // 2(2¹³⁰ - 5) - 1 + in: "", + tag: "f9ffffffffffffffffffffffffffffff", + }, + { + key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + state: "000000000000000700000000000000000000000000000000", // 2¹³⁰ + in: "", + tag: "04000000000000000000000000000000", + }, + { + key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + state: "0000000000000007fffffffffffffffffffffffffffffff5", // 2(2¹³⁰ - 5) - 1 + in: "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff", + tag: "1b000e5e5dfe8f5c4da11dd17b7654e7", + }, + { + key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + state: "000000000000000700000000000000000000000000000001", // 2¹³⁰ + in: "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffff", + tag: "380859a4a5860b0e0967edfd711d37de", + }, } diff --git a/internal/testenv/exec.go b/internal/testenv/exec.go new file mode 100644 index 0000000000..df5d3c20df --- /dev/null +++ b/internal/testenv/exec.go @@ -0,0 +1,120 @@ +// Copyright 2023 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 testenv + +import ( + "context" + "os" + "os/exec" + "reflect" + "strconv" + "testing" + "time" +) + +// CommandContext is like exec.CommandContext, but: +// - skips t if the platform does not support os/exec, +// - sends SIGQUIT (if supported by the platform) instead of SIGKILL +// in its Cancel function +// - if the test has a deadline, adds a Context timeout and WaitDelay +// for an arbitrary grace period before the test's deadline expires, +// - fails the test if the command does not complete before the test's deadline, and +// - sets a Cleanup function that verifies that the test did not leak a subprocess. +func CommandContext(t testing.TB, ctx context.Context, name string, args ...string) *exec.Cmd { + t.Helper() + + var ( + cancelCtx context.CancelFunc + gracePeriod time.Duration // unlimited unless the test has a deadline (to allow for interactive debugging) + ) + + if t, ok := t.(interface { + testing.TB + Deadline() (time.Time, bool) + }); ok { + if td, ok := t.Deadline(); ok { + // Start with a minimum grace period, just long enough to consume the + // output of a reasonable program after it terminates. + gracePeriod = 100 * time.Millisecond + if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { + scale, err := strconv.Atoi(s) + if err != nil { + t.Fatalf("invalid GO_TEST_TIMEOUT_SCALE: %v", err) + } + gracePeriod *= time.Duration(scale) + } + + // If time allows, increase the termination grace period to 5% of the + // test's remaining time. + testTimeout := time.Until(td) + if gp := testTimeout / 20; gp > gracePeriod { + gracePeriod = gp + } + + // When we run commands that execute subprocesses, we want to reserve two + // grace periods to clean up: one for the delay between the first + // termination signal being sent (via the Cancel callback when the Context + // expires) and the process being forcibly terminated (via the WaitDelay + // field), and a second one for the delay between the process being + // terminated and the test logging its output for debugging. + // + // (We want to ensure that the test process itself has enough time to + // log the output before it is also terminated.) + cmdTimeout := testTimeout - 2*gracePeriod + + if cd, ok := ctx.Deadline(); !ok || time.Until(cd) > cmdTimeout { + // Either ctx doesn't have a deadline, or its deadline would expire + // after (or too close before) the test has already timed out. + // Add a shorter timeout so that the test will produce useful output. + ctx, cancelCtx = context.WithTimeout(ctx, cmdTimeout) + } + } + } + + cmd := exec.CommandContext(ctx, name, args...) + // Set the Cancel and WaitDelay fields only if present (go 1.20 and later). + // TODO: When Go 1.19 is no longer supported, remove this use of reflection + // and instead set the fields directly. + if cmdCancel := reflect.ValueOf(cmd).Elem().FieldByName("Cancel"); cmdCancel.IsValid() { + cmdCancel.Set(reflect.ValueOf(func() error { + if cancelCtx != nil && ctx.Err() == context.DeadlineExceeded { + // The command timed out due to running too close to the test's deadline. + // There is no way the test did that intentionally — it's too close to the + // wire! — so mark it as a test failure. That way, if the test expects the + // command to fail for some other reason, it doesn't have to distinguish + // between that reason and a timeout. + t.Errorf("test timed out while running command: %v", cmd) + } else { + // The command is being terminated due to ctx being canceled, but + // apparently not due to an explicit test deadline that we added. + // Log that information in case it is useful for diagnosing a failure, + // but don't actually fail the test because of it. + t.Logf("%v: terminating command: %v", ctx.Err(), cmd) + } + return cmd.Process.Signal(Sigquit) + })) + } + if cmdWaitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); cmdWaitDelay.IsValid() { + cmdWaitDelay.Set(reflect.ValueOf(gracePeriod)) + } + + t.Cleanup(func() { + if cancelCtx != nil { + cancelCtx() + } + if cmd.Process != nil && cmd.ProcessState == nil { + t.Errorf("command was started, but test did not wait for it to complete: %v", cmd) + } + }) + + return cmd +} + +// Command is like exec.Command, but applies the same changes as +// testenv.CommandContext (with a default Context). +func Command(t testing.TB, name string, args ...string) *exec.Cmd { + t.Helper() + return CommandContext(t, context.Background(), name, args...) +} diff --git a/internal/testenv/testenv_notunix.go b/internal/testenv/testenv_notunix.go new file mode 100644 index 0000000000..c8918ce592 --- /dev/null +++ b/internal/testenv/testenv_notunix.go @@ -0,0 +1,15 @@ +// Copyright 2021 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. + +//go:build windows || plan9 || (js && wasm) || wasip1 + +package testenv + +import ( + "os" +) + +// Sigquit is the signal to send to kill a hanging subprocess. +// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. +var Sigquit = os.Kill diff --git a/internal/testenv/testenv_unix.go b/internal/testenv/testenv_unix.go new file mode 100644 index 0000000000..4f51823ec6 --- /dev/null +++ b/internal/testenv/testenv_unix.go @@ -0,0 +1,15 @@ +// Copyright 2021 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. + +//go:build unix + +package testenv + +import ( + "syscall" +) + +// Sigquit is the signal to send to kill a hanging subprocess. +// Send SIGQUIT to get a stack trace. +var Sigquit = syscall.SIGQUIT diff --git a/internal/wycheproof/README.md b/internal/wycheproof/README.md new file mode 100644 index 0000000000..8ae6c6c3d5 --- /dev/null +++ b/internal/wycheproof/README.md @@ -0,0 +1,12 @@ +This package runs a set of the Wycheproof tests provided by +https://github.com/google/wycheproof. + +The JSON test files live in +https://github.com/google/wycheproof/tree/master/testvectors +and are being fetched and cached at a pinned version every time +these tests are run. To change the version of the wycheproof +repository that is being used for testing, update wycheproofModVer. + +The structs for these tests are generated from the +schemas provided in https://github.com/google/wycheproof/tree/master/schemas +using https://github.com/a-h/generate. \ No newline at end of file diff --git a/internal/wycheproof/aead_test.go b/internal/wycheproof/aead_test.go new file mode 100644 index 0000000000..292d85425f --- /dev/null +++ b/internal/wycheproof/aead_test.go @@ -0,0 +1,176 @@ +// Copyright 2020 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 wycheproof + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "fmt" + "testing" + + "golang.org/x/crypto/chacha20poly1305" +) + +func TestAEAD(t *testing.T) { + // AeadTestVector + type AeadTestVector struct { + + // additional authenticated data + Aad string `json:"aad,omitempty"` + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // the ciphertext (without iv and tag) + Ct string `json:"ct,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // the nonce + Iv string `json:"iv,omitempty"` + + // the key + Key string `json:"key,omitempty"` + + // the plaintext + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // the authentication tag + Tag string `json:"tag,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // AeadTestGroup + type AeadTestGroup struct { + + // the IV size in bits + IvSize int `json:"ivSize,omitempty"` + + // the keySize in bits + KeySize int `json:"keySize,omitempty"` + + // the expected size of the tag in bits + TagSize int `json:"tagSize,omitempty"` + Tests []*AeadTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*AeadTestGroup `json:"testGroups,omitempty"` + } + + testSealOpen := func(t *testing.T, aead cipher.AEAD, tv *AeadTestVector, recoverBadNonce func()) { + defer recoverBadNonce() + + iv, tag, ct, msg, aad := decodeHex(tv.Iv), decodeHex(tv.Tag), decodeHex(tv.Ct), decodeHex(tv.Msg), decodeHex(tv.Aad) + + genCT := aead.Seal(nil, iv, msg, aad) + genMsg, err := aead.Open(nil, iv, genCT, aad) + if err != nil { + t.Errorf("failed to decrypt generated ciphertext: %s", err) + } + if !bytes.Equal(genMsg, msg) { + t.Errorf("unexpected roundtripped plaintext: got %x, want %x", genMsg, msg) + } + + ctWithTag := append(ct, tag...) + msg2, err := aead.Open(nil, iv, ctWithTag, aad) + wantPass := shouldPass(tv.Result, tv.Flags, nil) + if !wantPass && err == nil { + t.Error("decryption succeeded when it should've failed") + } else if wantPass { + if err != nil { + t.Fatalf("decryption failed: %s", err) + } + if !bytes.Equal(genCT, ctWithTag) { + t.Errorf("generated ciphertext doesn't match expected: got %x, want %x", genCT, ctWithTag) + } + if !bytes.Equal(msg, msg2) { + t.Errorf("decrypted ciphertext doesn't match expected: got %x, want %x", msg2, msg) + } + } + } + + vectors := map[string]func(*testing.T, []byte) cipher.AEAD{ + "aes_gcm_test.json": func(t *testing.T, key []byte) cipher.AEAD { + aesCipher, err := aes.NewCipher(key) + if err != nil { + t.Fatalf("failed to construct cipher: %s", err) + } + aead, err := cipher.NewGCM(aesCipher) + if err != nil { + t.Fatalf("failed to construct cipher: %s", err) + } + return aead + }, + "chacha20_poly1305_test.json": func(t *testing.T, key []byte) cipher.AEAD { + aead, err := chacha20poly1305.New(key) + if err != nil { + t.Fatalf("failed to construct cipher: %s", err) + } + return aead + }, + "xchacha20_poly1305_test.json": func(t *testing.T, key []byte) cipher.AEAD { + aead, err := chacha20poly1305.NewX(key) + if err != nil { + t.Fatalf("failed to construct cipher: %s", err) + } + return aead + }, + } + for file, cipherInit := range vectors { + var root Root + readTestVector(t, file, &root) + for _, tg := range root.TestGroups { + for _, tv := range tg.Tests { + testName := fmt.Sprintf("%s #%d", file, tv.TcId) + if tv.Comment != "" { + testName += fmt.Sprintf(" %s", tv.Comment) + } + t.Run(testName, func(t *testing.T) { + aead := cipherInit(t, decodeHex(tv.Key)) + testSealOpen(t, aead, tv, func() { + // A bad nonce causes a panic in AEAD.Seal and AEAD.Open, + // so should be recovered. Fail the test if it broke for + // some other reason. + if r := recover(); r != nil { + if tg.IvSize/8 == aead.NonceSize() { + t.Error("unexpected panic") + } + } + }) + }) + } + } + } +} diff --git a/internal/wycheproof/aes_cbc_test.go b/internal/wycheproof/aes_cbc_test.go new file mode 100644 index 0000000000..0a60fc355c --- /dev/null +++ b/internal/wycheproof/aes_cbc_test.go @@ -0,0 +1,127 @@ +// Copyright 2019 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 wycheproof + +import ( + "crypto/aes" + "crypto/cipher" + "encoding/hex" + "fmt" + "testing" +) + +func TestAesCbc(t *testing.T) { + // IndCpaTestVector + type IndCpaTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // the raw ciphertext (without IV) + Ct string `json:"ct,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // the initialization vector + Iv string `json:"iv,omitempty"` + + // the key + Key string `json:"key,omitempty"` + + // the plaintext + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // IndCpaTestGroup + type IndCpaTestGroup struct { + + // the IV size in bits + IvSize int `json:"ivSize,omitempty"` + + // the keySize in bits + KeySize int `json:"keySize,omitempty"` + + // the expected size of the tag in bits + TagSize int `json:"tagSize,omitempty"` + Tests []*IndCpaTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*IndCpaTestGroup `json:"testGroups,omitempty"` + } + + var root Root + readTestVector(t, "aes_cbc_pkcs5_test.json", &root) + for _, tg := range root.TestGroups { + tests: + for _, tv := range tg.Tests { + block, err := aes.NewCipher(decodeHex(tv.Key)) + if err != nil { + t.Fatalf("#%d: %v", tv.TcId, err) + } + mode := cipher.NewCBCDecrypter(block, decodeHex(tv.Iv)) + ct := decodeHex(tv.Ct) + if len(ct)%aes.BlockSize != 0 { + panic(fmt.Sprintf("#%d: ciphertext is not a multiple of the block size", tv.TcId)) + } + mode.CryptBlocks(ct, ct) // decrypt the block in place + + // Skip the tests that are broken due to bad padding. Panic if there are any + // tests left that are invalid for some other reason in the future, to + // evaluate what to do with those tests. + for _, flag := range tv.Flags { + if flag == "BadPadding" { + continue tests + } + } + if !shouldPass(tv.Result, tv.Flags, nil) { + panic(fmt.Sprintf("#%d: found an invalid test that is broken for some reason other than bad padding", tv.TcId)) + } + + // Remove the PKCS#5 padding from the given ciphertext to validate it + padding := ct[len(ct)-1] + paddingNum := int(padding) + for i := paddingNum; i > 0; i-- { + if ct[len(ct)-i] != padding { // panic if the padding is unexpectedly bad + panic(fmt.Sprintf("#%d: bad padding at index=%d of %v", tv.TcId, i, ct)) + } + } + ct = ct[:len(ct)-paddingNum] + + if got, want := hex.EncodeToString(ct), tv.Msg; got != want { + t.Errorf("#%d, type: %s, comment: %q, decoded ciphertext not equal: %s, want %s", tv.TcId, tv.Result, tv.Comment, got, want) + } + } + } +} diff --git a/internal/wycheproof/boring.go b/internal/wycheproof/boring.go new file mode 100644 index 0000000000..aefa3ab30d --- /dev/null +++ b/internal/wycheproof/boring.go @@ -0,0 +1,9 @@ +// Copyright 2022 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. + +//go:build boringcrypto + +package wycheproof + +const boringcryptoEnabled = true diff --git a/internal/wycheproof/dsa_test.go b/internal/wycheproof/dsa_test.go new file mode 100644 index 0000000000..e554708460 --- /dev/null +++ b/internal/wycheproof/dsa_test.go @@ -0,0 +1,123 @@ +// Copyright 2019 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 wycheproof + +import ( + "crypto/dsa" + "testing" + + wdsa "golang.org/x/crypto/internal/wycheproof/internal/dsa" +) + +func TestDsa(t *testing.T) { + // AsnSignatureTestVector + type AsnSignatureTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // The message to sign + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // An ASN encoded signature for msg + Sig string `json:"sig,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // DsaPublicKey + type DsaPublicKey struct { + + // the generator of the multiplicative subgroup + G string `json:"g,omitempty"` + + // the key size in bits + KeySize int `json:"keySize,omitempty"` + + // the modulus p + P string `json:"p,omitempty"` + + // the order of the generator g + Q string `json:"q,omitempty"` + + // the key type + Type string `json:"type,omitempty"` + + // the public key value + Y string `json:"y,omitempty"` + } + + // DsaTestGroup + type DsaTestGroup struct { + + // unenocded DSA public key + Key *DsaPublicKey `json:"key,omitempty"` + + // DER encoded public key + KeyDer string `json:"keyDer,omitempty"` + + // Pem encoded public key + KeyPem string `json:"keyPem,omitempty"` + + // the hash function used for DSA + Sha string `json:"sha,omitempty"` + Tests []*AsnSignatureTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*DsaTestGroup `json:"testGroups,omitempty"` + } + + flagsShouldPass := map[string]bool{ + // An encoded ASN.1 integer missing a leading zero is invalid, but accepted by some implementations. + "NoLeadingZero": false, + } + + var root Root + readTestVector(t, "dsa_test.json", &root) + for _, tg := range root.TestGroups { + pub := decodePublicKey(tg.KeyDer).(*dsa.PublicKey) + h := parseHash(tg.Sha).New() + for _, sig := range tg.Tests { + h.Reset() + h.Write(decodeHex(sig.Msg)) + hashed := h.Sum(nil) + hashed = hashed[:pub.Q.BitLen()/8] // Truncate to the byte-length of the subgroup (Q) + got := wdsa.VerifyASN1(pub, hashed, decodeHex(sig.Sig)) + if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { + t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) + } + } + } +} diff --git a/internal/wycheproof/ecdh_stdlib_test.go b/internal/wycheproof/ecdh_stdlib_test.go new file mode 100644 index 0000000000..24a83e245b --- /dev/null +++ b/internal/wycheproof/ecdh_stdlib_test.go @@ -0,0 +1,140 @@ +// Copyright 2022 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 wycheproof + +import ( + "bytes" + "crypto/ecdh" + "fmt" + "testing" +) + +func TestECDHStdLib(t *testing.T) { + type ECDHTestVector struct { + // A brief description of the test case + Comment string `json:"comment,omitempty"` + // A list of flags + Flags []string `json:"flags,omitempty"` + // the private key + Private string `json:"private,omitempty"` + // Encoded public key + Public string `json:"public,omitempty"` + // Test result + Result string `json:"result,omitempty"` + // The shared secret key + Shared string `json:"shared,omitempty"` + // Identifier of the test case + TcID int `json:"tcId,omitempty"` + } + + type ECDHTestGroup struct { + Curve string `json:"curve,omitempty"` + Tests []*ECDHTestVector `json:"tests,omitempty"` + } + + type Root struct { + TestGroups []*ECDHTestGroup `json:"testGroups,omitempty"` + } + + flagsShouldPass := map[string]bool{ + // We don't support compressed points. + "CompressedPoint": false, + // We don't support decoding custom curves. + "UnnamedCurve": false, + // WrongOrder and UnusedParam are only found with UnnamedCurve. + "WrongOrder": false, + "UnusedParam": false, + + // X25519 specific flags + "Twist": true, + "SmallPublicKey": false, + "LowOrderPublic": false, + "ZeroSharedSecret": false, + "NonCanonicalPublic": true, + } + + // curveToCurve is a map of all elliptic curves supported + // by crypto/elliptic, which can subsequently be parsed and tested. + curveToCurve := map[string]ecdh.Curve{ + "secp256r1": ecdh.P256(), + "secp384r1": ecdh.P384(), + "secp521r1": ecdh.P521(), + "curve25519": ecdh.X25519(), + } + + curveToKeySize := map[string]int{ + "secp256r1": 32, + "secp384r1": 48, + "secp521r1": 66, + "curve25519": 32, + } + + for _, f := range []string{ + "ecdh_secp256r1_ecpoint_test.json", + "ecdh_secp384r1_ecpoint_test.json", + "ecdh_secp521r1_ecpoint_test.json", + "x25519_test.json", + } { + var root Root + readTestVector(t, f, &root) + for _, tg := range root.TestGroups { + if _, ok := curveToCurve[tg.Curve]; !ok { + continue + } + for _, tt := range tg.Tests { + tg, tt := tg, tt + t.Run(fmt.Sprintf("%s/%d", tg.Curve, tt.TcID), func(t *testing.T) { + t.Logf("Type: %v", tt.Result) + t.Logf("Flags: %q", tt.Flags) + t.Log(tt.Comment) + + shouldPass := shouldPass(tt.Result, tt.Flags, flagsShouldPass) + + curve := curveToCurve[tg.Curve] + p := decodeHex(tt.Public) + pub, err := curve.NewPublicKey(p) + if err != nil { + if shouldPass { + t.Errorf("NewPublicKey: %v", err) + } + return + } + + privBytes := decodeHex(tt.Private) + if len(privBytes) != curveToKeySize[tg.Curve] { + t.Skipf("non-standard key size %d", len(privBytes)) + } + + priv, err := curve.NewPrivateKey(privBytes) + if err != nil { + if shouldPass { + t.Errorf("NewPrivateKey: %v", err) + } + return + } + + shared := decodeHex(tt.Shared) + x, err := priv.ECDH(pub) + if err != nil { + if tg.Curve == "curve25519" && !shouldPass { + // ECDH is expected to only return an error when using X25519, + // in all other cases an error is unexpected. + return + } + t.Fatalf("ECDH: %v", err) + } + + if bytes.Equal(shared, x) != shouldPass { + if shouldPass { + t.Errorf("ECDH = %x, want %x", shared, x) + } else { + t.Errorf("ECDH = %x, want anything else", shared) + } + } + }) + } + } + } +} diff --git a/internal/wycheproof/ecdh_test.go b/internal/wycheproof/ecdh_test.go new file mode 100644 index 0000000000..a3918ba62f --- /dev/null +++ b/internal/wycheproof/ecdh_test.go @@ -0,0 +1,163 @@ +// Copyright 2019 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 wycheproof + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/x509" + "encoding/asn1" + "errors" + "fmt" + "testing" + + "golang.org/x/crypto/cryptobyte" + casn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +func TestECDH(t *testing.T) { + type ECDHTestVector struct { + // A brief description of the test case + Comment string `json:"comment,omitempty"` + // A list of flags + Flags []string `json:"flags,omitempty"` + // the private key + Private string `json:"private,omitempty"` + // Encoded public key + Public string `json:"public,omitempty"` + // Test result + Result string `json:"result,omitempty"` + // The shared secret key + Shared string `json:"shared,omitempty"` + // Identifier of the test case + TcID int `json:"tcId,omitempty"` + } + + type ECDHTestGroup struct { + Curve string `json:"curve,omitempty"` + Tests []*ECDHTestVector `json:"tests,omitempty"` + } + + type Root struct { + TestGroups []*ECDHTestGroup `json:"testGroups,omitempty"` + } + + flagsShouldPass := map[string]bool{ + // ParsePKIXPublicKey doesn't support compressed points, but we test + // them against UnmarshalCompressed anyway. + "CompressedPoint": true, + // We don't support decoding custom curves. + "UnnamedCurve": false, + // WrongOrder and UnusedParam are only found with UnnamedCurve. + "WrongOrder": false, + "UnusedParam": false, + } + + // supportedCurves is a map of all elliptic curves supported + // by crypto/elliptic, which can subsequently be parsed and tested. + supportedCurves := map[string]bool{ + "secp224r1": true, + "secp256r1": true, + "secp384r1": true, + "secp521r1": true, + } + + var root Root + readTestVector(t, "ecdh_test.json", &root) + for _, tg := range root.TestGroups { + if !supportedCurves[tg.Curve] { + continue + } + for _, tt := range tg.Tests { + tg, tt := tg, tt + t.Run(fmt.Sprintf("%s/%d", tg.Curve, tt.TcID), func(t *testing.T) { + t.Logf("Type: %v", tt.Result) + t.Logf("Flags: %q", tt.Flags) + t.Log(tt.Comment) + + shouldPass := shouldPass(tt.Result, tt.Flags, flagsShouldPass) + + p := decodeHex(tt.Public) + pp, err := x509.ParsePKIXPublicKey(p) + if err != nil { + pp, err = decodeCompressedPKIX(p) + } + if err != nil { + if shouldPass { + t.Errorf("unexpected parsing error: %s", err) + } + return + } + pub := pp.(*ecdsa.PublicKey) + + priv := decodeHex(tt.Private) + shared := decodeHex(tt.Shared) + + x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, priv) + xBytes := make([]byte, (pub.Curve.Params().BitSize+7)/8) + got := bytes.Equal(shared, x.FillBytes(xBytes)) + + if want := shouldPass; got != want { + t.Errorf("wanted success %v, got %v", want, got) + } + }) + } + } +} + +func decodeCompressedPKIX(der []byte) (interface{}, error) { + s := cryptobyte.String(der) + var s1, s2 cryptobyte.String + var algoOID, namedCurveOID asn1.ObjectIdentifier + var pointDER []byte + if !s.ReadASN1(&s1, casn1.SEQUENCE) || !s.Empty() || + !s1.ReadASN1(&s2, casn1.SEQUENCE) || + !s2.ReadASN1ObjectIdentifier(&algoOID) || + !s2.ReadASN1ObjectIdentifier(&namedCurveOID) || !s2.Empty() || + !s1.ReadASN1BitStringAsBytes(&pointDER) || !s1.Empty() { + return nil, errors.New("failed to parse PKIX structure") + } + + if !algoOID.Equal(oidPublicKeyECDSA) { + return nil, errors.New("wrong algorithm OID") + } + namedCurve := namedCurveFromOID(namedCurveOID) + if namedCurve == nil { + return nil, errors.New("unsupported elliptic curve") + } + x, y := elliptic.UnmarshalCompressed(namedCurve, pointDER) + if x == nil { + return nil, errors.New("failed to unmarshal elliptic curve point") + } + pub := &ecdsa.PublicKey{ + Curve: namedCurve, + X: x, + Y: y, + } + return pub, nil +} + +var ( + oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} + oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} + oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} + oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} + oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} +) + +func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { + switch { + case oid.Equal(oidNamedCurveP224): + return elliptic.P224() + case oid.Equal(oidNamedCurveP256): + return elliptic.P256() + case oid.Equal(oidNamedCurveP384): + return elliptic.P384() + case oid.Equal(oidNamedCurveP521): + return elliptic.P521() + } + return nil +} diff --git a/internal/wycheproof/ecdsa_test.go b/internal/wycheproof/ecdsa_test.go new file mode 100644 index 0000000000..80125ada75 --- /dev/null +++ b/internal/wycheproof/ecdsa_test.go @@ -0,0 +1,105 @@ +// Copyright 2019 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 wycheproof + +import ( + "crypto/ecdsa" + "math/big" + "testing" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) + +func TestECDSA(t *testing.T) { + type ASNSignatureTestVector struct { + // A brief description of the test case + Comment string `json:"comment"` + // A list of flags + Flags []string `json:"flags"` + // The message to sign + Msg string `json:"msg"` + // Test result + Result string `json:"result"` + // An ASN.1 encoded signature for msg + Sig string `json:"sig"` + // Identifier of the test case + TcID int `json:"tcId"` + } + + type ECPublicKey struct { + // The EC group used by this public key + Curve interface{} `json:"curve"` + } + + type ECDSATestGroup struct { + // Unencoded EC public key + Key *ECPublicKey `json:"key"` + // DER encoded public key + KeyDER string `json:"keyDer"` + // the hash function used for ECDSA + SHA string `json:"sha"` + Tests []*ASNSignatureTestVector `json:"tests"` + } + + type Root struct { + TestGroups []*ECDSATestGroup `json:"testGroups"` + } + + flagsShouldPass := map[string]bool{ + // An encoded ASN.1 integer missing a leading zero is invalid, but + // accepted by some implementations. + "MissingZero": false, + // A signature using a weaker hash than the EC params is not a security + // risk, as long as the hash is secure. + // https://www.imperialviolet.org/2014/05/25/strengthmatching.html + "WeakHash": true, + } + + // supportedCurves is a map of all elliptic curves supported + // by crypto/elliptic, which can subsequently be parsed and tested. + supportedCurves := map[string]bool{ + "secp224r1": true, + "secp256r1": true, + "secp384r1": true, + "secp521r1": true, + } + + var root Root + readTestVector(t, "ecdsa_test.json", &root) + for _, tg := range root.TestGroups { + curve := tg.Key.Curve.(string) + if !supportedCurves[curve] { + continue + } + pub := decodePublicKey(tg.KeyDER).(*ecdsa.PublicKey) + h := parseHash(tg.SHA).New() + for _, sig := range tg.Tests { + h.Reset() + h.Write(decodeHex(sig.Msg)) + hashed := h.Sum(nil) + sigBytes := decodeHex(sig.Sig) + got := ecdsa.VerifyASN1(pub, hashed, sigBytes) + if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { + t.Errorf("tcid: %d, type: %s, comment: %q, VerifyASN1 wanted success: %t", sig.TcID, sig.Result, sig.Comment, want) + } + + var r, s big.Int + var inner cryptobyte.String + input := cryptobyte.String(sigBytes) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Integer(&r) || + !inner.ReadASN1Integer(&s) || + !inner.Empty() { + continue + } + got = ecdsa.Verify(pub, hashed, &r, &s) + if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { + t.Errorf("tcid: %d, type: %s, comment: %q, Verify wanted success: %t", sig.TcID, sig.Result, sig.Comment, want) + } + } + } +} diff --git a/internal/wycheproof/eddsa_test.go b/internal/wycheproof/eddsa_test.go new file mode 100644 index 0000000000..a74f343f02 --- /dev/null +++ b/internal/wycheproof/eddsa_test.go @@ -0,0 +1,97 @@ +// Copyright 2019 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 wycheproof + +import ( + "crypto/ed25519" + "testing" +) + +func TestEddsa(t *testing.T) { + // Jwk the private key in webcrypto format + type Jwk struct { + } + + // Key unencoded key pair + type Key struct { + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // SignatureTestVector + type SignatureTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // The message to sign + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // A signature for msg + Sig string `json:"sig,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // EddsaTestGroup + type EddsaTestGroup struct { + + // the private key in webcrypto format + Jwk *Jwk `json:"jwk,omitempty"` + + // unencoded key pair + Key *Key `json:"key,omitempty"` + + // Asn encoded public key + KeyDer string `json:"keyDer,omitempty"` + + // Pem encoded public key + KeyPem string `json:"keyPem,omitempty"` + Tests []*SignatureTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*EddsaTestGroup `json:"testGroups,omitempty"` + } + + var root Root + readTestVector(t, "eddsa_test.json", &root) + for _, tg := range root.TestGroups { + pub := decodePublicKey(tg.KeyDer).(ed25519.PublicKey) + for _, sig := range tg.Tests { + got := ed25519.Verify(pub, decodeHex(sig.Msg), decodeHex(sig.Sig)) + if want := shouldPass(sig.Result, sig.Flags, nil); got != want { + t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) + } + } + } +} diff --git a/internal/wycheproof/hkdf_test.go b/internal/wycheproof/hkdf_test.go new file mode 100644 index 0000000000..6b72e2c870 --- /dev/null +++ b/internal/wycheproof/hkdf_test.go @@ -0,0 +1,111 @@ +// Copyright 2019 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 wycheproof + +import ( + "bytes" + "io" + "testing" + + "golang.org/x/crypto/hkdf" +) + +func TestHkdf(t *testing.T) { + + // HkdfTestVector + type HkdfTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // the key (input key material) + Ikm string `json:"ikm,omitempty"` + + // additional information used in the key derivation + Info string `json:"info,omitempty"` + + // the generated bytes (output key material) + Okm string `json:"okm,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // the salt for the key derivation + Salt string `json:"salt,omitempty"` + + // the size of the output in bytes + Size int `json:"size,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // HkdfTestGroup + type HkdfTestGroup struct { + + // the size of the ikm in bits + KeySize int `json:"keySize,omitempty"` + Tests []*HkdfTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*HkdfTestGroup `json:"testGroups,omitempty"` + } + + fileHashAlgorithms := map[string]string{ + "hkdf_sha1_test.json": "SHA-1", + "hkdf_sha256_test.json": "SHA-256", + "hkdf_sha384_test.json": "SHA-384", + "hkdf_sha512_test.json": "SHA-512", + } + + for f := range fileHashAlgorithms { + var root Root + readTestVector(t, f, &root) + for _, tg := range root.TestGroups { + for _, tv := range tg.Tests { + h := parseHash(fileHashAlgorithms[f]).New + hkdf := hkdf.New(h, decodeHex(tv.Ikm), decodeHex(tv.Salt), decodeHex(tv.Info)) + key := make([]byte, tv.Size) + wantPass := shouldPass(tv.Result, tv.Flags, nil) + _, err := io.ReadFull(hkdf, key) + if (err == nil) != wantPass { + t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t, got: %v", tv.TcId, tv.Result, tv.Comment, wantPass, err) + } + if err != nil { + continue // don't validate output text if reading failed + } + if got, want := key, decodeHex(tv.Okm); !bytes.Equal(got, want) { + t.Errorf("tcid: %d, type: %s, comment: %q, output bytes don't match", tv.TcId, tv.Result, tv.Comment) + } + } + } + } +} diff --git a/internal/wycheproof/hmac_test.go b/internal/wycheproof/hmac_test.go new file mode 100644 index 0000000000..bcc56f28fc --- /dev/null +++ b/internal/wycheproof/hmac_test.go @@ -0,0 +1,105 @@ +// Copyright 2020 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 wycheproof + +import ( + "crypto/hmac" + "testing" +) + +func TestHMAC(t *testing.T) { + // MacTestVector + type MacTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // the key + Key string `json:"key,omitempty"` + + // the plaintext + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // the authentication tag + Tag string `json:"tag,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // MacTestGroup + type MacTestGroup struct { + + // the keySize in bits + KeySize int `json:"keySize,omitempty"` + + // the expected size of the tag in bits + TagSize int `json:"tagSize,omitempty"` + Tests []*MacTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*MacTestGroup `json:"testGroups,omitempty"` + } + + fileHashAlgs := map[string]string{ + "hmac_sha1_test.json": "SHA-1", + "hmac_sha224_test.json": "SHA-224", + "hmac_sha256_test.json": "SHA-256", + "hmac_sha384_test.json": "SHA-384", + "hmac_sha512_test.json": "SHA-512", + } + + for f := range fileHashAlgs { + var root Root + readTestVector(t, f, &root) + for _, tg := range root.TestGroups { + h := parseHash(fileHashAlgs[f]) + // Skip test vectors where the tag length does not equal the + // hash length, since crypto/hmac does not support generating + // these truncated tags. + if tg.TagSize/8 != h.Size() { + continue + } + for _, tv := range tg.Tests { + hm := hmac.New(h.New, decodeHex(tv.Key)) + hm.Write(decodeHex(tv.Msg)) + tag := hm.Sum(nil) + got := hmac.Equal(decodeHex(tv.Tag), tag) + if want := shouldPass(tv.Result, tv.Flags, nil); want != got { + t.Errorf("%s, tcid: %d, type: %s, comment: %q, unexpected result", f, tv.TcId, tv.Result, tv.Comment) + } + } + } + } +} diff --git a/internal/wycheproof/internal/dsa/dsa.go b/internal/wycheproof/internal/dsa/dsa.go new file mode 100644 index 0000000000..3101dfc1c2 --- /dev/null +++ b/internal/wycheproof/internal/dsa/dsa.go @@ -0,0 +1,33 @@ +// Copyright 2019 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 dsa provides an internal version of dsa.Verify +// that is used for the Wycheproof tests. +package dsa + +import ( + "crypto/dsa" + "math/big" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) + +// VerifyASN1 verifies the ASN1 encoded signature, sig, of hash using the +// public key, pub. Its return value records whether the signature is valid. +func VerifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool { + var ( + r, s = &big.Int{}, &big.Int{} + inner cryptobyte.String + ) + input := cryptobyte.String(sig) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Integer(r) || + !inner.ReadASN1Integer(s) || + !inner.Empty() { + return false + } + return dsa.Verify(pub, hash, r, s) +} diff --git a/internal/wycheproof/notboring.go b/internal/wycheproof/notboring.go new file mode 100644 index 0000000000..746af130f1 --- /dev/null +++ b/internal/wycheproof/notboring.go @@ -0,0 +1,9 @@ +// Copyright 2022 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. + +//go:build !boringcrypto + +package wycheproof + +const boringcryptoEnabled = false diff --git a/internal/wycheproof/rsa_oaep_decrypt_test.go b/internal/wycheproof/rsa_oaep_decrypt_test.go new file mode 100644 index 0000000000..19cc4fdcb7 --- /dev/null +++ b/internal/wycheproof/rsa_oaep_decrypt_test.go @@ -0,0 +1,149 @@ +// Copyright 2020 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 wycheproof + +import ( + "bytes" + "crypto/rsa" + "crypto/x509" + "fmt" + "testing" +) + +func TestRSAOAEPDecrypt(t *testing.T) { + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // RsaesOaepTestVector + type RsaesOaepTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // An encryption of msg + Ct string `json:"ct,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // The label used for the encryption + Label string `json:"label,omitempty"` + + // The encrypted message + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // RsaesOaepTestGroup + type RsaesOaepTestGroup struct { + + // The private exponent + D string `json:"d,omitempty"` + + // The public exponent + E string `json:"e,omitempty"` + + // the message generating function (e.g. MGF1) + Mgf string `json:"mgf,omitempty"` + + // The hash function used for the message generating function. + MgfSha string `json:"mgfSha,omitempty"` + + // The modulus of the key + N string `json:"n,omitempty"` + + // Pem encoded private key + PrivateKeyPem string `json:"privateKeyPem,omitempty"` + + // Pkcs 8 encoded private key. + PrivateKeyPkcs8 string `json:"privateKeyPkcs8,omitempty"` + + // The hash function for hashing the label. + Sha string `json:"sha,omitempty"` + Tests []*RsaesOaepTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*RsaesOaepTestGroup `json:"testGroups,omitempty"` + } + + // rsa.DecryptOAEP doesn't support using a different hash for the + // MGF and the label, so skip all of the test vectors that use + // these unbalanced constructions. rsa_oaep_misc_test.json contains + // both balanced and unbalanced constructions so in that case + // we just filter out any test groups where MgfSha != Sha + files := []string{ + "rsa_oaep_2048_sha1_mgf1sha1_test.json", + "rsa_oaep_2048_sha224_mgf1sha224_test.json", + "rsa_oaep_2048_sha256_mgf1sha256_test.json", + "rsa_oaep_2048_sha384_mgf1sha384_test.json", + "rsa_oaep_2048_sha512_mgf1sha512_test.json", + "rsa_oaep_3072_sha256_mgf1sha256_test.json", + "rsa_oaep_3072_sha512_mgf1sha512_test.json", + "rsa_oaep_4096_sha256_mgf1sha256_test.json", + "rsa_oaep_4096_sha512_mgf1sha512_test.json", + "rsa_oaep_misc_test.json", + } + + flagsShouldPass := map[string]bool{ + // rsa.DecryptOAEP happily supports small key sizes + "SmallModulus": true, + } + + for _, f := range files { + var root Root + readTestVector(t, f, &root) + for _, tg := range root.TestGroups { + if tg.MgfSha != tg.Sha { + continue + } + priv, err := x509.ParsePKCS8PrivateKey(decodeHex(tg.PrivateKeyPkcs8)) + if err != nil { + t.Fatalf("%s failed to parse PKCS #8 private key: %s", f, err) + } + hash := parseHash(tg.Sha) + for _, tv := range tg.Tests { + t.Run(fmt.Sprintf("%s #%d", f, tv.TcId), func(t *testing.T) { + wantPass := shouldPass(tv.Result, tv.Flags, flagsShouldPass) + plaintext, err := rsa.DecryptOAEP(hash.New(), nil, priv.(*rsa.PrivateKey), decodeHex(tv.Ct), decodeHex(tv.Label)) + if wantPass { + if err != nil { + t.Fatalf("comment: %s, expected success: %s", tv.Comment, err) + } + if !bytes.Equal(plaintext, decodeHex(tv.Msg)) { + t.Errorf("comment: %s, unexpected plaintext: got %x, want %s", tv.Comment, plaintext, tv.Msg) + } + } else if err == nil { + t.Errorf("comment: %s, expected failure", tv.Comment) + } + }) + } + } + } +} diff --git a/internal/wycheproof/rsa_pss_test.go b/internal/wycheproof/rsa_pss_test.go new file mode 100644 index 0000000000..f2f9b6ebae --- /dev/null +++ b/internal/wycheproof/rsa_pss_test.go @@ -0,0 +1,169 @@ +// Copyright 2019 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 wycheproof + +import ( + "crypto/rsa" + "testing" +) + +func TestRsaPss(t *testing.T) { + // KeyJwk Public key in JWK format + type KeyJwk struct { + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // SignatureTestVector + type SignatureTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // The message to sign + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // A signature for msg + Sig string `json:"sig,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // RsassaPkcs1TestGroup + type RsassaPkcs1TestGroup struct { + + // The private exponent + D string `json:"d,omitempty"` + + // The public exponent + E string `json:"e,omitempty"` + + // ASN encoding of the sequence [n, e] + KeyAsn string `json:"keyAsn,omitempty"` + + // ASN encoding of the public key + KeyDer string `json:"keyDer,omitempty"` + + // Public key in JWK format + KeyJwk *KeyJwk `json:"keyJwk,omitempty"` + + // Pem encoded public key + KeyPem string `json:"keyPem,omitempty"` + + // the size of the modulus in bits + KeySize int `json:"keySize,omitempty"` + + // The modulus of the key + N string `json:"n,omitempty"` + + // The salt length + SLen int `json:"sLen,omitempty"` + + // the hash function used for the message + Sha string `json:"sha,omitempty"` + Tests []*SignatureTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"` + } + + flagsShouldPass := map[string]bool{ + // A signature using a weaker hash than the EC params is not a security risk, as long as the hash is secure. + // https://www.imperialviolet.org/2014/05/25/strengthmatching.html + "WeakHash": true, + } + + // filesOverrideToPassZeroSLen is a map of all test files + // and which TcIds that should be overridden to pass if the + // rsa.PSSOptions.SaltLength is zero. + // These tests expect a failure with a PSSOptions.SaltLength: 0 + // and a signature that uses a different salt length. However, + // a salt length of 0 is defined as rsa.PSSSaltLengthAuto which + // works deterministically to auto-detect the length when + // verifying, so these tests actually pass as they should. + filesOverrideToPassZeroSLen := map[string][]int{ + "rsa_pss_2048_sha1_mgf1_20_test.json": []int{46, 47}, + "rsa_pss_2048_sha256_mgf1_0_test.json": []int{67, 68}, + "rsa_pss_2048_sha256_mgf1_32_test.json": []int{67, 68}, + "rsa_pss_3072_sha256_mgf1_32_test.json": []int{67, 68}, + "rsa_pss_4096_sha256_mgf1_32_test.json": []int{67, 68}, + "rsa_pss_4096_sha512_mgf1_32_test.json": []int{136, 137}, + // "rsa_pss_misc_test.json": nil, // TODO: This ones seems to be broken right now, but can enable later on. + } + + if !boringcryptoEnabled { + // boringcrypto doesn't support the truncated SHA-512 hashes, so only + // test them if boringcrypto isn't enabled. + filesOverrideToPassZeroSLen["rsa_pss_2048_sha512_256_mgf1_28_test.json"] = []int{13, 14, 15} + filesOverrideToPassZeroSLen["rsa_pss_2048_sha512_256_mgf1_32_test.json"] = []int{13, 14} + } + + for f := range filesOverrideToPassZeroSLen { + var root Root + readTestVector(t, f, &root) + for _, tg := range root.TestGroups { + pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey) + ch := parseHash(tg.Sha) + h := ch.New() + opts := &rsa.PSSOptions{ + Hash: ch, + SaltLength: rsa.PSSSaltLengthAuto, + } + // Run all the tests twice: the first time with the salt length + // as PSSSaltLengthAuto, and the second time with the salt length + // explicitly set to tg.SLen. + for i := 0; i < 2; i++ { + for _, sig := range tg.Tests { + h.Reset() + h.Write(decodeHex(sig.Msg)) + hashed := h.Sum(nil) + err := rsa.VerifyPSS(pub, ch, hashed, decodeHex(sig.Sig), opts) + want := shouldPass(sig.Result, sig.Flags, flagsShouldPass) + if opts.SaltLength == 0 { + for _, id := range filesOverrideToPassZeroSLen[f] { + if sig.TcId == id { + want = true + break + } + } + } + if (err == nil) != want { + t.Errorf("file: %v, tcid: %d, type: %s, opts.SaltLength: %v, comment: %q, wanted success: %t", f, sig.TcId, sig.Result, opts.SaltLength, sig.Comment, want) + } + } + // Update opts.SaltLength for the second run of the tests. + opts.SaltLength = tg.SLen + } + } + } +} diff --git a/internal/wycheproof/rsa_signature_test.go b/internal/wycheproof/rsa_signature_test.go new file mode 100644 index 0000000000..3c31c22552 --- /dev/null +++ b/internal/wycheproof/rsa_signature_test.go @@ -0,0 +1,123 @@ +// Copyright 2019 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 wycheproof + +import ( + "crypto/rsa" + "testing" +) + +func TestRsa(t *testing.T) { + // KeyJwk Public key in JWK format + type KeyJwk struct { + } + + // Notes a description of the labels used in the test vectors + type Notes struct { + } + + // SignatureTestVector + type SignatureTestVector struct { + + // A brief description of the test case + Comment string `json:"comment,omitempty"` + + // A list of flags + Flags []string `json:"flags,omitempty"` + + // The message to sign + Msg string `json:"msg,omitempty"` + + // Test result + Result string `json:"result,omitempty"` + + // A signature for msg + Sig string `json:"sig,omitempty"` + + // Identifier of the test case + TcId int `json:"tcId,omitempty"` + } + + // RsassaPkcs1TestGroup + type RsassaPkcs1TestGroup struct { + + // The private exponent + D string `json:"d,omitempty"` + + // The public exponent + E string `json:"e,omitempty"` + + // ASN encoding of the sequence [n, e] + KeyAsn string `json:"keyAsn,omitempty"` + + // ASN encoding of the public key + KeyDer string `json:"keyDer,omitempty"` + + // Public key in JWK format + KeyJwk *KeyJwk `json:"keyJwk,omitempty"` + + // Pem encoded public key + KeyPem string `json:"keyPem,omitempty"` + + // the size of the modulus in bits + KeySize int `json:"keySize,omitempty"` + + // The modulus of the key + N string `json:"n,omitempty"` + + // the hash function used for the message + Sha string `json:"sha,omitempty"` + Tests []*SignatureTestVector `json:"tests,omitempty"` + Type interface{} `json:"type,omitempty"` + } + + // Root + type Root struct { + + // the primitive tested in the test file + Algorithm string `json:"algorithm,omitempty"` + + // the version of the test vectors. + GeneratorVersion string `json:"generatorVersion,omitempty"` + + // additional documentation + Header []string `json:"header,omitempty"` + + // a description of the labels used in the test vectors + Notes *Notes `json:"notes,omitempty"` + + // the number of test vectors in this test + NumberOfTests int `json:"numberOfTests,omitempty"` + Schema interface{} `json:"schema,omitempty"` + TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"` + } + + flagsShouldPass := map[string]bool{ + // Omitting the parameter field in an ASN encoded integer is a legacy behavior. + "MissingNull": false, + // Keys with a modulus less than 2048 bits are supported by crypto/rsa. + "SmallModulus": true, + // Small public keys are supported by crypto/rsa. + "SmallPublicKey": true, + } + + var root Root + readTestVector(t, "rsa_signature_test.json", &root) + for _, tg := range root.TestGroups { + pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey) + ch := parseHash(tg.Sha) + h := ch.New() + for _, sig := range tg.Tests { + h.Reset() + h.Write(decodeHex(sig.Msg)) + hashed := h.Sum(nil) + err := rsa.VerifyPKCS1v15(pub, ch, hashed, decodeHex(sig.Sig)) + want := shouldPass(sig.Result, sig.Flags, flagsShouldPass) + if (err == nil) != want { + t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) + } + } + } +} diff --git a/internal/wycheproof/wycheproof_test.go b/internal/wycheproof/wycheproof_test.go new file mode 100644 index 0000000000..bbaae3b338 --- /dev/null +++ b/internal/wycheproof/wycheproof_test.go @@ -0,0 +1,141 @@ +// Copyright 2019 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 wycheproof runs a set of the Wycheproof tests +// provided by https://github.com/google/wycheproof. +package wycheproof + +import ( + "crypto" + "crypto/x509" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "testing" + + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" +) + +const wycheproofModVer = "v0.0.0-20191219022705-2196000605e4" + +var wycheproofTestVectorsDir string + +func TestMain(m *testing.M) { + flag.Parse() + if flag.Lookup("test.short").Value.(flag.Getter).Get().(bool) { + log.Println("skipping test that downloads testdata via 'go mod download' in short mode") + os.Exit(0) + } + if _, err := exec.LookPath("go"); err != nil { + log.Printf("skipping test because 'go' command is unavailable: %v", err) + os.Exit(0) + } + if os.Getenv("GO_BUILDER_FLAKY_NET") != "" { + log.Printf("skipping test because GO_BUILDER_FLAKY_NET is set") + os.Exit(0) + } + + // Download the JSON test files from github.com/google/wycheproof + // using `go mod download -json` so the cached source of the testdata + // can be used in the following tests. + path := "github.com/google/wycheproof@" + wycheproofModVer + cmd := exec.Command("go", "mod", "download", "-json", path) + output, err := cmd.Output() + if err != nil { + log.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output) + } + var dm struct { + Dir string // absolute path to cached source root directory + } + if err := json.Unmarshal(output, &dm); err != nil { + log.Fatal(err) + } + // Now that the module has been downloaded, use the absolute path of the + // cached source as the root directory for all tests going forward. + wycheproofTestVectorsDir = filepath.Join(dm.Dir, "testvectors") + os.Exit(m.Run()) +} + +func readTestVector(t *testing.T, f string, dest interface{}) { + b, err := os.ReadFile(filepath.Join(wycheproofTestVectorsDir, f)) + if err != nil { + t.Fatalf("failed to read json file: %v", err) + } + if err := json.Unmarshal(b, &dest); err != nil { + t.Fatalf("failed to unmarshal json file: %v", err) + } +} + +func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func decodePublicKey(der string) interface{} { + d := decodeHex(der) + pub, err := x509.ParsePKIXPublicKey(d) + if err != nil { + panic(fmt.Sprintf("failed to parse DER encoded public key: %v", err)) + } + return pub +} + +func parseHash(h string) crypto.Hash { + switch h { + case "SHA-1": + return crypto.SHA1 + case "SHA-256": + return crypto.SHA256 + case "SHA-224": + return crypto.SHA224 + case "SHA-384": + return crypto.SHA384 + case "SHA-512": + return crypto.SHA512 + case "SHA-512/224": + return crypto.SHA512_224 + case "SHA-512/256": + return crypto.SHA512_256 + default: + panic(fmt.Sprintf("could not identify SHA hash algorithm: %q", h)) + } +} + +// shouldPass returns whether or not the test should pass. +// flagsShouldPass is a map associated with whether or not +// a flag for an "acceptable" result should pass. +// Every possible flag value that's associated with an +// "acceptable" result should be explicitly specified, +// otherwise the test will panic. +func shouldPass(result string, flags []string, flagsShouldPass map[string]bool) bool { + switch result { + case "valid": + return true + case "invalid": + return false + case "acceptable": + for _, flag := range flags { + pass, ok := flagsShouldPass[flag] + if !ok { + panic(fmt.Sprintf("unspecified flag: %q", flag)) + } + if !pass { + return false + } + } + return true // There are no flags, or all are meant to pass. + default: + panic(fmt.Sprintf("unexpected result: %v", result)) + } +} diff --git a/md4/md4.go b/md4/md4.go index 59d3480693..7d9281e025 100644 --- a/md4/md4.go +++ b/md4/md4.go @@ -4,10 +4,10 @@ // Package md4 implements the MD4 hash algorithm as defined in RFC 1320. // -// Deprecated: MD4 is cryptographically broken and should should only be used +// Deprecated: MD4 is cryptographically broken and should only be used // where compatibility with legacy systems, not security, is the goal. Instead, // use a secure hash like SHA-256 (from crypto/sha256). -package md4 // import "golang.org/x/crypto/md4" +package md4 import ( "crypto" diff --git a/md4/md4block.go b/md4/md4block.go index 3fed475f3f..5ea1ba966e 100644 --- a/md4/md4block.go +++ b/md4/md4block.go @@ -8,9 +8,11 @@ package md4 -var shift1 = []uint{3, 7, 11, 19} -var shift2 = []uint{3, 5, 9, 13} -var shift3 = []uint{3, 9, 11, 15} +import "math/bits" + +var shift1 = []int{3, 7, 11, 19} +var shift2 = []int{3, 5, 9, 13} +var shift3 = []int{3, 9, 11, 15} var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15} var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} @@ -48,7 +50,7 @@ func _Block(dig *digest, p []byte) int { s := shift1[i%4] f := ((c ^ d) & b) ^ d a += f + X[x] - a = a<>(32-s) + a = bits.RotateLeft32(a, s) a, b, c, d = d, a, b, c } @@ -58,7 +60,7 @@ func _Block(dig *digest, p []byte) int { s := shift2[i%4] g := (b & c) | (b & d) | (c & d) a += g + X[x] + 0x5a827999 - a = a<>(32-s) + a = bits.RotateLeft32(a, s) a, b, c, d = d, a, b, c } @@ -68,7 +70,7 @@ func _Block(dig *digest, p []byte) int { s := shift3[i%4] h := b ^ c ^ d a += h + X[x] + 0x6ed9eba1 - a = a<>(32-s) + a = bits.RotateLeft32(a, s) a, b, c, d = d, a, b, c } diff --git a/nacl/auth/auth.go b/nacl/auth/auth.go index ec1d6ebe4a..136093841f 100644 --- a/nacl/auth/auth.go +++ b/nacl/auth/auth.go @@ -2,25 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -/* -Package auth authenticates a message using a secret key. - -The Sum function, viewed as a function of the message for a uniform random -key, is designed to meet the standard notion of unforgeability. This means -that an attacker cannot find authenticators for any messages not authenticated -by the sender, even if the attacker has adaptively influenced the messages -authenticated by the sender. For a formal definition see, e.g., Section 2.4 -of Bellare, Kilian, and Rogaway, "The security of the cipher block chaining -message authentication code," Journal of Computer and System Sciences 61 (2000), -362–399; http://www-cse.ucsd.edu/~mihir/papers/cbc.html. - -auth does not make any promises regarding "strong" unforgeability; perhaps -one valid authenticator can be converted into another valid authenticator for -the same message. NaCl also does not make any promises regarding "truncated -unforgeability." - -This package is interoperable with NaCl: https://nacl.cr.yp.to/auth.html. -*/ +// Package auth authenticates a message using a secret key. +// +// This package is interoperable with [NaCl]. +// +// The auth package is essentially a wrapper for HMAC-SHA-512 (implemented by +// crypto/hmac and crypto/sha512), truncated to 32 bytes. It is [frozen] and is +// not accepting new features. +// +// [NaCl]: https://nacl.cr.yp.to/auth.html +// [frozen]: https://go.dev/wiki/Frozen package auth import ( @@ -40,7 +31,7 @@ const ( func Sum(m []byte, key *[KeySize]byte) *[Size]byte { mac := hmac.New(sha512.New, key[:]) mac.Write(m) - out := new([KeySize]byte) + out := new([Size]byte) copy(out[:], mac.Sum(nil)[:Size]) return out } diff --git a/nacl/box/box.go b/nacl/box/box.go index 31b697be44..357bdc773c 100644 --- a/nacl/box/box.go +++ b/nacl/box/box.go @@ -31,19 +31,30 @@ Thus large amounts of data should be chunked so that each message is small. chunk size. This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. +Anonymous sealing/opening is an extension of NaCl defined by and interoperable +with libsodium: +https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes. */ -package box // import "golang.org/x/crypto/nacl/box" +package box import ( + cryptorand "crypto/rand" "io" + "golang.org/x/crypto/blake2b" "golang.org/x/crypto/curve25519" "golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/salsa20/salsa" ) -// Overhead is the number of bytes of overhead when boxing a message. -const Overhead = secretbox.Overhead +const ( + // Overhead is the number of bytes of overhead when boxing a message. + Overhead = secretbox.Overhead + + // AnonymousOverhead is the number of bytes of overhead when using anonymous + // sealed boxes. + AnonymousOverhead = Overhead + 32 +) // GenerateKey generates a new public/private key pair suitable for use with // Seal and Open. @@ -101,3 +112,71 @@ func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { return secretbox.Open(out, box, nonce, sharedKey) } + +// SealAnonymous appends an encrypted and authenticated copy of message to out, +// which will be AnonymousOverhead bytes longer than the original and must not +// overlap it. This differs from Seal in that the sender is not required to +// provide a private key. +func SealAnonymous(out, message []byte, recipient *[32]byte, rand io.Reader) ([]byte, error) { + if rand == nil { + rand = cryptorand.Reader + } + ephemeralPub, ephemeralPriv, err := GenerateKey(rand) + if err != nil { + return nil, err + } + + var nonce [24]byte + if err := sealNonce(ephemeralPub, recipient, &nonce); err != nil { + return nil, err + } + + if total := len(out) + AnonymousOverhead + len(message); cap(out) < total { + original := out + out = make([]byte, 0, total) + out = append(out, original...) + } + out = append(out, ephemeralPub[:]...) + + return Seal(out, message, &nonce, recipient, ephemeralPriv), nil +} + +// OpenAnonymous authenticates and decrypts a box produced by SealAnonymous and +// appends the message to out, which must not overlap box. The output will be +// AnonymousOverhead bytes smaller than box. +func OpenAnonymous(out, box []byte, publicKey, privateKey *[32]byte) (message []byte, ok bool) { + if len(box) < AnonymousOverhead { + return nil, false + } + + var ephemeralPub [32]byte + copy(ephemeralPub[:], box[:32]) + + var nonce [24]byte + if err := sealNonce(&ephemeralPub, publicKey, &nonce); err != nil { + return nil, false + } + + return Open(out, box[32:], &nonce, &ephemeralPub, privateKey) +} + +// sealNonce generates a 24 byte nonce that is a blake2b digest of the +// ephemeral public key and the receiver's public key. +func sealNonce(ephemeralPub, peersPublicKey *[32]byte, nonce *[24]byte) error { + h, err := blake2b.New(24, nil) + if err != nil { + return err + } + + if _, err = h.Write(ephemeralPub[:]); err != nil { + return err + } + + if _, err = h.Write(peersPublicKey[:]); err != nil { + return err + } + + h.Sum(nonce[:0]) + + return nil +} diff --git a/nacl/box/box_test.go b/nacl/box/box_test.go index 481ade28ae..404925743c 100644 --- a/nacl/box/box_test.go +++ b/nacl/box/box_test.go @@ -76,3 +76,106 @@ func TestBox(t *testing.T) { t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) } } + +func TestSealOpenAnonymous(t *testing.T) { + publicKey, privateKey, _ := GenerateKey(rand.Reader) + message := []byte("test message") + + box, err := SealAnonymous(nil, message, publicKey, nil) + if err != nil { + t.Fatalf("Unexpected error sealing %v", err) + } + opened, ok := OpenAnonymous(nil, box, publicKey, privateKey) + if !ok { + t.Fatalf("failed to open box") + } + + if !bytes.Equal(opened, message) { + t.Fatalf("got %x, want %x", opened, message) + } + + for i := range box { + box[i] ^= 0x40 + _, ok := OpenAnonymous(nil, box, publicKey, privateKey) + if ok { + t.Fatalf("opened box with byte %d corrupted", i) + } + box[i] ^= 0x40 + } + + // allocates new slice if out isn't long enough + out := []byte("hello") + orig := append([]byte(nil), out...) + box, err = SealAnonymous(out, message, publicKey, nil) + if err != nil { + t.Fatalf("Unexpected error sealing %v", err) + } + if !bytes.Equal(out, orig) { + t.Fatal("expected out to be unchanged") + } + if !bytes.HasPrefix(box, orig) { + t.Fatal("expected out to be copied to returned slice") + } + _, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey) + if !ok { + t.Fatalf("failed to open box") + } + + // uses provided slice if it's long enough + out = append(make([]byte, 0, 1000), []byte("hello")...) + orig = append([]byte(nil), out...) + box, err = SealAnonymous(out, message, publicKey, nil) + if err != nil { + t.Fatalf("Unexpected error sealing %v", err) + } + if !bytes.Equal(out, orig) { + t.Fatal("expected out to be unchanged") + } + if &out[0] != &box[0] { + t.Fatal("expected box to point to out") + } + _, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey) + if !ok { + t.Fatalf("failed to open box") + } +} + +func TestSealedBox(t *testing.T) { + var privateKey [32]byte + for i := range privateKey[:] { + privateKey[i] = 1 + } + + var publicKey [32]byte + curve25519.ScalarBaseMult(&publicKey, &privateKey) + var message [64]byte + for i := range message[:] { + message[i] = 3 + } + + fakeRand := bytes.NewReader([]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}) + box, err := SealAnonymous(nil, message[:], &publicKey, fakeRand) + if err != nil { + t.Fatalf("Unexpected error sealing %v", err) + } + + // expected was generated using the C implementation of libsodium with a + // random implementation that always returns 5. + // https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7 + expected, _ := hex.DecodeString("50a61409b1ddd0325e9b16b700e719e9772c07000b1bd7786e907c653d20495d2af1697137a53b1b1dfc9befc49b6eeb38f86be720e155eb2be61976d2efb34d67ecd44a6ad634625eb9c288bfc883431a84ab0f5557dfe673aa6f74c19f033e648a947358cfcc606397fa1747d5219a") + + if !bytes.Equal(box, expected) { + t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) + } + + // box was generated using the C implementation of libsodium. + // https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7 + box, _ = hex.DecodeString("3462e0640728247a6f581e3812850d6edc3dcad1ea5d8184c072f62fb65cb357e27ffa8b76f41656bc66a0882c4d359568410665746d27462a700f01e314f382edd7aae9064879b0f8ba7b88866f88f5e4fbd7649c850541877f9f33ebd25d46d9cbcce09b69a9ba07f0eb1d105d4264") + result, ok := OpenAnonymous(nil, box, &publicKey, &privateKey) + if !ok { + t.Fatalf("failed to open box") + } + if !bytes.Equal(result, message[:]) { + t.Fatalf("message didn't match, got\n%x\n, expected\n%x", result, message[:]) + } +} diff --git a/nacl/secretbox/secretbox.go b/nacl/secretbox/secretbox.go index a98d1bd45c..1fe600ad03 100644 --- a/nacl/secretbox/secretbox.go +++ b/nacl/secretbox/secretbox.go @@ -32,11 +32,11 @@ chunk size. This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. */ -package secretbox // import "golang.org/x/crypto/nacl/secretbox" +package secretbox import ( - "golang.org/x/crypto/internal/subtle" - "golang.org/x/crypto/poly1305" + "golang.org/x/crypto/internal/alias" + "golang.org/x/crypto/internal/poly1305" "golang.org/x/crypto/salsa20/salsa" ) @@ -88,7 +88,7 @@ func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { copy(poly1305Key[:], firstBlock[:]) ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) - if subtle.AnyOverlap(out, message) { + if alias.AnyOverlap(out, message) { panic("nacl: invalid buffer overlap") } @@ -147,7 +147,7 @@ func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { } ret, out := sliceForAppend(out, len(box)-Overhead) - if subtle.AnyOverlap(out, box) { + if alias.AnyOverlap(out, box) { panic("nacl: invalid buffer overlap") } diff --git a/nacl/sign/sign.go b/nacl/sign/sign.go index d07627019e..1cf2c4be2c 100644 --- a/nacl/sign/sign.go +++ b/nacl/sign/sign.go @@ -4,27 +4,22 @@ // Package sign signs small messages using public-key cryptography. // -// Sign uses Ed25519 to sign messages. The length of messages is not hidden. -// Messages should be small because: -// 1. The whole message needs to be held in memory to be processed. -// 2. Using large messages pressures implementations on small machines to process -// plaintext without verifying the signature. This is very dangerous, and this API -// discourages it, but a protocol that uses excessive message sizes might present -// some implementations with no other choice. -// 3. Performance may be improved by working with messages that fit into data caches. -// Thus large amounts of data should be chunked so that each message is small. +// This package is interoperable with [libsodium], as well as [TweetNaCl]. // -// This package is not interoperable with the current release of NaCl -// (https://nacl.cr.yp.to/sign.html), which does not support Ed25519 yet. However, -// it is compatible with the NaCl fork libsodium (https://www.libsodium.org), as well -// as TweetNaCl (https://tweetnacl.cr.yp.to/). +// The sign package is essentially a wrapper for the Ed25519 signature +// algorithm (implemented by crypto/ed25519). It is [frozen] and is not accepting +// new features. +// +// [libsodium]: https://libsodium.gitbook.io/doc/public-key_cryptography/public-key_signatures +// [TweetNaCl]: https://tweetnacl.cr.yp.to/ +// [frozen]: https://go.dev/wiki/Frozen package sign import ( + "crypto/ed25519" "io" - "golang.org/x/crypto/ed25519" - "golang.org/x/crypto/internal/subtle" + "golang.org/x/crypto/internal/alias" ) // Overhead is the number of bytes of overhead when signing a message. @@ -48,7 +43,7 @@ func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err func Sign(out, message []byte, privateKey *[64]byte) []byte { sig := ed25519.Sign(ed25519.PrivateKey((*privateKey)[:]), message) ret, out := sliceForAppend(out, Overhead+len(message)) - if subtle.AnyOverlap(out, message) { + if alias.AnyOverlap(out, message) { panic("nacl: invalid buffer overlap") } copy(out, sig) @@ -67,7 +62,7 @@ func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool) { return nil, false } ret, out := sliceForAppend(out, len(signedMessage)-Overhead) - if subtle.AnyOverlap(out, signedMessage) { + if alias.AnyOverlap(out, signedMessage) { panic("nacl: invalid buffer overlap") } copy(out, signedMessage[Overhead:]) diff --git a/nacl/sign/sign_test.go b/nacl/sign/sign_test.go index db269014c2..95ba801f2c 100644 --- a/nacl/sign/sign_test.go +++ b/nacl/sign/sign_test.go @@ -69,6 +69,6 @@ func TestGenerateSignOpen(t *testing.T) { } if !bytes.Equal(message, testMessage) { - t.Fatalf("verified message does not match signed messge, got\n%x\n, expected\n%x", message, testMessage) + t.Fatalf("verified message does not match signed message, got\n%x\n, expected\n%x", message, testMessage) } } diff --git a/ocsp/ocsp.go b/ocsp/ocsp.go index d297ac92ea..e6c645e7ce 100644 --- a/ocsp/ocsp.go +++ b/ocsp/ocsp.go @@ -5,7 +5,7 @@ // Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses // are signed messages attesting to the validity of a certificate for a small // period of time. This is used to manage revocation for X.509 certificates. -package ocsp // import "golang.org/x/crypto/ocsp" +package ocsp import ( "crypto" @@ -279,21 +279,22 @@ func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { // This is the exposed reflection of the internal OCSP structures. -// The status values that can be expressed in OCSP. See RFC 6960. +// The status values that can be expressed in OCSP. See RFC 6960. +// These are used for the Response.Status field. const ( // Good means that the certificate is valid. - Good = iota + Good = 0 // Revoked means that the certificate has been deliberately revoked. - Revoked + Revoked = 1 // Unknown means that the OCSP responder doesn't know about the certificate. - Unknown + Unknown = 2 // ServerFailed is unused and was never used (see // https://go-review.googlesource.com/#/c/18944). ParseResponse will // return a ResponseError when an error response is parsed. - ServerFailed + ServerFailed = 3 ) -// The enumerated reasons for revoking a certificate. See RFC 5280. +// The enumerated reasons for revoking a certificate. See RFC 5280. const ( Unspecified = 0 KeyCompromise = 1 @@ -345,6 +346,8 @@ func (req *Request) Marshal() ([]byte, error) { // Response represents an OCSP response containing a single SingleResponse. See // RFC 6960. type Response struct { + Raw []byte + // Status is one of {Good, Revoked, Unknown} Status int SerialNumber *big.Int @@ -445,10 +448,18 @@ func ParseRequest(bytes []byte) (*Request, error) { }, nil } -// ParseResponse parses an OCSP response in DER form. It only supports -// responses for a single certificate. If the response contains a certificate -// then the signature over the response is checked. If issuer is not nil then -// it will be used to validate the signature or embedded certificate. +// ParseResponse parses an OCSP response in DER form. The response must contain +// only one certificate status. To parse the status of a specific certificate +// from a response which may contain multiple statuses, use ParseResponseForCert +// instead. +// +// If the response contains an embedded certificate, then that certificate will +// be used to verify the response signature. If the response contains an +// embedded certificate and issuer is not nil, then issuer will be used to verify +// the signature on the embedded certificate. +// +// If the response does not contain an embedded certificate and issuer is not +// nil, then issuer will be used to verify the response signature. // // Invalid responses and parse failures will result in a ParseError. // Error responses will result in a ResponseError. @@ -456,14 +467,11 @@ func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { return ParseResponseForCert(bytes, nil, issuer) } -// ParseResponseForCert parses an OCSP response in DER form and searches for a -// Response relating to cert. If such a Response is found and the OCSP response -// contains a certificate then the signature over the response is checked. If -// issuer is not nil then it will be used to validate the signature or embedded -// certificate. -// -// Invalid responses and parse failures will result in a ParseError. -// Error responses will result in a ResponseError. +// ParseResponseForCert acts identically to ParseResponse, except it supports +// parsing responses that contain multiple statuses. If the response contains +// multiple statuses and cert is not nil, then ParseResponseForCert will return +// the first status which contains a matching serial, otherwise it will return an +// error. If cert is nil, then the first status in the response will be returned. func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { var resp responseASN1 rest, err := asn1.Unmarshal(bytes, &resp) @@ -513,6 +521,7 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon } ret := &Response{ + Raw: bytes, TBSResponseData: basicResp.TBSResponseData.Raw, Signature: basicResp.Signature.RightAlign(), SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), @@ -663,7 +672,7 @@ func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte // The responder cert is used to populate the responder's name field, and the // certificate itself is provided alongside the OCSP response signature. // -// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. +// The issuer cert is used to populate the IssuerNameHash and IssuerKeyHash fields. // // The template is used to populate the SerialNumber, Status, RevokedAt, // RevocationReason, ThisUpdate, and NextUpdate fields. diff --git a/ocsp/ocsp_test.go b/ocsp/ocsp_test.go index 70b19764f5..6dc273ec28 100644 --- a/ocsp/ocsp_test.go +++ b/ocsp/ocsp_test.go @@ -2,18 +2,19 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.7 - package ocsp import ( "bytes" "crypto" + "crypto/rand" + "crypto/rsa" "crypto/sha1" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "encoding/hex" + "encoding/pem" "math/big" "reflect" "testing" @@ -27,19 +28,26 @@ func TestOCSPDecode(t *testing.T) { t.Fatal(err) } - responderCert, _ := hex.DecodeString(startComResponderCertHex) - responder, err := x509.ParseCertificate(responderCert) + // keyHash is the SKID of the issuer of the certificate the OCSP + // response is for. + keyHash, err := hex.DecodeString("8a747faf85cdee95cd3d9cd0e24614f371351d27") + if err != nil { + t.Fatal(err) + } + // serialBytes is the serial number of the certificate the OCSP + // response is for. + serialBytes, err := hex.DecodeString("f374542e3c7a68360a00000001103462") if err != nil { t.Fatal(err) } expected := Response{ Status: Good, - SerialNumber: big.NewInt(0x1d0fa), + SerialNumber: big.NewInt(0).SetBytes(serialBytes), RevocationReason: Unspecified, - ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC), - NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC), - RawResponderName: responder.RawSubject, + ThisUpdate: time.Date(2021, 11, 7, 14, 25, 51, 0, time.UTC), + NextUpdate: time.Date(2021, 11, 14, 13, 25, 50, 0, time.UTC), + ResponderKeyHash: keyHash, } if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) { @@ -104,8 +112,8 @@ func TestOCSPDecodeWithExtensions(t *testing.T) { } func TestOCSPSignature(t *testing.T) { - issuerCert, _ := hex.DecodeString(startComHex) - issuer, err := x509.ParseCertificate(issuerCert) + b, _ := pem.Decode([]byte(GTSRoot)) + issuer, err := x509.ParseCertificate(b.Bytes) if err != nil { t.Fatal(err) } @@ -325,131 +333,154 @@ func TestErrorResponse(t *testing.T) { } } +func createMultiResp() ([]byte, error) { + rawResponderID := asn1.RawValue{ + Class: 2, // context-specific + Tag: 1, // Name (explicit tag) + IsCompound: true, + Bytes: []byte{48, 0}, + } + tbsResponseData := responseData{ + Version: 0, + RawResponderID: rawResponderID, + ProducedAt: time.Now().Truncate(time.Minute).UTC(), + } + this := time.Now() + next := this.Add(time.Hour * 24 * 4) + for i := int64(0); i < 5; i++ { + tbsResponseData.Responses = append(tbsResponseData.Responses, singleResponse{ + CertID: certID{ + HashAlgorithm: pkix.AlgorithmIdentifier{ + Algorithm: hashOIDs[crypto.SHA1], + Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, + }, + NameHash: []byte{1, 2, 3}, + IssuerKeyHash: []byte{4, 5, 6}, + SerialNumber: big.NewInt(i), + }, + ThisUpdate: this.UTC(), + NextUpdate: next.UTC(), + Good: true, + }) + } + + tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) + if err != nil { + return nil, err + } + + k, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + return nil, err + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(k.Public(), x509.SHA1WithRSA) + if err != nil { + return nil, err + } + + responseHash := hashFunc.New() + responseHash.Write(tbsResponseDataDER) + signature, err := k.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) + if err != nil { + return nil, err + } + + response := basicResponse{ + TBSResponseData: tbsResponseData, + SignatureAlgorithm: signatureAlgorithm, + Signature: asn1.BitString{ + Bytes: signature, + BitLength: 8 * len(signature), + }, + } + responseDER, err := asn1.Marshal(response) + if err != nil { + return nil, err + } + + return asn1.Marshal(responseASN1{ + Status: asn1.Enumerated(Success), + Response: responseBytes{ + ResponseType: idPKIXOCSPBasic, + Response: responseDER, + }, + }) +} + func TestOCSPDecodeMultiResponse(t *testing.T) { - inclCert, _ := hex.DecodeString(ocspMultiResponseCertHex) - cert, err := x509.ParseCertificate(inclCert) + respBytes, err := createMultiResp() if err != nil { t.Fatal(err) } - - responseBytes, _ := hex.DecodeString(ocspMultiResponseHex) - resp, err := ParseResponseForCert(responseBytes, cert, nil) + matchingCert := &x509.Certificate{SerialNumber: big.NewInt(3)} + resp, err := ParseResponseForCert(respBytes, matchingCert, nil) if err != nil { t.Fatal(err) } - if resp.SerialNumber.Cmp(cert.SerialNumber) != 0 { - t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, cert.SerialNumber) + if resp.SerialNumber.Cmp(matchingCert.SerialNumber) != 0 { + t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, 3) } } func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) { - wrongCert, _ := hex.DecodeString(startComHex) - cert, err := x509.ParseCertificate(wrongCert) + respBytes, err := createMultiResp() if err != nil { t.Fatal(err) } - - responseBytes, _ := hex.DecodeString(ocspMultiResponseHex) - _, err = ParseResponseForCert(responseBytes, cert, nil) + _, err = ParseResponseForCert(respBytes, &x509.Certificate{SerialNumber: big.NewInt(100)}, nil) want := ParseError("no response matching the supplied certificate") if err != want { t.Errorf("err: got %q, want %q", err, want) } } -// This OCSP response was taken from Thawte's public OCSP responder. +// This OCSP response was taken from GTS's public OCSP responder. // To recreate: -// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443 +// $ openssl s_client -tls1 -showcerts -servername golang.org -connect golang.org:443 // Copy and paste the first certificate into /tmp/cert.crt and the second into // /tmp/intermediate.crt -// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der +// Note: depending on what version of openssl you are using, you may need to use the key=value +// form for the header argument (i.e. -header host=ocsp.pki.goog) +// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.pki.goog/gts1c3 -header host ocsp.pki.goog -resp_text -respout /tmp/ocsp.der // Then hex encode the result: // $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")' -const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" + - "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" + - "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" + - "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" + - "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" + - "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" + - "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" + - "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" + - "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" + - "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" + - "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" + - "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" + - "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" + - "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" + - "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" + - "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" + - "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" + - "69676974616c204365727469666963617465205369676e696e6731383036060355040313" + - "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" + - "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" + - "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" + - "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" + - "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" + - "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" + - "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" + - "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" + - "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" + - "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" + - "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" + - "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" + - "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" + - "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" + - "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" + - "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" + - "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" + - "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" + - "4469676974616c204365727469666963617465205369676e696e67312930270603550403" + - "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" + - "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" + - "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" + - "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" + - "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" + - "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" + - "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" + - "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" + - "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" + - "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" + - "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42" - -const startComResponderCertHex = "308204b23082039aa003020102020101300d06092a864886f70d010105050030818c310b" + - "300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e31" + - "2b3029060355040b1322536563757265204469676974616c204365727469666963617465" + - "205369676e696e67313830360603550403132f5374617274436f6d20436c617373203120" + - "5072696d61727920496e7465726d65646961746520536572766572204341301e170d3037" + - "313032353030323330365a170d3132313032333030323330365a304c310b300906035504" + - "061302494c31163014060355040a130d5374617274436f6d204c74642e31253023060355" + - "0403131c5374617274436f6d20436c6173732031204f435350205369676e657230820122" + - "300d06092a864886f70d01010105000382010f003082010a0282010100b9561b4c453187" + - "17178084e96e178df2255e18ed8d8ecc7c2b7b51a6c1c2e6bf0aa3603066f132fe10ae97" + - "b50e99fa24b83fc53dd2777496387d14e1c3a9b6a4933e2ac12413d085570a95b8147414" + - "a0bc007c7bcf222446ef7f1a156d7ea1c577fc5f0facdfd42eb0f5974990cb2f5cefebce" + - "ef4d1bdc7ae5c1075c5a99a93171f2b0845b4ff0864e973fcfe32f9d7511ff87a3e94341" + - "0c90a4493a306b6944359340a9ca96f02b66ce67f028df2980a6aaee8d5d5d452b8b0eb9" + - "3f923cc1e23fcccbdbe7ffcb114d08fa7a6a3c404f825d1a0e715935cf623a8c7b596700" + - "14ed0622f6089a9447a7a19010f7fe58f84129a2765ea367824d1c3bb2fda30853020301" + - "0001a382015c30820158300c0603551d130101ff04023000300b0603551d0f0404030203" + - "a8301e0603551d250417301506082b0601050507030906092b0601050507300105301d06" + - "03551d0e0416041445e0a36695414c5dd449bc00e33cdcdbd2343e173081a80603551d23" + - "0481a030819d8014eb4234d098b0ab9ff41b6b08f7cc642eef0e2c45a18181a47f307d31" + - "0b300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e" + - "312b3029060355040b1322536563757265204469676974616c2043657274696669636174" + - "65205369676e696e6731293027060355040313205374617274436f6d2043657274696669" + - "636174696f6e20417574686f7269747982010a30230603551d12041c301a861868747470" + - "3a2f2f7777772e737461727473736c2e636f6d2f302c06096086480186f842010d041f16" + - "1d5374617274436f6d205265766f636174696f6e20417574686f72697479300d06092a86" + - "4886f70d01010505000382010100182d22158f0fc0291324fa8574c49bb8ff2835085adc" + - "bf7b7fc4191c397ab6951328253fffe1e5ec2a7da0d50fca1a404e6968481366939e666c" + - "0a6209073eca57973e2fefa9ed1718e8176f1d85527ff522c08db702e3b2b180f1cbff05" + - "d98128252cf0f450f7dd2772f4188047f19dc85317366f94bc52d60f453a550af58e308a" + - "aab00ced33040b62bf37f5b1ab2a4f7f0f80f763bf4d707bc8841d7ad9385ee2a4244469" + - "260b6f2bf085977af9074796048ecc2f9d48a1d24ce16e41a9941568fec5b42771e118f1" + - "6c106a54ccc339a4b02166445a167902e75e6d8620b0825dcd18a069b90fd851d10fa8ef" + - "fd409deec02860d26d8d833f304b10669b42" +const ocspResponseHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba308201b630819fa21604148a747faf85cdee95cd3d9cd0e24614f371351d27180f32303231313130373134323535335a30743072304a300906052b0e03021a05000414c72e798addff6134b3baed4742b8bbc6c024076304148a747faf85cdee95cd3d9cd0e24614f371351d27021100f374542e3c7a68360a000000011034628000180f32303231313130373134323535315aa011180f32303231313131343133323535305a300d06092a864886f70d01010b0500038201010087749296e681abe36f2efef047730178ce57e948426959ac62ac5f25b9a63ba3b7f31b9f683aea384d21845c8dda09498f2531c78f3add3969ca4092f31f58ac3c2613719d63b7b9a5260e52814c827f8dd44f4f753b2528bcd03ccec02cdcd4918247f5323f8cfc12cee4ac8f0361587b267019cfd12336db09b04eac59807a480213cfcd9913a3aa2d13a6c88c0a750475a0e991806d94ec0fc9dab599171a43a08e6d935b4a4a13dff9c4a97ad46cef6fb4d61cb2363d788c12d81cce851b478889c2e05d80cd00ae346772a1e7502f011e2ed9be8ef4b194c8b65d6e33671d878cfb30267972075b062ff3d56b51984bf685161afc6e2538dd6e6a23063c" + +const GTSRoot = `-----BEGIN CERTIFICATE----- +MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw +MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp +kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX +lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm +BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA +gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL +tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T +AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD +VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG +CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw +AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt +MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG +A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br +aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN +AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ +cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL +RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U ++o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr +PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER +lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs +Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO +z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG +AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw +juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl +1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd +-----END CERTIFICATE-----` const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + @@ -590,169 +621,6 @@ const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b060105 "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" + "9a94299a65a709756c7a3e568be049d5c38839" -const ocspMultiResponseHex = "30820ee60a0100a0820edf30820edb06092b060105050730010104820ecc30820ec83082" + - "0839a216041445ac2ecd75f53f1cf6e4c51d3de0047ad0aa7465180f3230313530363032" + - "3130303033305a3082080c3065303d300906052b0e03021a05000414f7452a0080601527" + - "72e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204" + - "5456656a8000180f32303135303630323039303230375aa011180f323031353036303331" + - "30303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e7" + - "6e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656b80" + - "00180f32303135303630323039303230375aa011180f3230313530363033313030303330" + - "5a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0" + - "f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656c8000180f3230" + - "3135303630323039303230375aa011180f32303135303630333130303033305a3065303d" + - "300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414ed" + - "d8f2ee977252853a330b297a18f5c993853b3f02045456656d8000180f32303135303630" + - "323039303230375aa011180f32303135303630333130303033305a3065303d300906052b" + - "0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee9772" + - "52853a330b297a18f5c993853b3f02045456656e8000180f323031353036303230393032" + - "30375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a05" + - "000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b" + - "297a18f5c993853b3f02045456656f8000180f32303135303630323039303230375aa011" + - "180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f745" + - "2a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c9" + - "93853b3f0204545665708000180f32303135303630323039303230375aa011180f323031" + - "35303630333130303033305a3065303d300906052b0e03021a05000414f7452a00806015" + - "2772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02" + - "04545665718000180f32303135303630323039303230375aa011180f3230313530363033" + - "3130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135" + - "e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f020454566572" + - "8000180f32303135303630323039303230375aa011180f32303135303630333130303033" + - "305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fd" + - "e0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665738000180f32" + - "303135303630323039303230375aa011180f32303135303630333130303033305a306530" + - "3d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414" + - "edd8f2ee977252853a330b297a18f5c993853b3f0204545665748000180f323031353036" + - "30323039303230375aa011180f32303135303630333130303033305a3065303d30090605" + - "2b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee97" + - "7252853a330b297a18f5c993853b3f0204545665758000180f3230313530363032303930" + - "3230375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a" + - "05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a33" + - "0b297a18f5c993853b3f0204545665768000180f32303135303630323039303230375aa0" + - "11180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f7" + - "452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5" + - "c993853b3f0204545665778000180f32303135303630323039303230375aa011180f3230" + - "3135303630333130303033305a3065303d300906052b0e03021a05000414f7452a008060" + - "152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f" + - "0204545665788000180f32303135303630323039303230375aa011180f32303135303630" + - "333130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a1" + - "35e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665" + - "798000180f32303135303630323039303230375aa011180f323031353036303331303030" + - "33305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52" + - "fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456657a8000180f" + - "32303135303630323039303230375aa011180f32303135303630333130303033305a3065" + - "303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f15804" + - "14edd8f2ee977252853a330b297a18f5c993853b3f02045456657b8000180f3230313530" + - "3630323039303230375aa011180f32303135303630333130303033305a3065303d300906" + - "052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee" + - "977252853a330b297a18f5c993853b3f02045456657c8000180f32303135303630323039" + - "303230375aa011180f32303135303630333130303033305a3065303d300906052b0e0302" + - "1a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a" + - "330b297a18f5c993853b3f02045456657d8000180f32303135303630323039303230375a" + - "a011180f32303135303630333130303033305a300d06092a864886f70d01010505000382" + - "01010016b73b92859979f27d15eb018cf069eed39c3d280213565f3026de11ba15bdb94d" + - "764cf2d0fdd204ef926c588d7b183483c8a2b1995079c7ed04dcefcc650c1965be4b6832" + - "a8839e832f7f60f638425eccdf9bc3a81fbe700fda426ddf4f06c29bee431bbbe81effda" + - "a60b7da5b378f199af2f3c8380be7ba6c21c8e27124f8a4d8989926aea19055700848d33" + - "799e833512945fd75364edbd2dd18b783c1e96e332266b17979a0b88c35b43f47c87c493" + - "19155056ad8dbbae5ff2afad3c0e1c69ed111206ffda49875e8e4efc0926264823bc4423" + - "c8a002f34288c4bc22516f98f54fc609943721f590ddd8d24f989457526b599b0eb75cb5" + - "a80da1ad93a621a08205733082056f3082056b30820453a0030201020204545638c4300d" + - "06092a864886f70d01010b0500308182310b300906035504061302555331183016060355" + - "040a130f552e532e20476f7665726e6d656e7431233021060355040b131a446570617274" + - "6d656e74206f662074686520547265617375727931223020060355040b13194365727469" + - "6669636174696f6e20417574686f7269746965733110300e060355040b13074f43494f20" + - "4341301e170d3135303332303131353531335a170d3135303633303034303030305a3081" + - "98310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" + - "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" + - "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" + - "69746965733110300e060355040b13074f43494f204341311430120603550403130b4f43" + - "5350205369676e657230820122300d06092a864886f70d01010105000382010f00308201" + - "0a0282010100c1b6fe1ba1ad50bb98c855811acbd67fe68057f48b8e08d3800e7f2c51b7" + - "9e20551934971fd92b9c9e6c49453097927cba83a94c0b2fea7124ba5ac442b38e37dba6" + - "7303d4962dd7d92b22a04b0e0e182e9ea67620b1c6ce09ee607c19e0e6e3adae81151db1" + - "2bb7f706149349a292e21c1eb28565b6839df055e1a838a772ff34b5a1452618e2c26042" + - "705d53f0af4b57aae6163f58216af12f3887813fe44b0321827b3a0c52b0e47d0aab94a2" + - "f768ab0ba3901d22f8bb263823090b0e37a7f8856db4b0d165c42f3aa7e94f5f6ce1855e" + - "98dc57adea0ae98ad39f67ecdec00b88685566e9e8d69f6cefb6ddced53015d0d3b862bc" + - "be21f3d72251eefcec730203010001a38201cf308201cb300e0603551d0f0101ff040403" + - "020780306b0603551d2004643062300c060a60864801650302010502300c060a60864801" + - "650302010503300c060a60864801650302010504300c060a60864801650302010507300c" + - "060a60864801650302010508300c060a6086480165030201030d300c060a608648016503" + - "020103113081e506082b060105050701010481d83081d5303006082b0601050507300286" + - "24687474703a2f2f706b692e74726561732e676f762f746f63615f65655f6169612e7037" + - "633081a006082b060105050730028681936c6461703a2f2f6c6461702e74726561732e67" + - "6f762f6f753d4f43494f25323043412c6f753d43657274696669636174696f6e25323041" + - "7574686f7269746965732c6f753d4465706172746d656e742532306f6625323074686525" + - "323054726561737572792c6f3d552e532e253230476f7665726e6d656e742c633d55533f" + - "634143657274696669636174653b62696e61727930130603551d25040c300a06082b0601" + - "0505070309300f06092b060105050730010504020500301f0603551d23041830168014a2" + - "13a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e0416041451f98046818a" + - "e46d953ac90c210ccfaa1a06980c300d06092a864886f70d01010b050003820101003a37" + - "0b301d14ffdeb370883639bec5ae6f572dcbddadd672af16ee2a8303316b14e1fbdca8c2" + - "8f4bad9c7b1410250e149c14e9830ca6f17370a8d13151205d956e28c141cc0500379596" + - "c5b9239fcfa3d2de8f1d4f1a2b1bf2d1851bed1c86012ee8135bdc395cd4496ce69fadd0" + - "3b682b90350ca7b4f458190b7a0ab5c33a04cf1347a77d541877a380a4c94988c5658908" + - "44fdc22637a72b9fa410333e2caf969477f9fe07f50e3681c204fb3bf073b9da01cd8d91" + - "8044c40b1159955af12a3263ab1d34119d7f59bfa6cae88ed058addc4e08250263f8f836" + - "2f5bdffd45636fea7474c60a55c535954477b2f286e1b2535f0dd12c162f1b353c370e08" + - "be67" - -const ocspMultiResponseCertHex = "308207943082067ca003020102020454566573300d06092a864886f70d01010b05003081" + - "82310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" + - "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" + - "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" + - "69746965733110300e060355040b13074f43494f204341301e170d313530343130313535" + - "3733385a170d3138303431303136323733385a30819d310b300906035504061302555331" + - "183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b131a" + - "4465706172746d656e74206f662074686520547265617375727931253023060355040b13" + - "1c427572656175206f66207468652046697363616c20536572766963653110300e060355" + - "040b130744657669636573311630140603550403130d706b692e74726561732e676f7630" + - "820122300d06092a864886f70d01010105000382010f003082010a0282010100c7273623" + - "8c49c48bf501515a2490ef6e5ae0c06e0ad2aa9a6bb77f3d0370d846b2571581ebf38fd3" + - "1948daad3dec7a4da095f1dcbe9654e65bcf7acdfd4ee802421dad9b90536c721d2bca58" + - "8413e6bfd739a72470560bb7d64f9a09284f90ff8af1d5a3c5c84d0f95a00f9c6d988dd0" + - "d87f1d0d3344580901c955139f54d09de0acdbd3322b758cb0c58881bf04913243401f44" + - "013fd9f6d8348044cc8bb0a71978ad93366b2a4687a5274b2ee07d0fb40225453eb244ed" + - "b20152251ac77c59455260ff07eeceb3cb3c60fb8121cf92afd3daa2a4650e1942ccb555" + - "de10b3d481feb299838ef05d0fd1810b146753472ae80da65dd34da25ca1f89971f10039" + - "0203010001a38203f3308203ef300e0603551d0f0101ff0404030205a030170603551d20" + - "0410300e300c060a60864801650302010503301106096086480186f84201010404030206" + - "4030130603551d25040c300a06082b060105050703013082010806082b06010505070101" + - "0481fb3081f8303006082b060105050730028624687474703a2f2f706b692e7472656173" + - "2e676f762f746f63615f65655f6169612e7037633081a006082b06010505073002868193" + - "6c6461703a2f2f6c6461702e74726561732e676f762f6f753d4f43494f25323043412c6f" + - "753d43657274696669636174696f6e253230417574686f7269746965732c6f753d446570" + - "6172746d656e742532306f6625323074686525323054726561737572792c6f3d552e532e" + - "253230476f7665726e6d656e742c633d55533f634143657274696669636174653b62696e" + - "617279302106082b060105050730018615687474703a2f2f6f6373702e74726561732e67" + - "6f76307b0603551d1104743072811c6373612d7465616d4066697363616c2e7472656173" + - "7572792e676f768210706b692e74726561737572792e676f768210706b692e64696d632e" + - "6468732e676f76820d706b692e74726561732e676f76811f6563622d686f7374696e6740" + - "66697363616c2e74726561737572792e676f76308201890603551d1f048201803082017c" + - "3027a025a0238621687474703a2f2f706b692e74726561732e676f762f4f43494f5f4341" + - "332e63726c3082014fa082014ba0820147a48197308194310b3009060355040613025553" + - "31183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b13" + - "1a4465706172746d656e74206f662074686520547265617375727931223020060355040b" + - "131943657274696669636174696f6e20417574686f7269746965733110300e060355040b" + - "13074f43494f2043413110300e0603550403130743524c313430398681aa6c6461703a2f" + - "2f6c6461702e74726561732e676f762f636e3d43524c313430392c6f753d4f43494f2532" + - "3043412c6f753d43657274696669636174696f6e253230417574686f7269746965732c6f" + - "753d4465706172746d656e742532306f6625323074686525323054726561737572792c6f" + - "3d552e532e253230476f7665726e6d656e742c633d55533f636572746966696361746552" + - "65766f636174696f6e4c6973743b62696e617279302b0603551d1004243022800f323031" + - "35303431303135353733385a810f32303138303431303136323733385a301f0603551d23" + - "041830168014a213a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e041604" + - "14b0869c12c293914cd460e33ed43e6c5a26e0d68f301906092a864886f67d074100040c" + - "300a1b0456382e31030203a8300d06092a864886f70d01010b050003820101004968d182" + - "8f9efdc147e747bb5dda15536a42a079b32d3d7f87e619b483aeee70b7e26bda393c6028" + - "7c733ecb468fe8b8b11bf809ff76add6b90eb25ad8d3a1052e43ee281e48a3a1ebe7efb5" + - "9e2c4a48765dedeb23f5346242145786cc988c762d230d28dd33bf4c2405d80cbb2cb1d6" + - "4c8f10ba130d50cb174f6ffb9cfc12808297a2cefba385f4fad170f39b51ebd87c12abf9" + - "3c51fc000af90d8aaba78f48923908804a5eb35f617ccf71d201e3708a559e6d16f9f13e" + - "074361eb9007e28d86bb4e0bfa13aad0e9ddd9124e84519de60e2fc6040b18d9fd602b02" + - "684b4c071c3019fc842197d00c120c41654bcbfbc4a096a1c637b79112b81ce1fa3899f9" - const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + "bcbb235d44ccc7dba62e72" diff --git a/openpgp/armor/armor.go b/openpgp/armor/armor.go index 592d186436..e664d127cb 100644 --- a/openpgp/armor/armor.go +++ b/openpgp/armor/armor.go @@ -4,25 +4,34 @@ // Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is // very similar to PEM except that it has an additional CRC checksum. -package armor // import "golang.org/x/crypto/openpgp/armor" +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package armor import ( "bufio" "bytes" "encoding/base64" - "golang.org/x/crypto/openpgp/errors" "io" + + "golang.org/x/crypto/openpgp/errors" ) // A Block represents an OpenPGP armored structure. // // The encoded form is: -// -----BEGIN Type----- -// Headers // -// base64-encoded Bytes -// '=' base64 encoded checksum -// -----END Type----- +// -----BEGIN Type----- +// Headers +// +// base64-encoded Bytes +// '=' base64 encoded checksum +// -----END Type----- +// // where Headers is a possibly empty sequence of Key: Value lines. // // Since the armored data can be very large, this package presents a streaming @@ -62,10 +71,11 @@ var armorEndOfLine = []byte("-----") // lineReader wraps a line based reader. It watches for the end of an armor // block and records the expected CRC value. type lineReader struct { - in *bufio.Reader - buf []byte - eof bool - crc uint32 + in *bufio.Reader + buf []byte + eof bool + crc uint32 + crcSet bool } func (l *lineReader) Read(p []byte) (n int, err error) { @@ -87,6 +97,11 @@ func (l *lineReader) Read(p []byte) (n int, err error) { return 0, ArmorCorrupt } + if bytes.HasPrefix(line, armorEnd) { + l.eof = true + return 0, io.EOF + } + if len(line) == 5 && line[0] == '=' { // This is the checksum line var expectedBytes [3]byte @@ -108,6 +123,7 @@ func (l *lineReader) Read(p []byte) (n int, err error) { } l.eof = true + l.crcSet = true return 0, io.EOF } @@ -141,10 +157,8 @@ func (r *openpgpReader) Read(p []byte) (n int, err error) { n, err = r.b64Reader.Read(p) r.currentCRC = crc24(r.currentCRC, p[:n]) - if err == io.EOF { - if r.lReader.crc != uint32(r.currentCRC&crc24Mask) { - return 0, ArmorCorrupt - } + if err == io.EOF && r.lReader.crcSet && r.lReader.crc != r.currentCRC&crc24Mask { + return 0, ArmorCorrupt } return diff --git a/openpgp/armor/armor_test.go b/openpgp/armor/armor_test.go index 9334e94e96..c05af95fde 100644 --- a/openpgp/armor/armor_test.go +++ b/openpgp/armor/armor_test.go @@ -7,7 +7,7 @@ package armor import ( "bytes" "hash/adler32" - "io/ioutil" + "io" "testing" ) @@ -29,7 +29,7 @@ func TestDecodeEncode(t *testing.T) { t.Errorf("result.Header: got:%#v", result.Header) } - contents, err := ioutil.ReadAll(result.Body) + contents, err := io.ReadAll(result.Body) if err != nil { t.Error(err) } diff --git a/openpgp/armor/encode.go b/openpgp/armor/encode.go index 6f07582c37..5b6e16c19d 100644 --- a/openpgp/armor/encode.go +++ b/openpgp/armor/encode.go @@ -96,7 +96,8 @@ func (l *lineBreaker) Close() (err error) { // trailer. // // It's built into a stack of io.Writers: -// encoding -> base64 encoder -> lineBreaker -> out +// +// encoding -> base64 encoder -> lineBreaker -> out type encoding struct { out io.Writer breaker *lineBreaker diff --git a/openpgp/clearsign/clearsign.go b/openpgp/clearsign/clearsign.go index c360460219..cea48efdcd 100644 --- a/openpgp/clearsign/clearsign.go +++ b/openpgp/clearsign/clearsign.go @@ -7,7 +7,13 @@ // // Clearsigned messages are cryptographically signed, but the contents of the // message are kept in plaintext so that it can be read without special tools. -package clearsign // import "golang.org/x/crypto/openpgp/clearsign" +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package clearsign import ( "bufio" diff --git a/openpgp/clearsign/clearsign_test.go b/openpgp/clearsign/clearsign_test.go index 737f41fc46..821c35ff47 100644 --- a/openpgp/clearsign/clearsign_test.go +++ b/openpgp/clearsign/clearsign_test.go @@ -7,6 +7,7 @@ package clearsign import ( "bytes" "fmt" + "io" "testing" "golang.org/x/crypto/openpgp" @@ -122,24 +123,12 @@ func TestSigning(t *testing.T) { } } -// We use this to make test keys, so that they aren't all the same. -type quickRand byte - -func (qr *quickRand) Read(p []byte) (int, error) { - for i := range p { - p[i] = byte(*qr) - } - *qr++ - return len(p), nil -} - func TestMultiSign(t *testing.T) { if testing.Short() { t.Skip("skipping long test in -short mode") } - zero := quickRand(0) - config := packet.Config{Rand: &zero} + var config packet.Config for nKeys := 0; nKeys < 4; nKeys++ { nextTest: @@ -191,6 +180,22 @@ func TestMultiSign(t *testing.T) { } } +func TestDecodeMissingCRC(t *testing.T) { + block, rest := Decode(clearsignInput3) + if block == nil { + t.Fatal("failed to decode PGP signature missing a CRC") + } + if len(rest) > 0 { + t.Fatalf("Decode should not have any remaining data left: %s", rest) + } + if _, err := packet.Read(block.ArmoredSignature.Body); err != nil { + t.Error(err) + } + if _, err := packet.Read(block.ArmoredSignature.Body); err != io.EOF { + t.Error(err) + } +} + const signatureBlock = ` -----BEGIN PGP SIGNATURE----- Version: OpenPrivacy 0.99 @@ -286,6 +291,65 @@ qZg6BaTvOxepqOxnhVU= trailing`) +var clearsignInput3 = []byte(`-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +Origin: vscode stable +Label: vscode stable +Suite: stable +Codename: stable +Date: Mon, 13 Jan 2020 08:41:45 UTC +Architectures: amd64 +Components: main +Description: Generated by aptly +MD5Sum: + 66437152b3082616d8053e52c4bafafb 5821166 Contents-amd64 + 8024662ed51109946a517754bbafdd33 286298 Contents-amd64.gz + 66437152b3082616d8053e52c4bafafb 5821166 main/Contents-amd64 + 8024662ed51109946a517754bbafdd33 286298 main/Contents-amd64.gz + 3062a08b3eca94a65d6d17ba1dafcf3e 1088265 main/binary-amd64/Packages + b8ee22200fba8fa3be56c1ff946cdd24 159344 main/binary-amd64/Packages.bz2 + f89c47c81ebd25caf287c8e6dda16c1a 169456 main/binary-amd64/Packages.gz + 4c9ca25b556f111a5536c78df885ad82 95 main/binary-amd64/Release +SHA1: + 2b62d0e322746b7d094878278f49993ca4314bf7 5821166 Contents-amd64 + aafe35cce12e03d8b1939e403ddf5c0958c6e9bd 286298 Contents-amd64.gz + 2b62d0e322746b7d094878278f49993ca4314bf7 5821166 main/Contents-amd64 + aafe35cce12e03d8b1939e403ddf5c0958c6e9bd 286298 main/Contents-amd64.gz + 30316ac5d4ce3b472a96a797eeb0a2a82d43ed3e 1088265 main/binary-amd64/Packages + 6507e0b4da8194fd1048fcbb74c6e7433edaf3d6 159344 main/binary-amd64/Packages.bz2 + ec9d39c39567c74001221e4900fb5d11ec11b833 169456 main/binary-amd64/Packages.gz + 58bf20987a91d35936f18efce75ea233d43dbf8b 95 main/binary-amd64/Release +SHA256: + deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39 5821166 Contents-amd64 + f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462 286298 Contents-amd64.gz + deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39 5821166 main/Contents-amd64 + f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462 286298 main/Contents-amd64.gz + 0fba50799ef72d0c2b354d0bcbbc8c623f6dae5a7fd7c218a54ea44dd8a49d5e 1088265 main/binary-amd64/Packages + 69382470a88b67acde80fe45ab223016adebc445713ff0aa3272902581d21f13 159344 main/binary-amd64/Packages.bz2 + 1724b8ace5bd8882943e9463d8525006f33ca704480da0186fd47937451dc216 169456 main/binary-amd64/Packages.gz + 0f509a0cb07e0ab433176fa47a21dccccc6b519f25f640cc58561104c11de6c2 95 main/binary-amd64/Release +SHA512: + f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c 5821166 Contents-amd64 + 46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a 286298 Contents-amd64.gz + f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c 5821166 main/Contents-amd64 + 46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a 286298 main/Contents-amd64.gz + 3f78baf5adbaf0100996555b154807c794622fd0b5879b568ae0b6560e988fbfabed8d97db5a703d1a58514b9690fc6b60f9ad2eeece473d86ab257becd0ae41 1088265 main/binary-amd64/Packages + 18f26df90beff29192662ca40525367c3c04f4581d59d2e9ab1cd0700a145b6a292a1609ca33ebe1c211f13718a8eee751f41fd8189cf93d52aa3e0851542dfc 159344 main/binary-amd64/Packages.bz2 + 6a6d917229e0cf06c493e174a87d76e815717676f2c70bcbd3bc689a80bd3c5489ea97db83b8f74cba8e70f374f9d9974f22b1ed2687a4ba1dacd22fdef7e14d 169456 main/binary-amd64/Packages.gz + e1a4378ad266c13c2edf8a0e590fa4d11973ab99ce79f15af005cb838f1600f66f3dc6da8976fa8b474da9073c118039c27623ab3360c6df115071497fe4f50c 95 main/binary-amd64/Release + +-----BEGIN PGP SIGNATURE----- +Version: BSN Pgp v1.0.0.0 + +iQEcBAEBCAAGBQJeHC1bAAoJEOs+lK2+EinPAg8H/1rrhcgfm1HYL+Vmr9Ns6ton +LWQ8r13ADN66UTRa3XsO9V+q1fYowTqpXq6EZt2Gmlby/cpDf7mFPM5IteOXWLl7 +QcWxPKHcdPIUi+h5F7BkFW65imP9GyX+V5Pxx5X544op7hYKaI0gAQ1oYtWDb3HE +4D27fju6icbj8w6E8TePcrDn82UvWAcaI5WSLboyhXCt2DxS3PNGFlyaP58zKJ8F +9cbBzksuMgMaTPAAMrU0zrFGfGeQz0Yo6nV/gRGiQaL9pSeIJWSKLNCMG/nIGmv2 +xHVNFqTEetREY6UcQmuhwOn4HezyigH6XCBVp/Uez1izXiNdwBOet34SSvnkuJ4= +-----END PGP SIGNATURE-----`) + var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) diff --git a/openpgp/elgamal/elgamal.go b/openpgp/elgamal/elgamal.go index 73f4fe3785..f922bdbcaa 100644 --- a/openpgp/elgamal/elgamal.go +++ b/openpgp/elgamal/elgamal.go @@ -10,7 +10,13 @@ // This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it // unsuitable for other protocols. RSA should be used in preference in any // case. -package elgamal // import "golang.org/x/crypto/openpgp/elgamal" +// +// Deprecated: this package was only provided to support ElGamal encryption in +// OpenPGP. The golang.org/x/crypto/openpgp package is now deprecated (see +// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has +// compatibility and security issues (see https://eprint.iacr.org/2021/923). +// Moreover, this package doesn't protect against side-channel attacks. +package elgamal import ( "crypto/rand" @@ -71,12 +77,14 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err // returns the plaintext of the message. An error can result only if the // ciphertext is invalid. Users should keep in mind that this is a padding // oracle and thus, if exposed to an adaptive chosen ciphertext attack, can -// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks -// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel +// be used to break the cryptosystem. See “Chosen Ciphertext Attacks +// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel // Bleichenbacher, Advances in Cryptology (Crypto '98), func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { s := new(big.Int).Exp(c1, priv.X, priv.P) - s.ModInverse(s, priv.P) + if s.ModInverse(s, priv.P) == nil { + return nil, errors.New("elgamal: invalid private key") + } s.Mul(s, c2) s.Mod(s, priv.P) em := s.Bytes() diff --git a/openpgp/elgamal/elgamal_test.go b/openpgp/elgamal/elgamal_test.go index c4f99f5c48..9f0a8547c3 100644 --- a/openpgp/elgamal/elgamal_test.go +++ b/openpgp/elgamal/elgamal_test.go @@ -47,3 +47,18 @@ func TestEncryptDecrypt(t *testing.T) { t.Errorf("decryption failed, got: %x, want: %x", message2, message) } } + +func TestDecryptBadKey(t *testing.T) { + priv := &PrivateKey{ + PublicKey: PublicKey{ + G: fromHex(generatorHex), + P: fromHex("2"), + }, + X: fromHex("42"), + } + priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) + c1, c2 := fromHex("8"), fromHex("8") + if _, err := Decrypt(priv, c1, c2); err == nil { + t.Errorf("unexpected success decrypting") + } +} diff --git a/openpgp/errors/errors.go b/openpgp/errors/errors.go index eb0550b2d0..a328749471 100644 --- a/openpgp/errors/errors.go +++ b/openpgp/errors/errors.go @@ -3,7 +3,13 @@ // license that can be found in the LICENSE file. // Package errors contains common error types for the OpenPGP packages. -package errors // import "golang.org/x/crypto/openpgp/errors" +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package errors import ( "strconv" diff --git a/openpgp/keys.go b/openpgp/keys.go index faa2fb3693..d62f787e9d 100644 --- a/openpgp/keys.go +++ b/openpgp/keys.go @@ -61,7 +61,7 @@ type Key struct { type KeyRing interface { // KeysById returns the set of keys that have the given key id. KeysById(id uint64) []Key - // KeysByIdAndUsage returns the set of keys with the given id + // KeysByIdUsage returns the set of keys with the given id // that also meet the key usage given by requiredUsage. // The requiredUsage is expressed as the bitwise-OR of // packet.KeyFlag* values. @@ -183,7 +183,7 @@ func (el EntityList) KeysById(id uint64) (keys []Key) { return } -// KeysByIdAndUsage returns the set of keys with the given id that also meet +// KeysByIdUsage returns the set of keys with the given id that also meet // the key usage given by requiredUsage. The requiredUsage is expressed as // the bitwise-OR of packet.KeyFlag* values. func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { diff --git a/openpgp/keys_test.go b/openpgp/keys_test.go index 0eb1a9ef29..9631eb6408 100644 --- a/openpgp/keys_test.go +++ b/openpgp/keys_test.go @@ -132,7 +132,7 @@ func TestRevokedUserID(t *testing.T) { } } -// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. +// TestExternallyRevocableKey attempts to load and parse a key with a third party revocation permission. func TestExternallyRevocableKey(t *testing.T) { kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) if err != nil { diff --git a/openpgp/packet/compressed.go b/openpgp/packet/compressed.go index e8f0b5caa7..353f945247 100644 --- a/openpgp/packet/compressed.go +++ b/openpgp/packet/compressed.go @@ -60,7 +60,7 @@ func (c *Compressed) parse(r io.Reader) error { return err } -// compressedWriterCloser represents the serialized compression stream +// compressedWriteCloser represents the serialized compression stream // header and the compressor. Its Close() method ensures that both the // compressor and serialized stream header are closed. Its Write() // method writes to the compressor. diff --git a/openpgp/packet/compressed_test.go b/openpgp/packet/compressed_test.go index cb2d70bd41..37fcc0b097 100644 --- a/openpgp/packet/compressed_test.go +++ b/openpgp/packet/compressed_test.go @@ -8,7 +8,6 @@ import ( "bytes" "encoding/hex" "io" - "io/ioutil" "testing" ) @@ -25,7 +24,7 @@ func TestCompressed(t *testing.T) { return } - contents, err := ioutil.ReadAll(c.Body) + contents, err := io.ReadAll(c.Body) if err != nil && err != io.EOF { t.Error(err) return diff --git a/openpgp/packet/encrypted_key.go b/openpgp/packet/encrypted_key.go index 02b372cf37..6d7639722c 100644 --- a/openpgp/packet/encrypted_key.go +++ b/openpgp/packet/encrypted_key.go @@ -5,6 +5,7 @@ package packet import ( + "crypto" "crypto/rsa" "encoding/binary" "io" @@ -78,8 +79,9 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { // padding oracle attacks. switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - k := priv.PrivateKey.(*rsa.PrivateKey) - b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes)) + // Supports both *rsa.PrivateKey and crypto.Decrypter + k := priv.PrivateKey.(crypto.Decrypter) + b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) case PubKeyAlgoElGamal: c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) diff --git a/openpgp/packet/encrypted_key_test.go b/openpgp/packet/encrypted_key_test.go index f2fcf4d354..ecb22bc2ba 100644 --- a/openpgp/packet/encrypted_key_test.go +++ b/openpgp/packet/encrypted_key_test.go @@ -6,9 +6,11 @@ package packet import ( "bytes" + "crypto" "crypto/rsa" "encoding/hex" "fmt" + "io" "math/big" "testing" ) @@ -80,6 +82,73 @@ func TestDecryptingEncryptedKey(t *testing.T) { } } +type rsaDecrypter struct { + rsaPrivateKey *rsa.PrivateKey + decryptCount int +} + +func (r *rsaDecrypter) Public() crypto.PublicKey { + return &r.rsaPrivateKey.PublicKey +} + +func (r *rsaDecrypter) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { + r.decryptCount++ + return r.rsaPrivateKey.Decrypt(rand, msg, opts) +} + +func TestRSADecrypter(t *testing.T) { + const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" + + const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" + + p, err := Read(readerFromHex(encryptedKeyHex)) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("didn't parse an EncryptedKey, got %#v", p) + return + } + + if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + customDecrypter := &rsaDecrypter{ + rsaPrivateKey: encryptedKeyRSAPriv, + } + + customKeyPriv := &PrivateKey{ + PublicKey: PublicKey{ + PubKeyAlgo: PubKeyAlgoRSA, + }, + PrivateKey: customDecrypter, + } + + err = ek.Decrypt(customKeyPriv, nil) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + if ek.CipherFunc != CipherAES256 { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) + } + + if customDecrypter.decryptCount != 1 { + t.Errorf("Expected customDecrypter.Decrypt() to be called 1 time, but was called %d times", customDecrypter.decryptCount) + } +} + func TestEncryptingEncryptedKey(t *testing.T) { key := []byte{1, 2, 3, 4} const expectedKeyHex = "01020304" diff --git a/openpgp/packet/opaque.go b/openpgp/packet/opaque.go index 456d807f25..3984477310 100644 --- a/openpgp/packet/opaque.go +++ b/openpgp/packet/opaque.go @@ -7,7 +7,6 @@ package packet import ( "bytes" "io" - "io/ioutil" "golang.org/x/crypto/openpgp/errors" ) @@ -26,7 +25,7 @@ type OpaquePacket struct { } func (op *OpaquePacket) parse(r io.Reader) (err error) { - op.Contents, err = ioutil.ReadAll(r) + op.Contents, err = io.ReadAll(r) return } diff --git a/openpgp/packet/opaque_test.go b/openpgp/packet/opaque_test.go index 61159f4683..06a3bbf019 100644 --- a/openpgp/packet/opaque_test.go +++ b/openpgp/packet/opaque_test.go @@ -51,7 +51,7 @@ func TestOpaqueParseReason(t *testing.T) { const expectedBad = 3 // Test post-conditions, make sure we actually parsed packets as expected. if badPackets != expectedBad { - t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad) + t.Errorf("unexpected # unparsable packets: %d (want %d)", badPackets, expectedBad) } if uid == nil { t.Errorf("failed to find expected UID in unsupported keyring") diff --git a/openpgp/packet/packet.go b/openpgp/packet/packet.go index 5af64c5421..a84a1a214e 100644 --- a/openpgp/packet/packet.go +++ b/openpgp/packet/packet.go @@ -4,7 +4,13 @@ // Package packet implements parsing and serialization of OpenPGP packets, as // specified in RFC 4880. -package packet // import "golang.org/x/crypto/openpgp/packet" +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package packet import ( "bufio" @@ -14,6 +20,7 @@ import ( "crypto/rsa" "io" "math/big" + "math/bits" "golang.org/x/crypto/cast5" "golang.org/x/crypto/openpgp/errors" @@ -100,33 +107,65 @@ func (r *partialLengthReader) Read(p []byte) (n int, err error) { type partialLengthWriter struct { w io.WriteCloser lengthByte [1]byte + sentFirst bool + buf []byte } +// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long. +const minFirstPartialWrite = 512 + func (w *partialLengthWriter) Write(p []byte) (n int, err error) { + off := 0 + if !w.sentFirst { + if len(w.buf) > 0 || len(p) < minFirstPartialWrite { + off = len(w.buf) + w.buf = append(w.buf, p...) + if len(w.buf) < minFirstPartialWrite { + return len(p), nil + } + p = w.buf + w.buf = nil + } + w.sentFirst = true + } + + power := uint8(30) for len(p) > 0 { - for power := uint(14); power < 32; power-- { - l := 1 << power - if len(p) >= l { - w.lengthByte[0] = 224 + uint8(power) - _, err = w.w.Write(w.lengthByte[:]) - if err != nil { - return - } - var m int - m, err = w.w.Write(p[:l]) - n += m - if err != nil { - return - } - p = p[l:] - break + l := 1 << power + if len(p) < l { + power = uint8(bits.Len32(uint32(len(p)))) - 1 + l = 1 << power + } + w.lengthByte[0] = 224 + power + _, err = w.w.Write(w.lengthByte[:]) + if err == nil { + var m int + m, err = w.w.Write(p[:l]) + n += m + } + if err != nil { + if n < off { + return 0, err } + return n - off, err } + p = p[l:] } - return + return n - off, nil } func (w *partialLengthWriter) Close() error { + if len(w.buf) > 0 { + // In this case we can't send a 512 byte packet. + // Just send what we have. + p := w.buf + w.sentFirst = true + w.buf = nil + if _, err := w.Write(p); err != nil { + return err + } + } + w.lengthByte[0] = 0 _, err := w.w.Write(w.lengthByte[:]) if err != nil { diff --git a/openpgp/packet/packet_test.go b/openpgp/packet/packet_test.go index 1dab5c3d58..c8fc4e50c0 100644 --- a/openpgp/packet/packet_test.go +++ b/openpgp/packet/packet_test.go @@ -10,7 +10,6 @@ import ( "fmt" "golang.org/x/crypto/openpgp/errors" "io" - "io/ioutil" "testing" ) @@ -100,7 +99,7 @@ var partialLengthReaderTests = []struct { func TestPartialLengthReader(t *testing.T) { for i, test := range partialLengthReaderTests { r := &partialLengthReader{readerFromHex(test.hexInput), 0, true} - out, err := ioutil.ReadAll(r) + out, err := io.ReadAll(r) if test.err != nil { if err != test.err { t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) @@ -172,7 +171,7 @@ func TestReadHeader(t *testing.T) { continue } - body, err := ioutil.ReadAll(contents) + body, err := io.ReadAll(contents) if err != nil { if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { t.Errorf("%d: unexpected error from contents: %s", i, err) @@ -232,7 +231,21 @@ func TestPartialLengths(t *testing.T) { t.Errorf("error from write: %s", err) } } - w.Close() + if err := w.Close(); err != nil { + t.Fatal(err) + } + + // The first packet should be at least 512 bytes. + first, err := buf.ReadByte() + if err != nil { + t.Fatal(err) + } + if plen := 1 << (first & 0x1f); plen < 512 { + t.Errorf("first packet too short: got %d want at least %d", plen, 512) + } + if err := buf.UnreadByte(); err != nil { + t.Fatal(err) + } want := (maxChunkSize * (maxChunkSize + 1)) / 2 copyBuf := bytes.NewBuffer(nil) @@ -253,3 +266,25 @@ func TestPartialLengths(t *testing.T) { } } } + +func TestPartialLengthsShortWrite(t *testing.T) { + buf := bytes.NewBuffer(nil) + w := &partialLengthWriter{ + w: noOpCloser{buf}, + } + data := bytes.Repeat([]byte("a"), 510) + if _, err := w.Write(data); err != nil { + t.Fatal(err) + } + if err := w.Close(); err != nil { + t.Fatal(err) + } + copyBuf := bytes.NewBuffer(nil) + r := &partialLengthReader{buf, 0, true} + if _, err := io.Copy(copyBuf, r); err != nil { + t.Fatal(err) + } + if !bytes.Equal(copyBuf.Bytes(), data) { + t.Errorf("got %q want %q", buf.Bytes(), data) + } +} diff --git a/openpgp/packet/private_key.go b/openpgp/packet/private_key.go index 6f8ec09384..192aac376d 100644 --- a/openpgp/packet/private_key.go +++ b/openpgp/packet/private_key.go @@ -13,7 +13,6 @@ import ( "crypto/rsa" "crypto/sha1" "io" - "io/ioutil" "math/big" "strconv" "time" @@ -31,7 +30,7 @@ type PrivateKey struct { encryptedData []byte cipher CipherFunction s2k func(out, in []byte) - PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer. + PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). sha1Checksum bool iv []byte } @@ -133,7 +132,7 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) { } } - pk.encryptedData, err = ioutil.ReadAll(r) + pk.encryptedData, err = io.ReadAll(r) if err != nil { return } diff --git a/openpgp/packet/signature_v3_test.go b/openpgp/packet/signature_v3_test.go index ad7b62ac19..abb2d8c144 100644 --- a/openpgp/packet/signature_v3_test.go +++ b/openpgp/packet/signature_v3_test.go @@ -9,7 +9,6 @@ import ( "crypto" "encoding/hex" "io" - "io/ioutil" "testing" "golang.org/x/crypto/openpgp/armor" @@ -45,7 +44,7 @@ func TestSignatureV3Reserialize(t *testing.T) { t.Errorf("error reserializing: %s", err) return } - expected, err := ioutil.ReadAll(v3KeyReader(t)) + expected, err := io.ReadAll(v3KeyReader(t)) if err != nil { t.Error(err) return @@ -66,18 +65,23 @@ func v3KeyReader(t *testing.T) io.Reader { // keySigV3Armor is some V3 public key I found in an SKS dump. // Old: Public Key Packet(tag 6)(141 bytes) -// Ver 4 - new -// Public key creation time - Fri Sep 16 17:13:54 CDT 1994 -// Pub alg - unknown(pub 0) -// Unknown public key(pub 0) +// +// Ver 4 - new +// Public key creation time - Fri Sep 16 17:13:54 CDT 1994 +// Pub alg - unknown(pub 0) +// Unknown public key(pub 0) +// // Old: User ID Packet(tag 13)(39 bytes) -// User ID - Armin M. Warda +// +// User ID - Armin M. Warda +// // Old: Signature Packet(tag 2)(149 bytes) -// Ver 4 - new -// Sig type - unknown(05) -// Pub alg - ElGamal Encrypt-Only(pub 16) -// Hash alg - unknown(hash 46) -// Hashed Sub: unknown(sub 81, critical)(1988 bytes) +// +// Ver 4 - new +// Sig type - unknown(05) +// Pub alg - ElGamal Encrypt-Only(pub 16) +// Hash alg - unknown(hash 46) +// Hashed Sub: unknown(sub 81, critical)(1988 bytes) const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK----- Version: SKS 1.0.10 diff --git a/openpgp/packet/symmetric_key_encrypted_test.go b/openpgp/packet/symmetric_key_encrypted_test.go index e1d52c122e..5471d77706 100644 --- a/openpgp/packet/symmetric_key_encrypted_test.go +++ b/openpgp/packet/symmetric_key_encrypted_test.go @@ -8,7 +8,6 @@ import ( "bytes" "encoding/hex" "io" - "io/ioutil" "testing" ) @@ -46,7 +45,7 @@ func TestSymmetricKeyEncrypted(t *testing.T) { return } - contents, err := ioutil.ReadAll(r) + contents, err := io.ReadAll(r) if err != nil && err != io.EOF { t.Error(err) return diff --git a/openpgp/packet/symmetrically_encrypted.go b/openpgp/packet/symmetrically_encrypted.go index 6126030eb9..1a1a62964f 100644 --- a/openpgp/packet/symmetrically_encrypted.go +++ b/openpgp/packet/symmetrically_encrypted.go @@ -236,7 +236,7 @@ func (w *seMDCWriter) Close() (err error) { return w.w.Close() } -// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +// noOpCloser is like an io.NopCloser, but for an io.Writer. type noOpCloser struct { w io.Writer } diff --git a/openpgp/packet/symmetrically_encrypted_test.go b/openpgp/packet/symmetrically_encrypted_test.go index c5c00f7b9c..4c47c7b145 100644 --- a/openpgp/packet/symmetrically_encrypted_test.go +++ b/openpgp/packet/symmetrically_encrypted_test.go @@ -10,7 +10,6 @@ import ( "encoding/hex" "golang.org/x/crypto/openpgp/errors" "io" - "io/ioutil" "testing" ) @@ -42,7 +41,7 @@ func testMDCReader(t *testing.T) { for stride := 1; stride < len(mdcPlaintext)/2; stride++ { r := &testReader{data: mdcPlaintext, stride: stride} mdcReader := &seMDCReader{in: r, h: sha1.New()} - body, err := ioutil.ReadAll(mdcReader) + body, err := io.ReadAll(mdcReader) if err != nil { t.Errorf("stride: %d, error: %s", stride, err) continue @@ -62,7 +61,7 @@ func testMDCReader(t *testing.T) { r := &testReader{data: mdcPlaintext, stride: 2} mdcReader := &seMDCReader{in: r, h: sha1.New()} - _, err := ioutil.ReadAll(mdcReader) + _, err := io.ReadAll(mdcReader) if err != nil { t.Errorf("corruption test, error: %s", err) return diff --git a/openpgp/packet/userattribute.go b/openpgp/packet/userattribute.go index d19ffbc786..ff7ef53075 100644 --- a/openpgp/packet/userattribute.go +++ b/openpgp/packet/userattribute.go @@ -9,7 +9,6 @@ import ( "image" "image/jpeg" "io" - "io/ioutil" ) const UserAttrImageSubpacket = 1 @@ -56,7 +55,7 @@ func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { func (uat *UserAttribute) parse(r io.Reader) (err error) { // RFC 4880, section 5.13 - b, err := ioutil.ReadAll(r) + b, err := io.ReadAll(r) if err != nil { return } diff --git a/openpgp/packet/userid.go b/openpgp/packet/userid.go index d6bea7d4ac..359a462eb8 100644 --- a/openpgp/packet/userid.go +++ b/openpgp/packet/userid.go @@ -6,7 +6,6 @@ package packet import ( "io" - "io/ioutil" "strings" ) @@ -66,7 +65,7 @@ func NewUserId(name, comment, email string) *UserId { func (uid *UserId) parse(r io.Reader) (err error) { // RFC 4880, section 5.11 - b, err := ioutil.ReadAll(r) + b, err := io.ReadAll(r) if err != nil { return } diff --git a/openpgp/read.go b/openpgp/read.go index 6ec664f44a..cff3db9196 100644 --- a/openpgp/read.go +++ b/openpgp/read.go @@ -3,7 +3,13 @@ // license that can be found in the LICENSE file. // Package openpgp implements high level operations on OpenPGP messages. -package openpgp // import "golang.org/x/crypto/openpgp" +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package openpgp import ( "crypto" diff --git a/openpgp/read_test.go b/openpgp/read_test.go index f5bba3019c..6bbfaf1afb 100644 --- a/openpgp/read_test.go +++ b/openpgp/read_test.go @@ -9,7 +9,6 @@ import ( _ "crypto/sha512" "encoding/hex" "io" - "io/ioutil" "strings" "testing" @@ -128,7 +127,7 @@ func checkSignedMessage(t *testing.T, signedHex, expected string) { t.Errorf("bad MessageDetails: %#v", md) } - contents, err := ioutil.ReadAll(md.UnverifiedBody) + contents, err := io.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("error reading UnverifiedBody: %s", err) } @@ -221,7 +220,7 @@ func TestSignedEncryptedMessage(t *testing.T) { t.Errorf("#%d: bad MessageDetails: %#v", i, md) } - contents, err := ioutil.ReadAll(md.UnverifiedBody) + contents, err := io.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("#%d: error reading UnverifiedBody: %s", i, err) } @@ -245,7 +244,7 @@ func TestUnspecifiedRecipient(t *testing.T) { return } - contents, err := ioutil.ReadAll(md.UnverifiedBody) + contents, err := io.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("error reading UnverifiedBody: %s", err) } @@ -280,7 +279,7 @@ func TestSymmetricallyEncrypted(t *testing.T) { return } - contents, err := ioutil.ReadAll(md.UnverifiedBody) + contents, err := io.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("ReadAll: %s", err) } @@ -454,7 +453,7 @@ func TestSignatureV3Message(t *testing.T) { return } - _, err = ioutil.ReadAll(md.UnverifiedBody) + _, err = io.ReadAll(md.UnverifiedBody) if err != nil { t.Error(err) return diff --git a/openpgp/s2k/s2k.go b/openpgp/s2k/s2k.go index 4b9a44ca26..490cb633ce 100644 --- a/openpgp/s2k/s2k.go +++ b/openpgp/s2k/s2k.go @@ -4,7 +4,13 @@ // Package s2k implements the various OpenPGP string-to-key transforms as // specified in RFC 4800 section 3.7.1. -package s2k // import "golang.org/x/crypto/openpgp/s2k" +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package s2k import ( "crypto" @@ -47,7 +53,7 @@ func (c *Config) hash() crypto.Hash { func (c *Config) encodedCount() uint8 { if c == nil || c.S2KCount == 0 { - return 96 // The common case. Correspoding to 65536 + return 96 // The common case. Corresponding to 65536 } i := c.S2KCount @@ -262,7 +268,7 @@ func HashIdToString(id byte) (name string, ok bool) { return "", false } -// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. +// HashToHashId returns an OpenPGP hash id which corresponds the given Hash. func HashToHashId(h crypto.Hash) (id byte, ok bool) { for _, m := range hashToHashIdMapping { if m.hash == h { diff --git a/openpgp/write.go b/openpgp/write.go index 4ee71784eb..b89d48b81d 100644 --- a/openpgp/write.go +++ b/openpgp/write.go @@ -402,7 +402,7 @@ func (s signatureWriter) Close() error { return s.encryptedData.Close() } -// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +// noOpCloser is like an io.NopCloser, but for an io.Writer. // TODO: we have two of these in OpenPGP packages alone. This probably needs // to be promoted somewhere more common. type noOpCloser struct { diff --git a/openpgp/write_test.go b/openpgp/write_test.go index cbc8f4dac1..8b686789ee 100644 --- a/openpgp/write_test.go +++ b/openpgp/write_test.go @@ -7,7 +7,6 @@ package openpgp import ( "bytes" "io" - "io/ioutil" "testing" "time" @@ -245,7 +244,7 @@ func TestEncryption(t *testing.T) { } } - plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + plaintext, err := io.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("#%d: error reading encrypted contents: %s", i, err) continue @@ -342,7 +341,7 @@ func TestSigning(t *testing.T) { t.Errorf("#%d: failed to find the signing Entity", i) } - plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + plaintext, err := io.ReadAll(md.UnverifiedBody) if err != nil { t.Errorf("#%d: error reading contents: %v", i, err) continue diff --git a/otr/libotr_test_helper.c b/otr/libotr_test_helper.c index b3ca072d48..aae03a3df7 100644 --- a/otr/libotr_test_helper.c +++ b/otr/libotr_test_helper.c @@ -5,7 +5,7 @@ // This code can be compiled and used to test the otr package against libotr. // See otr_test.go. -// +build ignore +//go:build ignore #include #include diff --git a/otr/otr.go b/otr/otr.go index 29121e9bb6..a36f7ca245 100644 --- a/otr/otr.go +++ b/otr/otr.go @@ -8,7 +8,11 @@ // The version of OTR implemented by this package has been deprecated // (https://bugs.otr.im/lib/libotr/issues/140). An implementation of OTRv3 is // available at https://github.com/coyim/otr3. -package otr // import "golang.org/x/crypto/otr" +// +// The otr package is [frozen] and is not accepting new features. +// +// [frozen]: https://go.dev/wiki/Frozen +package otr import ( "bytes" diff --git a/otr/otr_test.go b/otr/otr_test.go index cfcd062b27..3b7aa1986e 100644 --- a/otr/otr_test.go +++ b/otr/otr_test.go @@ -75,8 +75,8 @@ const libOTRPrivateKey = `(privkeys (account (name "foo@example.com") (protocol prpl-jabber) -(private-key - (dsa +(private-key + (dsa (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) @@ -402,7 +402,7 @@ func TestAgainstLibOTR(t *testing.T) { // This test requires otr.c.test to be built as /tmp/a.out. // If enabled, this tests runs forever performing OTR handshakes in a // loop. - return + t.Skip("This test requires otr.c.test to be built as /tmp/a.out") alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) var alice Conversation diff --git a/pbkdf2/pbkdf2.go b/pbkdf2/pbkdf2.go index 593f653008..28cd99c7f3 100644 --- a/pbkdf2/pbkdf2.go +++ b/pbkdf2/pbkdf2.go @@ -16,7 +16,7 @@ Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To choose, you can pass the `New` functions from the different SHA packages to pbkdf2.Key. */ -package pbkdf2 // import "golang.org/x/crypto/pbkdf2" +package pbkdf2 import ( "crypto/hmac" @@ -32,7 +32,7 @@ import ( // can get a derived key for e.g. AES-256 (which needs a 32-byte key) by // doing: // -// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) +// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) // // Remember to get a good random salt. At least 8 bytes is recommended by the // RFC. diff --git a/pkcs12/crypto.go b/pkcs12/crypto.go index 484ca51b71..212538cb5a 100644 --- a/pkcs12/crypto.go +++ b/pkcs12/crypto.go @@ -26,7 +26,7 @@ type pbeCipher interface { create(key []byte) (cipher.Block, error) // deriveKey returns a key derived from the given password and salt. deriveKey(salt, password []byte, iterations int) []byte - // deriveKey returns an IV derived from the given password and salt. + // deriveIV returns an IV derived from the given password and salt. deriveIV(salt, password []byte, iterations int) []byte } @@ -117,7 +117,7 @@ func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) } ps := decrypted[len(decrypted)-psLen:] decrypted = decrypted[:len(decrypted)-psLen] - if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 { + if !bytes.Equal(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) { return nil, ErrDecryption } diff --git a/pkcs12/internal/rc2/rc2.go b/pkcs12/internal/rc2/rc2.go index 7499e3fb69..05de9cc2cd 100644 --- a/pkcs12/internal/rc2/rc2.go +++ b/pkcs12/internal/rc2/rc2.go @@ -14,6 +14,7 @@ package rc2 import ( "crypto/cipher" "encoding/binary" + "math/bits" ) // The rc2 block size in bytes @@ -80,10 +81,6 @@ func expandKey(key []byte, t1 int) [64]uint16 { return k } -func rotl16(x uint16, b uint) uint16 { - return (x >> (16 - b)) | (x << b) -} - func (c *rc2Cipher) Encrypt(dst, src []byte) { r0 := binary.LittleEndian.Uint16(src[0:]) @@ -96,22 +93,22 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) { for j <= 16 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) - r0 = rotl16(r0, 1) + r0 = bits.RotateLeft16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) - r1 = rotl16(r1, 2) + r1 = bits.RotateLeft16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) - r2 = rotl16(r2, 3) + r2 = bits.RotateLeft16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) - r3 = rotl16(r3, 5) + r3 = bits.RotateLeft16(r3, 5) j++ } @@ -124,22 +121,22 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) { for j <= 40 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) - r0 = rotl16(r0, 1) + r0 = bits.RotateLeft16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) - r1 = rotl16(r1, 2) + r1 = bits.RotateLeft16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) - r2 = rotl16(r2, 3) + r2 = bits.RotateLeft16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) - r3 = rotl16(r3, 5) + r3 = bits.RotateLeft16(r3, 5) j++ } @@ -152,22 +149,22 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) { for j <= 60 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) - r0 = rotl16(r0, 1) + r0 = bits.RotateLeft16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) - r1 = rotl16(r1, 2) + r1 = bits.RotateLeft16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) - r2 = rotl16(r2, 3) + r2 = bits.RotateLeft16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) - r3 = rotl16(r3, 5) + r3 = bits.RotateLeft16(r3, 5) j++ } @@ -188,22 +185,22 @@ func (c *rc2Cipher) Decrypt(dst, src []byte) { for j >= 44 { // unmix r3 - r3 = rotl16(r3, 16-5) + r3 = bits.RotateLeft16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 - r2 = rotl16(r2, 16-3) + r2 = bits.RotateLeft16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 - r1 = rotl16(r1, 16-2) + r1 = bits.RotateLeft16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 - r0 = rotl16(r0, 16-1) + r0 = bits.RotateLeft16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } @@ -215,22 +212,22 @@ func (c *rc2Cipher) Decrypt(dst, src []byte) { for j >= 20 { // unmix r3 - r3 = rotl16(r3, 16-5) + r3 = bits.RotateLeft16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 - r2 = rotl16(r2, 16-3) + r2 = bits.RotateLeft16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 - r1 = rotl16(r1, 16-2) + r1 = bits.RotateLeft16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 - r0 = rotl16(r0, 16-1) + r0 = bits.RotateLeft16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- @@ -243,22 +240,22 @@ func (c *rc2Cipher) Decrypt(dst, src []byte) { for j >= 0 { // unmix r3 - r3 = rotl16(r3, 16-5) + r3 = bits.RotateLeft16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 - r2 = rotl16(r2, 16-3) + r2 = bits.RotateLeft16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 - r1 = rotl16(r1, 16-2) + r1 = bits.RotateLeft16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 - r0 = rotl16(r0, 16-1) + r0 = bits.RotateLeft16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- diff --git a/pkcs12/pkcs12.go b/pkcs12/pkcs12.go index 55f7691d48..374d9facf8 100644 --- a/pkcs12/pkcs12.go +++ b/pkcs12/pkcs12.go @@ -4,12 +4,16 @@ // Package pkcs12 implements some of PKCS#12. // -// This implementation is distilled from https://tools.ietf.org/html/rfc7292 -// and referenced documents. It is intended for decoding P12/PFX-stored -// certificates and keys for use with the crypto/tls package. +// This implementation is distilled from [RFC 7292] and referenced documents. +// It is intended for decoding P12/PFX-stored certificates and keys for use +// with the crypto/tls package. // -// This package is frozen. If it's missing functionality you need, consider -// an alternative like software.sslmate.com/src/go-pkcs12. +// The pkcs12 package is [frozen] and is not accepting new features. +// If it's missing functionality you need, consider an alternative like +// software.sslmate.com/src/go-pkcs12. +// +// [RFC 7292]: https://datatracker.ietf.org/doc/html/rfc7292 +// [frozen]: https://go.dev/wiki/Frozen package pkcs12 import ( @@ -30,6 +34,8 @@ var ( oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) + + errUnknownAttributeOID = errors.New("pkcs12: unknown attribute OID") ) type pfxPdu struct { @@ -104,6 +110,11 @@ func unmarshal(in []byte, out interface{}) error { } // ToPEM converts all "safe bags" contained in pfxData to PEM blocks. +// Unknown attributes are discarded. +// +// Note that although the returned PEM blocks for private keys have type +// "PRIVATE KEY", the bytes are not encoded according to PKCS #8, but according +// to PKCS #1 for RSA keys and SEC 1 for ECDSA keys. func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { encodedPassword, err := bmpString(password) if err != nil { @@ -135,6 +146,9 @@ func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { for _, attribute := range bag.Attributes { k, v, err := convertAttribute(&attribute) + if err == errUnknownAttributeOID { + continue + } if err != nil { return nil, err } @@ -188,7 +202,7 @@ func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) key = "Microsoft CSP Name" isString = true default: - return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String()) + return "", "", errUnknownAttributeOID } if isString { @@ -252,6 +266,7 @@ func Decode(pfxData []byte, password string) (privateKey interface{}, certificat case bag.Id.Equal(oidPKCS8ShroundedKeyBag): if privateKey != nil { err = errors.New("pkcs12: expected exactly one key bag") + return nil, nil, err } if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { diff --git a/pkcs12/pkcs12_test.go b/pkcs12/pkcs12_test.go index 14dd2a6c5d..68476a822f 100644 --- a/pkcs12/pkcs12_test.go +++ b/pkcs12/pkcs12_test.go @@ -89,6 +89,9 @@ func ExampleToPEM() { var testdata = map[string]string{ // 'null' password test case "Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`, + // Windows IAS PEAP & LDAPS certificates test case + // Unknown OID 1.3.6.1.4.1.311.17.2 should be dropped + "Windows IAS PEAP & LDAPS certificates": `MIIHPQIBAzCCBwMGCSqGSIb3DQEHAaCCBvQEggbwMIIG7DCCAz8GCSqGSIb3DQEHBqCCAzAwggMsAgEAMIIDJQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIrosqK6kNi9sCAggAgIIC+IcOaLAkrLiBCnw06bFGOUMGkVsuiYZlkTBzW55DQS4JUefZ71CPMUofo7U4z7bL1JYGV2aO9REMnb8gm0jQYgVEFNQbsDDICZBA8Xfjki0MULw3kEyFxfk7AV51IMRVjAGImS2asDAWW+dVgLLbBV+Q8L+D917sS8pz0VLT4GzxZHLdGXVXKp2MHkHc3nx4eDeWkBAZoSqansgJXTM3JOWOSxUEFZA2Wb7UerykCLuzK+RmR2pkmV88JIFbneP/NjQg/nZDN4bGXGJf+3gRqq07T4q7QKzmZRrQgLJwSZ1wzhB2HoIfIm/ylOEUly5XzMbf6nzc94BrDXv6q4efXMApztTfAsq9hysMiImQrPGxYBj3CAxfWCfc7K4XlbdRwZTmbCutf5O93aYALVAkzPf4x2NWxcw5sLYfGH8ma9xF3VZk+h1DJw+6Iq0+g/8lZ7uGJPAZav40YIW+RZ3vsDx3uw7OkQNwP0b/lahgnftTa0WcF3OwocTVb1o3zbtAW+pQxTRvdvTX6jENVTJVk10probfq+iDoolGe382c9d5qo4Yh/AhZHWqL2YqU2ypq16rxz1RPGSpceHAtVVZYSTKk9VKg0fevz8P8wjUKboZmpLnSu2P5ABwkoSbrGQIKMtE3CSswxKQVzEreKbcyeNBt0A0vSTOrwSzDQxFE4Ur+lUnqJC8sHW2NpA84S+TCLEAzhPMIFo5MJ90jN8N3tfTYnXVZDk1mt0pJEmWRxRofVJm2/J6Slak6x51s+TKiss/rG3y1XpzCgN9Nzb7uOHs7G6l9pOP0Bd6Z4s4DIeddG5MgpZkdn+vQNuGNbhZretg80Wj0lNZ2Oor/q0TSE0UoGZNEK1bZ3SHWqtY4J87aBkKGDcBCMqyLU1pGXBtpdJ8xoW+Ya6nM+I47jUoAJi8ChKDY8ZSKBoYsi1OuFNWl9xdn382rvpYtXqqBtA+mCAGJXiSFXUNkhSjlIFU/87v/4gsdFcAxMZVYxJVLdx2ldSyBnuAv9AwggOlBgkqhkiG9w0BBwGgggOWBIIDkjCCA44wggOKBgsqhkiG9w0BDAoBAqCCAqYwggKiMBwGCiqGSIb3DQEMAQMwDgQI44fv4XLfEhoCAggABIICgC+Cc/yNrM3ovTargtsTI2Ut8MzmLSIVPOgc7K77xwz7daXkJ5ucDRVfYEOzIlY0NfKsWqiYc+2vfZRqm6fBrpj1/1zhC+A6wzxxNY1BxVXDdLVvigNBvPNxj5Z+K8kFApi3tqUOpz6uzj9B6PMywETQ/lKIQ0PUVa5KRbx3JztFfGIXq+zoGuUSxzzVpLQQE7ON7qtUJbkAA7x/vwq4fKKxC4nxXwPSFaUi+S4m6JDQ4XS02RcK/m2NEzKxPQBFQMSbfkqJd/HrjWbY9msebdTPI8Q+o2rrnQ5K225IZCxqcOwa//108rdx7fDJz28ywSv3rBgPynb9/1iSpeQ25C1gl+skTvgQmz5U/7DzSJkLNSwFIcEZUSyYM4uWjtKHSaTgCkh/D3+7AvloQKNgNSKJ9WM053jzYaYRs11BKCYm7UG9v0cgUbI84GJFomrzxRcOfX0ps2UVnXMTq6kJrGB/X1xM5Quvn7kvuK+S0ZMTn1yHpFaOxdn0Z1On/Y05XWz86Y316WfkSrBeuqbH5HTI74F2yWl4K4PEerIyqX14s3oEGdtlJ24o/kAQTbCrntPFu3ZKxF4z5bkpO3bZwaURRLCmT3sLenlthsLysE2riUbacFl33mkaGTvBeqUOofHfO5LNJcE/J8YBzekewLFBcOY59WZkZBbUasPzkOomdZtkrzlzMjJ1pTCd5RCyretHP6j681Wq3+tDvR/ycrgKO+JY8kwIk8HB3BX+xRn6rFULAcLsUhsGbsZ6ig9yeXTCx2xh97Rh5A0pzSkv9A7UFT155amZ3cVJuPdruWj9yLQ9JEIi83q1olMh7mbaA3qKbYDnou+Aj0OlDySAo+MxgdAwDQYJKwYBBAGCNxECMQAwIwYJKoZIhvcNAQkVMRYEFGclVjS+gkQdguj0myihwM1yC/1bMC8GCSqGSIb3DQEJFDEiHiAAUABFAEEAUAAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZTBpBgkrBgEEAYI3EQExXB5aAE0AaQBjAHIAbwBzAG8AZgB0ACAAUgBTAEEAIABTAEMAaABhAG4AbgBlAGwAIABDAHIAeQBwAHQAbwBnAHIAYQBwAGgAaQBjACAAUAByAG8AdgBpAGQAZQByMDEwITAJBgUrDgMCGgUABBSerVeCcXV8OLmAwfi2hYXAmA5I3gQIHpTh4gRG/3MCAggA`, // empty string password test case "testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L diff --git a/poly1305/poly1305_compat.go b/poly1305/poly1305_compat.go new file mode 100644 index 0000000000..cb9207f300 --- /dev/null +++ b/poly1305/poly1305_compat.go @@ -0,0 +1,91 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package poly1305 implements Poly1305 one-time message authentication code as +// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. +// +// Poly1305 is a fast, one-time authentication function. It is infeasible for an +// attacker to generate an authenticator for a message without the key. However, a +// key must only be used for a single message. Authenticating two different +// messages with the same key allows an attacker to forge authenticators for other +// messages with the same key. +// +// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was +// used with a fixed key in order to generate one-time keys from an nonce. +// However, in this package AES isn't used and the one-time key is specified +// directly. +// +// Deprecated: Poly1305 as implemented by this package is a cryptographic +// building block that is not safe for general purpose use. +// For encryption, use the full ChaCha20-Poly1305 construction implemented by +// golang.org/x/crypto/chacha20poly1305. For authentication, use a general +// purpose MAC such as HMAC implemented by crypto/hmac. +package poly1305 + +import "golang.org/x/crypto/internal/poly1305" + +// TagSize is the size, in bytes, of a poly1305 authenticator. +// +// For use with golang.org/x/crypto/chacha20poly1305, chacha20poly1305.Overhead +// can be used instead. +const TagSize = 16 + +// 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 *[16]byte, m []byte, key *[32]byte) { + poly1305.Sum(out, m, key) +} + +// Verify returns true if mac is a valid authenticator for m with the given key. +func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { + return poly1305.Verify(mac, m, key) +} + +// New returns a new MAC computing an authentication +// tag of all data written to it with the given key. +// This allows writing the message progressively instead +// of passing it as a single slice. Common users should use +// the Sum function instead. +// +// The key must be unique for each message, as authenticating +// two different messages with the same key allows an attacker +// to forge messages at will. +func New(key *[32]byte) *MAC { + return &MAC{mac: poly1305.New(key)} +} + +// MAC is an io.Writer computing an authentication tag +// of the data written to it. +// +// MAC cannot be used like common hash.Hash implementations, +// because using a poly1305 key twice breaks its security. +// Therefore writing data to a running MAC after calling +// Sum or Verify causes it to panic. +type MAC struct { + mac *poly1305.MAC +} + +// Size returns the number of bytes Sum will return. +func (h *MAC) Size() int { return TagSize } + +// Write adds more data to the running message authentication code. +// It never returns an error. +// +// It must not be called after the first call of Sum or Verify. +func (h *MAC) Write(p []byte) (n int, err error) { + return h.mac.Write(p) +} + +// Sum computes the authenticator of all data written to the +// message authentication code. +func (h *MAC) Sum(b []byte) []byte { + return h.mac.Sum(b) +} + +// Verify returns whether the authenticator of all data written to +// the message authentication code matches the expected value. +func (h *MAC) Verify(expected []byte) bool { + return h.mac.Verify(expected) +} diff --git a/poly1305/sum_amd64.go b/poly1305/sum_amd64.go deleted file mode 100644 index 2dbf42aa53..0000000000 --- a/poly1305/sum_amd64.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -package poly1305 - -//go:noescape -func initialize(state *[7]uint64, key *[32]byte) - -//go:noescape -func update(state *[7]uint64, msg []byte) - -//go:noescape -func finalize(tag *[TagSize]byte, state *[7]uint64) - -// 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) { - h := newMAC(key) - h.Write(m) - h.Sum(out) -} - -func newMAC(key *[32]byte) (h mac) { - initialize(&h.state, key) - return -} - -type mac struct { - state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 } - - buffer [TagSize]byte - offset int -} - -func (h *mac) Write(p []byte) (n int, err error) { - n = len(p) - if h.offset > 0 { - remaining := TagSize - h.offset - if n < remaining { - h.offset += copy(h.buffer[h.offset:], p) - return n, nil - } - copy(h.buffer[h.offset:], p[:remaining]) - p = p[remaining:] - h.offset = 0 - update(&h.state, h.buffer[:]) - } - if nn := len(p) - (len(p) % TagSize); nn > 0 { - update(&h.state, p[:nn]) - p = p[nn:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return n, nil -} - -func (h *mac) Sum(out *[16]byte) { - state := h.state - if h.offset > 0 { - update(&state, h.buffer[:h.offset]) - } - finalize(out, &state) -} diff --git a/poly1305/sum_amd64.s b/poly1305/sum_amd64.s deleted file mode 100644 index 7d600f13cc..0000000000 --- a/poly1305/sum_amd64.s +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -#include "textflag.h" - -#define POLY1305_ADD(msg, h0, h1, h2) \ - ADDQ 0(msg), h0; \ - ADCQ 8(msg), h1; \ - ADCQ $1, h2; \ - LEAQ 16(msg), msg - -#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ - MOVQ r0, AX; \ - MULQ h0; \ - MOVQ AX, t0; \ - MOVQ DX, t1; \ - MOVQ r0, AX; \ - MULQ h1; \ - ADDQ AX, t1; \ - ADCQ $0, DX; \ - MOVQ r0, t2; \ - IMULQ h2, t2; \ - ADDQ DX, t2; \ - \ - MOVQ r1, AX; \ - MULQ h0; \ - ADDQ AX, t1; \ - ADCQ $0, DX; \ - MOVQ DX, h0; \ - MOVQ r1, t3; \ - IMULQ h2, t3; \ - MOVQ r1, AX; \ - MULQ h1; \ - ADDQ AX, t2; \ - ADCQ DX, t3; \ - ADDQ h0, t2; \ - ADCQ $0, t3; \ - \ - MOVQ t0, h0; \ - MOVQ t1, h1; \ - MOVQ t2, h2; \ - ANDQ $3, h2; \ - MOVQ t2, t0; \ - ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ - ADDQ t0, h0; \ - ADCQ t3, h1; \ - ADCQ $0, h2; \ - SHRQ $2, t3, t2; \ - SHRQ $2, t3; \ - ADDQ t2, h0; \ - ADCQ t3, h1; \ - ADCQ $0, h2 - -DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -GLOBL ·poly1305Mask<>(SB), RODATA, $16 - -// func update(state *[7]uint64, msg []byte) -TEXT ·update(SB), $0-32 - MOVQ state+0(FP), DI - MOVQ msg_base+8(FP), SI - MOVQ msg_len+16(FP), R15 - - MOVQ 0(DI), R8 // h0 - MOVQ 8(DI), R9 // h1 - MOVQ 16(DI), R10 // h2 - MOVQ 24(DI), R11 // r0 - MOVQ 32(DI), R12 // r1 - - CMPQ R15, $16 - JB bytes_between_0_and_15 - -loop: - POLY1305_ADD(SI, R8, R9, R10) - -multiply: - POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) - SUBQ $16, R15 - CMPQ R15, $16 - JAE loop - -bytes_between_0_and_15: - TESTQ R15, R15 - JZ done - MOVQ $1, BX - XORQ CX, CX - XORQ R13, R13 - ADDQ R15, SI - -flush_buffer: - SHLQ $8, BX, CX - SHLQ $8, BX - MOVB -1(SI), R13 - XORQ R13, BX - DECQ SI - DECQ R15 - JNZ flush_buffer - - ADDQ BX, R8 - ADCQ CX, R9 - ADCQ $0, R10 - MOVQ $16, R15 - JMP multiply - -done: - MOVQ R8, 0(DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - RET - -// func initialize(state *[7]uint64, key *[32]byte) -TEXT ·initialize(SB), $0-16 - MOVQ state+0(FP), DI - MOVQ key+8(FP), SI - - // state[0...7] is initialized with zero - MOVOU 0(SI), X0 - MOVOU 16(SI), X1 - MOVOU ·poly1305Mask<>(SB), X2 - PAND X2, X0 - MOVOU X0, 24(DI) - MOVOU X1, 40(DI) - RET - -// func finalize(tag *[TagSize]byte, state *[7]uint64) -TEXT ·finalize(SB), $0-16 - MOVQ tag+0(FP), DI - MOVQ state+8(FP), SI - - MOVQ 0(SI), AX - MOVQ 8(SI), BX - MOVQ 16(SI), CX - MOVQ AX, R8 - MOVQ BX, R9 - SUBQ $0xFFFFFFFFFFFFFFFB, AX - SBBQ $0xFFFFFFFFFFFFFFFF, BX - SBBQ $3, CX - CMOVQCS R8, AX - CMOVQCS R9, BX - ADDQ 40(SI), AX - ADCQ 48(SI), BX - - MOVQ AX, 0(DI) - MOVQ BX, 8(DI) - RET diff --git a/poly1305/sum_arm.go b/poly1305/sum_arm.go deleted file mode 100644 index 5dc321c2f3..0000000000 --- a/poly1305/sum_arm.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build arm,!gccgo,!appengine,!nacl - -package poly1305 - -// This function is implemented in sum_arm.s -//go:noescape -func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) - -// Sum generates an authenticator for m using a one-time key and puts the -// 16-byte result into out. Authenticating two different messages with the same -// key allows an attacker to forge messages at will. -func Sum(out *[16]byte, m []byte, key *[32]byte) { - var mPtr *byte - if len(m) > 0 { - mPtr = &m[0] - } - poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) -} diff --git a/poly1305/sum_arm.s b/poly1305/sum_arm.s deleted file mode 100644 index f70b4ac484..0000000000 --- a/poly1305/sum_arm.s +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build arm,!gccgo,!appengine,!nacl - -#include "textflag.h" - -// This code was translated into a form compatible with 5a from the public -// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. - -DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff -DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 -DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff -DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff -DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff -GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20 - -// Warning: the linker may use R11 to synthesize certain instructions. Please -// take care and verify that no synthetic instructions use it. - -TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0 - // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It - // might look like it's only 60 bytes of space but the final four bytes - // will be written by another function.) We need to skip over four - // bytes of stack because that's saving the value of 'g'. - ADD $4, R13, R8 - MOVM.IB [R4-R7], (R8) - MOVM.IA.W (R1), [R2-R5] - MOVW $·poly1305_init_constants_armv6<>(SB), R7 - MOVW R2, R8 - MOVW R2>>26, R9 - MOVW R3>>20, g - MOVW R4>>14, R11 - MOVW R5>>8, R12 - ORR R3<<6, R9, R9 - ORR R4<<12, g, g - ORR R5<<18, R11, R11 - MOVM.IA (R7), [R2-R6] - AND R8, R2, R2 - AND R9, R3, R3 - AND g, R4, R4 - AND R11, R5, R5 - AND R12, R6, R6 - MOVM.IA.W [R2-R6], (R0) - EOR R2, R2, R2 - EOR R3, R3, R3 - EOR R4, R4, R4 - EOR R5, R5, R5 - EOR R6, R6, R6 - MOVM.IA.W [R2-R6], (R0) - MOVM.IA.W (R1), [R2-R5] - MOVM.IA [R2-R6], (R0) - ADD $20, R13, R0 - MOVM.DA (R0), [R4-R7] - RET - -#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ - MOVBU (offset+0)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+0)(Rdst); \ - MOVBU (offset+1)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+1)(Rdst); \ - MOVBU (offset+2)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+2)(Rdst); \ - MOVBU (offset+3)(Rsrc), Rtmp; \ - MOVBU Rtmp, (offset+3)(Rdst) - -TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0 - // Needs 24 bytes of stack for saved registers and then 88 bytes of - // scratch space after that. We assume that 24 bytes at (R13) have - // already been used: four bytes for the link register saved in the - // prelude of poly1305_auth_armv6, four bytes for saving the value of g - // in that function and 16 bytes of scratch space used around - // poly1305_finish_ext_armv6_skip1. - ADD $24, R13, R12 - MOVM.IB [R4-R8, R14], (R12) - MOVW R0, 88(R13) - MOVW R1, 92(R13) - MOVW R2, 96(R13) - MOVW R1, R14 - MOVW R2, R12 - MOVW 56(R0), R8 - WORD $0xe1180008 // TST R8, R8 not working see issue 5921 - EOR R6, R6, R6 - MOVW.EQ $(1<<24), R6 - MOVW R6, 84(R13) - ADD $116, R13, g - MOVM.IA (R0), [R0-R9] - MOVM.IA [R0-R4], (g) - CMP $16, R12 - BLO poly1305_blocks_armv6_done - -poly1305_blocks_armv6_mainloop: - WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 - BEQ poly1305_blocks_armv6_mainloop_aligned - ADD $100, R13, g - MOVW_UNALIGNED(R14, g, R0, 0) - MOVW_UNALIGNED(R14, g, R0, 4) - MOVW_UNALIGNED(R14, g, R0, 8) - MOVW_UNALIGNED(R14, g, R0, 12) - MOVM.IA (g), [R0-R3] - ADD $16, R14 - B poly1305_blocks_armv6_mainloop_loaded - -poly1305_blocks_armv6_mainloop_aligned: - MOVM.IA.W (R14), [R0-R3] - -poly1305_blocks_armv6_mainloop_loaded: - MOVW R0>>26, g - MOVW R1>>20, R11 - MOVW R2>>14, R12 - MOVW R14, 92(R13) - MOVW R3>>8, R4 - ORR R1<<6, g, g - ORR R2<<12, R11, R11 - ORR R3<<18, R12, R12 - BIC $0xfc000000, R0, R0 - BIC $0xfc000000, g, g - MOVW 84(R13), R3 - BIC $0xfc000000, R11, R11 - BIC $0xfc000000, R12, R12 - ADD R0, R5, R5 - ADD g, R6, R6 - ORR R3, R4, R4 - ADD R11, R7, R7 - ADD $116, R13, R14 - ADD R12, R8, R8 - ADD R4, R9, R9 - MOVM.IA (R14), [R0-R4] - MULLU R4, R5, (R11, g) - MULLU R3, R5, (R14, R12) - MULALU R3, R6, (R11, g) - MULALU R2, R6, (R14, R12) - MULALU R2, R7, (R11, g) - MULALU R1, R7, (R14, R12) - ADD R4<<2, R4, R4 - ADD R3<<2, R3, R3 - MULALU R1, R8, (R11, g) - MULALU R0, R8, (R14, R12) - MULALU R0, R9, (R11, g) - MULALU R4, R9, (R14, R12) - MOVW g, 76(R13) - MOVW R11, 80(R13) - MOVW R12, 68(R13) - MOVW R14, 72(R13) - MULLU R2, R5, (R11, g) - MULLU R1, R5, (R14, R12) - MULALU R1, R6, (R11, g) - MULALU R0, R6, (R14, R12) - MULALU R0, R7, (R11, g) - MULALU R4, R7, (R14, R12) - ADD R2<<2, R2, R2 - ADD R1<<2, R1, R1 - MULALU R4, R8, (R11, g) - MULALU R3, R8, (R14, R12) - MULALU R3, R9, (R11, g) - MULALU R2, R9, (R14, R12) - MOVW g, 60(R13) - MOVW R11, 64(R13) - MOVW R12, 52(R13) - MOVW R14, 56(R13) - MULLU R0, R5, (R11, g) - MULALU R4, R6, (R11, g) - MULALU R3, R7, (R11, g) - MULALU R2, R8, (R11, g) - MULALU R1, R9, (R11, g) - ADD $52, R13, R0 - MOVM.IA (R0), [R0-R7] - MOVW g>>26, R12 - MOVW R4>>26, R14 - ORR R11<<6, R12, R12 - ORR R5<<6, R14, R14 - BIC $0xfc000000, g, g - BIC $0xfc000000, R4, R4 - ADD.S R12, R0, R0 - ADC $0, R1, R1 - ADD.S R14, R6, R6 - ADC $0, R7, R7 - MOVW R0>>26, R12 - MOVW R6>>26, R14 - ORR R1<<6, R12, R12 - ORR R7<<6, R14, R14 - BIC $0xfc000000, R0, R0 - BIC $0xfc000000, R6, R6 - ADD R14<<2, R14, R14 - ADD.S R12, R2, R2 - ADC $0, R3, R3 - ADD R14, g, g - MOVW R2>>26, R12 - MOVW g>>26, R14 - ORR R3<<6, R12, R12 - BIC $0xfc000000, g, R5 - BIC $0xfc000000, R2, R7 - ADD R12, R4, R4 - ADD R14, R0, R0 - MOVW R4>>26, R12 - BIC $0xfc000000, R4, R8 - ADD R12, R6, R9 - MOVW 96(R13), R12 - MOVW 92(R13), R14 - MOVW R0, R6 - CMP $32, R12 - SUB $16, R12, R12 - MOVW R12, 96(R13) - BHS poly1305_blocks_armv6_mainloop - -poly1305_blocks_armv6_done: - MOVW 88(R13), R12 - MOVW R5, 20(R12) - MOVW R6, 24(R12) - MOVW R7, 28(R12) - MOVW R8, 32(R12) - MOVW R9, 36(R12) - ADD $48, R13, R0 - MOVM.DA (R0), [R4-R8, R14] - RET - -#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ - MOVBU.P 1(Rsrc), Rtmp; \ - MOVBU.P Rtmp, 1(Rdst); \ - MOVBU.P 1(Rsrc), Rtmp; \ - MOVBU.P Rtmp, 1(Rdst) - -#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ - MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ - MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) - -// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) -TEXT ·poly1305_auth_armv6(SB), $196-16 - // The value 196, just above, is the sum of 64 (the size of the context - // structure) and 132 (the amount of stack needed). - // - // At this point, the stack pointer (R13) has been moved down. It - // points to the saved link register and there's 196 bytes of free - // space above it. - // - // The stack for this function looks like: - // - // +--------------------- - // | - // | 64 bytes of context structure - // | - // +--------------------- - // | - // | 112 bytes for poly1305_blocks_armv6 - // | - // +--------------------- - // | 16 bytes of final block, constructed at - // | poly1305_finish_ext_armv6_skip8 - // +--------------------- - // | four bytes of saved 'g' - // +--------------------- - // | lr, saved by prelude <- R13 points here - // +--------------------- - MOVW g, 4(R13) - - MOVW out+0(FP), R4 - MOVW m+4(FP), R5 - MOVW mlen+8(FP), R6 - MOVW key+12(FP), R7 - - ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112 - MOVW R7, R1 - - // poly1305_init_ext_armv6 will write to the stack from R13+4, but - // that's ok because none of the other values have been written yet. - BL poly1305_init_ext_armv6<>(SB) - BIC.S $15, R6, R2 - BEQ poly1305_auth_armv6_noblocks - ADD $136, R13, R0 - MOVW R5, R1 - ADD R2, R5, R5 - SUB R2, R6, R6 - BL poly1305_blocks_armv6<>(SB) - -poly1305_auth_armv6_noblocks: - ADD $136, R13, R0 - MOVW R5, R1 - MOVW R6, R2 - MOVW R4, R3 - - MOVW R0, R5 - MOVW R1, R6 - MOVW R2, R7 - MOVW R3, R8 - AND.S R2, R2, R2 - BEQ poly1305_finish_ext_armv6_noremaining - EOR R0, R0 - ADD $8, R13, R9 // 8 = offset to 16 byte scratch space - MOVW R0, (R9) - MOVW R0, 4(R9) - MOVW R0, 8(R9) - MOVW R0, 12(R9) - WORD $0xe3110003 // TST R1, #3 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_aligned - WORD $0xe3120008 // TST R2, #8 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip8 - MOVWP_UNALIGNED(R1, R9, g) - MOVWP_UNALIGNED(R1, R9, g) - -poly1305_finish_ext_armv6_skip8: - WORD $0xe3120004 // TST $4, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip4 - MOVWP_UNALIGNED(R1, R9, g) - -poly1305_finish_ext_armv6_skip4: - WORD $0xe3120002 // TST $2, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip2 - MOVHUP_UNALIGNED(R1, R9, g) - B poly1305_finish_ext_armv6_skip2 - -poly1305_finish_ext_armv6_aligned: - WORD $0xe3120008 // TST R2, #8 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip8_aligned - MOVM.IA.W (R1), [g-R11] - MOVM.IA.W [g-R11], (R9) - -poly1305_finish_ext_armv6_skip8_aligned: - WORD $0xe3120004 // TST $4, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip4_aligned - MOVW.P 4(R1), g - MOVW.P g, 4(R9) - -poly1305_finish_ext_armv6_skip4_aligned: - WORD $0xe3120002 // TST $2, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip2 - MOVHU.P 2(R1), g - MOVH.P g, 2(R9) - -poly1305_finish_ext_armv6_skip2: - WORD $0xe3120001 // TST $1, R2 not working see issue 5921 - BEQ poly1305_finish_ext_armv6_skip1 - MOVBU.P 1(R1), g - MOVBU.P g, 1(R9) - -poly1305_finish_ext_armv6_skip1: - MOVW $1, R11 - MOVBU R11, 0(R9) - MOVW R11, 56(R5) - MOVW R5, R0 - ADD $8, R13, R1 - MOVW $16, R2 - BL poly1305_blocks_armv6<>(SB) - -poly1305_finish_ext_armv6_noremaining: - MOVW 20(R5), R0 - MOVW 24(R5), R1 - MOVW 28(R5), R2 - MOVW 32(R5), R3 - MOVW 36(R5), R4 - MOVW R4>>26, R12 - BIC $0xfc000000, R4, R4 - ADD R12<<2, R12, R12 - ADD R12, R0, R0 - MOVW R0>>26, R12 - BIC $0xfc000000, R0, R0 - ADD R12, R1, R1 - MOVW R1>>26, R12 - BIC $0xfc000000, R1, R1 - ADD R12, R2, R2 - MOVW R2>>26, R12 - BIC $0xfc000000, R2, R2 - ADD R12, R3, R3 - MOVW R3>>26, R12 - BIC $0xfc000000, R3, R3 - ADD R12, R4, R4 - ADD $5, R0, R6 - MOVW R6>>26, R12 - BIC $0xfc000000, R6, R6 - ADD R12, R1, R7 - MOVW R7>>26, R12 - BIC $0xfc000000, R7, R7 - ADD R12, R2, g - MOVW g>>26, R12 - BIC $0xfc000000, g, g - ADD R12, R3, R11 - MOVW $-(1<<26), R12 - ADD R11>>26, R12, R12 - BIC $0xfc000000, R11, R11 - ADD R12, R4, R9 - MOVW R9>>31, R12 - SUB $1, R12 - AND R12, R6, R6 - AND R12, R7, R7 - AND R12, g, g - AND R12, R11, R11 - AND R12, R9, R9 - MVN R12, R12 - AND R12, R0, R0 - AND R12, R1, R1 - AND R12, R2, R2 - AND R12, R3, R3 - AND R12, R4, R4 - ORR R6, R0, R0 - ORR R7, R1, R1 - ORR g, R2, R2 - ORR R11, R3, R3 - ORR R9, R4, R4 - ORR R1<<26, R0, R0 - MOVW R1>>6, R1 - ORR R2<<20, R1, R1 - MOVW R2>>12, R2 - ORR R3<<14, R2, R2 - MOVW R3>>18, R3 - ORR R4<<8, R3, R3 - MOVW 40(R5), R6 - MOVW 44(R5), R7 - MOVW 48(R5), g - MOVW 52(R5), R11 - ADD.S R6, R0, R0 - ADC.S R7, R1, R1 - ADC.S g, R2, R2 - ADC.S R11, R3, R3 - MOVM.IA [R0-R3], (R8) - MOVW R5, R12 - EOR R0, R0, R0 - EOR R1, R1, R1 - EOR R2, R2, R2 - EOR R3, R3, R3 - EOR R4, R4, R4 - EOR R5, R5, R5 - EOR R6, R6, R6 - EOR R7, R7, R7 - MOVM.IA.W [R0-R7], (R12) - MOVM.IA [R0-R7], (R12) - MOVW 4(R13), g - RET diff --git a/poly1305/sum_generic.go b/poly1305/sum_generic.go deleted file mode 100644 index bab76ef0d8..0000000000 --- a/poly1305/sum_generic.go +++ /dev/null @@ -1,172 +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 poly1305 - -import "encoding/binary" - -const ( - msgBlock = uint32(1 << 24) - finalBlock = uint32(0) -) - -// sumGeneric generates an authenticator for msg using a one-time key and -// puts the 16-byte result into out. This is the generic implementation of -// Sum and should be called if no assembly implementation is available. -func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { - h := newMACGeneric(key) - h.Write(msg) - h.Sum(out) -} - -func newMACGeneric(key *[32]byte) (h macGeneric) { - h.r[0] = binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff - h.r[1] = (binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03 - h.r[2] = (binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff - h.r[3] = (binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff - h.r[4] = (binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff - - h.s[0] = binary.LittleEndian.Uint32(key[16:]) - h.s[1] = binary.LittleEndian.Uint32(key[20:]) - h.s[2] = binary.LittleEndian.Uint32(key[24:]) - h.s[3] = binary.LittleEndian.Uint32(key[28:]) - return -} - -type macGeneric struct { - h, r [5]uint32 - s [4]uint32 - - buffer [TagSize]byte - offset int -} - -func (h *macGeneric) Write(p []byte) (n int, err error) { - n = len(p) - if h.offset > 0 { - remaining := TagSize - h.offset - if n < remaining { - h.offset += copy(h.buffer[h.offset:], p) - return n, nil - } - copy(h.buffer[h.offset:], p[:remaining]) - p = p[remaining:] - h.offset = 0 - updateGeneric(h.buffer[:], msgBlock, &(h.h), &(h.r)) - } - if nn := len(p) - (len(p) % TagSize); nn > 0 { - updateGeneric(p, msgBlock, &(h.h), &(h.r)) - p = p[nn:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return n, nil -} - -func (h *macGeneric) Sum(out *[16]byte) { - H, R := h.h, h.r - if h.offset > 0 { - var buffer [TagSize]byte - copy(buffer[:], h.buffer[:h.offset]) - buffer[h.offset] = 1 // invariant: h.offset < TagSize - updateGeneric(buffer[:], finalBlock, &H, &R) - } - finalizeGeneric(out, &H, &(h.s)) -} - -func updateGeneric(msg []byte, flag uint32, h, r *[5]uint32) { - h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4] - r0, r1, r2, r3, r4 := uint64(r[0]), uint64(r[1]), uint64(r[2]), uint64(r[3]), uint64(r[4]) - R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5 - - for len(msg) >= TagSize { - // h += msg - h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff - h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff - h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff - h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff - h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | flag - - // h *= r - d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1) - d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2) - d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3) - d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4) - d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0) - - // h %= p - h0 = uint32(d0) & 0x3ffffff - h1 = uint32(d1) & 0x3ffffff - h2 = uint32(d2) & 0x3ffffff - h3 = uint32(d3) & 0x3ffffff - h4 = uint32(d4) & 0x3ffffff - - h0 += uint32(d4>>26) * 5 - h1 += h0 >> 26 - h0 = h0 & 0x3ffffff - - msg = msg[TagSize:] - } - - h[0], h[1], h[2], h[3], h[4] = h0, h1, h2, h3, h4 -} - -func finalizeGeneric(out *[TagSize]byte, h *[5]uint32, s *[4]uint32) { - h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4] - - // h %= p reduction - h2 += h1 >> 26 - h1 &= 0x3ffffff - h3 += h2 >> 26 - h2 &= 0x3ffffff - h4 += h3 >> 26 - h3 &= 0x3ffffff - h0 += 5 * (h4 >> 26) - h4 &= 0x3ffffff - h1 += h0 >> 26 - h0 &= 0x3ffffff - - // h - p - t0 := h0 + 5 - t1 := h1 + (t0 >> 26) - t2 := h2 + (t1 >> 26) - t3 := h3 + (t2 >> 26) - t4 := h4 + (t3 >> 26) - (1 << 26) - t0 &= 0x3ffffff - t1 &= 0x3ffffff - t2 &= 0x3ffffff - t3 &= 0x3ffffff - - // select h if h < p else h - p - t_mask := (t4 >> 31) - 1 - h_mask := ^t_mask - h0 = (h0 & h_mask) | (t0 & t_mask) - h1 = (h1 & h_mask) | (t1 & t_mask) - h2 = (h2 & h_mask) | (t2 & t_mask) - h3 = (h3 & h_mask) | (t3 & t_mask) - h4 = (h4 & h_mask) | (t4 & t_mask) - - // h %= 2^128 - h0 |= h1 << 26 - h1 = ((h1 >> 6) | (h2 << 20)) - h2 = ((h2 >> 12) | (h3 << 14)) - h3 = ((h3 >> 18) | (h4 << 8)) - - // s: the s part of the key - // tag = (h + s) % (2^128) - t := uint64(h0) + uint64(s[0]) - h0 = uint32(t) - t = uint64(h1) + uint64(s[1]) + (t >> 32) - h1 = uint32(t) - t = uint64(h2) + uint64(s[2]) + (t >> 32) - h2 = uint32(t) - t = uint64(h3) + uint64(s[3]) + (t >> 32) - h3 = uint32(t) - - binary.LittleEndian.PutUint32(out[0:], h0) - binary.LittleEndian.PutUint32(out[4:], h1) - binary.LittleEndian.PutUint32(out[8:], h2) - binary.LittleEndian.PutUint32(out[12:], h3) -} diff --git a/poly1305/sum_noasm.go b/poly1305/sum_noasm.go deleted file mode 100644 index 8a9c2070b9..0000000000 --- a/poly1305/sum_noasm.go +++ /dev/null @@ -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,!go1.11 !arm,!amd64,!s390x,!ppc64le 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) { - h := newMAC(key) - h.Write(msg) - h.Sum(out) -} diff --git a/poly1305/sum_ppc64le.go b/poly1305/sum_ppc64le.go deleted file mode 100644 index 2402b6371b..0000000000 --- a/poly1305/sum_ppc64le.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2019 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 ppc64le,!gccgo,!appengine - -package poly1305 - -//go:noescape -func initialize(state *[7]uint64, key *[32]byte) - -//go:noescape -func update(state *[7]uint64, msg []byte) - -//go:noescape -func finalize(tag *[TagSize]byte, state *[7]uint64) - -// 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) { - h := newMAC(key) - h.Write(m) - h.Sum(out) -} - -func newMAC(key *[32]byte) (h mac) { - initialize(&h.state, key) - return -} - -type mac struct { - state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 } - - buffer [TagSize]byte - offset int -} - -func (h *mac) Write(p []byte) (n int, err error) { - n = len(p) - if h.offset > 0 { - remaining := TagSize - h.offset - if n < remaining { - h.offset += copy(h.buffer[h.offset:], p) - return n, nil - } - copy(h.buffer[h.offset:], p[:remaining]) - p = p[remaining:] - h.offset = 0 - update(&h.state, h.buffer[:]) - } - if nn := len(p) - (len(p) % TagSize); nn > 0 { - update(&h.state, p[:nn]) - p = p[nn:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return n, nil -} - -func (h *mac) Sum(out *[16]byte) { - state := h.state - if h.offset > 0 { - update(&state, h.buffer[:h.offset]) - } - finalize(out, &state) -} diff --git a/poly1305/sum_s390x.go b/poly1305/sum_s390x.go deleted file mode 100644 index ec99e07e9f..0000000000 --- a/poly1305/sum_s390x.go +++ /dev/null @@ -1,42 +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 - -import ( - "golang.org/x/sys/cpu" -) - -// 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 cpu.S390X.HasVX { - var mPtr *byte - if len(m) > 0 { - mPtr = &m[0] - } - if cpu.S390X.HasVXE && len(m) > 256 { - poly1305vmsl(out, mPtr, uint64(len(m)), key) - } else { - poly1305vx(out, mPtr, uint64(len(m)), key) - } - } else { - sumGeneric(out, m, key) - } -} diff --git a/poly1305/sum_s390x.s b/poly1305/sum_s390x.s deleted file mode 100644 index ca5a309d86..0000000000 --- a/poly1305/sum_s390x.s +++ /dev/null @@ -1,378 +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 diff --git a/poly1305/sum_vmsl_s390x.s b/poly1305/sum_vmsl_s390x.s deleted file mode 100644 index e60bbc1d7f..0000000000 --- a/poly1305/sum_vmsl_s390x.s +++ /dev/null @@ -1,909 +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 diff --git a/ripemd160/ripemd160.go b/ripemd160/ripemd160.go index cf3eeb158a..b6d33ef074 100644 --- a/ripemd160/ripemd160.go +++ b/ripemd160/ripemd160.go @@ -7,7 +7,7 @@ // Deprecated: RIPEMD-160 is a legacy hash and should not be used for new // applications. Also, this package does not and will not provide an optimized // implementation. Instead, use a modern hash like SHA-256 (from crypto/sha256). -package ripemd160 // import "golang.org/x/crypto/ripemd160" +package ripemd160 // RIPEMD-160 is designed by Hans Dobbertin, Antoon Bosselaers, and Bart // Preneel with specifications available at: diff --git a/salsa20/salsa/_asm/go.mod b/salsa20/salsa/_asm/go.mod new file mode 100644 index 0000000000..2de7bf107b --- /dev/null +++ b/salsa20/salsa/_asm/go.mod @@ -0,0 +1,14 @@ +module salsa20/salsa/_asm + +go 1.23 + +require ( + github.com/mmcloughlin/avo v0.6.0 + golang.org/x/crypto v0.33.0 +) + +require ( + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect +) diff --git a/salsa20/salsa/_asm/go.sum b/salsa20/salsa/_asm/go.sum new file mode 100644 index 0000000000..4d48823d47 --- /dev/null +++ b/salsa20/salsa/_asm/go.sum @@ -0,0 +1,10 @@ +github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= +github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= diff --git a/salsa20/salsa/_asm/salsa20_amd64_asm.go b/salsa20/salsa/_asm/salsa20_amd64_asm.go new file mode 100644 index 0000000000..6546791c4c --- /dev/null +++ b/salsa20/salsa/_asm/salsa20_amd64_asm.go @@ -0,0 +1,932 @@ +// Copyright 2024 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html + +package main + +import ( + . "github.com/mmcloughlin/avo/build" + "github.com/mmcloughlin/avo/ir" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" + _ "golang.org/x/crypto/salsa20/salsa" +) + +//go:generate go run . -out ../salsa20_amd64.s -pkg salsa + +func main() { + Package("golang.org/x/crypto/salsa20/salsa") + ConstraintExpr("amd64,!purego,gc") + salsa2020XORKeyStream() + Generate() +} + +func salsa2020XORKeyStream() { + Implement("salsa2020XORKeyStream") + Attributes(0) + AllocLocal(456) // frame = 424 + 32 byte alignment + Comment("This needs up to 64 bytes at 360(R12); hence the non-obvious frame size.") + + Load(Param("out"), RDI) + Load(Param("in"), RSI) + Load(Param("n"), RDX) + Load(Param("nonce"), RCX) + Load(Param("key"), R8) + + MOVQ(RSP, R12) + ADDQ(Imm(31), R12) + ANDQ(I32(^31), R12) + + MOVQ(RDX, R9) + MOVQ(RCX, RDX) + MOVQ(R8, R10) + CMPQ(R9, Imm(0)) + JBE(LabelRef("DONE")) + + START() + BYTESATLEAST256() + MAINLOOP1() + BYTESBETWEEN1AND255() + NOCOPY() + MAINLOOP2() + + Label("BYTESATLEAST64") + Label("DONE") + RET() + Label("BYTESATLEAST65") + SUBQ(Imm(64), R9) + ADDQ(Imm(64), RDI) + ADDQ(Imm(64), RSI) + JMP(LabelRef("BYTESBETWEEN1AND255")) +} + +func START() { + Label("START") + MOVL(Mem{Base: R10}.Offset(20), ECX) + MOVL(Mem{Base: R10}.Offset(0), R8L) + MOVL(Mem{Base: EDX}.Offset(0), EAX) + MOVL(Mem{Base: R10}.Offset(16), R11L) + MOVL(ECX, Mem{Base: R12}.Offset(0)) + MOVL(R8L, Mem{Base: R12}.Offset(4)) + MOVL(EAX, Mem{Base: R12}.Offset(8)) + MOVL(R11L, Mem{Base: R12}.Offset(12)) + MOVL(Mem{Base: EDX}.Offset(8), ECX) + MOVL(Mem{Base: R10}.Offset(24), R8L) + MOVL(Mem{Base: R10}.Offset(4), EAX) + MOVL(Mem{Base: EDX}.Offset(4), R11L) + MOVL(ECX, Mem{Base: R12}.Offset(16)) + MOVL(R8L, Mem{Base: R12}.Offset(20)) + MOVL(EAX, Mem{Base: R12}.Offset(24)) + MOVL(R11L, Mem{Base: R12}.Offset(28)) + MOVL(Mem{Base: EDX}.Offset(12), ECX) + MOVL(Mem{Base: R10}.Offset(12), EDX) + MOVL(Mem{Base: R10}.Offset(28), R8L) + MOVL(Mem{Base: R10}.Offset(8), EAX) + MOVL(EDX, Mem{Base: R12}.Offset(32)) + MOVL(ECX, Mem{Base: R12}.Offset(36)) + MOVL(R8L, Mem{Base: R12}.Offset(40)) + MOVL(EAX, Mem{Base: R12}.Offset(44)) + MOVQ(Imm(1634760805), RDX) + MOVQ(Imm(857760878), RCX) + MOVQ(Imm(2036477234), R8) + MOVQ(Imm(1797285236), RAX) + MOVL(EDX, Mem{Base: R12}.Offset(48)) + MOVL(ECX, Mem{Base: R12}.Offset(52)) + MOVL(R8L, Mem{Base: R12}.Offset(56)) + MOVL(EAX, Mem{Base: R12}.Offset(60)) + CMPQ(R9, U32(256)) + JB(LabelRef("BYTESBETWEEN1AND255")) + MOVOA(Mem{Base: R12}.Offset(48), X0) + PSHUFL(Imm(0x55), X0, X1) + PSHUFL(Imm(0xAA), X0, X2) + PSHUFL(Imm(0xFF), X0, X3) + PSHUFL(Imm(0x00), X0, X0) + MOVOA(X1, Mem{Base: R12}.Offset(64)) + MOVOA(X2, Mem{Base: R12}.Offset(80)) + MOVOA(X3, Mem{Base: R12}.Offset(96)) + MOVOA(X0, Mem{Base: R12}.Offset(112)) + MOVOA(Mem{Base: R12}.Offset(0), X0) + PSHUFL(Imm(0xAA), X0, X1) + PSHUFL(Imm(0xFF), X0, X2) + PSHUFL(Imm(0x00), X0, X3) + PSHUFL(Imm(0x55), X0, X0) + MOVOA(X1, Mem{Base: R12}.Offset(128)) + MOVOA(X2, Mem{Base: R12}.Offset(144)) + MOVOA(X3, Mem{Base: R12}.Offset(160)) + MOVOA(X0, Mem{Base: R12}.Offset(176)) + MOVOA(Mem{Base: R12}.Offset(16), X0) + PSHUFL(Imm(0xFF), X0, X1) + PSHUFL(Imm(0x55), X0, X2) + PSHUFL(Imm(0xAA), X0, X0) + MOVOA(X1, Mem{Base: R12}.Offset(192)) + MOVOA(X2, Mem{Base: R12}.Offset(208)) + MOVOA(X0, Mem{Base: R12}.Offset(224)) + MOVOA(Mem{Base: R12}.Offset(32), X0) + PSHUFL(Imm(0x00), X0, X1) + PSHUFL(Imm(0xAA), X0, X2) + PSHUFL(Imm(0xFF), X0, X0) + MOVOA(X1, Mem{Base: R12}.Offset(240)) + MOVOA(X2, Mem{Base: R12}.Offset(256)) + MOVOA(X0, Mem{Base: R12}.Offset(272)) + +} + +func BYTESATLEAST256() { + Label("BYTESATLEAST256") + MOVL(Mem{Base: R12}.Offset(16), EDX) + MOVL(Mem{Base: R12}.Offset(36), ECX) + MOVL(EDX, Mem{Base: R12}.Offset(288)) + MOVL(ECX, Mem{Base: R12}.Offset(304)) + SHLQ(Imm(32), RCX) + ADDQ(RCX, RDX) + ADDQ(Imm(1), RDX) + MOVQ(RDX, RCX) + SHRQ(Imm(32), RCX) + MOVL(EDX, Mem{Base: R12}.Offset(292)) + MOVL(ECX, Mem{Base: R12}.Offset(308)) + ADDQ(Imm(1), RDX) + MOVQ(RDX, RCX) + SHRQ(Imm(32), RCX) + MOVL(EDX, Mem{Base: R12}.Offset(296)) + MOVL(ECX, Mem{Base: R12}.Offset(312)) + ADDQ(Imm(1), RDX) + MOVQ(RDX, RCX) + SHRQ(Imm(32), RCX) + MOVL(EDX, Mem{Base: R12}.Offset(300)) + MOVL(ECX, Mem{Base: R12}.Offset(316)) + ADDQ(Imm(1), RDX) + MOVQ(RDX, RCX) + SHRQ(Imm(32), RCX) + MOVL(EDX, Mem{Base: R12}.Offset(16)) + MOVL(ECX, Mem{Base: R12}.Offset(36)) + MOVQ(R9, Mem{Base: R12}.Offset(352)) + MOVQ(U32(20), RDX) + MOVOA(Mem{Base: R12}.Offset(64), X0) + MOVOA(Mem{Base: R12}.Offset(80), X1) + MOVOA(Mem{Base: R12}.Offset(96), X2) + MOVOA(Mem{Base: R12}.Offset(256), X3) + MOVOA(Mem{Base: R12}.Offset(272), X4) + MOVOA(Mem{Base: R12}.Offset(128), X5) + MOVOA(Mem{Base: R12}.Offset(144), X6) + MOVOA(Mem{Base: R12}.Offset(176), X7) + MOVOA(Mem{Base: R12}.Offset(192), X8) + MOVOA(Mem{Base: R12}.Offset(208), X9) + MOVOA(Mem{Base: R12}.Offset(224), X10) + MOVOA(Mem{Base: R12}.Offset(304), X11) + MOVOA(Mem{Base: R12}.Offset(112), X12) + MOVOA(Mem{Base: R12}.Offset(160), X13) + MOVOA(Mem{Base: R12}.Offset(240), X14) + MOVOA(Mem{Base: R12}.Offset(288), X15) +} + +func MAINLOOP1() { + Label("MAINLOOP1") + MOVOA(X1, Mem{Base: R12}.Offset(320)) + MOVOA(X2, Mem{Base: R12}.Offset(336)) + MOVOA(X13, X1) + PADDL(X12, X1) + MOVOA(X1, X2) + PSLLL(Imm(7), X1) + PXOR(X1, X14) + PSRLL(Imm(25), X2) + PXOR(X2, X14) + MOVOA(X7, X1) + PADDL(X0, X1) + MOVOA(X1, X2) + PSLLL(Imm(7), X1) + PXOR(X1, X11) + PSRLL(Imm(25), X2) + PXOR(X2, X11) + MOVOA(X12, X1) + PADDL(X14, X1) + MOVOA(X1, X2) + PSLLL(Imm(9), X1) + PXOR(X1, X15) + PSRLL(Imm(23), X2) + PXOR(X2, X15) + MOVOA(X0, X1) + PADDL(X11, X1) + MOVOA(X1, X2) + PSLLL(Imm(9), X1) + PXOR(X1, X9) + PSRLL(Imm(23), X2) + PXOR(X2, X9) + MOVOA(X14, X1) + PADDL(X15, X1) + MOVOA(X1, X2) + PSLLL(Imm(13), X1) + PXOR(X1, X13) + PSRLL(Imm(19), X2) + PXOR(X2, X13) + MOVOA(X11, X1) + PADDL(X9, X1) + MOVOA(X1, X2) + PSLLL(Imm(13), X1) + PXOR(X1, X7) + PSRLL(Imm(19), X2) + PXOR(X2, X7) + MOVOA(X15, X1) + PADDL(X13, X1) + MOVOA(X1, X2) + PSLLL(Imm(18), X1) + PXOR(X1, X12) + PSRLL(Imm(14), X2) + PXOR(X2, X12) + MOVOA(Mem{Base: R12}.Offset(320), X1) + MOVOA(X12, Mem{Base: R12}.Offset(320)) + MOVOA(X9, X2) + PADDL(X7, X2) + MOVOA(X2, X12) + PSLLL(Imm(18), X2) + PXOR(X2, X0) + PSRLL(Imm(14), X12) + PXOR(X12, X0) + MOVOA(X5, X2) + PADDL(X1, X2) + MOVOA(X2, X12) + PSLLL(Imm(7), X2) + PXOR(X2, X3) + PSRLL(Imm(25), X12) + PXOR(X12, X3) + MOVOA(Mem{Base: R12}.Offset(336), X2) + MOVOA(X0, Mem{Base: R12}.Offset(336)) + MOVOA(X6, X0) + PADDL(X2, X0) + MOVOA(X0, X12) + PSLLL(Imm(7), X0) + PXOR(X0, X4) + PSRLL(Imm(25), X12) + PXOR(X12, X4) + MOVOA(X1, X0) + PADDL(X3, X0) + MOVOA(X0, X12) + PSLLL(Imm(9), X0) + PXOR(X0, X10) + PSRLL(Imm(23), X12) + PXOR(X12, X10) + MOVOA(X2, X0) + PADDL(X4, X0) + MOVOA(X0, X12) + PSLLL(Imm(9), X0) + PXOR(X0, X8) + PSRLL(Imm(23), X12) + PXOR(X12, X8) + MOVOA(X3, X0) + PADDL(X10, X0) + MOVOA(X0, X12) + PSLLL(Imm(13), X0) + PXOR(X0, X5) + PSRLL(Imm(19), X12) + PXOR(X12, X5) + MOVOA(X4, X0) + PADDL(X8, X0) + MOVOA(X0, X12) + PSLLL(Imm(13), X0) + PXOR(X0, X6) + PSRLL(Imm(19), X12) + PXOR(X12, X6) + MOVOA(X10, X0) + PADDL(X5, X0) + MOVOA(X0, X12) + PSLLL(Imm(18), X0) + PXOR(X0, X1) + PSRLL(Imm(14), X12) + PXOR(X12, X1) + MOVOA(Mem{Base: R12}.Offset(320), X0) + MOVOA(X1, Mem{Base: R12}.Offset(320)) + MOVOA(X4, X1) + PADDL(X0, X1) + MOVOA(X1, X12) + PSLLL(Imm(7), X1) + PXOR(X1, X7) + PSRLL(Imm(25), X12) + PXOR(X12, X7) + MOVOA(X8, X1) + PADDL(X6, X1) + MOVOA(X1, X12) + PSLLL(Imm(18), X1) + PXOR(X1, X2) + PSRLL(Imm(14), X12) + PXOR(X12, X2) + MOVOA(Mem{Base: R12}.Offset(336), X12) + MOVOA(X2, Mem{Base: R12}.Offset(336)) + MOVOA(X14, X1) + PADDL(X12, X1) + MOVOA(X1, X2) + PSLLL(Imm(7), X1) + PXOR(X1, X5) + PSRLL(Imm(25), X2) + PXOR(X2, X5) + MOVOA(X0, X1) + PADDL(X7, X1) + MOVOA(X1, X2) + PSLLL(Imm(9), X1) + PXOR(X1, X10) + PSRLL(Imm(23), X2) + PXOR(X2, X10) + MOVOA(X12, X1) + PADDL(X5, X1) + MOVOA(X1, X2) + PSLLL(Imm(9), X1) + PXOR(X1, X8) + PSRLL(Imm(23), X2) + PXOR(X2, X8) + MOVOA(X7, X1) + PADDL(X10, X1) + MOVOA(X1, X2) + PSLLL(Imm(13), X1) + PXOR(X1, X4) + PSRLL(Imm(19), X2) + PXOR(X2, X4) + MOVOA(X5, X1) + PADDL(X8, X1) + MOVOA(X1, X2) + PSLLL(Imm(13), X1) + PXOR(X1, X14) + PSRLL(Imm(19), X2) + PXOR(X2, X14) + MOVOA(X10, X1) + PADDL(X4, X1) + MOVOA(X1, X2) + PSLLL(Imm(18), X1) + PXOR(X1, X0) + PSRLL(Imm(14), X2) + PXOR(X2, X0) + MOVOA(Mem{Base: R12}.Offset(320), X1) + MOVOA(X0, Mem{Base: R12}.Offset(320)) + MOVOA(X8, X0) + PADDL(X14, X0) + MOVOA(X0, X2) + PSLLL(Imm(18), X0) + PXOR(X0, X12) + PSRLL(Imm(14), X2) + PXOR(X2, X12) + MOVOA(X11, X0) + PADDL(X1, X0) + MOVOA(X0, X2) + PSLLL(Imm(7), X0) + PXOR(X0, X6) + PSRLL(Imm(25), X2) + PXOR(X2, X6) + MOVOA(Mem{Base: R12}.Offset(336), X2) + MOVOA(X12, Mem{Base: R12}.Offset(336)) + MOVOA(X3, X0) + PADDL(X2, X0) + MOVOA(X0, X12) + PSLLL(Imm(7), X0) + PXOR(X0, X13) + PSRLL(Imm(25), X12) + PXOR(X12, X13) + MOVOA(X1, X0) + PADDL(X6, X0) + MOVOA(X0, X12) + PSLLL(Imm(9), X0) + PXOR(X0, X15) + PSRLL(Imm(23), X12) + PXOR(X12, X15) + MOVOA(X2, X0) + PADDL(X13, X0) + MOVOA(X0, X12) + PSLLL(Imm(9), X0) + PXOR(X0, X9) + PSRLL(Imm(23), X12) + PXOR(X12, X9) + MOVOA(X6, X0) + PADDL(X15, X0) + MOVOA(X0, X12) + PSLLL(Imm(13), X0) + PXOR(X0, X11) + PSRLL(Imm(19), X12) + PXOR(X12, X11) + MOVOA(X13, X0) + PADDL(X9, X0) + MOVOA(X0, X12) + PSLLL(Imm(13), X0) + PXOR(X0, X3) + PSRLL(Imm(19), X12) + PXOR(X12, X3) + MOVOA(X15, X0) + PADDL(X11, X0) + MOVOA(X0, X12) + PSLLL(Imm(18), X0) + PXOR(X0, X1) + PSRLL(Imm(14), X12) + PXOR(X12, X1) + MOVOA(X9, X0) + PADDL(X3, X0) + MOVOA(X0, X12) + PSLLL(Imm(18), X0) + PXOR(X0, X2) + PSRLL(Imm(14), X12) + PXOR(X12, X2) + MOVOA(Mem{Base: R12}.Offset(320), X12) + MOVOA(Mem{Base: R12}.Offset(336), X0) + SUBQ(Imm(2), RDX) + JA(LabelRef("MAINLOOP1")) + PADDL(Mem{Base: R12}.Offset(112), X12) + PADDL(Mem{Base: R12}.Offset(176), X7) + PADDL(Mem{Base: R12}.Offset(224), X10) + PADDL(Mem{Base: R12}.Offset(272), X4) + MOVD(X12, EDX) + MOVD(X7, ECX) + MOVD(X10, R8) + MOVD(X4, R9) + PSHUFL(Imm(0x39), X12, X12) + PSHUFL(Imm(0x39), X7, X7) + PSHUFL(Imm(0x39), X10, X10) + PSHUFL(Imm(0x39), X4, X4) + XORL(Mem{Base: SI}.Offset(0), EDX) + XORL(Mem{Base: SI}.Offset(4), ECX) + XORL(Mem{Base: SI}.Offset(8), R8L) + XORL(Mem{Base: SI}.Offset(12), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(0)) + MOVL(ECX, Mem{Base: DI}.Offset(4)) + MOVL(R8L, Mem{Base: DI}.Offset(8)) + MOVL(R9L, Mem{Base: DI}.Offset(12)) + MOVD(X12, EDX) + MOVD(X7, ECX) + MOVD(X10, R8) + MOVD(X4, R9) + PSHUFL(Imm(0x39), X12, X12) + PSHUFL(Imm(0x39), X7, X7) + PSHUFL(Imm(0x39), X10, X10) + PSHUFL(Imm(0x39), X4, X4) + XORL(Mem{Base: SI}.Offset(64), EDX) + XORL(Mem{Base: SI}.Offset(68), ECX) + XORL(Mem{Base: SI}.Offset(72), R8L) + XORL(Mem{Base: SI}.Offset(76), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(64)) + MOVL(ECX, Mem{Base: DI}.Offset(68)) + MOVL(R8L, Mem{Base: DI}.Offset(72)) + MOVL(R9L, Mem{Base: DI}.Offset(76)) + MOVD(X12, EDX) + MOVD(X7, ECX) + MOVD(X10, R8) + MOVD(X4, R9) + PSHUFL(Imm(0x39), X12, X12) + PSHUFL(Imm(0x39), X7, X7) + PSHUFL(Imm(0x39), X10, X10) + PSHUFL(Imm(0x39), X4, X4) + XORL(Mem{Base: SI}.Offset(128), EDX) + XORL(Mem{Base: SI}.Offset(132), ECX) + XORL(Mem{Base: SI}.Offset(136), R8L) + XORL(Mem{Base: SI}.Offset(140), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(128)) + MOVL(ECX, Mem{Base: DI}.Offset(132)) + MOVL(R8L, Mem{Base: DI}.Offset(136)) + MOVL(R9L, Mem{Base: DI}.Offset(140)) + MOVD(X12, EDX) + MOVD(X7, ECX) + MOVD(X10, R8) + MOVD(X4, R9) + XORL(Mem{Base: SI}.Offset(192), EDX) + XORL(Mem{Base: SI}.Offset(196), ECX) + XORL(Mem{Base: SI}.Offset(200), R8L) + XORL(Mem{Base: SI}.Offset(204), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(192)) + MOVL(ECX, Mem{Base: DI}.Offset(196)) + MOVL(R8L, Mem{Base: DI}.Offset(200)) + MOVL(R9L, Mem{Base: DI}.Offset(204)) + PADDL(Mem{Base: R12}.Offset(240), X14) + PADDL(Mem{Base: R12}.Offset(64), X0) + PADDL(Mem{Base: R12}.Offset(128), X5) + PADDL(Mem{Base: R12}.Offset(192), X8) + MOVD(X14, EDX) + MOVD(X0, ECX) + MOVD(X5, R8) + MOVD(X8, R9) + PSHUFL(Imm(0x39), X14, X14) + PSHUFL(Imm(0x39), X0, X0) + PSHUFL(Imm(0x39), X5, X5) + PSHUFL(Imm(0x39), X8, X8) + XORL(Mem{Base: SI}.Offset(16), EDX) + XORL(Mem{Base: SI}.Offset(20), ECX) + XORL(Mem{Base: SI}.Offset(24), R8L) + XORL(Mem{Base: SI}.Offset(28), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(16)) + MOVL(ECX, Mem{Base: DI}.Offset(20)) + MOVL(R8L, Mem{Base: DI}.Offset(24)) + MOVL(R9L, Mem{Base: DI}.Offset(28)) + MOVD(X14, EDX) + MOVD(X0, ECX) + MOVD(X5, R8) + MOVD(X8, R9) + PSHUFL(Imm(0x39), X14, X14) + PSHUFL(Imm(0x39), X0, X0) + PSHUFL(Imm(0x39), X5, X5) + PSHUFL(Imm(0x39), X8, X8) + XORL(Mem{Base: SI}.Offset(80), EDX) + XORL(Mem{Base: SI}.Offset(84), ECX) + XORL(Mem{Base: SI}.Offset(88), R8L) + XORL(Mem{Base: SI}.Offset(92), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(80)) + MOVL(ECX, Mem{Base: DI}.Offset(84)) + MOVL(R8L, Mem{Base: DI}.Offset(88)) + MOVL(R9L, Mem{Base: DI}.Offset(92)) + MOVD(X14, EDX) + MOVD(X0, ECX) + MOVD(X5, R8) + MOVD(X8, R9) + PSHUFL(Imm(0x39), X14, X14) + PSHUFL(Imm(0x39), X0, X0) + PSHUFL(Imm(0x39), X5, X5) + PSHUFL(Imm(0x39), X8, X8) + XORL(Mem{Base: SI}.Offset(144), EDX) + XORL(Mem{Base: SI}.Offset(148), ECX) + XORL(Mem{Base: SI}.Offset(152), R8L) + XORL(Mem{Base: SI}.Offset(156), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(144)) + MOVL(ECX, Mem{Base: DI}.Offset(148)) + MOVL(R8L, Mem{Base: DI}.Offset(152)) + MOVL(R9L, Mem{Base: DI}.Offset(156)) + MOVD(X14, EDX) + MOVD(X0, ECX) + MOVD(X5, R8) + MOVD(X8, R9) + XORL(Mem{Base: SI}.Offset(208), EDX) + XORL(Mem{Base: SI}.Offset(212), ECX) + XORL(Mem{Base: SI}.Offset(216), R8L) + XORL(Mem{Base: SI}.Offset(220), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(208)) + MOVL(ECX, Mem{Base: DI}.Offset(212)) + MOVL(R8L, Mem{Base: DI}.Offset(216)) + MOVL(R9L, Mem{Base: DI}.Offset(220)) + PADDL(Mem{Base: R12}.Offset(288), X15) + PADDL(Mem{Base: R12}.Offset(304), X11) + PADDL(Mem{Base: R12}.Offset(80), X1) + PADDL(Mem{Base: R12}.Offset(144), X6) + MOVD(X15, EDX) + MOVD(X11, ECX) + MOVD(X1, R8) + MOVD(X6, R9) + PSHUFL(Imm(0x39), X15, X15) + PSHUFL(Imm(0x39), X11, X11) + PSHUFL(Imm(0x39), X1, X1) + PSHUFL(Imm(0x39), X6, X6) + XORL(Mem{Base: SI}.Offset(32), EDX) + XORL(Mem{Base: SI}.Offset(36), ECX) + XORL(Mem{Base: SI}.Offset(40), R8L) + XORL(Mem{Base: SI}.Offset(44), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(32)) + MOVL(ECX, Mem{Base: DI}.Offset(36)) + MOVL(R8L, Mem{Base: DI}.Offset(40)) + MOVL(R9L, Mem{Base: DI}.Offset(44)) + MOVD(X15, EDX) + MOVD(X11, ECX) + MOVD(X1, R8) + MOVD(X6, R9) + PSHUFL(Imm(0x39), X15, X15) + PSHUFL(Imm(0x39), X11, X11) + PSHUFL(Imm(0x39), X1, X1) + PSHUFL(Imm(0x39), X6, X6) + XORL(Mem{Base: SI}.Offset(96), EDX) + XORL(Mem{Base: SI}.Offset(100), ECX) + XORL(Mem{Base: SI}.Offset(104), R8L) + XORL(Mem{Base: SI}.Offset(108), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(96)) + MOVL(ECX, Mem{Base: DI}.Offset(100)) + MOVL(R8L, Mem{Base: DI}.Offset(104)) + MOVL(R9L, Mem{Base: DI}.Offset(108)) + MOVD(X15, EDX) + MOVD(X11, ECX) + MOVD(X1, R8) + MOVD(X6, R9) + PSHUFL(Imm(0x39), X15, X15) + PSHUFL(Imm(0x39), X11, X11) + PSHUFL(Imm(0x39), X1, X1) + PSHUFL(Imm(0x39), X6, X6) + XORL(Mem{Base: SI}.Offset(160), EDX) + XORL(Mem{Base: SI}.Offset(164), ECX) + XORL(Mem{Base: SI}.Offset(168), R8L) + XORL(Mem{Base: SI}.Offset(172), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(160)) + MOVL(ECX, Mem{Base: DI}.Offset(164)) + MOVL(R8L, Mem{Base: DI}.Offset(168)) + MOVL(R9L, Mem{Base: DI}.Offset(172)) + MOVD(X15, EDX) + MOVD(X11, ECX) + MOVD(X1, R8) + MOVD(X6, R9) + XORL(Mem{Base: SI}.Offset(224), EDX) + XORL(Mem{Base: SI}.Offset(228), ECX) + XORL(Mem{Base: SI}.Offset(232), R8L) + XORL(Mem{Base: SI}.Offset(236), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(224)) + MOVL(ECX, Mem{Base: DI}.Offset(228)) + MOVL(R8L, Mem{Base: DI}.Offset(232)) + MOVL(R9L, Mem{Base: DI}.Offset(236)) + PADDL(Mem{Base: R12}.Offset(160), X13) + PADDL(Mem{Base: R12}.Offset(208), X9) + PADDL(Mem{Base: R12}.Offset(256), X3) + PADDL(Mem{Base: R12}.Offset(96), X2) + MOVD(X13, EDX) + MOVD(X9, ECX) + MOVD(X3, R8) + MOVD(X2, R9) + PSHUFL(Imm(0x39), X13, X13) + PSHUFL(Imm(0x39), X9, X9) + PSHUFL(Imm(0x39), X3, X3) + PSHUFL(Imm(0x39), X2, X2) + XORL(Mem{Base: SI}.Offset(48), EDX) + XORL(Mem{Base: SI}.Offset(52), ECX) + XORL(Mem{Base: SI}.Offset(56), R8L) + XORL(Mem{Base: SI}.Offset(60), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(48)) + MOVL(ECX, Mem{Base: DI}.Offset(52)) + MOVL(R8L, Mem{Base: DI}.Offset(56)) + MOVL(R9L, Mem{Base: DI}.Offset(60)) + MOVD(X13, EDX) + MOVD(X9, ECX) + MOVD(X3, R8) + MOVD(X2, R9) + PSHUFL(Imm(0x39), X13, X13) + PSHUFL(Imm(0x39), X9, X9) + PSHUFL(Imm(0x39), X3, X3) + PSHUFL(Imm(0x39), X2, X2) + XORL(Mem{Base: SI}.Offset(112), EDX) + XORL(Mem{Base: SI}.Offset(116), ECX) + XORL(Mem{Base: SI}.Offset(120), R8L) + XORL(Mem{Base: SI}.Offset(124), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(112)) + MOVL(ECX, Mem{Base: DI}.Offset(116)) + MOVL(R8L, Mem{Base: DI}.Offset(120)) + MOVL(R9L, Mem{Base: DI}.Offset(124)) + MOVD(X13, EDX) + MOVD(X9, ECX) + MOVD(X3, R8) + MOVD(X2, R9) + PSHUFL(Imm(0x39), X13, X13) + PSHUFL(Imm(0x39), X9, X9) + PSHUFL(Imm(0x39), X3, X3) + PSHUFL(Imm(0x39), X2, X2) + XORL(Mem{Base: SI}.Offset(176), EDX) + XORL(Mem{Base: SI}.Offset(180), ECX) + XORL(Mem{Base: SI}.Offset(184), R8L) + XORL(Mem{Base: SI}.Offset(188), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(176)) + MOVL(ECX, Mem{Base: DI}.Offset(180)) + MOVL(R8L, Mem{Base: DI}.Offset(184)) + MOVL(R9L, Mem{Base: DI}.Offset(188)) + MOVD(X13, EDX) + MOVD(X9, ECX) + MOVD(X3, R8) + MOVD(X2, R9) + XORL(Mem{Base: SI}.Offset(240), EDX) + XORL(Mem{Base: SI}.Offset(244), ECX) + XORL(Mem{Base: SI}.Offset(248), R8L) + XORL(Mem{Base: SI}.Offset(252), R9L) + MOVL(EDX, Mem{Base: DI}.Offset(240)) + MOVL(ECX, Mem{Base: DI}.Offset(244)) + MOVL(R8L, Mem{Base: DI}.Offset(248)) + MOVL(R9L, Mem{Base: DI}.Offset(252)) + MOVQ(Mem{Base: R12}.Offset(352), R9) + SUBQ(U32(256), R9) + ADDQ(U32(256), RSI) + ADDQ(U32(256), RDI) + CMPQ(R9, U32(256)) + JAE(LabelRef("BYTESATLEAST256")) + CMPQ(R9, Imm(0)) + JBE(LabelRef("DONE")) +} + +func BYTESBETWEEN1AND255() { + Label("BYTESBETWEEN1AND255") + CMPQ(R9, Imm(64)) + JAE(LabelRef("NOCOPY")) + MOVQ(RDI, RDX) + LEAQ(Mem{Base: R12}.Offset(360), RDI) + MOVQ(R9, RCX) + // Hack to get Avo to emit: + // REP; MOVSB + Instruction(&ir.Instruction{Opcode: "REP; MOVSB"}) + LEAQ(Mem{Base: R12}.Offset(360), RDI) + LEAQ(Mem{Base: R12}.Offset(360), RSI) +} + +func NOCOPY() { + Label("NOCOPY") + MOVQ(R9, Mem{Base: R12}.Offset(352)) + MOVOA(Mem{Base: R12}.Offset(48), X0) + MOVOA(Mem{Base: R12}.Offset(0), X1) + MOVOA(Mem{Base: R12}.Offset(16), X2) + MOVOA(Mem{Base: R12}.Offset(32), X3) + MOVOA(X1, X4) + MOVQ(U32(20), RCX) +} + +func MAINLOOP2() { + Label("MAINLOOP2") + PADDL(X0, X4) + MOVOA(X0, X5) + MOVOA(X4, X6) + PSLLL(Imm(7), X4) + PSRLL(Imm(25), X6) + PXOR(X4, X3) + PXOR(X6, X3) + PADDL(X3, X5) + MOVOA(X3, X4) + MOVOA(X5, X6) + PSLLL(Imm(9), X5) + PSRLL(Imm(23), X6) + PXOR(X5, X2) + PSHUFL(Imm(0x93), X3, X3) + PXOR(X6, X2) + PADDL(X2, X4) + MOVOA(X2, X5) + MOVOA(X4, X6) + PSLLL(Imm(13), X4) + PSRLL(Imm(19), X6) + PXOR(X4, X1) + PSHUFL(Imm(0x4E), X2, X2) + PXOR(X6, X1) + PADDL(X1, X5) + MOVOA(X3, X4) + MOVOA(X5, X6) + PSLLL(Imm(18), X5) + PSRLL(Imm(14), X6) + PXOR(X5, X0) + PSHUFL(Imm(0x39), X1, X1) + PXOR(X6, X0) + PADDL(X0, X4) + MOVOA(X0, X5) + MOVOA(X4, X6) + PSLLL(Imm(7), X4) + PSRLL(Imm(25), X6) + PXOR(X4, X1) + PXOR(X6, X1) + PADDL(X1, X5) + MOVOA(X1, X4) + MOVOA(X5, X6) + PSLLL(Imm(9), X5) + PSRLL(Imm(23), X6) + PXOR(X5, X2) + PSHUFL(Imm(0x93), X1, X1) + PXOR(X6, X2) + PADDL(X2, X4) + MOVOA(X2, X5) + MOVOA(X4, X6) + PSLLL(Imm(13), X4) + PSRLL(Imm(19), X6) + PXOR(X4, X3) + PSHUFL(Imm(0x4E), X2, X2) + PXOR(X6, X3) + PADDL(X3, X5) + MOVOA(X1, X4) + MOVOA(X5, X6) + PSLLL(Imm(18), X5) + PSRLL(Imm(14), X6) + PXOR(X5, X0) + PSHUFL(Imm(0x39), X3, X3) + PXOR(X6, X0) + PADDL(X0, X4) + MOVOA(X0, X5) + MOVOA(X4, X6) + PSLLL(Imm(7), X4) + PSRLL(Imm(25), X6) + PXOR(X4, X3) + PXOR(X6, X3) + PADDL(X3, X5) + MOVOA(X3, X4) + MOVOA(X5, X6) + PSLLL(Imm(9), X5) + PSRLL(Imm(23), X6) + PXOR(X5, X2) + PSHUFL(Imm(0x93), X3, X3) + PXOR(X6, X2) + PADDL(X2, X4) + MOVOA(X2, X5) + MOVOA(X4, X6) + PSLLL(Imm(13), X4) + PSRLL(Imm(19), X6) + PXOR(X4, X1) + PSHUFL(Imm(0x4E), X2, X2) + PXOR(X6, X1) + PADDL(X1, X5) + MOVOA(X3, X4) + MOVOA(X5, X6) + PSLLL(Imm(18), X5) + PSRLL(Imm(14), X6) + PXOR(X5, X0) + PSHUFL(Imm(0x39), X1, X1) + PXOR(X6, X0) + PADDL(X0, X4) + MOVOA(X0, X5) + MOVOA(X4, X6) + PSLLL(Imm(7), X4) + PSRLL(Imm(25), X6) + PXOR(X4, X1) + PXOR(X6, X1) + PADDL(X1, X5) + MOVOA(X1, X4) + MOVOA(X5, X6) + PSLLL(Imm(9), X5) + PSRLL(Imm(23), X6) + PXOR(X5, X2) + PSHUFL(Imm(0x93), X1, X1) + PXOR(X6, X2) + PADDL(X2, X4) + MOVOA(X2, X5) + MOVOA(X4, X6) + PSLLL(Imm(13), X4) + PSRLL(Imm(19), X6) + PXOR(X4, X3) + PSHUFL(Imm(0x4E), X2, X2) + PXOR(X6, X3) + SUBQ(Imm(4), RCX) + PADDL(X3, X5) + MOVOA(X1, X4) + MOVOA(X5, X6) + PSLLL(Imm(18), X5) + PXOR(X7, X7) + PSRLL(Imm(14), X6) + PXOR(X5, X0) + PSHUFL(Imm(0x39), X3, X3) + PXOR(X6, X0) + JA(LabelRef("MAINLOOP2")) + PADDL(Mem{Base: R12}.Offset(48), X0) + PADDL(Mem{Base: R12}.Offset(0), X1) + PADDL(Mem{Base: R12}.Offset(16), X2) + PADDL(Mem{Base: R12}.Offset(32), X3) + MOVD(X0, ECX) + MOVD(X1, R8) + MOVD(X2, R9) + MOVD(X3, EAX) + PSHUFL(Imm(0x39), X0, X0) + PSHUFL(Imm(0x39), X1, X1) + PSHUFL(Imm(0x39), X2, X2) + PSHUFL(Imm(0x39), X3, X3) + XORL(Mem{Base: SI}.Offset(0), ECX) + XORL(Mem{Base: SI}.Offset(48), R8L) + XORL(Mem{Base: SI}.Offset(32), R9L) + XORL(Mem{Base: SI}.Offset(16), EAX) + MOVL(ECX, Mem{Base: DI}.Offset(0)) + MOVL(R8L, Mem{Base: DI}.Offset(48)) + MOVL(R9L, Mem{Base: DI}.Offset(32)) + MOVL(EAX, Mem{Base: DI}.Offset(16)) + MOVD(X0, ECX) + MOVD(X1, R8) + MOVD(X2, R9) + MOVD(X3, EAX) + PSHUFL(Imm(0x39), X0, X0) + PSHUFL(Imm(0x39), X1, X1) + PSHUFL(Imm(0x39), X2, X2) + PSHUFL(Imm(0x39), X3, X3) + XORL(Mem{Base: SI}.Offset(20), ECX) + XORL(Mem{Base: SI}.Offset(4), R8L) + XORL(Mem{Base: SI}.Offset(52), R9L) + XORL(Mem{Base: SI}.Offset(36), EAX) + MOVL(ECX, Mem{Base: DI}.Offset(20)) + MOVL(R8L, Mem{Base: DI}.Offset(4)) + MOVL(R9L, Mem{Base: DI}.Offset(52)) + MOVL(EAX, Mem{Base: DI}.Offset(36)) + MOVD(X0, ECX) + MOVD(X1, R8) + MOVD(X2, R9) + MOVD(X3, EAX) + PSHUFL(Imm(0x39), X0, X0) + PSHUFL(Imm(0x39), X1, X1) + PSHUFL(Imm(0x39), X2, X2) + PSHUFL(Imm(0x39), X3, X3) + XORL(Mem{Base: SI}.Offset(40), ECX) + XORL(Mem{Base: SI}.Offset(24), R8L) + XORL(Mem{Base: SI}.Offset(8), R9L) + XORL(Mem{Base: SI}.Offset(56), EAX) + MOVL(ECX, Mem{Base: DI}.Offset(40)) + MOVL(R8L, Mem{Base: DI}.Offset(24)) + MOVL(R9L, Mem{Base: DI}.Offset(8)) + MOVL(EAX, Mem{Base: DI}.Offset(56)) + MOVD(X0, ECX) + MOVD(X1, R8) + MOVD(X2, R9) + MOVD(X3, EAX) + XORL(Mem{Base: SI}.Offset(60), ECX) + XORL(Mem{Base: SI}.Offset(44), R8L) + XORL(Mem{Base: SI}.Offset(28), R9L) + XORL(Mem{Base: SI}.Offset(12), EAX) + MOVL(ECX, Mem{Base: DI}.Offset(60)) + MOVL(R8L, Mem{Base: DI}.Offset(44)) + MOVL(R9L, Mem{Base: DI}.Offset(28)) + MOVL(EAX, Mem{Base: DI}.Offset(12)) + MOVQ(Mem{Base: R12}.Offset(352), R9) + MOVL(Mem{Base: R12}.Offset(16), ECX) + MOVL(Mem{Base: R12}.Offset(36), R8L) + ADDQ(Imm(1), RCX) + SHLQ(Imm(32), R8) + ADDQ(R8, RCX) + MOVQ(RCX, R8) + SHRQ(Imm(32), R8) + MOVL(ECX, Mem{Base: R12}.Offset(16)) + MOVL(R8L, Mem{Base: R12}.Offset(36)) + CMPQ(R9, Imm(64)) + JA(LabelRef("BYTESATLEAST65")) + JAE(LabelRef("BYTESATLEAST64")) + MOVQ(RDI, RSI) + MOVQ(RDX, RDI) + MOVQ(R9, RCX) + // Hack to get Avo to emit: + // REP; MOVSB + Instruction(&ir.Instruction{Opcode: "REP; MOVSB"}) +} diff --git a/salsa20/salsa/hsalsa20.go b/salsa20/salsa/hsalsa20.go index 4c96147c86..75df77406d 100644 --- a/salsa20/salsa/hsalsa20.go +++ b/salsa20/salsa/hsalsa20.go @@ -3,7 +3,13 @@ // license that can be found in the LICENSE file. // Package salsa provides low-level access to functions in the Salsa family. -package salsa // import "golang.org/x/crypto/salsa20/salsa" +// +// Deprecated: this package exposes unsafe low-level operations. New applications +// should consider using the AEAD construction in golang.org/x/crypto/chacha20poly1305 +// instead. Existing users should migrate to golang.org/x/crypto/salsa20. +package salsa + +import "math/bits" // Sigma is the Salsa20 constant for 256-bit keys. var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} @@ -31,76 +37,76 @@ func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { for i := 0; i < 20; i += 2 { u := x0 + x12 - x4 ^= u<<7 | u>>(32-7) + x4 ^= bits.RotateLeft32(u, 7) u = x4 + x0 - x8 ^= u<<9 | u>>(32-9) + x8 ^= bits.RotateLeft32(u, 9) u = x8 + x4 - x12 ^= u<<13 | u>>(32-13) + x12 ^= bits.RotateLeft32(u, 13) u = x12 + x8 - x0 ^= u<<18 | u>>(32-18) + x0 ^= bits.RotateLeft32(u, 18) u = x5 + x1 - x9 ^= u<<7 | u>>(32-7) + x9 ^= bits.RotateLeft32(u, 7) u = x9 + x5 - x13 ^= u<<9 | u>>(32-9) + x13 ^= bits.RotateLeft32(u, 9) u = x13 + x9 - x1 ^= u<<13 | u>>(32-13) + x1 ^= bits.RotateLeft32(u, 13) u = x1 + x13 - x5 ^= u<<18 | u>>(32-18) + x5 ^= bits.RotateLeft32(u, 18) u = x10 + x6 - x14 ^= u<<7 | u>>(32-7) + x14 ^= bits.RotateLeft32(u, 7) u = x14 + x10 - x2 ^= u<<9 | u>>(32-9) + x2 ^= bits.RotateLeft32(u, 9) u = x2 + x14 - x6 ^= u<<13 | u>>(32-13) + x6 ^= bits.RotateLeft32(u, 13) u = x6 + x2 - x10 ^= u<<18 | u>>(32-18) + x10 ^= bits.RotateLeft32(u, 18) u = x15 + x11 - x3 ^= u<<7 | u>>(32-7) + x3 ^= bits.RotateLeft32(u, 7) u = x3 + x15 - x7 ^= u<<9 | u>>(32-9) + x7 ^= bits.RotateLeft32(u, 9) u = x7 + x3 - x11 ^= u<<13 | u>>(32-13) + x11 ^= bits.RotateLeft32(u, 13) u = x11 + x7 - x15 ^= u<<18 | u>>(32-18) + x15 ^= bits.RotateLeft32(u, 18) u = x0 + x3 - x1 ^= u<<7 | u>>(32-7) + x1 ^= bits.RotateLeft32(u, 7) u = x1 + x0 - x2 ^= u<<9 | u>>(32-9) + x2 ^= bits.RotateLeft32(u, 9) u = x2 + x1 - x3 ^= u<<13 | u>>(32-13) + x3 ^= bits.RotateLeft32(u, 13) u = x3 + x2 - x0 ^= u<<18 | u>>(32-18) + x0 ^= bits.RotateLeft32(u, 18) u = x5 + x4 - x6 ^= u<<7 | u>>(32-7) + x6 ^= bits.RotateLeft32(u, 7) u = x6 + x5 - x7 ^= u<<9 | u>>(32-9) + x7 ^= bits.RotateLeft32(u, 9) u = x7 + x6 - x4 ^= u<<13 | u>>(32-13) + x4 ^= bits.RotateLeft32(u, 13) u = x4 + x7 - x5 ^= u<<18 | u>>(32-18) + x5 ^= bits.RotateLeft32(u, 18) u = x10 + x9 - x11 ^= u<<7 | u>>(32-7) + x11 ^= bits.RotateLeft32(u, 7) u = x11 + x10 - x8 ^= u<<9 | u>>(32-9) + x8 ^= bits.RotateLeft32(u, 9) u = x8 + x11 - x9 ^= u<<13 | u>>(32-13) + x9 ^= bits.RotateLeft32(u, 13) u = x9 + x8 - x10 ^= u<<18 | u>>(32-18) + x10 ^= bits.RotateLeft32(u, 18) u = x15 + x14 - x12 ^= u<<7 | u>>(32-7) + x12 ^= bits.RotateLeft32(u, 7) u = x12 + x15 - x13 ^= u<<9 | u>>(32-9) + x13 ^= bits.RotateLeft32(u, 9) u = x13 + x12 - x14 ^= u<<13 | u>>(32-13) + x14 ^= bits.RotateLeft32(u, 13) u = x14 + x13 - x15 ^= u<<18 | u>>(32-18) + x15 ^= bits.RotateLeft32(u, 18) } out[0] = byte(x0) out[1] = byte(x0 >> 8) diff --git a/salsa20/salsa/salsa208.go b/salsa20/salsa/salsa208.go index 9bfc0927ce..7ec7bb39bc 100644 --- a/salsa20/salsa/salsa208.go +++ b/salsa20/salsa/salsa208.go @@ -4,6 +4,8 @@ package salsa +import "math/bits" + // Core208 applies the Salsa20/8 core function to the 64-byte array in and puts // the result into the 64-byte array out. The input and output may be the same array. func Core208(out *[64]byte, in *[64]byte) { @@ -29,76 +31,76 @@ func Core208(out *[64]byte, in *[64]byte) { for i := 0; i < 8; i += 2 { u := x0 + x12 - x4 ^= u<<7 | u>>(32-7) + x4 ^= bits.RotateLeft32(u, 7) u = x4 + x0 - x8 ^= u<<9 | u>>(32-9) + x8 ^= bits.RotateLeft32(u, 9) u = x8 + x4 - x12 ^= u<<13 | u>>(32-13) + x12 ^= bits.RotateLeft32(u, 13) u = x12 + x8 - x0 ^= u<<18 | u>>(32-18) + x0 ^= bits.RotateLeft32(u, 18) u = x5 + x1 - x9 ^= u<<7 | u>>(32-7) + x9 ^= bits.RotateLeft32(u, 7) u = x9 + x5 - x13 ^= u<<9 | u>>(32-9) + x13 ^= bits.RotateLeft32(u, 9) u = x13 + x9 - x1 ^= u<<13 | u>>(32-13) + x1 ^= bits.RotateLeft32(u, 13) u = x1 + x13 - x5 ^= u<<18 | u>>(32-18) + x5 ^= bits.RotateLeft32(u, 18) u = x10 + x6 - x14 ^= u<<7 | u>>(32-7) + x14 ^= bits.RotateLeft32(u, 7) u = x14 + x10 - x2 ^= u<<9 | u>>(32-9) + x2 ^= bits.RotateLeft32(u, 9) u = x2 + x14 - x6 ^= u<<13 | u>>(32-13) + x6 ^= bits.RotateLeft32(u, 13) u = x6 + x2 - x10 ^= u<<18 | u>>(32-18) + x10 ^= bits.RotateLeft32(u, 18) u = x15 + x11 - x3 ^= u<<7 | u>>(32-7) + x3 ^= bits.RotateLeft32(u, 7) u = x3 + x15 - x7 ^= u<<9 | u>>(32-9) + x7 ^= bits.RotateLeft32(u, 9) u = x7 + x3 - x11 ^= u<<13 | u>>(32-13) + x11 ^= bits.RotateLeft32(u, 13) u = x11 + x7 - x15 ^= u<<18 | u>>(32-18) + x15 ^= bits.RotateLeft32(u, 18) u = x0 + x3 - x1 ^= u<<7 | u>>(32-7) + x1 ^= bits.RotateLeft32(u, 7) u = x1 + x0 - x2 ^= u<<9 | u>>(32-9) + x2 ^= bits.RotateLeft32(u, 9) u = x2 + x1 - x3 ^= u<<13 | u>>(32-13) + x3 ^= bits.RotateLeft32(u, 13) u = x3 + x2 - x0 ^= u<<18 | u>>(32-18) + x0 ^= bits.RotateLeft32(u, 18) u = x5 + x4 - x6 ^= u<<7 | u>>(32-7) + x6 ^= bits.RotateLeft32(u, 7) u = x6 + x5 - x7 ^= u<<9 | u>>(32-9) + x7 ^= bits.RotateLeft32(u, 9) u = x7 + x6 - x4 ^= u<<13 | u>>(32-13) + x4 ^= bits.RotateLeft32(u, 13) u = x4 + x7 - x5 ^= u<<18 | u>>(32-18) + x5 ^= bits.RotateLeft32(u, 18) u = x10 + x9 - x11 ^= u<<7 | u>>(32-7) + x11 ^= bits.RotateLeft32(u, 7) u = x11 + x10 - x8 ^= u<<9 | u>>(32-9) + x8 ^= bits.RotateLeft32(u, 9) u = x8 + x11 - x9 ^= u<<13 | u>>(32-13) + x9 ^= bits.RotateLeft32(u, 13) u = x9 + x8 - x10 ^= u<<18 | u>>(32-18) + x10 ^= bits.RotateLeft32(u, 18) u = x15 + x14 - x12 ^= u<<7 | u>>(32-7) + x12 ^= bits.RotateLeft32(u, 7) u = x12 + x15 - x13 ^= u<<9 | u>>(32-9) + x13 ^= bits.RotateLeft32(u, 9) u = x13 + x12 - x14 ^= u<<13 | u>>(32-13) + x14 ^= bits.RotateLeft32(u, 13) u = x14 + x13 - x15 ^= u<<18 | u>>(32-18) + x15 ^= bits.RotateLeft32(u, 18) } x0 += j0 x1 += j1 diff --git a/salsa20/salsa/salsa20_amd64.go b/salsa20/salsa/salsa20_amd64.go index 656e8df942..e76b44fe59 100644 --- a/salsa20/salsa/salsa20_amd64.go +++ b/salsa20/salsa/salsa20_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,!appengine,!gccgo +//go:build amd64 && !purego && gc package salsa diff --git a/salsa20/salsa/salsa20_amd64.s b/salsa20/salsa/salsa20_amd64.s index 18085d2e8c..3883e0ec22 100644 --- a/salsa20/salsa/salsa20_amd64.s +++ b/salsa20/salsa/salsa20_amd64.s @@ -1,883 +1,880 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run salsa20_amd64_asm.go -out ../salsa20_amd64.s -pkg salsa. DO NOT EDIT. -// +build amd64,!appengine,!gccgo +//go:build amd64 && !purego && gc -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html +// func salsa2020XORKeyStream(out *byte, in *byte, n uint64, nonce *byte, key *byte) +// Requires: SSE2 +TEXT ·salsa2020XORKeyStream(SB), $456-40 + // This needs up to 64 bytes at 360(R12); hence the non-obvious frame size. + MOVQ out+0(FP), DI + MOVQ in+8(FP), SI + MOVQ n+16(FP), DX + MOVQ nonce+24(FP), CX + MOVQ key+32(FP), R8 + MOVQ SP, R12 + ADDQ $0x1f, R12 + ANDQ $-32, R12 + MOVQ DX, R9 + MOVQ CX, DX + MOVQ R8, R10 + CMPQ R9, $0x00 + JBE DONE + MOVL 20(R10), CX + MOVL (R10), R8 + MOVL (DX), AX + MOVL 16(R10), R11 + MOVL CX, (R12) + MOVL R8, 4(R12) + MOVL AX, 8(R12) + MOVL R11, 12(R12) + MOVL 8(DX), CX + MOVL 24(R10), R8 + MOVL 4(R10), AX + MOVL 4(DX), R11 + MOVL CX, 16(R12) + MOVL R8, 20(R12) + MOVL AX, 24(R12) + MOVL R11, 28(R12) + MOVL 12(DX), CX + MOVL 12(R10), DX + MOVL 28(R10), R8 + MOVL 8(R10), AX + MOVL DX, 32(R12) + MOVL CX, 36(R12) + MOVL R8, 40(R12) + MOVL AX, 44(R12) + MOVQ $0x61707865, DX + MOVQ $0x3320646e, CX + MOVQ $0x79622d32, R8 + MOVQ $0x6b206574, AX + MOVL DX, 48(R12) + MOVL CX, 52(R12) + MOVL R8, 56(R12) + MOVL AX, 60(R12) + CMPQ R9, $0x00000100 + JB BYTESBETWEEN1AND255 + MOVOA 48(R12), X0 + PSHUFL $0x55, X0, X1 + PSHUFL $0xaa, X0, X2 + PSHUFL $0xff, X0, X3 + PSHUFL $0x00, X0, X0 + MOVOA X1, 64(R12) + MOVOA X2, 80(R12) + MOVOA X3, 96(R12) + MOVOA X0, 112(R12) + MOVOA (R12), X0 + PSHUFL $0xaa, X0, X1 + PSHUFL $0xff, X0, X2 + PSHUFL $0x00, X0, X3 + PSHUFL $0x55, X0, X0 + MOVOA X1, 128(R12) + MOVOA X2, 144(R12) + MOVOA X3, 160(R12) + MOVOA X0, 176(R12) + MOVOA 16(R12), X0 + PSHUFL $0xff, X0, X1 + PSHUFL $0x55, X0, X2 + PSHUFL $0xaa, X0, X0 + MOVOA X1, 192(R12) + MOVOA X2, 208(R12) + MOVOA X0, 224(R12) + MOVOA 32(R12), X0 + PSHUFL $0x00, X0, X1 + PSHUFL $0xaa, X0, X2 + PSHUFL $0xff, X0, X0 + MOVOA X1, 240(R12) + MOVOA X2, 256(R12) + MOVOA X0, 272(R12) -// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) -// This needs up to 64 bytes at 360(SP); hence the non-obvious frame size. -TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVQ out+0(FP),DI - MOVQ in+8(FP),SI - MOVQ n+16(FP),DX - MOVQ nonce+24(FP),CX - MOVQ key+32(FP),R8 +BYTESATLEAST256: + MOVL 16(R12), DX + MOVL 36(R12), CX + MOVL DX, 288(R12) + MOVL CX, 304(R12) + SHLQ $0x20, CX + ADDQ CX, DX + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 292(R12) + MOVL CX, 308(R12) + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 296(R12) + MOVL CX, 312(R12) + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 300(R12) + MOVL CX, 316(R12) + ADDQ $0x01, DX + MOVQ DX, CX + SHRQ $0x20, CX + MOVL DX, 16(R12) + MOVL CX, 36(R12) + MOVQ R9, 352(R12) + MOVQ $0x00000014, DX + MOVOA 64(R12), X0 + MOVOA 80(R12), X1 + MOVOA 96(R12), X2 + MOVOA 256(R12), X3 + MOVOA 272(R12), X4 + MOVOA 128(R12), X5 + MOVOA 144(R12), X6 + MOVOA 176(R12), X7 + MOVOA 192(R12), X8 + MOVOA 208(R12), X9 + MOVOA 224(R12), X10 + MOVOA 304(R12), X11 + MOVOA 112(R12), X12 + MOVOA 160(R12), X13 + MOVOA 240(R12), X14 + MOVOA 288(R12), X15 - MOVQ SP,R12 - MOVQ SP,R9 - ADDQ $31, R9 - ANDQ $~31, R9 - MOVQ R9, SP +MAINLOOP1: + MOVOA X1, 320(R12) + MOVOA X2, 336(R12) + MOVOA X13, X1 + PADDL X12, X1 + MOVOA X1, X2 + PSLLL $0x07, X1 + PXOR X1, X14 + PSRLL $0x19, X2 + PXOR X2, X14 + MOVOA X7, X1 + PADDL X0, X1 + MOVOA X1, X2 + PSLLL $0x07, X1 + PXOR X1, X11 + PSRLL $0x19, X2 + PXOR X2, X11 + MOVOA X12, X1 + PADDL X14, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X15 + PSRLL $0x17, X2 + PXOR X2, X15 + MOVOA X0, X1 + PADDL X11, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X9 + PSRLL $0x17, X2 + PXOR X2, X9 + MOVOA X14, X1 + PADDL X15, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X13 + PSRLL $0x13, X2 + PXOR X2, X13 + MOVOA X11, X1 + PADDL X9, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X7 + PSRLL $0x13, X2 + PXOR X2, X7 + MOVOA X15, X1 + PADDL X13, X1 + MOVOA X1, X2 + PSLLL $0x12, X1 + PXOR X1, X12 + PSRLL $0x0e, X2 + PXOR X2, X12 + MOVOA 320(R12), X1 + MOVOA X12, 320(R12) + MOVOA X9, X2 + PADDL X7, X2 + MOVOA X2, X12 + PSLLL $0x12, X2 + PXOR X2, X0 + PSRLL $0x0e, X12 + PXOR X12, X0 + MOVOA X5, X2 + PADDL X1, X2 + MOVOA X2, X12 + PSLLL $0x07, X2 + PXOR X2, X3 + PSRLL $0x19, X12 + PXOR X12, X3 + MOVOA 336(R12), X2 + MOVOA X0, 336(R12) + MOVOA X6, X0 + PADDL X2, X0 + MOVOA X0, X12 + PSLLL $0x07, X0 + PXOR X0, X4 + PSRLL $0x19, X12 + PXOR X12, X4 + MOVOA X1, X0 + PADDL X3, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X10 + PSRLL $0x17, X12 + PXOR X12, X10 + MOVOA X2, X0 + PADDL X4, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X8 + PSRLL $0x17, X12 + PXOR X12, X8 + MOVOA X3, X0 + PADDL X10, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X5 + PSRLL $0x13, X12 + PXOR X12, X5 + MOVOA X4, X0 + PADDL X8, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X6 + PSRLL $0x13, X12 + PXOR X12, X6 + MOVOA X10, X0 + PADDL X5, X0 + MOVOA X0, X12 + PSLLL $0x12, X0 + PXOR X0, X1 + PSRLL $0x0e, X12 + PXOR X12, X1 + MOVOA 320(R12), X0 + MOVOA X1, 320(R12) + MOVOA X4, X1 + PADDL X0, X1 + MOVOA X1, X12 + PSLLL $0x07, X1 + PXOR X1, X7 + PSRLL $0x19, X12 + PXOR X12, X7 + MOVOA X8, X1 + PADDL X6, X1 + MOVOA X1, X12 + PSLLL $0x12, X1 + PXOR X1, X2 + PSRLL $0x0e, X12 + PXOR X12, X2 + MOVOA 336(R12), X12 + MOVOA X2, 336(R12) + MOVOA X14, X1 + PADDL X12, X1 + MOVOA X1, X2 + PSLLL $0x07, X1 + PXOR X1, X5 + PSRLL $0x19, X2 + PXOR X2, X5 + MOVOA X0, X1 + PADDL X7, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X10 + PSRLL $0x17, X2 + PXOR X2, X10 + MOVOA X12, X1 + PADDL X5, X1 + MOVOA X1, X2 + PSLLL $0x09, X1 + PXOR X1, X8 + PSRLL $0x17, X2 + PXOR X2, X8 + MOVOA X7, X1 + PADDL X10, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X4 + PSRLL $0x13, X2 + PXOR X2, X4 + MOVOA X5, X1 + PADDL X8, X1 + MOVOA X1, X2 + PSLLL $0x0d, X1 + PXOR X1, X14 + PSRLL $0x13, X2 + PXOR X2, X14 + MOVOA X10, X1 + PADDL X4, X1 + MOVOA X1, X2 + PSLLL $0x12, X1 + PXOR X1, X0 + PSRLL $0x0e, X2 + PXOR X2, X0 + MOVOA 320(R12), X1 + MOVOA X0, 320(R12) + MOVOA X8, X0 + PADDL X14, X0 + MOVOA X0, X2 + PSLLL $0x12, X0 + PXOR X0, X12 + PSRLL $0x0e, X2 + PXOR X2, X12 + MOVOA X11, X0 + PADDL X1, X0 + MOVOA X0, X2 + PSLLL $0x07, X0 + PXOR X0, X6 + PSRLL $0x19, X2 + PXOR X2, X6 + MOVOA 336(R12), X2 + MOVOA X12, 336(R12) + MOVOA X3, X0 + PADDL X2, X0 + MOVOA X0, X12 + PSLLL $0x07, X0 + PXOR X0, X13 + PSRLL $0x19, X12 + PXOR X12, X13 + MOVOA X1, X0 + PADDL X6, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X15 + PSRLL $0x17, X12 + PXOR X12, X15 + MOVOA X2, X0 + PADDL X13, X0 + MOVOA X0, X12 + PSLLL $0x09, X0 + PXOR X0, X9 + PSRLL $0x17, X12 + PXOR X12, X9 + MOVOA X6, X0 + PADDL X15, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X11 + PSRLL $0x13, X12 + PXOR X12, X11 + MOVOA X13, X0 + PADDL X9, X0 + MOVOA X0, X12 + PSLLL $0x0d, X0 + PXOR X0, X3 + PSRLL $0x13, X12 + PXOR X12, X3 + MOVOA X15, X0 + PADDL X11, X0 + MOVOA X0, X12 + PSLLL $0x12, X0 + PXOR X0, X1 + PSRLL $0x0e, X12 + PXOR X12, X1 + MOVOA X9, X0 + PADDL X3, X0 + MOVOA X0, X12 + PSLLL $0x12, X0 + PXOR X0, X2 + PSRLL $0x0e, X12 + PXOR X12, X2 + MOVOA 320(R12), X12 + MOVOA 336(R12), X0 + SUBQ $0x02, DX + JA MAINLOOP1 + PADDL 112(R12), X12 + PADDL 176(R12), X7 + PADDL 224(R12), X10 + PADDL 272(R12), X4 + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + PSHUFL $0x39, X12, X12 + PSHUFL $0x39, X7, X7 + PSHUFL $0x39, X10, X10 + PSHUFL $0x39, X4, X4 + XORL (SI), DX + XORL 4(SI), CX + XORL 8(SI), R8 + XORL 12(SI), R9 + MOVL DX, (DI) + MOVL CX, 4(DI) + MOVL R8, 8(DI) + MOVL R9, 12(DI) + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + PSHUFL $0x39, X12, X12 + PSHUFL $0x39, X7, X7 + PSHUFL $0x39, X10, X10 + PSHUFL $0x39, X4, X4 + XORL 64(SI), DX + XORL 68(SI), CX + XORL 72(SI), R8 + XORL 76(SI), R9 + MOVL DX, 64(DI) + MOVL CX, 68(DI) + MOVL R8, 72(DI) + MOVL R9, 76(DI) + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + PSHUFL $0x39, X12, X12 + PSHUFL $0x39, X7, X7 + PSHUFL $0x39, X10, X10 + PSHUFL $0x39, X4, X4 + XORL 128(SI), DX + XORL 132(SI), CX + XORL 136(SI), R8 + XORL 140(SI), R9 + MOVL DX, 128(DI) + MOVL CX, 132(DI) + MOVL R8, 136(DI) + MOVL R9, 140(DI) + MOVD X12, DX + MOVD X7, CX + MOVD X10, R8 + MOVD X4, R9 + XORL 192(SI), DX + XORL 196(SI), CX + XORL 200(SI), R8 + XORL 204(SI), R9 + MOVL DX, 192(DI) + MOVL CX, 196(DI) + MOVL R8, 200(DI) + MOVL R9, 204(DI) + PADDL 240(R12), X14 + PADDL 64(R12), X0 + PADDL 128(R12), X5 + PADDL 192(R12), X8 + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + PSHUFL $0x39, X14, X14 + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X5, X5 + PSHUFL $0x39, X8, X8 + XORL 16(SI), DX + XORL 20(SI), CX + XORL 24(SI), R8 + XORL 28(SI), R9 + MOVL DX, 16(DI) + MOVL CX, 20(DI) + MOVL R8, 24(DI) + MOVL R9, 28(DI) + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + PSHUFL $0x39, X14, X14 + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X5, X5 + PSHUFL $0x39, X8, X8 + XORL 80(SI), DX + XORL 84(SI), CX + XORL 88(SI), R8 + XORL 92(SI), R9 + MOVL DX, 80(DI) + MOVL CX, 84(DI) + MOVL R8, 88(DI) + MOVL R9, 92(DI) + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + PSHUFL $0x39, X14, X14 + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X5, X5 + PSHUFL $0x39, X8, X8 + XORL 144(SI), DX + XORL 148(SI), CX + XORL 152(SI), R8 + XORL 156(SI), R9 + MOVL DX, 144(DI) + MOVL CX, 148(DI) + MOVL R8, 152(DI) + MOVL R9, 156(DI) + MOVD X14, DX + MOVD X0, CX + MOVD X5, R8 + MOVD X8, R9 + XORL 208(SI), DX + XORL 212(SI), CX + XORL 216(SI), R8 + XORL 220(SI), R9 + MOVL DX, 208(DI) + MOVL CX, 212(DI) + MOVL R8, 216(DI) + MOVL R9, 220(DI) + PADDL 288(R12), X15 + PADDL 304(R12), X11 + PADDL 80(R12), X1 + PADDL 144(R12), X6 + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + PSHUFL $0x39, X15, X15 + PSHUFL $0x39, X11, X11 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X6, X6 + XORL 32(SI), DX + XORL 36(SI), CX + XORL 40(SI), R8 + XORL 44(SI), R9 + MOVL DX, 32(DI) + MOVL CX, 36(DI) + MOVL R8, 40(DI) + MOVL R9, 44(DI) + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + PSHUFL $0x39, X15, X15 + PSHUFL $0x39, X11, X11 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X6, X6 + XORL 96(SI), DX + XORL 100(SI), CX + XORL 104(SI), R8 + XORL 108(SI), R9 + MOVL DX, 96(DI) + MOVL CX, 100(DI) + MOVL R8, 104(DI) + MOVL R9, 108(DI) + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + PSHUFL $0x39, X15, X15 + PSHUFL $0x39, X11, X11 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X6, X6 + XORL 160(SI), DX + XORL 164(SI), CX + XORL 168(SI), R8 + XORL 172(SI), R9 + MOVL DX, 160(DI) + MOVL CX, 164(DI) + MOVL R8, 168(DI) + MOVL R9, 172(DI) + MOVD X15, DX + MOVD X11, CX + MOVD X1, R8 + MOVD X6, R9 + XORL 224(SI), DX + XORL 228(SI), CX + XORL 232(SI), R8 + XORL 236(SI), R9 + MOVL DX, 224(DI) + MOVL CX, 228(DI) + MOVL R8, 232(DI) + MOVL R9, 236(DI) + PADDL 160(R12), X13 + PADDL 208(R12), X9 + PADDL 256(R12), X3 + PADDL 96(R12), X2 + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + PSHUFL $0x39, X13, X13 + PSHUFL $0x39, X9, X9 + PSHUFL $0x39, X3, X3 + PSHUFL $0x39, X2, X2 + XORL 48(SI), DX + XORL 52(SI), CX + XORL 56(SI), R8 + XORL 60(SI), R9 + MOVL DX, 48(DI) + MOVL CX, 52(DI) + MOVL R8, 56(DI) + MOVL R9, 60(DI) + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + PSHUFL $0x39, X13, X13 + PSHUFL $0x39, X9, X9 + PSHUFL $0x39, X3, X3 + PSHUFL $0x39, X2, X2 + XORL 112(SI), DX + XORL 116(SI), CX + XORL 120(SI), R8 + XORL 124(SI), R9 + MOVL DX, 112(DI) + MOVL CX, 116(DI) + MOVL R8, 120(DI) + MOVL R9, 124(DI) + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + PSHUFL $0x39, X13, X13 + PSHUFL $0x39, X9, X9 + PSHUFL $0x39, X3, X3 + PSHUFL $0x39, X2, X2 + XORL 176(SI), DX + XORL 180(SI), CX + XORL 184(SI), R8 + XORL 188(SI), R9 + MOVL DX, 176(DI) + MOVL CX, 180(DI) + MOVL R8, 184(DI) + MOVL R9, 188(DI) + MOVD X13, DX + MOVD X9, CX + MOVD X3, R8 + MOVD X2, R9 + XORL 240(SI), DX + XORL 244(SI), CX + XORL 248(SI), R8 + XORL 252(SI), R9 + MOVL DX, 240(DI) + MOVL CX, 244(DI) + MOVL R8, 248(DI) + MOVL R9, 252(DI) + MOVQ 352(R12), R9 + SUBQ $0x00000100, R9 + ADDQ $0x00000100, SI + ADDQ $0x00000100, DI + CMPQ R9, $0x00000100 + JAE BYTESATLEAST256 + CMPQ R9, $0x00 + JBE DONE - MOVQ DX,R9 - MOVQ CX,DX - MOVQ R8,R10 - CMPQ R9,$0 - JBE DONE - START: - MOVL 20(R10),CX - MOVL 0(R10),R8 - MOVL 0(DX),AX - MOVL 16(R10),R11 - MOVL CX,0(SP) - MOVL R8, 4 (SP) - MOVL AX, 8 (SP) - MOVL R11, 12 (SP) - MOVL 8(DX),CX - MOVL 24(R10),R8 - MOVL 4(R10),AX - MOVL 4(DX),R11 - MOVL CX,16(SP) - MOVL R8, 20 (SP) - MOVL AX, 24 (SP) - MOVL R11, 28 (SP) - MOVL 12(DX),CX - MOVL 12(R10),DX - MOVL 28(R10),R8 - MOVL 8(R10),AX - MOVL DX,32(SP) - MOVL CX, 36 (SP) - MOVL R8, 40 (SP) - MOVL AX, 44 (SP) - MOVQ $1634760805,DX - MOVQ $857760878,CX - MOVQ $2036477234,R8 - MOVQ $1797285236,AX - MOVL DX,48(SP) - MOVL CX, 52 (SP) - MOVL R8, 56 (SP) - MOVL AX, 60 (SP) - CMPQ R9,$256 - JB BYTESBETWEEN1AND255 - MOVOA 48(SP),X0 - PSHUFL $0X55,X0,X1 - PSHUFL $0XAA,X0,X2 - PSHUFL $0XFF,X0,X3 - PSHUFL $0X00,X0,X0 - MOVOA X1,64(SP) - MOVOA X2,80(SP) - MOVOA X3,96(SP) - MOVOA X0,112(SP) - MOVOA 0(SP),X0 - PSHUFL $0XAA,X0,X1 - PSHUFL $0XFF,X0,X2 - PSHUFL $0X00,X0,X3 - PSHUFL $0X55,X0,X0 - MOVOA X1,128(SP) - MOVOA X2,144(SP) - MOVOA X3,160(SP) - MOVOA X0,176(SP) - MOVOA 16(SP),X0 - PSHUFL $0XFF,X0,X1 - PSHUFL $0X55,X0,X2 - PSHUFL $0XAA,X0,X0 - MOVOA X1,192(SP) - MOVOA X2,208(SP) - MOVOA X0,224(SP) - MOVOA 32(SP),X0 - PSHUFL $0X00,X0,X1 - PSHUFL $0XAA,X0,X2 - PSHUFL $0XFF,X0,X0 - MOVOA X1,240(SP) - MOVOA X2,256(SP) - MOVOA X0,272(SP) - BYTESATLEAST256: - MOVL 16(SP),DX - MOVL 36 (SP),CX - MOVL DX,288(SP) - MOVL CX,304(SP) - SHLQ $32,CX - ADDQ CX,DX - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX, 292 (SP) - MOVL CX, 308 (SP) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX, 296 (SP) - MOVL CX, 312 (SP) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX, 300 (SP) - MOVL CX, 316 (SP) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX - MOVL DX,16(SP) - MOVL CX, 36 (SP) - MOVQ R9,352(SP) - MOVQ $20,DX - MOVOA 64(SP),X0 - MOVOA 80(SP),X1 - MOVOA 96(SP),X2 - MOVOA 256(SP),X3 - MOVOA 272(SP),X4 - MOVOA 128(SP),X5 - MOVOA 144(SP),X6 - MOVOA 176(SP),X7 - MOVOA 192(SP),X8 - MOVOA 208(SP),X9 - MOVOA 224(SP),X10 - MOVOA 304(SP),X11 - MOVOA 112(SP),X12 - MOVOA 160(SP),X13 - MOVOA 240(SP),X14 - MOVOA 288(SP),X15 - MAINLOOP1: - MOVOA X1,320(SP) - MOVOA X2,336(SP) - MOVOA X13,X1 - PADDL X12,X1 - MOVOA X1,X2 - PSLLL $7,X1 - PXOR X1,X14 - PSRLL $25,X2 - PXOR X2,X14 - MOVOA X7,X1 - PADDL X0,X1 - MOVOA X1,X2 - PSLLL $7,X1 - PXOR X1,X11 - PSRLL $25,X2 - PXOR X2,X11 - MOVOA X12,X1 - PADDL X14,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X15 - PSRLL $23,X2 - PXOR X2,X15 - MOVOA X0,X1 - PADDL X11,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X9 - PSRLL $23,X2 - PXOR X2,X9 - MOVOA X14,X1 - PADDL X15,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X13 - PSRLL $19,X2 - PXOR X2,X13 - MOVOA X11,X1 - PADDL X9,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X7 - PSRLL $19,X2 - PXOR X2,X7 - MOVOA X15,X1 - PADDL X13,X1 - MOVOA X1,X2 - PSLLL $18,X1 - PXOR X1,X12 - PSRLL $14,X2 - PXOR X2,X12 - MOVOA 320(SP),X1 - MOVOA X12,320(SP) - MOVOA X9,X2 - PADDL X7,X2 - MOVOA X2,X12 - PSLLL $18,X2 - PXOR X2,X0 - PSRLL $14,X12 - PXOR X12,X0 - MOVOA X5,X2 - PADDL X1,X2 - MOVOA X2,X12 - PSLLL $7,X2 - PXOR X2,X3 - PSRLL $25,X12 - PXOR X12,X3 - MOVOA 336(SP),X2 - MOVOA X0,336(SP) - MOVOA X6,X0 - PADDL X2,X0 - MOVOA X0,X12 - PSLLL $7,X0 - PXOR X0,X4 - PSRLL $25,X12 - PXOR X12,X4 - MOVOA X1,X0 - PADDL X3,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X10 - PSRLL $23,X12 - PXOR X12,X10 - MOVOA X2,X0 - PADDL X4,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X8 - PSRLL $23,X12 - PXOR X12,X8 - MOVOA X3,X0 - PADDL X10,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X5 - PSRLL $19,X12 - PXOR X12,X5 - MOVOA X4,X0 - PADDL X8,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X6 - PSRLL $19,X12 - PXOR X12,X6 - MOVOA X10,X0 - PADDL X5,X0 - MOVOA X0,X12 - PSLLL $18,X0 - PXOR X0,X1 - PSRLL $14,X12 - PXOR X12,X1 - MOVOA 320(SP),X0 - MOVOA X1,320(SP) - MOVOA X4,X1 - PADDL X0,X1 - MOVOA X1,X12 - PSLLL $7,X1 - PXOR X1,X7 - PSRLL $25,X12 - PXOR X12,X7 - MOVOA X8,X1 - PADDL X6,X1 - MOVOA X1,X12 - PSLLL $18,X1 - PXOR X1,X2 - PSRLL $14,X12 - PXOR X12,X2 - MOVOA 336(SP),X12 - MOVOA X2,336(SP) - MOVOA X14,X1 - PADDL X12,X1 - MOVOA X1,X2 - PSLLL $7,X1 - PXOR X1,X5 - PSRLL $25,X2 - PXOR X2,X5 - MOVOA X0,X1 - PADDL X7,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X10 - PSRLL $23,X2 - PXOR X2,X10 - MOVOA X12,X1 - PADDL X5,X1 - MOVOA X1,X2 - PSLLL $9,X1 - PXOR X1,X8 - PSRLL $23,X2 - PXOR X2,X8 - MOVOA X7,X1 - PADDL X10,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X4 - PSRLL $19,X2 - PXOR X2,X4 - MOVOA X5,X1 - PADDL X8,X1 - MOVOA X1,X2 - PSLLL $13,X1 - PXOR X1,X14 - PSRLL $19,X2 - PXOR X2,X14 - MOVOA X10,X1 - PADDL X4,X1 - MOVOA X1,X2 - PSLLL $18,X1 - PXOR X1,X0 - PSRLL $14,X2 - PXOR X2,X0 - MOVOA 320(SP),X1 - MOVOA X0,320(SP) - MOVOA X8,X0 - PADDL X14,X0 - MOVOA X0,X2 - PSLLL $18,X0 - PXOR X0,X12 - PSRLL $14,X2 - PXOR X2,X12 - MOVOA X11,X0 - PADDL X1,X0 - MOVOA X0,X2 - PSLLL $7,X0 - PXOR X0,X6 - PSRLL $25,X2 - PXOR X2,X6 - MOVOA 336(SP),X2 - MOVOA X12,336(SP) - MOVOA X3,X0 - PADDL X2,X0 - MOVOA X0,X12 - PSLLL $7,X0 - PXOR X0,X13 - PSRLL $25,X12 - PXOR X12,X13 - MOVOA X1,X0 - PADDL X6,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X15 - PSRLL $23,X12 - PXOR X12,X15 - MOVOA X2,X0 - PADDL X13,X0 - MOVOA X0,X12 - PSLLL $9,X0 - PXOR X0,X9 - PSRLL $23,X12 - PXOR X12,X9 - MOVOA X6,X0 - PADDL X15,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X11 - PSRLL $19,X12 - PXOR X12,X11 - MOVOA X13,X0 - PADDL X9,X0 - MOVOA X0,X12 - PSLLL $13,X0 - PXOR X0,X3 - PSRLL $19,X12 - PXOR X12,X3 - MOVOA X15,X0 - PADDL X11,X0 - MOVOA X0,X12 - PSLLL $18,X0 - PXOR X0,X1 - PSRLL $14,X12 - PXOR X12,X1 - MOVOA X9,X0 - PADDL X3,X0 - MOVOA X0,X12 - PSLLL $18,X0 - PXOR X0,X2 - PSRLL $14,X12 - PXOR X12,X2 - MOVOA 320(SP),X12 - MOVOA 336(SP),X0 - SUBQ $2,DX - JA MAINLOOP1 - PADDL 112(SP),X12 - PADDL 176(SP),X7 - PADDL 224(SP),X10 - PADDL 272(SP),X4 - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - PSHUFL $0X39,X12,X12 - PSHUFL $0X39,X7,X7 - PSHUFL $0X39,X10,X10 - PSHUFL $0X39,X4,X4 - XORL 0(SI),DX - XORL 4(SI),CX - XORL 8(SI),R8 - XORL 12(SI),R9 - MOVL DX,0(DI) - MOVL CX,4(DI) - MOVL R8,8(DI) - MOVL R9,12(DI) - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - PSHUFL $0X39,X12,X12 - PSHUFL $0X39,X7,X7 - PSHUFL $0X39,X10,X10 - PSHUFL $0X39,X4,X4 - XORL 64(SI),DX - XORL 68(SI),CX - XORL 72(SI),R8 - XORL 76(SI),R9 - MOVL DX,64(DI) - MOVL CX,68(DI) - MOVL R8,72(DI) - MOVL R9,76(DI) - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - PSHUFL $0X39,X12,X12 - PSHUFL $0X39,X7,X7 - PSHUFL $0X39,X10,X10 - PSHUFL $0X39,X4,X4 - XORL 128(SI),DX - XORL 132(SI),CX - XORL 136(SI),R8 - XORL 140(SI),R9 - MOVL DX,128(DI) - MOVL CX,132(DI) - MOVL R8,136(DI) - MOVL R9,140(DI) - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 - MOVD X4,R9 - XORL 192(SI),DX - XORL 196(SI),CX - XORL 200(SI),R8 - XORL 204(SI),R9 - MOVL DX,192(DI) - MOVL CX,196(DI) - MOVL R8,200(DI) - MOVL R9,204(DI) - PADDL 240(SP),X14 - PADDL 64(SP),X0 - PADDL 128(SP),X5 - PADDL 192(SP),X8 - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - PSHUFL $0X39,X14,X14 - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X5,X5 - PSHUFL $0X39,X8,X8 - XORL 16(SI),DX - XORL 20(SI),CX - XORL 24(SI),R8 - XORL 28(SI),R9 - MOVL DX,16(DI) - MOVL CX,20(DI) - MOVL R8,24(DI) - MOVL R9,28(DI) - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - PSHUFL $0X39,X14,X14 - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X5,X5 - PSHUFL $0X39,X8,X8 - XORL 80(SI),DX - XORL 84(SI),CX - XORL 88(SI),R8 - XORL 92(SI),R9 - MOVL DX,80(DI) - MOVL CX,84(DI) - MOVL R8,88(DI) - MOVL R9,92(DI) - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - PSHUFL $0X39,X14,X14 - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X5,X5 - PSHUFL $0X39,X8,X8 - XORL 144(SI),DX - XORL 148(SI),CX - XORL 152(SI),R8 - XORL 156(SI),R9 - MOVL DX,144(DI) - MOVL CX,148(DI) - MOVL R8,152(DI) - MOVL R9,156(DI) - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 - MOVD X8,R9 - XORL 208(SI),DX - XORL 212(SI),CX - XORL 216(SI),R8 - XORL 220(SI),R9 - MOVL DX,208(DI) - MOVL CX,212(DI) - MOVL R8,216(DI) - MOVL R9,220(DI) - PADDL 288(SP),X15 - PADDL 304(SP),X11 - PADDL 80(SP),X1 - PADDL 144(SP),X6 - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - PSHUFL $0X39,X15,X15 - PSHUFL $0X39,X11,X11 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X6,X6 - XORL 32(SI),DX - XORL 36(SI),CX - XORL 40(SI),R8 - XORL 44(SI),R9 - MOVL DX,32(DI) - MOVL CX,36(DI) - MOVL R8,40(DI) - MOVL R9,44(DI) - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - PSHUFL $0X39,X15,X15 - PSHUFL $0X39,X11,X11 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X6,X6 - XORL 96(SI),DX - XORL 100(SI),CX - XORL 104(SI),R8 - XORL 108(SI),R9 - MOVL DX,96(DI) - MOVL CX,100(DI) - MOVL R8,104(DI) - MOVL R9,108(DI) - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - PSHUFL $0X39,X15,X15 - PSHUFL $0X39,X11,X11 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X6,X6 - XORL 160(SI),DX - XORL 164(SI),CX - XORL 168(SI),R8 - XORL 172(SI),R9 - MOVL DX,160(DI) - MOVL CX,164(DI) - MOVL R8,168(DI) - MOVL R9,172(DI) - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 - MOVD X6,R9 - XORL 224(SI),DX - XORL 228(SI),CX - XORL 232(SI),R8 - XORL 236(SI),R9 - MOVL DX,224(DI) - MOVL CX,228(DI) - MOVL R8,232(DI) - MOVL R9,236(DI) - PADDL 160(SP),X13 - PADDL 208(SP),X9 - PADDL 256(SP),X3 - PADDL 96(SP),X2 - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - PSHUFL $0X39,X13,X13 - PSHUFL $0X39,X9,X9 - PSHUFL $0X39,X3,X3 - PSHUFL $0X39,X2,X2 - XORL 48(SI),DX - XORL 52(SI),CX - XORL 56(SI),R8 - XORL 60(SI),R9 - MOVL DX,48(DI) - MOVL CX,52(DI) - MOVL R8,56(DI) - MOVL R9,60(DI) - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - PSHUFL $0X39,X13,X13 - PSHUFL $0X39,X9,X9 - PSHUFL $0X39,X3,X3 - PSHUFL $0X39,X2,X2 - XORL 112(SI),DX - XORL 116(SI),CX - XORL 120(SI),R8 - XORL 124(SI),R9 - MOVL DX,112(DI) - MOVL CX,116(DI) - MOVL R8,120(DI) - MOVL R9,124(DI) - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - PSHUFL $0X39,X13,X13 - PSHUFL $0X39,X9,X9 - PSHUFL $0X39,X3,X3 - PSHUFL $0X39,X2,X2 - XORL 176(SI),DX - XORL 180(SI),CX - XORL 184(SI),R8 - XORL 188(SI),R9 - MOVL DX,176(DI) - MOVL CX,180(DI) - MOVL R8,184(DI) - MOVL R9,188(DI) - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 - MOVD X2,R9 - XORL 240(SI),DX - XORL 244(SI),CX - XORL 248(SI),R8 - XORL 252(SI),R9 - MOVL DX,240(DI) - MOVL CX,244(DI) - MOVL R8,248(DI) - MOVL R9,252(DI) - MOVQ 352(SP),R9 - SUBQ $256,R9 - ADDQ $256,SI - ADDQ $256,DI - CMPQ R9,$256 - JAE BYTESATLEAST256 - CMPQ R9,$0 - JBE DONE - BYTESBETWEEN1AND255: - CMPQ R9,$64 - JAE NOCOPY - MOVQ DI,DX - LEAQ 360(SP),DI - MOVQ R9,CX +BYTESBETWEEN1AND255: + CMPQ R9, $0x40 + JAE NOCOPY + MOVQ DI, DX + LEAQ 360(R12), DI + MOVQ R9, CX REP; MOVSB - LEAQ 360(SP),DI - LEAQ 360(SP),SI - NOCOPY: - MOVQ R9,352(SP) - MOVOA 48(SP),X0 - MOVOA 0(SP),X1 - MOVOA 16(SP),X2 - MOVOA 32(SP),X3 - MOVOA X1,X4 - MOVQ $20,CX - MAINLOOP2: - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X3 - PXOR X6,X3 - PADDL X3,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X3,X3 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X1 - PSHUFL $0X4E,X2,X2 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X1,X1 - PXOR X6,X0 - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X1 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X1,X1 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X3 - PSHUFL $0X4E,X2,X2 - PXOR X6,X3 - PADDL X3,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X3,X3 - PXOR X6,X0 - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X3 - PXOR X6,X3 - PADDL X3,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X3,X3 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X1 - PSHUFL $0X4E,X2,X2 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X3,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X1,X1 - PXOR X6,X0 - PADDL X0,X4 - MOVOA X0,X5 - MOVOA X4,X6 - PSLLL $7,X4 - PSRLL $25,X6 - PXOR X4,X1 - PXOR X6,X1 - PADDL X1,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $9,X5 - PSRLL $23,X6 - PXOR X5,X2 - PSHUFL $0X93,X1,X1 - PXOR X6,X2 - PADDL X2,X4 - MOVOA X2,X5 - MOVOA X4,X6 - PSLLL $13,X4 - PSRLL $19,X6 - PXOR X4,X3 - PSHUFL $0X4E,X2,X2 - PXOR X6,X3 - SUBQ $4,CX - PADDL X3,X5 - MOVOA X1,X4 - MOVOA X5,X6 - PSLLL $18,X5 - PXOR X7,X7 - PSRLL $14,X6 - PXOR X5,X0 - PSHUFL $0X39,X3,X3 - PXOR X6,X0 - JA MAINLOOP2 - PADDL 48(SP),X0 - PADDL 0(SP),X1 - PADDL 16(SP),X2 - PADDL 32(SP),X3 - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X2,X2 - PSHUFL $0X39,X3,X3 - XORL 0(SI),CX - XORL 48(SI),R8 - XORL 32(SI),R9 - XORL 16(SI),AX - MOVL CX,0(DI) - MOVL R8,48(DI) - MOVL R9,32(DI) - MOVL AX,16(DI) - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X2,X2 - PSHUFL $0X39,X3,X3 - XORL 20(SI),CX - XORL 4(SI),R8 - XORL 52(SI),R9 - XORL 36(SI),AX - MOVL CX,20(DI) - MOVL R8,4(DI) - MOVL R9,52(DI) - MOVL AX,36(DI) - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - PSHUFL $0X39,X0,X0 - PSHUFL $0X39,X1,X1 - PSHUFL $0X39,X2,X2 - PSHUFL $0X39,X3,X3 - XORL 40(SI),CX - XORL 24(SI),R8 - XORL 8(SI),R9 - XORL 56(SI),AX - MOVL CX,40(DI) - MOVL R8,24(DI) - MOVL R9,8(DI) - MOVL AX,56(DI) - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 - MOVD X3,AX - XORL 60(SI),CX - XORL 44(SI),R8 - XORL 28(SI),R9 - XORL 12(SI),AX - MOVL CX,60(DI) - MOVL R8,44(DI) - MOVL R9,28(DI) - MOVL AX,12(DI) - MOVQ 352(SP),R9 - MOVL 16(SP),CX - MOVL 36 (SP),R8 - ADDQ $1,CX - SHLQ $32,R8 - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $32,R8 - MOVL CX,16(SP) - MOVL R8, 36 (SP) - CMPQ R9,$64 - JA BYTESATLEAST65 - JAE BYTESATLEAST64 - MOVQ DI,SI - MOVQ DX,DI - MOVQ R9,CX + LEAQ 360(R12), DI + LEAQ 360(R12), SI + +NOCOPY: + MOVQ R9, 352(R12) + MOVOA 48(R12), X0 + MOVOA (R12), X1 + MOVOA 16(R12), X2 + MOVOA 32(R12), X3 + MOVOA X1, X4 + MOVQ $0x00000014, CX + +MAINLOOP2: + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X3 + PXOR X6, X3 + PADDL X3, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X3, X3 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X1 + PSHUFL $0x4e, X2, X2 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X1, X1 + PXOR X6, X0 + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X1 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X1, X1 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X3 + PSHUFL $0x4e, X2, X2 + PXOR X6, X3 + PADDL X3, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X3, X3 + PXOR X6, X0 + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X3 + PXOR X6, X3 + PADDL X3, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X3, X3 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X1 + PSHUFL $0x4e, X2, X2 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X3, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X1, X1 + PXOR X6, X0 + PADDL X0, X4 + MOVOA X0, X5 + MOVOA X4, X6 + PSLLL $0x07, X4 + PSRLL $0x19, X6 + PXOR X4, X1 + PXOR X6, X1 + PADDL X1, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x09, X5 + PSRLL $0x17, X6 + PXOR X5, X2 + PSHUFL $0x93, X1, X1 + PXOR X6, X2 + PADDL X2, X4 + MOVOA X2, X5 + MOVOA X4, X6 + PSLLL $0x0d, X4 + PSRLL $0x13, X6 + PXOR X4, X3 + PSHUFL $0x4e, X2, X2 + PXOR X6, X3 + SUBQ $0x04, CX + PADDL X3, X5 + MOVOA X1, X4 + MOVOA X5, X6 + PSLLL $0x12, X5 + PXOR X7, X7 + PSRLL $0x0e, X6 + PXOR X5, X0 + PSHUFL $0x39, X3, X3 + PXOR X6, X0 + JA MAINLOOP2 + PADDL 48(R12), X0 + PADDL (R12), X1 + PADDL 16(R12), X2 + PADDL 32(R12), X3 + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X2, X2 + PSHUFL $0x39, X3, X3 + XORL (SI), CX + XORL 48(SI), R8 + XORL 32(SI), R9 + XORL 16(SI), AX + MOVL CX, (DI) + MOVL R8, 48(DI) + MOVL R9, 32(DI) + MOVL AX, 16(DI) + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X2, X2 + PSHUFL $0x39, X3, X3 + XORL 20(SI), CX + XORL 4(SI), R8 + XORL 52(SI), R9 + XORL 36(SI), AX + MOVL CX, 20(DI) + MOVL R8, 4(DI) + MOVL R9, 52(DI) + MOVL AX, 36(DI) + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + PSHUFL $0x39, X0, X0 + PSHUFL $0x39, X1, X1 + PSHUFL $0x39, X2, X2 + PSHUFL $0x39, X3, X3 + XORL 40(SI), CX + XORL 24(SI), R8 + XORL 8(SI), R9 + XORL 56(SI), AX + MOVL CX, 40(DI) + MOVL R8, 24(DI) + MOVL R9, 8(DI) + MOVL AX, 56(DI) + MOVD X0, CX + MOVD X1, R8 + MOVD X2, R9 + MOVD X3, AX + XORL 60(SI), CX + XORL 44(SI), R8 + XORL 28(SI), R9 + XORL 12(SI), AX + MOVL CX, 60(DI) + MOVL R8, 44(DI) + MOVL R9, 28(DI) + MOVL AX, 12(DI) + MOVQ 352(R12), R9 + MOVL 16(R12), CX + MOVL 36(R12), R8 + ADDQ $0x01, CX + SHLQ $0x20, R8 + ADDQ R8, CX + MOVQ CX, R8 + SHRQ $0x20, R8 + MOVL CX, 16(R12) + MOVL R8, 36(R12) + CMPQ R9, $0x40 + JA BYTESATLEAST65 + JAE BYTESATLEAST64 + MOVQ DI, SI + MOVQ DX, DI + MOVQ R9, CX REP; MOVSB - BYTESATLEAST64: - DONE: - MOVQ R12,SP + +BYTESATLEAST64: +DONE: RET - BYTESATLEAST65: - SUBQ $64,R9 - ADDQ $64,DI - ADDQ $64,SI - JMP BYTESBETWEEN1AND255 + +BYTESATLEAST65: + SUBQ $0x40, R9 + ADDQ $0x40, DI + ADDQ $0x40, SI + JMP BYTESBETWEEN1AND255 diff --git a/salsa20/salsa/salsa20_amd64_test.go b/salsa20/salsa/salsa20_amd64_test.go index d4e779cd06..fe14604fc9 100644 --- a/salsa20/salsa/salsa20_amd64_test.go +++ b/salsa20/salsa/salsa20_amd64_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,!appengine,!gccgo +//go:build amd64 && !purego && gc package salsa diff --git a/salsa20/salsa/salsa20_noasm.go b/salsa20/salsa/salsa20_noasm.go index 8a46bd2b3a..9448760f26 100644 --- a/salsa20/salsa/salsa20_noasm.go +++ b/salsa20/salsa/salsa20_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine gccgo +//go:build !amd64 || purego || !gc package salsa diff --git a/salsa20/salsa/salsa20_ref.go b/salsa20/salsa/salsa20_ref.go index 68169c6d68..e5cdb9a25b 100644 --- a/salsa20/salsa/salsa20_ref.go +++ b/salsa20/salsa/salsa20_ref.go @@ -4,6 +4,8 @@ package salsa +import "math/bits" + const rounds = 20 // core applies the Salsa20 core function to 16-byte input in, 32-byte key k, @@ -31,76 +33,76 @@ func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { for i := 0; i < rounds; i += 2 { u := x0 + x12 - x4 ^= u<<7 | u>>(32-7) + x4 ^= bits.RotateLeft32(u, 7) u = x4 + x0 - x8 ^= u<<9 | u>>(32-9) + x8 ^= bits.RotateLeft32(u, 9) u = x8 + x4 - x12 ^= u<<13 | u>>(32-13) + x12 ^= bits.RotateLeft32(u, 13) u = x12 + x8 - x0 ^= u<<18 | u>>(32-18) + x0 ^= bits.RotateLeft32(u, 18) u = x5 + x1 - x9 ^= u<<7 | u>>(32-7) + x9 ^= bits.RotateLeft32(u, 7) u = x9 + x5 - x13 ^= u<<9 | u>>(32-9) + x13 ^= bits.RotateLeft32(u, 9) u = x13 + x9 - x1 ^= u<<13 | u>>(32-13) + x1 ^= bits.RotateLeft32(u, 13) u = x1 + x13 - x5 ^= u<<18 | u>>(32-18) + x5 ^= bits.RotateLeft32(u, 18) u = x10 + x6 - x14 ^= u<<7 | u>>(32-7) + x14 ^= bits.RotateLeft32(u, 7) u = x14 + x10 - x2 ^= u<<9 | u>>(32-9) + x2 ^= bits.RotateLeft32(u, 9) u = x2 + x14 - x6 ^= u<<13 | u>>(32-13) + x6 ^= bits.RotateLeft32(u, 13) u = x6 + x2 - x10 ^= u<<18 | u>>(32-18) + x10 ^= bits.RotateLeft32(u, 18) u = x15 + x11 - x3 ^= u<<7 | u>>(32-7) + x3 ^= bits.RotateLeft32(u, 7) u = x3 + x15 - x7 ^= u<<9 | u>>(32-9) + x7 ^= bits.RotateLeft32(u, 9) u = x7 + x3 - x11 ^= u<<13 | u>>(32-13) + x11 ^= bits.RotateLeft32(u, 13) u = x11 + x7 - x15 ^= u<<18 | u>>(32-18) + x15 ^= bits.RotateLeft32(u, 18) u = x0 + x3 - x1 ^= u<<7 | u>>(32-7) + x1 ^= bits.RotateLeft32(u, 7) u = x1 + x0 - x2 ^= u<<9 | u>>(32-9) + x2 ^= bits.RotateLeft32(u, 9) u = x2 + x1 - x3 ^= u<<13 | u>>(32-13) + x3 ^= bits.RotateLeft32(u, 13) u = x3 + x2 - x0 ^= u<<18 | u>>(32-18) + x0 ^= bits.RotateLeft32(u, 18) u = x5 + x4 - x6 ^= u<<7 | u>>(32-7) + x6 ^= bits.RotateLeft32(u, 7) u = x6 + x5 - x7 ^= u<<9 | u>>(32-9) + x7 ^= bits.RotateLeft32(u, 9) u = x7 + x6 - x4 ^= u<<13 | u>>(32-13) + x4 ^= bits.RotateLeft32(u, 13) u = x4 + x7 - x5 ^= u<<18 | u>>(32-18) + x5 ^= bits.RotateLeft32(u, 18) u = x10 + x9 - x11 ^= u<<7 | u>>(32-7) + x11 ^= bits.RotateLeft32(u, 7) u = x11 + x10 - x8 ^= u<<9 | u>>(32-9) + x8 ^= bits.RotateLeft32(u, 9) u = x8 + x11 - x9 ^= u<<13 | u>>(32-13) + x9 ^= bits.RotateLeft32(u, 13) u = x9 + x8 - x10 ^= u<<18 | u>>(32-18) + x10 ^= bits.RotateLeft32(u, 18) u = x15 + x14 - x12 ^= u<<7 | u>>(32-7) + x12 ^= bits.RotateLeft32(u, 7) u = x12 + x15 - x13 ^= u<<9 | u>>(32-9) + x13 ^= bits.RotateLeft32(u, 9) u = x13 + x12 - x14 ^= u<<13 | u>>(32-13) + x14 ^= bits.RotateLeft32(u, 13) u = x14 + x13 - x15 ^= u<<18 | u>>(32-18) + x15 ^= bits.RotateLeft32(u, 18) } x0 += j0 x1 += j1 diff --git a/salsa20/salsa20.go b/salsa20/salsa20.go index 6f9bb106ca..e75c9342a8 100644 --- a/salsa20/salsa20.go +++ b/salsa20/salsa20.go @@ -19,12 +19,12 @@ This package also implements XSalsa20: a version of Salsa20 with a 24-byte nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply passing a 24-byte slice as the nonce triggers XSalsa20. */ -package salsa20 // import "golang.org/x/crypto/salsa20" +package salsa20 // TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. import ( - "golang.org/x/crypto/internal/subtle" + "golang.org/x/crypto/internal/alias" "golang.org/x/crypto/salsa20/salsa" ) @@ -35,7 +35,7 @@ func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { if len(out) < len(in) { panic("salsa20: output smaller than input") } - if subtle.InexactOverlap(out[:len(in)], in) { + if alias.InexactOverlap(out[:len(in)], in) { panic("salsa20: invalid buffer overlap") } diff --git a/scrypt/scrypt.go b/scrypt/scrypt.go index 2f81fe4148..76fa40fb20 100644 --- a/scrypt/scrypt.go +++ b/scrypt/scrypt.go @@ -5,10 +5,11 @@ // Package scrypt implements the scrypt key derivation function as defined in // Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard // Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf). -package scrypt // import "golang.org/x/crypto/scrypt" +package scrypt import ( "crypto/sha256" + "encoding/binary" "errors" "math/bits" @@ -143,36 +144,34 @@ func integer(b []uint32, r int) uint64 { func smix(b []byte, r, N int, v, xy []uint32) { var tmp [16]uint32 + R := 32 * r x := xy - y := xy[32*r:] + y := xy[R:] j := 0 - for i := 0; i < 32*r; i++ { - x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24 + for i := 0; i < R; i++ { + x[i] = binary.LittleEndian.Uint32(b[j:]) j += 4 } for i := 0; i < N; i += 2 { - blockCopy(v[i*(32*r):], x, 32*r) + blockCopy(v[i*R:], x, R) blockMix(&tmp, x, y, r) - blockCopy(v[(i+1)*(32*r):], y, 32*r) + blockCopy(v[(i+1)*R:], y, R) blockMix(&tmp, y, x, r) } for i := 0; i < N; i += 2 { j := int(integer(x, r) & uint64(N-1)) - blockXOR(x, v[j*(32*r):], 32*r) + blockXOR(x, v[j*R:], R) blockMix(&tmp, x, y, r) j = int(integer(y, r) & uint64(N-1)) - blockXOR(y, v[j*(32*r):], 32*r) + blockXOR(y, v[j*R:], R) blockMix(&tmp, y, x, r) } j = 0 - for _, v := range x[:32*r] { - b[j+0] = byte(v >> 0) - b[j+1] = byte(v >> 8) - b[j+2] = byte(v >> 16) - b[j+3] = byte(v >> 24) + for _, v := range x[:R] { + binary.LittleEndian.PutUint32(b[j:], v) j += 4 } } @@ -187,7 +186,7 @@ func smix(b []byte, r, N int, v, xy []uint32) { // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // -// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) +// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) // // The recommended parameters for interactive logins as of 2017 are N=32768, r=8 // and p=1. The parameters N, r, and p should be increased as memory latency and diff --git a/sha3/doc.go b/sha3/doc.go deleted file mode 100644 index c2fef30aff..0000000000 --- a/sha3/doc.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 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 sha3 implements the SHA-3 fixed-output-length hash functions and -// the SHAKE variable-output-length hash functions defined by FIPS-202. -// -// Both types of hash function use the "sponge" construction and the Keccak -// permutation. For a detailed specification see http://keccak.noekeon.org/ -// -// -// Guidance -// -// If you aren't sure what function you need, use SHAKE256 with at least 64 -// bytes of output. The SHAKE instances are faster than the SHA3 instances; -// the latter have to allocate memory to conform to the hash.Hash interface. -// -// If you need a secret-key MAC (message authentication code), prepend the -// secret key to the input, hash with SHAKE256 and read at least 32 bytes of -// output. -// -// -// Security strengths -// -// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security -// strength against preimage attacks of x bits. Since they only produce "x" -// bits of output, their collision-resistance is only "x/2" bits. -// -// The SHAKE-256 and -128 functions have a generic security strength of 256 and -// 128 bits against all attacks, provided that at least 2x bits of their output -// is used. Requesting more than 64 or 32 bytes of output, respectively, does -// not increase the collision-resistance of the SHAKE functions. -// -// -// The sponge construction -// -// A sponge builds a pseudo-random function from a public pseudo-random -// permutation, by applying the permutation to a state of "rate + capacity" -// bytes, but hiding "capacity" of the bytes. -// -// A sponge starts out with a zero state. To hash an input using a sponge, up -// to "rate" bytes of the input are XORed into the sponge's state. The sponge -// is then "full" and the permutation is applied to "empty" it. This process is -// repeated until all the input has been "absorbed". The input is then padded. -// The digest is "squeezed" from the sponge in the same way, except that output -// is copied out instead of input being XORed in. -// -// A sponge is parameterized by its generic security strength, which is equal -// to half its capacity; capacity + rate is equal to the permutation's width. -// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means -// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. -// -// -// Recommendations -// -// The SHAKE functions are recommended for most new uses. They can produce -// output of arbitrary length. SHAKE256, with an output length of at least -// 64 bytes, provides 256-bit security against all attacks. The Keccak team -// recommends it for most applications upgrading from SHA2-512. (NIST chose a -// much stronger, but much slower, sponge instance for SHA3-512.) -// -// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. -// They produce output of the same length, with the same security strengths -// against all attacks. This means, in particular, that SHA3-256 only has -// 128-bit collision resistance, because its output length is 32 bytes. -package sha3 // import "golang.org/x/crypto/sha3" diff --git a/sha3/hashes.go b/sha3/hashes.go index 0d8043fd2a..a51269d91a 100644 --- a/sha3/hashes.go +++ b/sha3/hashes.go @@ -2,96 +2,94 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Package sha3 implements the SHA-3 hash algorithms and the SHAKE extendable +// output functions defined in FIPS 202. +// +// Most of this package is a wrapper around the crypto/sha3 package in the +// standard library. The only exception is the legacy Keccak hash functions. package sha3 -// This file provides functions for creating instances of the SHA-3 -// and SHAKE hash functions, as well as utility functions for hashing -// bytes. - import ( + "crypto/sha3" "hash" ) // New224 creates a new SHA3-224 hash. // Its generic security strength is 224 bits against preimage attacks, // and 112 bits against collision attacks. +// +// It is a wrapper for the [sha3.New224] function in the standard library. +// +//go:fix inline func New224() hash.Hash { - if h := new224Asm(); h != nil { - return h - } - return &state{rate: 144, outputLen: 28, dsbyte: 0x06} + return sha3.New224() } // New256 creates a new SHA3-256 hash. // Its generic security strength is 256 bits against preimage attacks, // and 128 bits against collision attacks. +// +// It is a wrapper for the [sha3.New256] function in the standard library. +// +//go:fix inline func New256() hash.Hash { - if h := new256Asm(); h != nil { - return h - } - return &state{rate: 136, outputLen: 32, dsbyte: 0x06} + return sha3.New256() } // New384 creates a new SHA3-384 hash. // Its generic security strength is 384 bits against preimage attacks, // and 192 bits against collision attacks. +// +// It is a wrapper for the [sha3.New384] function in the standard library. +// +//go:fix inline func New384() hash.Hash { - if h := new384Asm(); h != nil { - return h - } - return &state{rate: 104, outputLen: 48, dsbyte: 0x06} + return sha3.New384() } // New512 creates a new SHA3-512 hash. // Its generic security strength is 512 bits against preimage attacks, // and 256 bits against collision attacks. +// +// It is a wrapper for the [sha3.New512] function in the standard library. +// +//go:fix inline func New512() hash.Hash { - if h := new512Asm(); h != nil { - return h - } - return &state{rate: 72, outputLen: 64, dsbyte: 0x06} + return sha3.New512() } -// NewLegacyKeccak256 creates a new Keccak-256 hash. +// Sum224 returns the SHA3-224 digest of the data. // -// Only use this function if you require compatibility with an existing cryptosystem -// that uses non-standard padding. All other users should use New256 instead. -func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } - -// NewLegacyKeccak512 creates a new Keccak-512 hash. +// It is a wrapper for the [sha3.Sum224] function in the standard library. // -// Only use this function if you require compatibility with an existing cryptosystem -// that uses non-standard padding. All other users should use New512 instead. -func NewLegacyKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } - -// Sum224 returns the SHA3-224 digest of the data. -func Sum224(data []byte) (digest [28]byte) { - h := New224() - h.Write(data) - h.Sum(digest[:0]) - return +//go:fix inline +func Sum224(data []byte) [28]byte { + return sha3.Sum224(data) } // Sum256 returns the SHA3-256 digest of the data. -func Sum256(data []byte) (digest [32]byte) { - h := New256() - h.Write(data) - h.Sum(digest[:0]) - return +// +// It is a wrapper for the [sha3.Sum256] function in the standard library. +// +//go:fix inline +func Sum256(data []byte) [32]byte { + return sha3.Sum256(data) } // Sum384 returns the SHA3-384 digest of the data. -func Sum384(data []byte) (digest [48]byte) { - h := New384() - h.Write(data) - h.Sum(digest[:0]) - return +// +// It is a wrapper for the [sha3.Sum384] function in the standard library. +// +//go:fix inline +func Sum384(data []byte) [48]byte { + return sha3.Sum384(data) } // Sum512 returns the SHA3-512 digest of the data. -func Sum512(data []byte) (digest [64]byte) { - h := New512() - h.Write(data) - h.Sum(digest[:0]) - return +// +// It is a wrapper for the [sha3.Sum512] function in the standard library. +// +//go:fix inline +func Sum512(data []byte) [64]byte { + return sha3.Sum512(data) } diff --git a/sha3/hashes_generic.go b/sha3/hashes_generic.go deleted file mode 100644 index f455147d21..0000000000 --- a/sha3/hashes_generic.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build gccgo appengine !s390x - -package sha3 - -import ( - "hash" -) - -// new224Asm returns an assembly implementation of SHA3-224 if available, -// otherwise it returns nil. -func new224Asm() hash.Hash { return nil } - -// new256Asm returns an assembly implementation of SHA3-256 if available, -// otherwise it returns nil. -func new256Asm() hash.Hash { return nil } - -// new384Asm returns an assembly implementation of SHA3-384 if available, -// otherwise it returns nil. -func new384Asm() hash.Hash { return nil } - -// new512Asm returns an assembly implementation of SHA3-512 if available, -// otherwise it returns nil. -func new512Asm() hash.Hash { return nil } diff --git a/sha3/keccakf_amd64.go b/sha3/keccakf_amd64.go deleted file mode 100644 index 7886795850..0000000000 --- a/sha3/keccakf_amd64.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!appengine,!gccgo - -package sha3 - -// This function is implemented in keccakf_amd64.s. - -//go:noescape - -func keccakF1600(a *[25]uint64) diff --git a/sha3/keccakf_amd64.s b/sha3/keccakf_amd64.s deleted file mode 100644 index f88533accd..0000000000 --- a/sha3/keccakf_amd64.s +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!appengine,!gccgo - -// This code was translated into a form compatible with 6a from the public -// domain sources at https://github.com/gvanas/KeccakCodePackage - -// Offsets in state -#define _ba (0*8) -#define _be (1*8) -#define _bi (2*8) -#define _bo (3*8) -#define _bu (4*8) -#define _ga (5*8) -#define _ge (6*8) -#define _gi (7*8) -#define _go (8*8) -#define _gu (9*8) -#define _ka (10*8) -#define _ke (11*8) -#define _ki (12*8) -#define _ko (13*8) -#define _ku (14*8) -#define _ma (15*8) -#define _me (16*8) -#define _mi (17*8) -#define _mo (18*8) -#define _mu (19*8) -#define _sa (20*8) -#define _se (21*8) -#define _si (22*8) -#define _so (23*8) -#define _su (24*8) - -// Temporary registers -#define rT1 AX - -// Round vars -#define rpState DI -#define rpStack SP - -#define rDa BX -#define rDe CX -#define rDi DX -#define rDo R8 -#define rDu R9 - -#define rBa R10 -#define rBe R11 -#define rBi R12 -#define rBo R13 -#define rBu R14 - -#define rCa SI -#define rCe BP -#define rCi rBi -#define rCo rBo -#define rCu R15 - -#define MOVQ_RBI_RCE MOVQ rBi, rCe -#define XORQ_RT1_RCA XORQ rT1, rCa -#define XORQ_RT1_RCE XORQ rT1, rCe -#define XORQ_RBA_RCU XORQ rBa, rCu -#define XORQ_RBE_RCU XORQ rBe, rCu -#define XORQ_RDU_RCU XORQ rDu, rCu -#define XORQ_RDA_RCA XORQ rDa, rCa -#define XORQ_RDE_RCE XORQ rDe, rCe - -#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ - /* Prepare round */ \ - MOVQ rCe, rDa; \ - ROLQ $1, rDa; \ - \ - MOVQ _bi(iState), rCi; \ - XORQ _gi(iState), rDi; \ - XORQ rCu, rDa; \ - XORQ _ki(iState), rCi; \ - XORQ _mi(iState), rDi; \ - XORQ rDi, rCi; \ - \ - MOVQ rCi, rDe; \ - ROLQ $1, rDe; \ - \ - MOVQ _bo(iState), rCo; \ - XORQ _go(iState), rDo; \ - XORQ rCa, rDe; \ - XORQ _ko(iState), rCo; \ - XORQ _mo(iState), rDo; \ - XORQ rDo, rCo; \ - \ - MOVQ rCo, rDi; \ - ROLQ $1, rDi; \ - \ - MOVQ rCu, rDo; \ - XORQ rCe, rDi; \ - ROLQ $1, rDo; \ - \ - MOVQ rCa, rDu; \ - XORQ rCi, rDo; \ - ROLQ $1, rDu; \ - \ - /* Result b */ \ - MOVQ _ba(iState), rBa; \ - MOVQ _ge(iState), rBe; \ - XORQ rCo, rDu; \ - MOVQ _ki(iState), rBi; \ - MOVQ _mo(iState), rBo; \ - MOVQ _su(iState), rBu; \ - XORQ rDe, rBe; \ - ROLQ $44, rBe; \ - XORQ rDi, rBi; \ - XORQ rDa, rBa; \ - ROLQ $43, rBi; \ - \ - MOVQ rBe, rCa; \ - MOVQ rc, rT1; \ - ORQ rBi, rCa; \ - XORQ rBa, rT1; \ - XORQ rT1, rCa; \ - MOVQ rCa, _ba(oState); \ - \ - XORQ rDu, rBu; \ - ROLQ $14, rBu; \ - MOVQ rBa, rCu; \ - ANDQ rBe, rCu; \ - XORQ rBu, rCu; \ - MOVQ rCu, _bu(oState); \ - \ - XORQ rDo, rBo; \ - ROLQ $21, rBo; \ - MOVQ rBo, rT1; \ - ANDQ rBu, rT1; \ - XORQ rBi, rT1; \ - MOVQ rT1, _bi(oState); \ - \ - NOTQ rBi; \ - ORQ rBa, rBu; \ - ORQ rBo, rBi; \ - XORQ rBo, rBu; \ - XORQ rBe, rBi; \ - MOVQ rBu, _bo(oState); \ - MOVQ rBi, _be(oState); \ - B_RBI_RCE; \ - \ - /* Result g */ \ - MOVQ _gu(iState), rBe; \ - XORQ rDu, rBe; \ - MOVQ _ka(iState), rBi; \ - ROLQ $20, rBe; \ - XORQ rDa, rBi; \ - ROLQ $3, rBi; \ - MOVQ _bo(iState), rBa; \ - MOVQ rBe, rT1; \ - ORQ rBi, rT1; \ - XORQ rDo, rBa; \ - MOVQ _me(iState), rBo; \ - MOVQ _si(iState), rBu; \ - ROLQ $28, rBa; \ - XORQ rBa, rT1; \ - MOVQ rT1, _ga(oState); \ - G_RT1_RCA; \ - \ - XORQ rDe, rBo; \ - ROLQ $45, rBo; \ - MOVQ rBi, rT1; \ - ANDQ rBo, rT1; \ - XORQ rBe, rT1; \ - MOVQ rT1, _ge(oState); \ - G_RT1_RCE; \ - \ - XORQ rDi, rBu; \ - ROLQ $61, rBu; \ - MOVQ rBu, rT1; \ - ORQ rBa, rT1; \ - XORQ rBo, rT1; \ - MOVQ rT1, _go(oState); \ - \ - ANDQ rBe, rBa; \ - XORQ rBu, rBa; \ - MOVQ rBa, _gu(oState); \ - NOTQ rBu; \ - G_RBA_RCU; \ - \ - ORQ rBu, rBo; \ - XORQ rBi, rBo; \ - MOVQ rBo, _gi(oState); \ - \ - /* Result k */ \ - MOVQ _be(iState), rBa; \ - MOVQ _gi(iState), rBe; \ - MOVQ _ko(iState), rBi; \ - MOVQ _mu(iState), rBo; \ - MOVQ _sa(iState), rBu; \ - XORQ rDi, rBe; \ - ROLQ $6, rBe; \ - XORQ rDo, rBi; \ - ROLQ $25, rBi; \ - MOVQ rBe, rT1; \ - ORQ rBi, rT1; \ - XORQ rDe, rBa; \ - ROLQ $1, rBa; \ - XORQ rBa, rT1; \ - MOVQ rT1, _ka(oState); \ - K_RT1_RCA; \ - \ - XORQ rDu, rBo; \ - ROLQ $8, rBo; \ - MOVQ rBi, rT1; \ - ANDQ rBo, rT1; \ - XORQ rBe, rT1; \ - MOVQ rT1, _ke(oState); \ - K_RT1_RCE; \ - \ - XORQ rDa, rBu; \ - ROLQ $18, rBu; \ - NOTQ rBo; \ - MOVQ rBo, rT1; \ - ANDQ rBu, rT1; \ - XORQ rBi, rT1; \ - MOVQ rT1, _ki(oState); \ - \ - MOVQ rBu, rT1; \ - ORQ rBa, rT1; \ - XORQ rBo, rT1; \ - MOVQ rT1, _ko(oState); \ - \ - ANDQ rBe, rBa; \ - XORQ rBu, rBa; \ - MOVQ rBa, _ku(oState); \ - K_RBA_RCU; \ - \ - /* Result m */ \ - MOVQ _ga(iState), rBe; \ - XORQ rDa, rBe; \ - MOVQ _ke(iState), rBi; \ - ROLQ $36, rBe; \ - XORQ rDe, rBi; \ - MOVQ _bu(iState), rBa; \ - ROLQ $10, rBi; \ - MOVQ rBe, rT1; \ - MOVQ _mi(iState), rBo; \ - ANDQ rBi, rT1; \ - XORQ rDu, rBa; \ - MOVQ _so(iState), rBu; \ - ROLQ $27, rBa; \ - XORQ rBa, rT1; \ - MOVQ rT1, _ma(oState); \ - M_RT1_RCA; \ - \ - XORQ rDi, rBo; \ - ROLQ $15, rBo; \ - MOVQ rBi, rT1; \ - ORQ rBo, rT1; \ - XORQ rBe, rT1; \ - MOVQ rT1, _me(oState); \ - M_RT1_RCE; \ - \ - XORQ rDo, rBu; \ - ROLQ $56, rBu; \ - NOTQ rBo; \ - MOVQ rBo, rT1; \ - ORQ rBu, rT1; \ - XORQ rBi, rT1; \ - MOVQ rT1, _mi(oState); \ - \ - ORQ rBa, rBe; \ - XORQ rBu, rBe; \ - MOVQ rBe, _mu(oState); \ - \ - ANDQ rBa, rBu; \ - XORQ rBo, rBu; \ - MOVQ rBu, _mo(oState); \ - M_RBE_RCU; \ - \ - /* Result s */ \ - MOVQ _bi(iState), rBa; \ - MOVQ _go(iState), rBe; \ - MOVQ _ku(iState), rBi; \ - XORQ rDi, rBa; \ - MOVQ _ma(iState), rBo; \ - ROLQ $62, rBa; \ - XORQ rDo, rBe; \ - MOVQ _se(iState), rBu; \ - ROLQ $55, rBe; \ - \ - XORQ rDu, rBi; \ - MOVQ rBa, rDu; \ - XORQ rDe, rBu; \ - ROLQ $2, rBu; \ - ANDQ rBe, rDu; \ - XORQ rBu, rDu; \ - MOVQ rDu, _su(oState); \ - \ - ROLQ $39, rBi; \ - S_RDU_RCU; \ - NOTQ rBe; \ - XORQ rDa, rBo; \ - MOVQ rBe, rDa; \ - ANDQ rBi, rDa; \ - XORQ rBa, rDa; \ - MOVQ rDa, _sa(oState); \ - S_RDA_RCA; \ - \ - ROLQ $41, rBo; \ - MOVQ rBi, rDe; \ - ORQ rBo, rDe; \ - XORQ rBe, rDe; \ - MOVQ rDe, _se(oState); \ - S_RDE_RCE; \ - \ - MOVQ rBo, rDi; \ - MOVQ rBu, rDo; \ - ANDQ rBu, rDi; \ - ORQ rBa, rDo; \ - XORQ rBi, rDi; \ - XORQ rBo, rDo; \ - MOVQ rDi, _si(oState); \ - MOVQ rDo, _so(oState) \ - -// func keccakF1600(state *[25]uint64) -TEXT ·keccakF1600(SB), 0, $200-8 - MOVQ state+0(FP), rpState - - // Convert the user state into an internal state - NOTQ _be(rpState) - NOTQ _bi(rpState) - NOTQ _go(rpState) - NOTQ _ki(rpState) - NOTQ _mi(rpState) - NOTQ _sa(rpState) - - // Execute the KeccakF permutation - MOVQ _ba(rpState), rCa - MOVQ _be(rpState), rCe - MOVQ _bu(rpState), rCu - - XORQ _ga(rpState), rCa - XORQ _ge(rpState), rCe - XORQ _gu(rpState), rCu - - XORQ _ka(rpState), rCa - XORQ _ke(rpState), rCe - XORQ _ku(rpState), rCu - - XORQ _ma(rpState), rCa - XORQ _me(rpState), rCe - XORQ _mu(rpState), rCu - - XORQ _sa(rpState), rCa - XORQ _se(rpState), rCe - MOVQ _si(rpState), rDi - MOVQ _so(rpState), rDo - XORQ _su(rpState), rCu - - mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) - - // Revert the internal state to the user state - NOTQ _be(rpState) - NOTQ _bi(rpState) - NOTQ _go(rpState) - NOTQ _ki(rpState) - NOTQ _mi(rpState) - NOTQ _sa(rpState) - - RET diff --git a/sha3/legacy_hash.go b/sha3/legacy_hash.go new file mode 100644 index 0000000000..b8784536e0 --- /dev/null +++ b/sha3/legacy_hash.go @@ -0,0 +1,263 @@ +// Copyright 2014 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 sha3 + +// This implementation is only used for NewLegacyKeccak256 and +// NewLegacyKeccak512, which are not implemented by crypto/sha3. +// All other functions in this package are wrappers around crypto/sha3. + +import ( + "crypto/subtle" + "encoding/binary" + "errors" + "hash" + "unsafe" + + "golang.org/x/sys/cpu" +) + +const ( + dsbyteKeccak = 0b00000001 + + // rateK[c] is the rate in bytes for Keccak[c] where c is the capacity in + // bits. Given the sponge size is 1600 bits, the rate is 1600 - c bits. + rateK256 = (1600 - 256) / 8 + rateK512 = (1600 - 512) / 8 + rateK1024 = (1600 - 1024) / 8 +) + +// NewLegacyKeccak256 creates a new Keccak-256 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New256 instead. +func NewLegacyKeccak256() hash.Hash { + return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak} +} + +// NewLegacyKeccak512 creates a new Keccak-512 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New512 instead. +func NewLegacyKeccak512() hash.Hash { + return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak} +} + +// spongeDirection indicates the direction bytes are flowing through the sponge. +type spongeDirection int + +const ( + // spongeAbsorbing indicates that the sponge is absorbing input. + spongeAbsorbing spongeDirection = iota + // spongeSqueezing indicates that the sponge is being squeezed. + spongeSqueezing +) + +type state struct { + a [1600 / 8]byte // main state of the hash + + // a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR + // into before running the permutation. If squeezing, it's the remaining + // output to produce before running the permutation. + n, rate int + + // dsbyte contains the "domain separation" bits and the first bit of + // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the + // SHA-3 and SHAKE functions by appending bitstrings to the message. + // Using a little-endian bit-ordering convention, these are "01" for SHA-3 + // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the + // padding rule from section 5.1 is applied to pad the message to a multiple + // of the rate, which involves adding a "1" bit, zero or more "0" bits, and + // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, + // giving 00000110b (0x06) and 00011111b (0x1f). + // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf + // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and + // Extendable-Output Functions (May 2014)" + dsbyte byte + + outputLen int // the default output size in bytes + state spongeDirection // whether the sponge is absorbing or squeezing +} + +// BlockSize returns the rate of sponge underlying this hash function. +func (d *state) BlockSize() int { return d.rate } + +// Size returns the output size of the hash function in bytes. +func (d *state) Size() int { return d.outputLen } + +// Reset clears the internal state by zeroing the sponge state and +// the buffer indexes, and setting Sponge.state to absorbing. +func (d *state) Reset() { + // Zero the permutation's state. + for i := range d.a { + d.a[i] = 0 + } + d.state = spongeAbsorbing + d.n = 0 +} + +func (d *state) clone() *state { + ret := *d + return &ret +} + +// permute applies the KeccakF-1600 permutation. +func (d *state) permute() { + var a *[25]uint64 + if cpu.IsBigEndian { + a = new([25]uint64) + for i := range a { + a[i] = binary.LittleEndian.Uint64(d.a[i*8:]) + } + } else { + a = (*[25]uint64)(unsafe.Pointer(&d.a)) + } + + keccakF1600(a) + d.n = 0 + + if cpu.IsBigEndian { + for i := range a { + binary.LittleEndian.PutUint64(d.a[i*8:], a[i]) + } + } +} + +// pads appends the domain separation bits in dsbyte, applies +// the multi-bitrate 10..1 padding rule, and permutes the state. +func (d *state) padAndPermute() { + // Pad with this instance's domain-separator bits. We know that there's + // at least one byte of space in the sponge because, if it were full, + // permute would have been called to empty it. dsbyte also contains the + // first one bit for the padding. See the comment in the state struct. + d.a[d.n] ^= d.dsbyte + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + d.a[d.rate-1] ^= 0x80 + // Apply the permutation + d.permute() + d.state = spongeSqueezing +} + +// Write absorbs more data into the hash's state. It panics if any +// output has already been read. +func (d *state) Write(p []byte) (n int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: Write after Read") + } + + n = len(p) + + for len(p) > 0 { + x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p) + d.n += x + p = p[x:] + + // If the sponge is full, apply the permutation. + if d.n == d.rate { + d.permute() + } + } + + return +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (d *state) Read(out []byte) (n int, err error) { + // If we're still absorbing, pad and apply the permutation. + if d.state == spongeAbsorbing { + d.padAndPermute() + } + + n = len(out) + + // Now, do the squeezing. + for len(out) > 0 { + // Apply the permutation if we've squeezed the sponge dry. + if d.n == d.rate { + d.permute() + } + + x := copy(out, d.a[d.n:d.rate]) + d.n += x + out = out[x:] + } + + return +} + +// Sum applies padding to the hash state and then squeezes out the desired +// number of output bytes. It panics if any output has already been read. +func (d *state) Sum(in []byte) []byte { + if d.state != spongeAbsorbing { + panic("sha3: Sum after Read") + } + + // Make a copy of the original hash so that caller can keep writing + // and summing. + dup := d.clone() + hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation + dup.Read(hash) + return append(in, hash...) +} + +const ( + magicKeccak = "sha\x0b" + // magic || rate || main state || n || sponge direction + marshaledSize = len(magicKeccak) + 1 + 200 + 1 + 1 +) + +func (d *state) MarshalBinary() ([]byte, error) { + return d.AppendBinary(make([]byte, 0, marshaledSize)) +} + +func (d *state) AppendBinary(b []byte) ([]byte, error) { + switch d.dsbyte { + case dsbyteKeccak: + b = append(b, magicKeccak...) + default: + panic("unknown dsbyte") + } + // rate is at most 168, and n is at most rate. + b = append(b, byte(d.rate)) + b = append(b, d.a[:]...) + b = append(b, byte(d.n), byte(d.state)) + return b, nil +} + +func (d *state) UnmarshalBinary(b []byte) error { + if len(b) != marshaledSize { + return errors.New("sha3: invalid hash state") + } + + magic := string(b[:len(magicKeccak)]) + b = b[len(magicKeccak):] + switch { + case magic == magicKeccak && d.dsbyte == dsbyteKeccak: + default: + return errors.New("sha3: invalid hash state identifier") + } + + rate := int(b[0]) + b = b[1:] + if rate != d.rate { + return errors.New("sha3: invalid hash state function") + } + + copy(d.a[:], b) + b = b[len(d.a):] + + n, state := int(b[0]), spongeDirection(b[1]) + if n > d.rate { + return errors.New("sha3: invalid hash state") + } + d.n = n + if state != spongeAbsorbing && state != spongeSqueezing { + return errors.New("sha3: invalid hash state") + } + d.state = state + + return nil +} diff --git a/sha3/keccakf.go b/sha3/legacy_keccakf.go similarity index 68% rename from sha3/keccakf.go rename to sha3/legacy_keccakf.go index 46d03ed385..101588c16c 100644 --- a/sha3/keccakf.go +++ b/sha3/legacy_keccakf.go @@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine gccgo - package sha3 +// This implementation is only used for NewLegacyKeccak256 and +// NewLegacyKeccak512, which are not implemented by crypto/sha3. +// All other functions in this package are wrappers around crypto/sha3. + +import "math/bits" + // rc stores the round constants for use in the ι step. var rc = [24]uint64{ 0x0000000000000001, @@ -59,13 +63,13 @@ func keccakF1600(a *[25]uint64) { bc0 = a[0] ^ d0 t = a[6] ^ d1 - bc1 = t<<44 | t>>(64-44) + bc1 = bits.RotateLeft64(t, 44) t = a[12] ^ d2 - bc2 = t<<43 | t>>(64-43) + bc2 = bits.RotateLeft64(t, 43) t = a[18] ^ d3 - bc3 = t<<21 | t>>(64-21) + bc3 = bits.RotateLeft64(t, 21) t = a[24] ^ d4 - bc4 = t<<14 | t>>(64-14) + bc4 = bits.RotateLeft64(t, 14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] a[6] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) @@ -73,15 +77,15 @@ func keccakF1600(a *[25]uint64) { a[24] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 - bc2 = t<<3 | t>>(64-3) + bc2 = bits.RotateLeft64(t, 3) t = a[16] ^ d1 - bc3 = t<<45 | t>>(64-45) + bc3 = bits.RotateLeft64(t, 45) t = a[22] ^ d2 - bc4 = t<<61 | t>>(64-61) + bc4 = bits.RotateLeft64(t, 61) t = a[3] ^ d3 - bc0 = t<<28 | t>>(64-28) + bc0 = bits.RotateLeft64(t, 28) t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) + bc1 = bits.RotateLeft64(t, 20) a[10] = bc0 ^ (bc2 &^ bc1) a[16] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) @@ -89,15 +93,15 @@ func keccakF1600(a *[25]uint64) { a[9] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 - bc4 = t<<18 | t>>(64-18) + bc4 = bits.RotateLeft64(t, 18) t = a[1] ^ d1 - bc0 = t<<1 | t>>(64-1) + bc0 = bits.RotateLeft64(t, 1) t = a[7] ^ d2 - bc1 = t<<6 | t>>(64-6) + bc1 = bits.RotateLeft64(t, 6) t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) + bc2 = bits.RotateLeft64(t, 25) t = a[19] ^ d4 - bc3 = t<<8 | t>>(64-8) + bc3 = bits.RotateLeft64(t, 8) a[20] = bc0 ^ (bc2 &^ bc1) a[1] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) @@ -105,15 +109,15 @@ func keccakF1600(a *[25]uint64) { a[19] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 - bc1 = t<<36 | t>>(64-36) + bc1 = bits.RotateLeft64(t, 36) t = a[11] ^ d1 - bc2 = t<<10 | t>>(64-10) + bc2 = bits.RotateLeft64(t, 10) t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) + bc3 = bits.RotateLeft64(t, 15) t = a[23] ^ d3 - bc4 = t<<56 | t>>(64-56) + bc4 = bits.RotateLeft64(t, 56) t = a[4] ^ d4 - bc0 = t<<27 | t>>(64-27) + bc0 = bits.RotateLeft64(t, 27) a[5] = bc0 ^ (bc2 &^ bc1) a[11] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) @@ -121,15 +125,15 @@ func keccakF1600(a *[25]uint64) { a[4] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 - bc3 = t<<41 | t>>(64-41) + bc3 = bits.RotateLeft64(t, 41) t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) + bc4 = bits.RotateLeft64(t, 2) t = a[2] ^ d2 - bc0 = t<<62 | t>>(64-62) + bc0 = bits.RotateLeft64(t, 62) t = a[8] ^ d3 - bc1 = t<<55 | t>>(64-55) + bc1 = bits.RotateLeft64(t, 55) t = a[14] ^ d4 - bc2 = t<<39 | t>>(64-39) + bc2 = bits.RotateLeft64(t, 39) a[15] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) @@ -150,13 +154,13 @@ func keccakF1600(a *[25]uint64) { bc0 = a[0] ^ d0 t = a[16] ^ d1 - bc1 = t<<44 | t>>(64-44) + bc1 = bits.RotateLeft64(t, 44) t = a[7] ^ d2 - bc2 = t<<43 | t>>(64-43) + bc2 = bits.RotateLeft64(t, 43) t = a[23] ^ d3 - bc3 = t<<21 | t>>(64-21) + bc3 = bits.RotateLeft64(t, 21) t = a[14] ^ d4 - bc4 = t<<14 | t>>(64-14) + bc4 = bits.RotateLeft64(t, 14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] a[16] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) @@ -164,15 +168,15 @@ func keccakF1600(a *[25]uint64) { a[14] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 - bc2 = t<<3 | t>>(64-3) + bc2 = bits.RotateLeft64(t, 3) t = a[11] ^ d1 - bc3 = t<<45 | t>>(64-45) + bc3 = bits.RotateLeft64(t, 45) t = a[2] ^ d2 - bc4 = t<<61 | t>>(64-61) + bc4 = bits.RotateLeft64(t, 61) t = a[18] ^ d3 - bc0 = t<<28 | t>>(64-28) + bc0 = bits.RotateLeft64(t, 28) t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) + bc1 = bits.RotateLeft64(t, 20) a[20] = bc0 ^ (bc2 &^ bc1) a[11] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) @@ -180,15 +184,15 @@ func keccakF1600(a *[25]uint64) { a[9] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 - bc4 = t<<18 | t>>(64-18) + bc4 = bits.RotateLeft64(t, 18) t = a[6] ^ d1 - bc0 = t<<1 | t>>(64-1) + bc0 = bits.RotateLeft64(t, 1) t = a[22] ^ d2 - bc1 = t<<6 | t>>(64-6) + bc1 = bits.RotateLeft64(t, 6) t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) + bc2 = bits.RotateLeft64(t, 25) t = a[4] ^ d4 - bc3 = t<<8 | t>>(64-8) + bc3 = bits.RotateLeft64(t, 8) a[15] = bc0 ^ (bc2 &^ bc1) a[6] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) @@ -196,15 +200,15 @@ func keccakF1600(a *[25]uint64) { a[4] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 - bc1 = t<<36 | t>>(64-36) + bc1 = bits.RotateLeft64(t, 36) t = a[1] ^ d1 - bc2 = t<<10 | t>>(64-10) + bc2 = bits.RotateLeft64(t, 10) t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) + bc3 = bits.RotateLeft64(t, 15) t = a[8] ^ d3 - bc4 = t<<56 | t>>(64-56) + bc4 = bits.RotateLeft64(t, 56) t = a[24] ^ d4 - bc0 = t<<27 | t>>(64-27) + bc0 = bits.RotateLeft64(t, 27) a[10] = bc0 ^ (bc2 &^ bc1) a[1] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) @@ -212,15 +216,15 @@ func keccakF1600(a *[25]uint64) { a[24] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 - bc3 = t<<41 | t>>(64-41) + bc3 = bits.RotateLeft64(t, 41) t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) + bc4 = bits.RotateLeft64(t, 2) t = a[12] ^ d2 - bc0 = t<<62 | t>>(64-62) + bc0 = bits.RotateLeft64(t, 62) t = a[3] ^ d3 - bc1 = t<<55 | t>>(64-55) + bc1 = bits.RotateLeft64(t, 55) t = a[19] ^ d4 - bc2 = t<<39 | t>>(64-39) + bc2 = bits.RotateLeft64(t, 39) a[5] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) @@ -241,13 +245,13 @@ func keccakF1600(a *[25]uint64) { bc0 = a[0] ^ d0 t = a[11] ^ d1 - bc1 = t<<44 | t>>(64-44) + bc1 = bits.RotateLeft64(t, 44) t = a[22] ^ d2 - bc2 = t<<43 | t>>(64-43) + bc2 = bits.RotateLeft64(t, 43) t = a[8] ^ d3 - bc3 = t<<21 | t>>(64-21) + bc3 = bits.RotateLeft64(t, 21) t = a[19] ^ d4 - bc4 = t<<14 | t>>(64-14) + bc4 = bits.RotateLeft64(t, 14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] a[11] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) @@ -255,15 +259,15 @@ func keccakF1600(a *[25]uint64) { a[19] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 - bc2 = t<<3 | t>>(64-3) + bc2 = bits.RotateLeft64(t, 3) t = a[1] ^ d1 - bc3 = t<<45 | t>>(64-45) + bc3 = bits.RotateLeft64(t, 45) t = a[12] ^ d2 - bc4 = t<<61 | t>>(64-61) + bc4 = bits.RotateLeft64(t, 61) t = a[23] ^ d3 - bc0 = t<<28 | t>>(64-28) + bc0 = bits.RotateLeft64(t, 28) t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) + bc1 = bits.RotateLeft64(t, 20) a[15] = bc0 ^ (bc2 &^ bc1) a[1] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) @@ -271,15 +275,15 @@ func keccakF1600(a *[25]uint64) { a[9] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 - bc4 = t<<18 | t>>(64-18) + bc4 = bits.RotateLeft64(t, 18) t = a[16] ^ d1 - bc0 = t<<1 | t>>(64-1) + bc0 = bits.RotateLeft64(t, 1) t = a[2] ^ d2 - bc1 = t<<6 | t>>(64-6) + bc1 = bits.RotateLeft64(t, 6) t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) + bc2 = bits.RotateLeft64(t, 25) t = a[24] ^ d4 - bc3 = t<<8 | t>>(64-8) + bc3 = bits.RotateLeft64(t, 8) a[5] = bc0 ^ (bc2 &^ bc1) a[16] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) @@ -287,15 +291,15 @@ func keccakF1600(a *[25]uint64) { a[24] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 - bc1 = t<<36 | t>>(64-36) + bc1 = bits.RotateLeft64(t, 36) t = a[6] ^ d1 - bc2 = t<<10 | t>>(64-10) + bc2 = bits.RotateLeft64(t, 10) t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) + bc3 = bits.RotateLeft64(t, 15) t = a[3] ^ d3 - bc4 = t<<56 | t>>(64-56) + bc4 = bits.RotateLeft64(t, 56) t = a[14] ^ d4 - bc0 = t<<27 | t>>(64-27) + bc0 = bits.RotateLeft64(t, 27) a[20] = bc0 ^ (bc2 &^ bc1) a[6] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) @@ -303,15 +307,15 @@ func keccakF1600(a *[25]uint64) { a[14] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 - bc3 = t<<41 | t>>(64-41) + bc3 = bits.RotateLeft64(t, 41) t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) + bc4 = bits.RotateLeft64(t, 2) t = a[7] ^ d2 - bc0 = t<<62 | t>>(64-62) + bc0 = bits.RotateLeft64(t, 62) t = a[18] ^ d3 - bc1 = t<<55 | t>>(64-55) + bc1 = bits.RotateLeft64(t, 55) t = a[4] ^ d4 - bc2 = t<<39 | t>>(64-39) + bc2 = bits.RotateLeft64(t, 39) a[10] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) @@ -332,13 +336,13 @@ func keccakF1600(a *[25]uint64) { bc0 = a[0] ^ d0 t = a[1] ^ d1 - bc1 = t<<44 | t>>(64-44) + bc1 = bits.RotateLeft64(t, 44) t = a[2] ^ d2 - bc2 = t<<43 | t>>(64-43) + bc2 = bits.RotateLeft64(t, 43) t = a[3] ^ d3 - bc3 = t<<21 | t>>(64-21) + bc3 = bits.RotateLeft64(t, 21) t = a[4] ^ d4 - bc4 = t<<14 | t>>(64-14) + bc4 = bits.RotateLeft64(t, 14) a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] a[1] = bc1 ^ (bc3 &^ bc2) a[2] = bc2 ^ (bc4 &^ bc3) @@ -346,15 +350,15 @@ func keccakF1600(a *[25]uint64) { a[4] = bc4 ^ (bc1 &^ bc0) t = a[5] ^ d0 - bc2 = t<<3 | t>>(64-3) + bc2 = bits.RotateLeft64(t, 3) t = a[6] ^ d1 - bc3 = t<<45 | t>>(64-45) + bc3 = bits.RotateLeft64(t, 45) t = a[7] ^ d2 - bc4 = t<<61 | t>>(64-61) + bc4 = bits.RotateLeft64(t, 61) t = a[8] ^ d3 - bc0 = t<<28 | t>>(64-28) + bc0 = bits.RotateLeft64(t, 28) t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) + bc1 = bits.RotateLeft64(t, 20) a[5] = bc0 ^ (bc2 &^ bc1) a[6] = bc1 ^ (bc3 &^ bc2) a[7] = bc2 ^ (bc4 &^ bc3) @@ -362,15 +366,15 @@ func keccakF1600(a *[25]uint64) { a[9] = bc4 ^ (bc1 &^ bc0) t = a[10] ^ d0 - bc4 = t<<18 | t>>(64-18) + bc4 = bits.RotateLeft64(t, 18) t = a[11] ^ d1 - bc0 = t<<1 | t>>(64-1) + bc0 = bits.RotateLeft64(t, 1) t = a[12] ^ d2 - bc1 = t<<6 | t>>(64-6) + bc1 = bits.RotateLeft64(t, 6) t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) + bc2 = bits.RotateLeft64(t, 25) t = a[14] ^ d4 - bc3 = t<<8 | t>>(64-8) + bc3 = bits.RotateLeft64(t, 8) a[10] = bc0 ^ (bc2 &^ bc1) a[11] = bc1 ^ (bc3 &^ bc2) a[12] = bc2 ^ (bc4 &^ bc3) @@ -378,15 +382,15 @@ func keccakF1600(a *[25]uint64) { a[14] = bc4 ^ (bc1 &^ bc0) t = a[15] ^ d0 - bc1 = t<<36 | t>>(64-36) + bc1 = bits.RotateLeft64(t, 36) t = a[16] ^ d1 - bc2 = t<<10 | t>>(64-10) + bc2 = bits.RotateLeft64(t, 10) t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) + bc3 = bits.RotateLeft64(t, 15) t = a[18] ^ d3 - bc4 = t<<56 | t>>(64-56) + bc4 = bits.RotateLeft64(t, 56) t = a[19] ^ d4 - bc0 = t<<27 | t>>(64-27) + bc0 = bits.RotateLeft64(t, 27) a[15] = bc0 ^ (bc2 &^ bc1) a[16] = bc1 ^ (bc3 &^ bc2) a[17] = bc2 ^ (bc4 &^ bc3) @@ -394,15 +398,15 @@ func keccakF1600(a *[25]uint64) { a[19] = bc4 ^ (bc1 &^ bc0) t = a[20] ^ d0 - bc3 = t<<41 | t>>(64-41) + bc3 = bits.RotateLeft64(t, 41) t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) + bc4 = bits.RotateLeft64(t, 2) t = a[22] ^ d2 - bc0 = t<<62 | t>>(64-62) + bc0 = bits.RotateLeft64(t, 62) t = a[23] ^ d3 - bc1 = t<<55 | t>>(64-55) + bc1 = bits.RotateLeft64(t, 55) t = a[24] ^ d4 - bc2 = t<<39 | t>>(64-39) + bc2 = bits.RotateLeft64(t, 39) a[20] = bc0 ^ (bc2 &^ bc1) a[21] = bc1 ^ (bc3 &^ bc2) a[22] = bc2 ^ (bc4 &^ bc3) diff --git a/sha3/register.go b/sha3/register.go deleted file mode 100644 index 3cf6a22e09..0000000000 --- a/sha3/register.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 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 go1.4 - -package sha3 - -import ( - "crypto" -) - -func init() { - crypto.RegisterHash(crypto.SHA3_224, New224) - crypto.RegisterHash(crypto.SHA3_256, New256) - crypto.RegisterHash(crypto.SHA3_384, New384) - crypto.RegisterHash(crypto.SHA3_512, New512) -} diff --git a/sha3/sha3.go b/sha3/sha3.go deleted file mode 100644 index b12a35c87f..0000000000 --- a/sha3/sha3.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2014 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 sha3 - -// spongeDirection indicates the direction bytes are flowing through the sponge. -type spongeDirection int - -const ( - // spongeAbsorbing indicates that the sponge is absorbing input. - spongeAbsorbing spongeDirection = iota - // spongeSqueezing indicates that the sponge is being squeezed. - spongeSqueezing -) - -const ( - // maxRate is the maximum size of the internal buffer. SHAKE-256 - // currently needs the largest buffer. - maxRate = 168 -) - -type state struct { - // Generic sponge components. - a [25]uint64 // main state of the hash - buf []byte // points into storage - rate int // the number of bytes of state to use - - // dsbyte contains the "domain separation" bits and the first bit of - // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the - // SHA-3 and SHAKE functions by appending bitstrings to the message. - // Using a little-endian bit-ordering convention, these are "01" for SHA-3 - // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the - // padding rule from section 5.1 is applied to pad the message to a multiple - // of the rate, which involves adding a "1" bit, zero or more "0" bits, and - // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, - // giving 00000110b (0x06) and 00011111b (0x1f). - // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf - // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and - // Extendable-Output Functions (May 2014)" - dsbyte byte - storage [maxRate]byte - - // Specific to SHA-3 and SHAKE. - outputLen int // the default output size in bytes - state spongeDirection // whether the sponge is absorbing or squeezing -} - -// BlockSize returns the rate of sponge underlying this hash function. -func (d *state) BlockSize() int { return d.rate } - -// Size returns the output size of the hash function in bytes. -func (d *state) Size() int { return d.outputLen } - -// Reset clears the internal state by zeroing the sponge state and -// the byte buffer, and setting Sponge.state to absorbing. -func (d *state) Reset() { - // Zero the permutation's state. - for i := range d.a { - d.a[i] = 0 - } - d.state = spongeAbsorbing - d.buf = d.storage[:0] -} - -func (d *state) clone() *state { - ret := *d - if ret.state == spongeAbsorbing { - ret.buf = ret.storage[:len(ret.buf)] - } else { - ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] - } - - return &ret -} - -// permute applies the KeccakF-1600 permutation. It handles -// any input-output buffering. -func (d *state) permute() { - switch d.state { - case spongeAbsorbing: - // If we're absorbing, we need to xor the input into the state - // before applying the permutation. - xorIn(d, d.buf) - d.buf = d.storage[:0] - keccakF1600(&d.a) - case spongeSqueezing: - // If we're squeezing, we need to apply the permutatin before - // copying more output. - keccakF1600(&d.a) - d.buf = d.storage[:d.rate] - copyOut(d, d.buf) - } -} - -// pads appends the domain separation bits in dsbyte, applies -// the multi-bitrate 10..1 padding rule, and permutes the state. -func (d *state) padAndPermute(dsbyte byte) { - if d.buf == nil { - d.buf = d.storage[:0] - } - // Pad with this instance's domain-separator bits. We know that there's - // at least one byte of space in d.buf because, if it were full, - // permute would have been called to empty it. dsbyte also contains the - // first one bit for the padding. See the comment in the state struct. - d.buf = append(d.buf, dsbyte) - zerosStart := len(d.buf) - d.buf = d.storage[:d.rate] - for i := zerosStart; i < d.rate; i++ { - d.buf[i] = 0 - } - // This adds the final one bit for the padding. Because of the way that - // bits are numbered from the LSB upwards, the final bit is the MSB of - // the last byte. - d.buf[d.rate-1] ^= 0x80 - // Apply the permutation - d.permute() - d.state = spongeSqueezing - d.buf = d.storage[:d.rate] - copyOut(d, d.buf) -} - -// Write absorbs more data into the hash's state. It produces an error -// if more data is written to the ShakeHash after writing -func (d *state) Write(p []byte) (written int, err error) { - if d.state != spongeAbsorbing { - panic("sha3: write to sponge after read") - } - if d.buf == nil { - d.buf = d.storage[:0] - } - written = len(p) - - for len(p) > 0 { - if len(d.buf) == 0 && len(p) >= d.rate { - // The fast path; absorb a full "rate" bytes of input and apply the permutation. - xorIn(d, p[:d.rate]) - p = p[d.rate:] - keccakF1600(&d.a) - } else { - // The slow path; buffer the input until we can fill the sponge, and then xor it in. - todo := d.rate - len(d.buf) - if todo > len(p) { - todo = len(p) - } - d.buf = append(d.buf, p[:todo]...) - p = p[todo:] - - // If the sponge is full, apply the permutation. - if len(d.buf) == d.rate { - d.permute() - } - } - } - - return -} - -// Read squeezes an arbitrary number of bytes from the sponge. -func (d *state) Read(out []byte) (n int, err error) { - // If we're still absorbing, pad and apply the permutation. - if d.state == spongeAbsorbing { - d.padAndPermute(d.dsbyte) - } - - n = len(out) - - // Now, do the squeezing. - for len(out) > 0 { - n := copy(out, d.buf) - d.buf = d.buf[n:] - out = out[n:] - - // Apply the permutation if we've squeezed the sponge dry. - if len(d.buf) == 0 { - d.permute() - } - } - - return -} - -// Sum applies padding to the hash state and then squeezes out the desired -// number of output bytes. -func (d *state) Sum(in []byte) []byte { - // Make a copy of the original hash so that caller can keep writing - // and summing. - dup := d.clone() - hash := make([]byte, dup.outputLen) - dup.Read(hash) - return append(in, hash...) -} diff --git a/sha3/sha3_s390x.go b/sha3/sha3_s390x.go deleted file mode 100644 index c13ec85b50..0000000000 --- a/sha3/sha3_s390x.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo,!appengine - -package sha3 - -// This file contains code for using the 'compute intermediate -// message digest' (KIMD) and 'compute last message digest' (KLMD) -// instructions to compute SHA-3 and SHAKE hashes on IBM Z. - -import ( - "hash" - - "golang.org/x/sys/cpu" -) - -// codes represent 7-bit KIMD/KLMD function codes as defined in -// the Principles of Operation. -type code uint64 - -const ( - // function codes for KIMD/KLMD - sha3_224 code = 32 - sha3_256 = 33 - sha3_384 = 34 - sha3_512 = 35 - shake_128 = 36 - shake_256 = 37 - nopad = 0x100 -) - -// kimd is a wrapper for the 'compute intermediate message digest' instruction. -// src must be a multiple of the rate for the given function code. -//go:noescape -func kimd(function code, chain *[200]byte, src []byte) - -// klmd is a wrapper for the 'compute last message digest' instruction. -// src padding is handled by the instruction. -//go:noescape -func klmd(function code, chain *[200]byte, dst, src []byte) - -type asmState struct { - a [200]byte // 1600 bit state - buf []byte // care must be taken to ensure cap(buf) is a multiple of rate - rate int // equivalent to block size - storage [3072]byte // underlying storage for buf - outputLen int // output length if fixed, 0 if not - function code // KIMD/KLMD function code - state spongeDirection // whether the sponge is absorbing or squeezing -} - -func newAsmState(function code) *asmState { - var s asmState - s.function = function - switch function { - case sha3_224: - s.rate = 144 - s.outputLen = 28 - case sha3_256: - s.rate = 136 - s.outputLen = 32 - case sha3_384: - s.rate = 104 - s.outputLen = 48 - case sha3_512: - s.rate = 72 - s.outputLen = 64 - case shake_128: - s.rate = 168 - case shake_256: - s.rate = 136 - default: - panic("sha3: unrecognized function code") - } - - // limit s.buf size to a multiple of s.rate - s.resetBuf() - return &s -} - -func (s *asmState) clone() *asmState { - c := *s - c.buf = c.storage[:len(s.buf):cap(s.buf)] - return &c -} - -// copyIntoBuf copies b into buf. It will panic if there is not enough space to -// store all of b. -func (s *asmState) copyIntoBuf(b []byte) { - bufLen := len(s.buf) - s.buf = s.buf[:len(s.buf)+len(b)] - copy(s.buf[bufLen:], b) -} - -// resetBuf points buf at storage, sets the length to 0 and sets cap to be a -// multiple of the rate. -func (s *asmState) resetBuf() { - max := (cap(s.storage) / s.rate) * s.rate - s.buf = s.storage[:0:max] -} - -// Write (via the embedded io.Writer interface) adds more data to the running hash. -// It never returns an error. -func (s *asmState) Write(b []byte) (int, error) { - if s.state != spongeAbsorbing { - panic("sha3: write to sponge after read") - } - length := len(b) - for len(b) > 0 { - if len(s.buf) == 0 && len(b) >= cap(s.buf) { - // Hash the data directly and push any remaining bytes - // into the buffer. - remainder := len(s.buf) % s.rate - kimd(s.function, &s.a, b[:len(b)-remainder]) - if remainder != 0 { - s.copyIntoBuf(b[len(b)-remainder:]) - } - return length, nil - } - - if len(s.buf) == cap(s.buf) { - // flush the buffer - kimd(s.function, &s.a, s.buf) - s.buf = s.buf[:0] - } - - // copy as much as we can into the buffer - n := len(b) - if len(b) > cap(s.buf)-len(s.buf) { - n = cap(s.buf) - len(s.buf) - } - s.copyIntoBuf(b[:n]) - b = b[n:] - } - return length, nil -} - -// Read squeezes an arbitrary number of bytes from the sponge. -func (s *asmState) Read(out []byte) (n int, err error) { - n = len(out) - - // need to pad if we were absorbing - if s.state == spongeAbsorbing { - s.state = spongeSqueezing - - // write hash directly into out if possible - if len(out)%s.rate == 0 { - klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 - s.buf = s.buf[:0] - return - } - - // write hash into buffer - max := cap(s.buf) - if max > len(out) { - max = (len(out)/s.rate)*s.rate + s.rate - } - klmd(s.function, &s.a, s.buf[:max], s.buf) - s.buf = s.buf[:max] - } - - for len(out) > 0 { - // flush the buffer - if len(s.buf) != 0 { - c := copy(out, s.buf) - out = out[c:] - s.buf = s.buf[c:] - continue - } - - // write hash directly into out if possible - if len(out)%s.rate == 0 { - klmd(s.function|nopad, &s.a, out, nil) - return - } - - // write hash into buffer - s.resetBuf() - if cap(s.buf) > len(out) { - s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] - } - klmd(s.function|nopad, &s.a, s.buf, nil) - } - return -} - -// Sum appends the current hash to b and returns the resulting slice. -// It does not change the underlying hash state. -func (s *asmState) Sum(b []byte) []byte { - if s.outputLen == 0 { - panic("sha3: cannot call Sum on SHAKE functions") - } - - // Copy the state to preserve the original. - a := s.a - - // Hash the buffer. Note that we don't clear it because we - // aren't updating the state. - klmd(s.function, &a, nil, s.buf) - return append(b, a[:s.outputLen]...) -} - -// Reset resets the Hash to its initial state. -func (s *asmState) Reset() { - for i := range s.a { - s.a[i] = 0 - } - s.resetBuf() - s.state = spongeAbsorbing -} - -// Size returns the number of bytes Sum will return. -func (s *asmState) Size() int { - return s.outputLen -} - -// BlockSize returns the hash's underlying block size. -// The Write method must be able to accept any amount -// of data, but it may operate more efficiently if all writes -// are a multiple of the block size. -func (s *asmState) BlockSize() int { - return s.rate -} - -// Clone returns a copy of the ShakeHash in its current state. -func (s *asmState) Clone() ShakeHash { - return s.clone() -} - -// new224Asm returns an assembly implementation of SHA3-224 if available, -// otherwise it returns nil. -func new224Asm() hash.Hash { - if cpu.S390X.HasSHA3 { - return newAsmState(sha3_224) - } - return nil -} - -// new256Asm returns an assembly implementation of SHA3-256 if available, -// otherwise it returns nil. -func new256Asm() hash.Hash { - if cpu.S390X.HasSHA3 { - return newAsmState(sha3_256) - } - return nil -} - -// new384Asm returns an assembly implementation of SHA3-384 if available, -// otherwise it returns nil. -func new384Asm() hash.Hash { - if cpu.S390X.HasSHA3 { - return newAsmState(sha3_384) - } - return nil -} - -// new512Asm returns an assembly implementation of SHA3-512 if available, -// otherwise it returns nil. -func new512Asm() hash.Hash { - if cpu.S390X.HasSHA3 { - return newAsmState(sha3_512) - } - return nil -} - -// newShake128Asm returns an assembly implementation of SHAKE-128 if available, -// otherwise it returns nil. -func newShake128Asm() ShakeHash { - if cpu.S390X.HasSHA3 { - return newAsmState(shake_128) - } - return nil -} - -// newShake256Asm returns an assembly implementation of SHAKE-256 if available, -// otherwise it returns nil. -func newShake256Asm() ShakeHash { - if cpu.S390X.HasSHA3 { - return newAsmState(shake_256) - } - return nil -} diff --git a/sha3/sha3_s390x.s b/sha3/sha3_s390x.s deleted file mode 100644 index 8a4458f63f..0000000000 --- a/sha3/sha3_s390x.s +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !gccgo,!appengine - -#include "textflag.h" - -// func kimd(function code, chain *[200]byte, src []byte) -TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 - MOVD function+0(FP), R0 - MOVD chain+8(FP), R1 - LMG src+16(FP), R2, R3 // R2=base, R3=len - -continue: - WORD $0xB93E0002 // KIMD --, R2 - BVS continue // continue if interrupted - MOVD $0, R0 // reset R0 for pre-go1.8 compilers - RET - -// func klmd(function code, chain *[200]byte, dst, src []byte) -TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 - // TODO: SHAKE support - MOVD function+0(FP), R0 - MOVD chain+8(FP), R1 - LMG dst+16(FP), R2, R3 // R2=base, R3=len - LMG src+40(FP), R4, R5 // R4=base, R5=len - -continue: - WORD $0xB93F0024 // KLMD R2, R4 - BVS continue // continue if interrupted - MOVD $0, R0 // reset R0 for pre-go1.8 compilers - RET diff --git a/sha3/sha3_test.go b/sha3/sha3_test.go index 005a24247b..bee9b10d46 100644 --- a/sha3/sha3_test.go +++ b/sha3/sha3_test.go @@ -13,10 +13,12 @@ package sha3 import ( "bytes" "compress/flate" + "encoding" "encoding/hex" "encoding/json" - "fmt" "hash" + "io" + "math/rand" "os" "strings" "testing" @@ -75,86 +77,73 @@ type KeccakKats struct { } } -func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { - xorInOrig, copyOutOrig := xorIn, copyOut - xorIn, copyOut = xorInGeneric, copyOutGeneric - testf("generic") - if xorImplementationUnaligned != "generic" { - xorIn, copyOut = xorInUnaligned, copyOutUnaligned - testf("unaligned") - } - xorIn, copyOut = xorInOrig, copyOutOrig -} - // TestKeccakKats tests the SHA-3 and Shake implementations against all the // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage // (The testvectors are stored in keccakKats.json.deflate due to their length.) func TestKeccakKats(t *testing.T) { - testUnalignedAndGeneric(t, func(impl string) { - // Read the KATs. - deflated, err := os.Open(katFilename) - if err != nil { - t.Errorf("error opening %s: %s", katFilename, err) - } - file := flate.NewReader(deflated) - dec := json.NewDecoder(file) - var katSet KeccakKats - err = dec.Decode(&katSet) - if err != nil { - t.Errorf("error decoding KATs: %s", err) - } + // Read the KATs. + deflated, err := os.Open(katFilename) + if err != nil { + t.Errorf("error opening %s: %s", katFilename, err) + } + file := flate.NewReader(deflated) + dec := json.NewDecoder(file) + var katSet KeccakKats + err = dec.Decode(&katSet) + if err != nil { + t.Errorf("error decoding KATs: %s", err) + } - for algo, function := range testDigests { - d := function() - for _, kat := range katSet.Kats[algo] { - d.Reset() - in, err := hex.DecodeString(kat.Message) - if err != nil { - t.Errorf("error decoding KAT: %s", err) - } - d.Write(in[:kat.Length/8]) - got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) - if got != kat.Digest { - t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", - algo, impl, kat.Length, kat.Message, got, kat.Digest) - t.Logf("wanted %+v", kat) - t.FailNow() - } - continue + for algo, function := range testDigests { + d := function() + for _, kat := range katSet.Kats[algo] { + d.Reset() + in, err := hex.DecodeString(kat.Message) + if err != nil { + t.Errorf("error decoding KAT: %s", err) + } + d.Write(in[:kat.Length/8]) + got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) + if got != kat.Digest { + t.Errorf("function=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", + algo, kat.Length, kat.Message, got, kat.Digest) + t.Logf("wanted %+v", kat) + t.FailNow() } + continue } + } - for algo, v := range testShakes { - for _, kat := range katSet.Kats[algo] { - N, err := hex.DecodeString(kat.N) - if err != nil { - t.Errorf("error decoding KAT: %s", err) - } + for algo, v := range testShakes { + for _, kat := range katSet.Kats[algo] { + N, err := hex.DecodeString(kat.N) + if err != nil { + t.Errorf("error decoding KAT: %s", err) + } - S, err := hex.DecodeString(kat.S) - if err != nil { - t.Errorf("error decoding KAT: %s", err) - } - d := v.constructor(N, S) - in, err := hex.DecodeString(kat.Message) - if err != nil { - t.Errorf("error decoding KAT: %s", err) - } + S, err := hex.DecodeString(kat.S) + if err != nil { + t.Errorf("error decoding KAT: %s", err) + } + d := v.constructor(N, S) + in, err := hex.DecodeString(kat.Message) + if err != nil { + t.Errorf("error decoding KAT: %s", err) + } - d.Write(in[:kat.Length/8]) - out := make([]byte, len(kat.Digest)/2) - d.Read(out) - got := strings.ToUpper(hex.EncodeToString(out)) - if got != kat.Digest { - t.Errorf("function=%s, implementation=%s, length=%d N:%s\n S:%s\nmessage:\n %s \ngot:\n %s\nwanted:\n %s", - algo, impl, kat.Length, kat.N, kat.S, kat.Message, got, kat.Digest) - t.Logf("wanted %+v", kat) - t.FailNow() - } - continue + d.Write(in[:kat.Length/8]) + out := make([]byte, len(kat.Digest)/2) + d.Read(out) + got := strings.ToUpper(hex.EncodeToString(out)) + if got != kat.Digest { + t.Errorf("function=%s, length=%d N:%s\n S:%s\nmessage:\n %s \ngot:\n %s\nwanted:\n %s", + algo, kat.Length, kat.N, kat.S, kat.Message, got, kat.Digest) + t.Logf("wanted %+v", kat) + t.FailNow() } + continue } - }) + } } // TestKeccak does a basic test of the non-standardized Keccak hash functions. @@ -187,127 +176,153 @@ func TestKeccak(t *testing.T) { } } +// TestShakeSum tests that the output of Sum matches the output of Read. +func TestShakeSum(t *testing.T) { + tests := [...]struct { + name string + hash ShakeHash + expectedLen int + }{ + {"SHAKE128", NewShake128(), 32}, + {"SHAKE256", NewShake256(), 64}, + {"cSHAKE128", NewCShake128([]byte{'X'}, nil), 32}, + {"cSHAKE256", NewCShake256([]byte{'X'}, nil), 64}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + s := test.hash.Sum(nil) + if len(s) != test.expectedLen { + t.Errorf("Unexpected digest length: got %d, want %d", len(s), test.expectedLen) + } + r := make([]byte, test.expectedLen) + test.hash.Read(r) + if !bytes.Equal(s, r) { + t.Errorf("Mismatch between Sum and Read:\nSum: %s\nRead: %s", hex.EncodeToString(s), hex.EncodeToString(r)) + } + }) + } +} + // TestUnalignedWrite tests that writing data in an arbitrary pattern with // small input buffers. func TestUnalignedWrite(t *testing.T) { - testUnalignedAndGeneric(t, func(impl string) { - buf := sequentialBytes(0x10000) - for alg, df := range testDigests { - d := df() - d.Reset() - d.Write(buf) - want := d.Sum(nil) - d.Reset() - for i := 0; i < len(buf); { - // Cycle through offsets which make a 137 byte sequence. - // Because 137 is prime this sequence should exercise all corner cases. - offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} - for _, j := range offsets { - if v := len(buf) - i; v < j { - j = v - } - d.Write(buf[i : i+j]) - i += j + buf := sequentialBytes(0x10000) + for alg, df := range testDigests { + d := df() + d.Reset() + d.Write(buf) + want := d.Sum(nil) + d.Reset() + for i := 0; i < len(buf); { + // Cycle through offsets which make a 137 byte sequence. + // Because 137 is prime this sequence should exercise all corner cases. + offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} + for _, j := range offsets { + if v := len(buf) - i; v < j { + j = v } - } - got := d.Sum(nil) - if !bytes.Equal(got, want) { - t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) + d.Write(buf[i : i+j]) + i += j } } + got := d.Sum(nil) + if !bytes.Equal(got, want) { + t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want) + } + } - // Same for SHAKE - for alg, df := range testShakes { - want := make([]byte, 16) - got := make([]byte, 16) - d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr)) - - d.Reset() - d.Write(buf) - d.Read(want) - d.Reset() - for i := 0; i < len(buf); { - // Cycle through offsets which make a 137 byte sequence. - // Because 137 is prime this sequence should exercise all corner cases. - offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} - for _, j := range offsets { - if v := len(buf) - i; v < j { - j = v - } - d.Write(buf[i : i+j]) - i += j + // Same for SHAKE + for alg, df := range testShakes { + want := make([]byte, 16) + got := make([]byte, 16) + d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr)) + + d.Reset() + d.Write(buf) + d.Read(want) + d.Reset() + for i := 0; i < len(buf); { + // Cycle through offsets which make a 137 byte sequence. + // Because 137 is prime this sequence should exercise all corner cases. + offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} + for _, j := range offsets { + if v := len(buf) - i; v < j { + j = v } - } - d.Read(got) - if !bytes.Equal(got, want) { - t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) + d.Write(buf[i : i+j]) + i += j } } - }) + d.Read(got) + if !bytes.Equal(got, want) { + t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want) + } + } } // TestAppend checks that appending works when reallocation is necessary. func TestAppend(t *testing.T) { - testUnalignedAndGeneric(t, func(impl string) { - d := New224() + d := New224() - for capacity := 2; capacity <= 66; capacity += 64 { - // The first time around the loop, Sum will have to reallocate. - // The second time, it will not. - buf := make([]byte, 2, capacity) - d.Reset() - d.Write([]byte{0xcc}) - buf = d.Sum(buf) - expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" - if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { - t.Errorf("got %s, want %s", got, expected) - } + for capacity := 2; capacity <= 66; capacity += 64 { + // The first time around the loop, Sum will have to reallocate. + // The second time, it will not. + buf := make([]byte, 2, capacity) + d.Reset() + d.Write([]byte{0xcc}) + buf = d.Sum(buf) + expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" + if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { + t.Errorf("got %s, want %s", got, expected) } - }) + } } // TestAppendNoRealloc tests that appending works when no reallocation is necessary. func TestAppendNoRealloc(t *testing.T) { - testUnalignedAndGeneric(t, func(impl string) { - buf := make([]byte, 1, 200) - d := New224() - d.Write([]byte{0xcc}) - buf = d.Sum(buf) - expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" - if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { - t.Errorf("%s: got %s, want %s", impl, got, expected) - } - }) + buf := make([]byte, 1, 200) + d := New224() + d.Write([]byte{0xcc}) + buf = d.Sum(buf) + expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" + if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { + t.Errorf("got %s, want %s", got, expected) + } } // TestSqueezing checks that squeezing the full output a single time produces // the same output as repeatedly squeezing the instance. func TestSqueezing(t *testing.T) { - testUnalignedAndGeneric(t, func(impl string) { - for algo, v := range testShakes { - d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) - d0.Write([]byte(testString)) - ref := make([]byte, 32) - d0.Read(ref) - - d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) - d1.Write([]byte(testString)) - var multiple []byte - for range ref { - one := make([]byte, 1) - d1.Read(one) - multiple = append(multiple, one...) - } - if !bytes.Equal(ref, multiple) { - t.Errorf("%s (%s): squeezing %d bytes one at a time failed", algo, impl, len(ref)) - } + for algo, v := range testShakes { + d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) + d0.Write([]byte(testString)) + ref := make([]byte, 32) + d0.Read(ref) + + d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) + d1.Write([]byte(testString)) + var multiple []byte + for range ref { + one := make([]byte, 1) + d1.Read(one) + multiple = append(multiple, one...) } - }) + if !bytes.Equal(ref, multiple) { + t.Errorf("%s: squeezing %d bytes one at a time failed", algo, len(ref)) + } + } } // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. +// +// The alignment of each slice is intentionally randomized to detect alignment +// issues in the implementation. See https://golang.org/issue/37644. +// Ideally, the compiler should fuzz the alignment itself. +// (See https://golang.org/issue/35128.) func sequentialBytes(size int) []byte { - result := make([]byte, size) + alignmentOffset := rand.Intn(8) + result := make([]byte, size+alignmentOffset)[alignmentOffset:] for i := range result { result[i] = byte(i) } @@ -361,123 +376,149 @@ func TestClone(t *testing.T) { } } -// BenchmarkPermutationFunction measures the speed of the permutation function -// with no input data. -func BenchmarkPermutationFunction(b *testing.B) { - b.SetBytes(int64(200)) - var lanes [25]uint64 - for i := 0; i < b.N; i++ { - keccakF1600(&lanes) - } +func TestCSHAKEAccumulated(t *testing.T) { + // Generated with pycryptodome@3.20.0 + // + // from Crypto.Hash import cSHAKE128 + // rng = cSHAKE128.new() + // acc = cSHAKE128.new() + // for n in range(200): + // N = rng.read(n) + // for s in range(200): + // S = rng.read(s) + // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N) + // c.update(rng.read(100)) + // acc.update(c.read(200)) + // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N) + // c.update(rng.read(168)) + // acc.update(c.read(200)) + // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N) + // c.update(rng.read(200)) + // acc.update(c.read(200)) + // print(acc.read(32).hex()) + // + // and with @noble/hashes@v1.5.0 + // + // import { bytesToHex } from "@noble/hashes/utils"; + // import { cshake128 } from "@noble/hashes/sha3-addons"; + // const rng = cshake128.create(); + // const acc = cshake128.create(); + // for (let n = 0; n < 200; n++) { + // const N = rng.xof(n); + // for (let s = 0; s < 200; s++) { + // const S = rng.xof(s); + // let c = cshake128.create({ NISTfn: N, personalization: S }); + // c.update(rng.xof(100)); + // acc.update(c.xof(200)); + // c = cshake128.create({ NISTfn: N, personalization: S }); + // c.update(rng.xof(168)); + // acc.update(c.xof(200)); + // c = cshake128.create({ NISTfn: N, personalization: S }); + // c.update(rng.xof(200)); + // acc.update(c.xof(200)); + // } + // } + // console.log(bytesToHex(acc.xof(32))); + // + t.Run("cSHAKE128", func(t *testing.T) { + testCSHAKEAccumulated(t, NewCShake128, rateK256, + "bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252") + }) + t.Run("cSHAKE256", func(t *testing.T) { + testCSHAKEAccumulated(t, NewCShake256, rateK512, + "0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef") + }) } -// benchmarkHash tests the speed to hash num buffers of buflen each. -func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { - b.StopTimer() - h.Reset() - data := sequentialBytes(size) - b.SetBytes(int64(size * num)) - b.StartTimer() - - var state []byte - for i := 0; i < b.N; i++ { - for j := 0; j < num; j++ { - h.Write(data) +func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) ShakeHash, rate int64, exp string) { + rnd := newCShake(nil, nil) + acc := newCShake(nil, nil) + for n := 0; n < 200; n++ { + N := make([]byte, n) + rnd.Read(N) + for s := 0; s < 200; s++ { + S := make([]byte, s) + rnd.Read(S) + + c := newCShake(N, S) + io.CopyN(c, rnd, 100 /* < rate */) + io.CopyN(acc, c, 200) + + c.Reset() + io.CopyN(c, rnd, rate) + io.CopyN(acc, c, 200) + + c.Reset() + io.CopyN(c, rnd, 200 /* > rate */) + io.CopyN(acc, c, 200) } - state = h.Sum(state[:0]) } - b.StopTimer() - h.Reset() + if got := hex.EncodeToString(acc.Sum(nil)[:32]); got != exp { + t.Errorf("got %s, want %s", got, exp) + } } -// benchmarkShake is specialized to the Shake instances, which don't -// require a copy on reading output. -func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { - b.StopTimer() - h.Reset() - data := sequentialBytes(size) - d := make([]byte, 32) - - b.SetBytes(int64(size * num)) - b.StartTimer() - - for i := 0; i < b.N; i++ { - h.Reset() - for j := 0; j < num; j++ { - h.Write(data) - } - h.Read(d) +func TestCSHAKELargeS(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") } -} -func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } -func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } -func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } -func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } - -func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } -func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } -func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } -func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } - -func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } - -func Example_sum() { - buf := []byte("some data to hash") - // A hash needs to be 64 bytes long to have 256-bit collision resistance. - h := make([]byte, 64) - // Compute a 64-byte hash of buf and put it in h. - ShakeSum256(h, buf) - fmt.Printf("%x\n", h) - // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d + // See https://go.dev/issue/66232. + const s = (1<<32)/8 + 1000 // s * 8 > 2^32 + S := make([]byte, s) + rnd := NewShake128() + rnd.Read(S) + c := NewCShake128(nil, S) + io.CopyN(c, rnd, 1000) + + // Generated with pycryptodome@3.20.0 + // + // from Crypto.Hash import cSHAKE128 + // rng = cSHAKE128.new() + // S = rng.read(536871912) + // c = cSHAKE128.new(custom=S) + // c.update(rng.read(1000)) + // print(c.read(32).hex()) + // + exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0" + if got := hex.EncodeToString(c.Sum(nil)); got != exp { + t.Errorf("got %s, want %s", got, exp) + } } -func Example_mac() { - k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") - buf := []byte("and this is some data to authenticate") - // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key. - h := make([]byte, 32) - d := NewShake256() - // Write the key into the hash. - d.Write(k) - // Now write the data. - d.Write(buf) - // Read 32 bytes of output from the hash into h. - d.Read(h) - fmt.Printf("%x\n", h) - // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff +func TestMarshalUnmarshal(t *testing.T) { + t.Run("SHA3-224", func(t *testing.T) { testMarshalUnmarshal(t, New224()) }) + t.Run("SHA3-256", func(t *testing.T) { testMarshalUnmarshal(t, New256()) }) + t.Run("SHA3-384", func(t *testing.T) { testMarshalUnmarshal(t, New384()) }) + t.Run("SHA3-512", func(t *testing.T) { testMarshalUnmarshal(t, New512()) }) + t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewShake128()) }) + t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewShake256()) }) + t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake128([]byte("N"), []byte("S"))) }) + t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake256([]byte("N"), []byte("S"))) }) + t.Run("Keccak-256", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak256()) }) + t.Run("Keccak-512", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak512()) }) } -func ExampleNewCShake256() { - out := make([]byte, 32) - msg := []byte("The quick brown fox jumps over the lazy dog") - - // Example 1: Simple cshake - c1 := NewCShake256([]byte("NAME"), []byte("Partition1")) - c1.Write(msg) - c1.Read(out) - fmt.Println(hex.EncodeToString(out)) - - // Example 2: Different customization string produces different digest - c1 = NewCShake256([]byte("NAME"), []byte("Partition2")) - c1.Write(msg) - c1.Read(out) - fmt.Println(hex.EncodeToString(out)) - - // Example 3: Longer output length produces longer digest - out = make([]byte, 64) - c1 = NewCShake256([]byte("NAME"), []byte("Partition1")) - c1.Write(msg) - c1.Read(out) - fmt.Println(hex.EncodeToString(out)) - - // Example 4: Next read produces different result - c1.Read(out) - fmt.Println(hex.EncodeToString(out)) - - // Output: - //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b - //a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0 - //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8 - //85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109 +// TODO(filippo): move this to crypto/internal/cryptotest. +func testMarshalUnmarshal(t *testing.T, h hash.Hash) { + buf := make([]byte, 200) + rand.Read(buf) + n := rand.Intn(200) + h.Write(buf) + want := h.Sum(nil) + h.Reset() + h.Write(buf[:n]) + b, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { + t.Errorf("MarshalBinary: %v", err) + } + h.Write(bytes.Repeat([]byte{0}, 200)) + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary(b); err != nil { + t.Errorf("UnmarshalBinary: %v", err) + } + h.Write(buf[n:]) + got := h.Sum(nil) + if !bytes.Equal(got, want) { + t.Errorf("got %x, want %x", got, want) + } } diff --git a/sha3/shake.go b/sha3/shake.go index d7be2954ab..6f3f70c265 100644 --- a/sha3/shake.go +++ b/sha3/shake.go @@ -4,132 +4,41 @@ package sha3 -// This file defines the ShakeHash interface, and provides -// functions for creating SHAKE and cSHAKE instances, as well as utility -// functions for hashing bytes to arbitrary-length output. -// -// -// SHAKE implementation is based on FIPS PUB 202 [1] -// cSHAKE implementations is based on NIST SP 800-185 [2] -// -// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf -// [2] https://doi.org/10.6028/NIST.SP.800-185 - import ( - "encoding/binary" + "crypto/sha3" + "hash" "io" ) -// ShakeHash defines the interface to hash functions that -// support arbitrary-length output. +// ShakeHash defines the interface to hash functions that support +// arbitrary-length output. When used as a plain [hash.Hash], it +// produces minimum-length outputs that provide full-strength generic +// security. type ShakeHash interface { - // Write absorbs more data into the hash's state. It panics if input is - // written to it after output has been read from it. - io.Writer + hash.Hash // Read reads more output from the hash; reading affects the hash's - // state. (ShakeHash.Read is thus very different from Hash.Sum) - // It never returns an error. + // state. (ShakeHash.Read is thus very different from Hash.Sum.) + // It never returns an error, but subsequent calls to Write or Sum + // will panic. io.Reader // Clone returns a copy of the ShakeHash in its current state. Clone() ShakeHash - - // Reset resets the ShakeHash to its initial state. - Reset() -} - -// cSHAKE specific context -type cshakeState struct { - *state // SHA-3 state context and Read/Write operations - - // initBlock is the cSHAKE specific initialization set of bytes. It is initialized - // by newCShake function and stores concatenation of N followed by S, encoded - // by the method specified in 3.3 of [1]. - // It is stored here in order for Reset() to be able to put context into - // initial state. - initBlock []byte -} - -// Consts for configuring initial SHA-3 state -const ( - dsbyteShake = 0x1f - dsbyteCShake = 0x04 - rate128 = 168 - rate256 = 136 -) - -func bytepad(input []byte, w int) []byte { - // leftEncode always returns max 9 bytes - buf := make([]byte, 0, 9+len(input)+w) - buf = append(buf, leftEncode(uint64(w))...) - buf = append(buf, input...) - padlen := w - (len(buf) % w) - return append(buf, make([]byte, padlen)...) -} - -func leftEncode(value uint64) []byte { - var b [9]byte - binary.BigEndian.PutUint64(b[1:], value) - // Trim all but last leading zero bytes - i := byte(1) - for i < 8 && b[i] == 0 { - i++ - } - // Prepend number of encoded bytes - b[i-1] = 9 - i - return b[i-1:] -} - -func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash { - c := cshakeState{state: &state{rate: rate, dsbyte: dsbyte}} - - // leftEncode returns max 9 bytes - c.initBlock = make([]byte, 0, 9*2+len(N)+len(S)) - c.initBlock = append(c.initBlock, leftEncode(uint64(len(N)*8))...) - c.initBlock = append(c.initBlock, N...) - c.initBlock = append(c.initBlock, leftEncode(uint64(len(S)*8))...) - c.initBlock = append(c.initBlock, S...) - c.Write(bytepad(c.initBlock, c.rate)) - return &c -} - -// Reset resets the hash to initial state. -func (c *cshakeState) Reset() { - c.state.Reset() - c.Write(bytepad(c.initBlock, c.rate)) -} - -// Clone returns copy of a cSHAKE context within its current state. -func (c *cshakeState) Clone() ShakeHash { - b := make([]byte, len(c.initBlock)) - copy(b, c.initBlock) - return &cshakeState{state: c.clone(), initBlock: b} -} - -// Clone returns copy of SHAKE context within its current state. -func (c *state) Clone() ShakeHash { - return c.clone() } // NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. // Its generic security strength is 128 bits against all attacks if at // least 32 bytes of its output are used. func NewShake128() ShakeHash { - if h := newShake128Asm(); h != nil { - return h - } - return &state{rate: rate128, dsbyte: dsbyteShake} + return &shakeWrapper{sha3.NewSHAKE128(), 32, false, sha3.NewSHAKE128} } // NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. // Its generic security strength is 256 bits against all attacks if // at least 64 bytes of its output are used. func NewShake256() ShakeHash { - if h := newShake256Asm(); h != nil { - return h - } - return &state{rate: rate256, dsbyte: dsbyteShake} + return &shakeWrapper{sha3.NewSHAKE256(), 64, false, sha3.NewSHAKE256} } // NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash, @@ -139,10 +48,9 @@ func NewShake256() ShakeHash { // computations on same input with different S yield unrelated outputs. // When N and S are both empty, this is equivalent to NewShake128. func NewCShake128(N, S []byte) ShakeHash { - if len(N) == 0 && len(S) == 0 { - return NewShake128() - } - return newCShake(N, S, rate128, dsbyteCShake) + return &shakeWrapper{sha3.NewCSHAKE128(N, S), 32, false, func() *sha3.SHAKE { + return sha3.NewCSHAKE128(N, S) + }} } // NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash, @@ -152,10 +60,9 @@ func NewCShake128(N, S []byte) ShakeHash { // computations on same input with different S yield unrelated outputs. // When N and S are both empty, this is equivalent to NewShake256. func NewCShake256(N, S []byte) ShakeHash { - if len(N) == 0 && len(S) == 0 { - return NewShake256() - } - return newCShake(N, S, rate256, dsbyteCShake) + return &shakeWrapper{sha3.NewCSHAKE256(N, S), 64, false, func() *sha3.SHAKE { + return sha3.NewCSHAKE256(N, S) + }} } // ShakeSum128 writes an arbitrary-length digest of data into hash. @@ -171,3 +78,42 @@ func ShakeSum256(hash, data []byte) { h.Write(data) h.Read(hash) } + +// shakeWrapper adds the Size, Sum, and Clone methods to a sha3.SHAKE +// to implement the ShakeHash interface. +type shakeWrapper struct { + *sha3.SHAKE + outputLen int + squeezing bool + newSHAKE func() *sha3.SHAKE +} + +func (w *shakeWrapper) Read(p []byte) (n int, err error) { + w.squeezing = true + return w.SHAKE.Read(p) +} + +func (w *shakeWrapper) Clone() ShakeHash { + s := w.newSHAKE() + b, err := w.MarshalBinary() + if err != nil { + panic(err) // unreachable + } + if err := s.UnmarshalBinary(b); err != nil { + panic(err) // unreachable + } + return &shakeWrapper{s, w.outputLen, w.squeezing, w.newSHAKE} +} + +func (w *shakeWrapper) Size() int { return w.outputLen } + +func (w *shakeWrapper) Sum(b []byte) []byte { + if w.squeezing { + panic("sha3: Sum after Read") + } + out := make([]byte, w.outputLen) + // Clone the state so that we don't affect future Write calls. + s := w.Clone() + s.Read(out) + return append(b, out...) +} diff --git a/sha3/shake_generic.go b/sha3/shake_generic.go deleted file mode 100644 index add4e73396..0000000000 --- a/sha3/shake_generic.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build gccgo appengine !s390x - -package sha3 - -// newShake128Asm returns an assembly implementation of SHAKE-128 if available, -// otherwise it returns nil. -func newShake128Asm() ShakeHash { - return nil -} - -// newShake256Asm returns an assembly implementation of SHAKE-256 if available, -// otherwise it returns nil. -func newShake256Asm() ShakeHash { - return nil -} diff --git a/sha3/xor.go b/sha3/xor.go deleted file mode 100644 index 46a0d63a6d..0000000000 --- a/sha3/xor.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !amd64,!386,!ppc64le appengine - -package sha3 - -var ( - xorIn = xorInGeneric - copyOut = copyOutGeneric - xorInUnaligned = xorInGeneric - copyOutUnaligned = copyOutGeneric -) - -const xorImplementationUnaligned = "generic" diff --git a/sha3/xor_generic.go b/sha3/xor_generic.go deleted file mode 100644 index fd35f02ef6..0000000000 --- a/sha3/xor_generic.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sha3 - -import "encoding/binary" - -// xorInGeneric xors the bytes in buf into the state; it -// makes no non-portable assumptions about memory layout -// or alignment. -func xorInGeneric(d *state, buf []byte) { - n := len(buf) / 8 - - for i := 0; i < n; i++ { - a := binary.LittleEndian.Uint64(buf) - d.a[i] ^= a - buf = buf[8:] - } -} - -// copyOutGeneric copies ulint64s to a byte buffer. -func copyOutGeneric(d *state, b []byte) { - for i := 0; len(b) >= 8; i++ { - binary.LittleEndian.PutUint64(b, d.a[i]) - b = b[8:] - } -} diff --git a/sha3/xor_unaligned.go b/sha3/xor_unaligned.go deleted file mode 100644 index 929a486a79..0000000000 --- a/sha3/xor_unaligned.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64 386 ppc64le -// +build !appengine - -package sha3 - -import "unsafe" - -func xorInUnaligned(d *state, buf []byte) { - bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) - n := len(buf) - if n >= 72 { - d.a[0] ^= bw[0] - d.a[1] ^= bw[1] - d.a[2] ^= bw[2] - d.a[3] ^= bw[3] - d.a[4] ^= bw[4] - d.a[5] ^= bw[5] - d.a[6] ^= bw[6] - d.a[7] ^= bw[7] - d.a[8] ^= bw[8] - } - if n >= 104 { - d.a[9] ^= bw[9] - d.a[10] ^= bw[10] - d.a[11] ^= bw[11] - d.a[12] ^= bw[12] - } - if n >= 136 { - d.a[13] ^= bw[13] - d.a[14] ^= bw[14] - d.a[15] ^= bw[15] - d.a[16] ^= bw[16] - } - if n >= 144 { - d.a[17] ^= bw[17] - } - if n >= 168 { - d.a[18] ^= bw[18] - d.a[19] ^= bw[19] - d.a[20] ^= bw[20] - } -} - -func copyOutUnaligned(d *state, buf []byte) { - ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) - copy(buf, ab[:]) -} - -var ( - xorIn = xorInUnaligned - copyOut = copyOutUnaligned -) - -const xorImplementationUnaligned = "unaligned" diff --git a/ssh/agent/client.go b/ssh/agent/client.go index 51f740500e..b357e18b0a 100644 --- a/ssh/agent/client.go +++ b/ssh/agent/client.go @@ -8,13 +8,15 @@ // ssh-agent process using the sample server. // // References: -// [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00 -package agent // import "golang.org/x/crypto/ssh/agent" +// +// [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00 +package agent import ( "bytes" "crypto/dsa" "crypto/ecdsa" + "crypto/ed25519" "crypto/elliptic" "crypto/rsa" "encoding/base64" @@ -25,8 +27,6 @@ import ( "math/big" "sync" - "crypto" - "golang.org/x/crypto/ed25519" "golang.org/x/crypto/ssh" ) @@ -93,7 +93,7 @@ type ExtendedAgent interface { type ConstraintExtension struct { // ExtensionName consist of a UTF-8 string suffixed by the // implementation domain following the naming scheme defined - // in Section 4.2 of [RFC4251], e.g. "foo@example.com". + // in Section 4.2 of RFC 4251, e.g. "foo@example.com". ExtensionName string // ExtensionDetails contains the actual content of the extended // constraint. @@ -102,8 +102,9 @@ type ConstraintExtension struct { // AddedKey describes an SSH key to be added to an Agent. type AddedKey struct { - // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or - // *ecdsa.PrivateKey, which will be inserted into the agent. + // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey, + // ed25519.PrivateKey or *ecdsa.PrivateKey, which will be inserted into the + // agent. PrivateKey interface{} // Certificate, if not nil, is communicated to the agent and will be // stored with the key. @@ -140,9 +141,14 @@ const ( agentAddSmartcardKeyConstrained = 26 // 3.7 Key constraint identifiers - agentConstrainLifetime = 1 - agentConstrainConfirm = 2 - agentConstrainExtension = 3 + agentConstrainLifetime = 1 + agentConstrainConfirm = 2 + // Constraint extension identifier up to version 2 of the protocol. A + // backward incompatible change will be required if we want to add support + // for SSH_AGENT_CONSTRAIN_MAXSIGN which uses the same ID. + agentConstrainExtensionV00 = 3 + // Constraint extension identifier in version 3 and later of the protocol. + agentConstrainExtension = 255 ) // maxAgentResponseBytes is the maximum agent reply size that is accepted. This @@ -204,7 +210,7 @@ type constrainLifetimeAgentMsg struct { } type constrainExtensionAgentMsg struct { - ExtensionName string `sshtype:"3"` + ExtensionName string `sshtype:"255|3"` ExtensionDetails []byte // Rest is a field used for parsing, not part of message @@ -225,7 +231,9 @@ var ErrExtensionUnsupported = errors.New("agent: extension unsupported") type extensionAgentMsg struct { ExtensionType string `sshtype:"27"` - Contents []byte + // NOTE: this matches OpenSSH's PROTOCOL.agent, not the IETF draft [PROTOCOL.agent], + // so that it matches what OpenSSH actually implements in the wild. + Contents []byte `ssh:"rest"` } // Key represents a protocol 2 public key as defined in @@ -422,8 +430,9 @@ func (c *client) List() ([]*Key, error) { return keys, nil case *failureAgentMsg: return nil, errors.New("agent: failed to list keys") + default: + return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) } - panic("unreachable") } // Sign has the agent sign the data using a protocol 2 key as defined @@ -454,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl return &sig, nil case *failureAgentMsg: return nil, errors.New("agent: failed to sign challenge") + default: + return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg) } - panic("unreachable") } // unmarshal parses an agent message in packet, returning the parsed @@ -547,7 +557,7 @@ func (c *client) insertKey(s interface{}, comment string, constraints []byte) er }) case *dsa.PrivateKey: req = ssh.Marshal(dsaKeyMsg{ - Type: ssh.KeyAlgoDSA, + Type: ssh.InsecureKeyAlgoDSA, P: k.P, Q: k.Q, G: k.G, @@ -566,6 +576,17 @@ func (c *client) insertKey(s interface{}, comment string, constraints []byte) er Comments: comment, Constraints: constraints, }) + case ed25519.PrivateKey: + req = ssh.Marshal(ed25519KeyMsg{ + Type: ssh.KeyAlgoED25519, + Pub: []byte(k)[32:], + Priv: []byte(k), + Comments: comment, + Constraints: constraints, + }) + // This function originally supported only *ed25519.PrivateKey, however the + // general idiom is to pass ed25519.PrivateKey by value, not by pointer. + // We still support the pointer variant for backwards compatibility. case *ed25519.PrivateKey: req = ssh.Marshal(ed25519KeyMsg{ Type: ssh.KeyAlgoED25519, @@ -683,6 +704,18 @@ func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string Comments: comment, Constraints: constraints, }) + case ed25519.PrivateKey: + req = ssh.Marshal(ed25519CertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + Pub: []byte(k)[32:], + Priv: []byte(k), + Comments: comment, + Constraints: constraints, + }) + // This function originally supported only *ed25519.PrivateKey, however the + // general idiom is to pass ed25519.PrivateKey by value, not by pointer. + // We still support the pointer variant for backwards compatibility. case *ed25519.PrivateKey: req = ssh.Marshal(ed25519CertMsg{ Type: cert.Type(), @@ -705,7 +738,7 @@ func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string if err != nil { return err } - if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { return errors.New("agent: signer and cert have different public key") } @@ -747,19 +780,53 @@ func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, return s.agent.Sign(s.pub, data) } -func (s *agentKeyringSigner) SignWithOpts(rand io.Reader, data []byte, opts crypto.SignerOpts) (*ssh.Signature, error) { +func (s *agentKeyringSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*ssh.Signature, error) { + if algorithm == "" || algorithm == underlyingAlgo(s.pub.Type()) { + return s.Sign(rand, data) + } + var flags SignatureFlags - if opts != nil { - switch opts.HashFunc() { - case crypto.SHA256: - flags = SignatureFlagRsaSha256 - case crypto.SHA512: - flags = SignatureFlagRsaSha512 - } + switch algorithm { + case ssh.KeyAlgoRSASHA256: + flags = SignatureFlagRsaSha256 + case ssh.KeyAlgoRSASHA512: + flags = SignatureFlagRsaSha512 + default: + return nil, fmt.Errorf("agent: unsupported algorithm %q", algorithm) } + return s.agent.SignWithFlags(s.pub, data, flags) } +var _ ssh.AlgorithmSigner = &agentKeyringSigner{} + +// certKeyAlgoNames is a mapping from known certificate algorithm names to the +// corresponding public key signature algorithm. +// +// This map must be kept in sync with the one in certs.go. +var certKeyAlgoNames = map[string]string{ + ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA, + ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256, + ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512, + ssh.InsecureCertAlgoDSAv01: ssh.InsecureKeyAlgoDSA, + ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256, + ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384, + ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521, + ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256, + ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519, + ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519, +} + +// underlyingAlgo returns the signature algorithm associated with algo (which is +// an advertised or negotiated public key or host key algorithm). These are +// usually the same, except for certificate algorithms. +func underlyingAlgo(algo string) string { + if a, ok := certKeyAlgoNames[algo]; ok { + return a + } + return algo +} + // Calls an extension method. It is up to the agent implementation as to whether or not // any particular extension is supported and may always return an error. Because the // type of the response is up to the implementation, this returns the bytes of the diff --git a/ssh/agent/client_test.go b/ssh/agent/client_test.go index c31853aa44..0fd284d786 100644 --- a/ssh/agent/client_test.go +++ b/ssh/agent/client_test.go @@ -7,14 +7,16 @@ package agent import ( "bytes" "crypto/rand" + "encoding/binary" "errors" "io" "net" "os" "os/exec" "path/filepath" + "runtime" "strconv" - "sync" + "strings" "testing" "time" @@ -28,6 +30,9 @@ func startOpenSSHAgent(t *testing.T) (client ExtendedAgent, socket string, clean // types supported vary by platform. t.Skip("skipping test due to -short") } + if runtime.GOOS == "windows" { + t.Skip("skipping on windows, we don't support connecting to the ssh-agent via a named pipe") + } bin, err := exec.LookPath("ssh-agent") if err != nil { @@ -35,17 +40,19 @@ func startOpenSSHAgent(t *testing.T) (client ExtendedAgent, socket string, clean } cmd := exec.Command(bin, "-s") + cmd.Env = []string{} // Do not let the user's environment influence ssh-agent behavior. + cmd.Stderr = new(bytes.Buffer) out, err := cmd.Output() if err != nil { - t.Fatalf("cmd.Output: %v", err) + t.Fatalf("%s failed: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) } - /* Output looks like: + // Output looks like: + // + // SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; + // SSH_AGENT_PID=15542; export SSH_AGENT_PID; + // echo Agent pid 15542; - SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; - SSH_AGENT_PID=15542; export SSH_AGENT_PID; - echo Agent pid 15542; - */ fields := bytes.Split(out, []byte(";")) line := bytes.SplitN(fields[0], []byte("="), 2) line[0] = bytes.TrimLeft(line[0], "\n") @@ -158,15 +165,23 @@ func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert data := []byte("hello") sig, err := agent.Sign(pubKey, data) if err != nil { - t.Fatalf("Sign(%s): %v", pubKey.Type(), err) - } - - if err := pubKey.Verify(data, sig); err != nil { - t.Fatalf("Verify(%s): %v", pubKey.Type(), err) + t.Logf("sign failed with key type %q", pubKey.Type()) + // In integration tests ssh-rsa (SHA1 signatures) may be disabled for + // security reasons, we check SHA-2 variants later. + if pubKey.Type() != ssh.KeyAlgoRSA && pubKey.Type() != ssh.CertAlgoRSAv01 { + t.Fatalf("Sign(%s): %v", pubKey.Type(), err) + } + } else { + if err := pubKey.Verify(data, sig); err != nil { + t.Logf("verify failed with key type %q", pubKey.Type()) + if pubKey.Type() != ssh.KeyAlgoRSA { + t.Fatalf("Verify(%s): %v", pubKey.Type(), err) + } + } } // For tests on RSA keys, try signing with SHA-256 and SHA-512 flags - if pubKey.Type() == "ssh-rsa" { + if pubKey.Type() == ssh.KeyAlgoRSA { sshFlagTest := func(flag SignatureFlags, expectedSigFormat string) { sig, err = agent.SignWithFlags(pubKey, data, flag) if err != nil { @@ -179,9 +194,8 @@ func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert t.Fatalf("Verify(%s): %v", pubKey.Type(), err) } } - sshFlagTest(0, ssh.SigAlgoRSA) - sshFlagTest(SignatureFlagRsaSha256, ssh.SigAlgoRSASHA2256) - sshFlagTest(SignatureFlagRsaSha512, ssh.SigAlgoRSASHA2512) + sshFlagTest(SignatureFlagRsaSha256, ssh.KeyAlgoRSASHA256) + sshFlagTest(SignatureFlagRsaSha512, ssh.KeyAlgoRSASHA512) } // If the key has a lifetime, is it removed when it should be? @@ -200,44 +214,26 @@ func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert func TestMalformedRequests(t *testing.T) { keyringAgent := NewKeyring() - listener, err := netListener() - if err != nil { - t.Fatalf("netListener: %v", err) - } - defer listener.Close() testCase := func(t *testing.T, requestBytes []byte, wantServerErr bool) { - var wg sync.WaitGroup - wg.Add(1) + c, s := net.Pipe() + defer c.Close() + defer s.Close() go func() { - defer wg.Done() - c, err := listener.Accept() + _, err := c.Write(requestBytes) if err != nil { - t.Errorf("listener.Accept: %v", err) - return - } - defer c.Close() - - err = ServeAgent(keyringAgent, c) - if err == nil { - t.Error("ServeAgent should have returned an error to malformed input") - } else { - if (err != io.EOF) != wantServerErr { - t.Errorf("ServeAgent returned expected error: %v", err) - } + t.Errorf("Unexpected error writing raw bytes on connection: %v", err) } + c.Close() }() - - c, err := net.Dial("tcp", listener.Addr().String()) - if err != nil { - t.Fatalf("net.Dial: %v", err) - } - _, err = c.Write(requestBytes) - if err != nil { - t.Errorf("Unexpected error writing raw bytes on connection: %v", err) + err := ServeAgent(keyringAgent, s) + if err == nil { + t.Error("ServeAgent should have returned an error to malformed input") + } else { + if (err != io.EOF) != wantServerErr { + t.Errorf("ServeAgent returned expected error: %v", err) + } } - c.Close() - wg.Wait() } var testCases = []struct { @@ -256,7 +252,7 @@ func TestMalformedRequests(t *testing.T) { } func TestAgent(t *testing.T) { - for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} { + for _, keyType := range []string{"rsa", "ecdsa", "ed25519"} { testOpenSSHAgent(t, testPrivateKeys[keyType], nil, 0) testKeyringAgent(t, testPrivateKeys[keyType], nil, 0) } @@ -314,6 +310,8 @@ func TestServerResponseTooLarge(t *testing.T) { if err != nil { t.Fatalf("netPipe: %v", err) } + done := make(chan struct{}) + defer func() { <-done }() defer a.Close() defer b.Close() @@ -324,9 +322,21 @@ func TestServerResponseTooLarge(t *testing.T) { agent := NewClient(a) go func() { - n, _ := b.Write(ssh.Marshal(response)) + defer close(done) + n, err := b.Write(ssh.Marshal(response)) if n < 4 { - t.Fatalf("At least 4 bytes (the response size) should have been successfully written: %d < 4", n) + if runtime.GOOS == "plan9" { + if e1, ok := err.(*net.OpError); ok { + if e2, ok := e1.Err.(*os.PathError); ok { + switch e2.Err.Error() { + case "Hangup", "i/o on hungup channel": + // syscall.Pwrite returns -1 in this case even when some data did get written. + return + } + } + } + } + t.Errorf("At least 4 bytes (the response size) should have been successfully written: %d < 4: %v", n, err) } }() _, err = agent.List() @@ -338,6 +348,53 @@ func TestServerResponseTooLarge(t *testing.T) { } } +func TestInvalidResponses(t *testing.T) { + a, b, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + done := make(chan struct{}) + defer func() { <-done }() + + defer a.Close() + defer b.Close() + + agent := NewClient(a) + go func() { + defer close(done) + + resp := []byte{agentSuccess} + msg := make([]byte, 4+len(resp)) + binary.BigEndian.PutUint32(msg[:4], uint32(len(resp))) + copy(msg[4:], resp) + + if _, err := b.Write(msg); err != nil { + t.Errorf("unexpected error sending agent reply: %v", err) + b.Close() + return + } + + if _, err := b.Write(msg); err != nil { + t.Errorf("unexpected error sending agent reply: %v", err) + b.Close() + } + }() + _, err = agent.List() + if err == nil { + t.Fatal("error expected") + } + if !strings.Contains(err.Error(), "failed to list keys, unexpected message type") { + t.Fatalf("unexpected error: %v", err) + } + _, err = agent.Sign(testPublicKeys["rsa"], []byte("message")) + if err == nil { + t.Fatal("error expected") + } + if !strings.Contains(err.Error(), "failed to sign challenge, unexpected message type") { + t.Fatalf("unexpected error: %v", err) + } +} + func TestAuth(t *testing.T) { agent, _, cleanup := startOpenSSHAgent(t) defer cleanup() @@ -367,7 +424,8 @@ func TestAuth(t *testing.T) { go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) if err != nil { - t.Fatalf("Server: %v", err) + t.Errorf("NewServerConn error: %v", err) + return } conn.Close() }() @@ -399,7 +457,7 @@ func testLockAgent(agent Agent, t *testing.T) { if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil { t.Errorf("Add: %v", err) } - if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil { + if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["ecdsa"], Comment: "comment ecdsa"}); err != nil { t.Errorf("Add: %v", err) } if keys, err := agent.List(); err != nil { diff --git a/ssh/agent/example_test.go b/ssh/agent/example_test.go index 85562253ea..1fedaea1d6 100644 --- a/ssh/agent/example_test.go +++ b/ssh/agent/example_test.go @@ -13,20 +13,20 @@ import ( "golang.org/x/crypto/ssh/agent" ) -func ExampleClientAgent() { - // ssh-agent has a UNIX socket under $SSH_AUTH_SOCK +func ExampleNewClient() { + // ssh-agent(1) provides a UNIX socket at $SSH_AUTH_SOCK. socket := os.Getenv("SSH_AUTH_SOCK") conn, err := net.Dial("unix", socket) if err != nil { - log.Fatalf("net.Dial: %v", err) + log.Fatalf("Failed to open SSH_AUTH_SOCK: %v", err) } + agentClient := agent.NewClient(conn) config := &ssh.ClientConfig{ - User: "username", + User: "gopher", Auth: []ssh.AuthMethod{ - // Use a callback rather than PublicKeys - // so we only consult the agent once the remote server - // wants it. + // Use a callback rather than PublicKeys so we only consult the + // agent once the remote server wants it. ssh.PublicKeysCallback(agentClient.Signers), }, HostKeyCallback: ssh.InsecureIgnoreHostKey(), @@ -34,8 +34,8 @@ func ExampleClientAgent() { sshc, err := ssh.Dial("tcp", "localhost:22", config) if err != nil { - log.Fatalf("Dial: %v", err) + log.Fatal(err) } - // .. use sshc + // Use sshc... sshc.Close() } diff --git a/ssh/agent/keyring.go b/ssh/agent/keyring.go index c9d9794307..d129875510 100644 --- a/ssh/agent/keyring.go +++ b/ssh/agent/keyring.go @@ -112,8 +112,8 @@ func (r *keyring) Unlock(passphrase []byte) error { } // expireKeysLocked removes expired keys from the keyring. If a key was added -// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have -// ellapsed, it is removed. The caller *must* be holding the keyring mutex. +// with a lifetimesecs constraint and seconds >= lifetimesecs seconds have +// elapsed, it is removed. The caller *must* be holding the keyring mutex. func (r *keyring) expireKeysLocked() { for _, k := range r.keys { if k.expire != nil && time.Now().After(*k.expire) { @@ -175,6 +175,15 @@ func (r *keyring) Add(key AddedKey) error { p.expire = &t } + // If we already have a Signer with the same public key, replace it with the + // new one. + for idx, k := range r.keys { + if bytes.Equal(k.signer.PublicKey().Marshal(), p.signer.PublicKey().Marshal()) { + r.keys[idx] = p + return nil + } + } + r.keys = append(r.keys, p) return nil @@ -205,9 +214,9 @@ func (r *keyring) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureF var algorithm string switch flags { case SignatureFlagRsaSha256: - algorithm = ssh.SigAlgoRSASHA2256 + algorithm = ssh.KeyAlgoRSASHA256 case SignatureFlagRsaSha512: - algorithm = ssh.SigAlgoRSASHA2512 + algorithm = ssh.KeyAlgoRSASHA512 default: return nil, fmt.Errorf("agent: unsupported signature flags: %d", flags) } diff --git a/ssh/agent/keyring_test.go b/ssh/agent/keyring_test.go index e5d50e7e0d..5e495d56d3 100644 --- a/ssh/agent/keyring_test.go +++ b/ssh/agent/keyring_test.go @@ -29,6 +29,10 @@ func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) { t.Fatalf("failed to list keys: %v", err) return } + if len(listedKeys) != len(expectedKeys) { + t.Fatalf("expected %d key, got %d", len(expectedKeys), len(listedKeys)) + return + } actualKeys := make(map[string]bool) for _, key := range listedKeys { actualKeys[key.Comment] = true @@ -74,3 +78,45 @@ func TestKeyringAddingAndRemoving(t *testing.T) { } validateListedKeys(t, k, []string{}) } + +func TestAddDuplicateKey(t *testing.T) { + keyNames := []string{"rsa", "user"} + + k := NewKeyring() + for _, keyName := range keyNames { + addTestKey(t, k, keyName) + } + validateListedKeys(t, k, keyNames) + // Add the keys again. + for _, keyName := range keyNames { + addTestKey(t, k, keyName) + } + validateListedKeys(t, k, keyNames) + // Add an existing key with an updated comment. + keyName := keyNames[0] + addedKey := AddedKey{ + PrivateKey: testPrivateKeys[keyName], + Comment: "comment updated", + } + err := k.Add(addedKey) + if err != nil { + t.Fatalf("failed to add key %q: %v", keyName, err) + } + // Check the that key is found and the comment was updated. + keys, err := k.List() + if err != nil { + t.Fatalf("failed to list keys: %v", err) + } + if len(keys) != len(keyNames) { + t.Fatalf("expected %d keys, got %d", len(keyNames), len(keys)) + } + isFound := false + for _, key := range keys { + if key.Comment == addedKey.Comment { + isFound = true + } + } + if !isFound { + t.Fatal("key with the updated comment not found") + } +} diff --git a/ssh/agent/server.go b/ssh/agent/server.go index 6e7a1e02f2..88ce4da6c4 100644 --- a/ssh/agent/server.go +++ b/ssh/agent/server.go @@ -7,6 +7,7 @@ package agent import ( "crypto/dsa" "crypto/ecdsa" + "crypto/ed25519" "crypto/elliptic" "crypto/rsa" "encoding/binary" @@ -16,11 +17,10 @@ import ( "log" "math/big" - "golang.org/x/crypto/ed25519" "golang.org/x/crypto/ssh" ) -// Server wraps an Agent and uses it to implement the agent side of +// server wraps an Agent and uses it to implement the agent side of // the SSH-agent, wire protocol. type server struct { agent Agent @@ -208,7 +208,7 @@ func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse case agentConstrainConfirm: confirmBeforeUse = true constraints = constraints[1:] - case agentConstrainExtension: + case agentConstrainExtension, agentConstrainExtensionV00: var msg constrainExtensionAgentMsg if err = ssh.Unmarshal(constraints, &msg); err != nil { return 0, false, nil, err @@ -506,7 +506,7 @@ func (s *server) insertIdentity(req []byte) error { switch record.Type { case ssh.KeyAlgoRSA: addedKey, err = parseRSAKey(req) - case ssh.KeyAlgoDSA: + case ssh.InsecureKeyAlgoDSA: addedKey, err = parseDSAKey(req) case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: addedKey, err = parseECDSAKey(req) @@ -514,7 +514,7 @@ func (s *server) insertIdentity(req []byte) error { addedKey, err = parseEd25519Key(req) case ssh.CertAlgoRSAv01: addedKey, err = parseRSACert(req) - case ssh.CertAlgoDSAv01: + case ssh.InsecureCertAlgoDSAv01: addedKey, err = parseDSACert(req) case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: addedKey, err = parseECDSACert(req) diff --git a/ssh/agent/server_test.go b/ssh/agent/server_test.go index 038018ebb1..7700d18f1a 100644 --- a/ssh/agent/server_test.go +++ b/ssh/agent/server_test.go @@ -53,10 +53,11 @@ func TestSetupForwardAgent(t *testing.T) { incoming := make(chan *ssh.ServerConn, 1) go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) + incoming <- conn if err != nil { - t.Fatalf("Server: %v", err) + t.Errorf("NewServerConn error: %v", err) + return } - incoming <- conn }() conf := ssh.ClientConfig{ @@ -71,8 +72,10 @@ func TestSetupForwardAgent(t *testing.T) { if err := ForwardToRemote(client, socket); err != nil { t.Fatalf("SetupForwardAgent: %v", err) } - server := <-incoming + if server == nil { + t.Fatal("Unable to get server") + } ch, reqs, err := server.OpenChannel(channelType, nil) if err != nil { t.Fatalf("OpenChannel(%q): %v", channelType, err) @@ -240,7 +243,11 @@ func TestParseConstraints(t *testing.T) { ExtensionDetails: []byte(fmt.Sprintf("details: %d", i)), } expect = append(expect, ext) - data = append(data, agentConstrainExtension) + if i%2 == 0 { + data = append(data, agentConstrainExtension) + } else { + data = append(data, agentConstrainExtensionV00) + } data = append(data, ssh.Marshal(ext)...) } _, _, extensions, err := parseConstraints(data) diff --git a/ssh/benchmark_test.go b/ssh/benchmark_test.go index a13235d743..b356330b46 100644 --- a/ssh/benchmark_test.go +++ b/ssh/benchmark_test.go @@ -6,6 +6,7 @@ package ssh import ( "errors" + "fmt" "io" "net" "testing" @@ -90,16 +91,16 @@ func BenchmarkEndToEnd(b *testing.B) { go func() { newCh, err := server.Accept() if err != nil { - b.Fatalf("Client: %v", err) + panic(fmt.Sprintf("Client: %v", err)) } ch, incoming, err := newCh.Accept() if err != nil { - b.Fatalf("Accept: %v", err) + panic(fmt.Sprintf("Accept: %v", err)) } go DiscardRequests(incoming) for i := 0; i < b.N; i++ { if _, err := io.ReadFull(ch, output); err != nil { - b.Fatalf("ReadFull: %v", err) + panic(fmt.Sprintf("ReadFull: %v", err)) } } ch.Close() diff --git a/ssh/certs.go b/ssh/certs.go index 00ed9923e7..139fa31e1b 100644 --- a/ssh/certs.go +++ b/ssh/certs.go @@ -14,15 +14,40 @@ import ( "time" ) -// These constants from [PROTOCOL.certkeys] represent the algorithm names -// for certificate types supported by this package. +// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear +// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. +// Unlike key algorithm names, these are not passed to AlgorithmSigner nor +// returned by MultiAlgorithmSigner and don't appear in the Signature.Format +// field. const ( - CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" - CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" - CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" - CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" - CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" - CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" + CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" + // Deprecated: DSA is only supported at insecure key sizes, and was removed + // from major implementations. + CertAlgoDSAv01 = InsecureCertAlgoDSAv01 + // Deprecated: DSA is only supported at insecure key sizes, and was removed + // from major implementations. + InsecureCertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" + CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" + CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" + CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" + CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" + CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" + CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" + + // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a + // Certificate.Type (or PublicKey.Type), but only in + // ClientConfig.HostKeyAlgorithms. + CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com" + CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com" +) + +const ( + // Deprecated: use CertAlgoRSAv01. + CertSigAlgoRSAv01 = CertAlgoRSAv01 + // Deprecated: use CertAlgoRSASHA256v01. + CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01 + // Deprecated: use CertAlgoRSASHA512v01. + CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01 ) // Certificate types distinguish between host and user @@ -37,6 +62,7 @@ const ( type Signature struct { Format string Blob []byte + Rest []byte `ssh:"rest"` } // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that @@ -207,7 +233,11 @@ func parseCert(in []byte, privAlgo string) (*Certificate, error) { if err != nil { return nil, err } - + // The Type() function is intended to return only certificate key types, but + // we use certKeyAlgoNames anyway for safety, to match [Certificate.Type]. + if _, ok := certKeyAlgoNames[k.Type()]; ok { + return nil, fmt.Errorf("ssh: the signature key type %q is invalid for certificates", k.Type()) + } c.SignatureKey = k c.Signature, rest, ok = parseSignatureBody(g.Signature) if !ok || len(rest) > 0 { @@ -231,14 +261,21 @@ type algorithmOpenSSHCertSigner struct { // private key is held by signer. It returns an error if the public key in cert // doesn't match the key used by signer. func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { - if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { return nil, errors.New("ssh: signer and cert have different public key") } - if algorithmSigner, ok := signer.(AlgorithmSigner); ok { + switch s := signer.(type) { + case MultiAlgorithmSigner: + return &multiAlgorithmSigner{ + AlgorithmSigner: &algorithmOpenSSHCertSigner{ + &openSSHCertSigner{cert, signer}, s}, + supportedAlgorithms: s.Algorithms(), + }, nil + case AlgorithmSigner: return &algorithmOpenSSHCertSigner{ - &openSSHCertSigner{cert, signer}, algorithmSigner}, nil - } else { + &openSSHCertSigner{cert, signer}, s}, nil + default: return &openSSHCertSigner{cert, signer}, nil } } @@ -268,16 +305,13 @@ type CertChecker struct { SupportedCriticalOptions []string // IsUserAuthority should return true if the key is recognized as an - // authority for the given user certificate. This allows for - // certificates to be signed by other certificates. This must be set - // if this CertChecker will be checking user certificates. + // authority for user certificate. This must be set if this CertChecker + // will be checking user certificates. IsUserAuthority func(auth PublicKey) bool // IsHostAuthority should report whether the key is recognized as - // an authority for this host. This allows for certificates to be - // signed by other keys, and for those other keys to only be valid - // signers for particular hostnames. This must be set if this - // CertChecker will be checking host certificates. + // an authority for this host. This must be set if this CertChecker + // will be checking host certificates. IsHostAuthority func(auth PublicKey, address string) bool // Clock is used for verifying time stamps. If nil, time.Now @@ -411,15 +445,46 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { return nil } -// SignCert sets c.SignatureKey to the authority's public key and stores a -// Signature, by authority, in the certificate. +// SignCert signs the certificate with an authority, setting the Nonce, +// SignatureKey, and Signature fields. If the authority implements the +// MultiAlgorithmSigner interface the first algorithm in the list is used. This +// is useful if you want to sign with a specific algorithm. As specified in +// [SSH-CERTS], Section 2.1.1, authority can't be a [Certificate]. func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { c.Nonce = make([]byte, 32) if _, err := io.ReadFull(rand, c.Nonce); err != nil { return err } + // The Type() function is intended to return only certificate key types, but + // we use certKeyAlgoNames anyway for safety, to match [Certificate.Type]. + if _, ok := certKeyAlgoNames[authority.PublicKey().Type()]; ok { + return fmt.Errorf("ssh: certificates cannot be used as authority (public key type %q)", + authority.PublicKey().Type()) + } c.SignatureKey = authority.PublicKey() + if v, ok := authority.(MultiAlgorithmSigner); ok { + if len(v.Algorithms()) == 0 { + return errors.New("the provided authority has no signature algorithm") + } + // Use the first algorithm in the list. + sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), v.Algorithms()[0]) + if err != nil { + return err + } + c.Signature = sig + return nil + } else if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { + // Default to KeyAlgoRSASHA512 for ssh-rsa signers. + // TODO: consider using KeyAlgoRSASHA256 as default. + sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512) + if err != nil { + return err + } + c.Signature = sig + return nil + } + sig, err := authority.Sign(rand, c.bytesForSigning()) if err != nil { return err @@ -428,24 +493,42 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { return nil } -var certAlgoNames = map[string]string{ - KeyAlgoRSA: CertAlgoRSAv01, - KeyAlgoDSA: CertAlgoDSAv01, - KeyAlgoECDSA256: CertAlgoECDSA256v01, - KeyAlgoECDSA384: CertAlgoECDSA384v01, - KeyAlgoECDSA521: CertAlgoECDSA521v01, - KeyAlgoED25519: CertAlgoED25519v01, +// certKeyAlgoNames is a mapping from known certificate algorithm names to the +// corresponding public key signature algorithm. +// +// This map must be kept in sync with the one in agent/client.go. +var certKeyAlgoNames = map[string]string{ + CertAlgoRSAv01: KeyAlgoRSA, + CertAlgoRSASHA256v01: KeyAlgoRSASHA256, + CertAlgoRSASHA512v01: KeyAlgoRSASHA512, + InsecureCertAlgoDSAv01: InsecureKeyAlgoDSA, + CertAlgoECDSA256v01: KeyAlgoECDSA256, + CertAlgoECDSA384v01: KeyAlgoECDSA384, + CertAlgoECDSA521v01: KeyAlgoECDSA521, + CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, + CertAlgoED25519v01: KeyAlgoED25519, + CertAlgoSKED25519v01: KeyAlgoSKED25519, } -// certToPrivAlgo returns the underlying algorithm for a certificate algorithm. -// Panics if a non-certificate algorithm is passed. -func certToPrivAlgo(algo string) string { - for privAlgo, pubAlgo := range certAlgoNames { - if pubAlgo == algo { - return privAlgo +// underlyingAlgo returns the signature algorithm associated with algo (which is +// an advertised or negotiated public key or host key algorithm). These are +// usually the same, except for certificate algorithms. +func underlyingAlgo(algo string) string { + if a, ok := certKeyAlgoNames[algo]; ok { + return a + } + return algo +} + +// certificateAlgo returns the certificate algorithms that uses the provided +// underlying signature algorithm. +func certificateAlgo(algo string) (certAlgo string, ok bool) { + for certName, algoName := range certKeyAlgoNames { + if algoName == algo { + return certName, true } } - panic("unknown cert algorithm") + return "", false } func (cert *Certificate) bytesForSigning() []byte { @@ -489,13 +572,13 @@ func (c *Certificate) Marshal() []byte { return result } -// Type returns the key name. It is part of the PublicKey interface. +// Type returns the certificate algorithm name. It is part of the PublicKey interface. func (c *Certificate) Type() string { - algo, ok := certAlgoNames[c.Key.Type()] + certName, ok := certificateAlgo(c.Key.Type()) if !ok { - panic("unknown cert key type " + c.Key.Type()) + panic("unknown certificate type for key type " + c.Key.Type()) } - return algo + return certName } // Verify verifies a signature against the certificate's public @@ -518,6 +601,12 @@ func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { return } + switch out.Format { + case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01: + out.Rest = in + return out, nil, ok + } + return out, in, ok } diff --git a/ssh/certs_test.go b/ssh/certs_test.go index c8e7cf5851..ba435ab9cf 100644 --- a/ssh/certs_test.go +++ b/ssh/certs_test.go @@ -9,6 +9,8 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "fmt" + "io" "net" "reflect" "testing" @@ -17,12 +19,8 @@ import ( "golang.org/x/crypto/ssh/testdata" ) -// Cert generated by ssh-keygen 6.0p1 Debian-4. -// % ssh-keygen -s ca-key -I test user-key -const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` - func TestParseCert(t *testing.T) { - authKeyBytes := []byte(exampleSSHCert) + authKeyBytes := bytes.TrimSuffix(testdata.SSHCertificates["rsa"], []byte(" host.example.com\n")) key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) if err != nil { @@ -49,14 +47,17 @@ func TestParseCert(t *testing.T) { // % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub // user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN // Critical Options: -// force-command /bin/sleep -// source-address 192.168.1.0/24 +// +// force-command /bin/sleep +// source-address 192.168.1.0/24 +// // Extensions: -// permit-X11-forwarding -// permit-agent-forwarding -// permit-port-forwarding -// permit-pty -// permit-user-rc +// +// permit-X11-forwarding +// permit-agent-forwarding +// permit-port-forwarding +// permit-pty +// permit-user-rc const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` func TestParseCertWithOptions(t *testing.T) { @@ -100,7 +101,7 @@ func TestParseCertWithOptions(t *testing.T) { } func TestValidateCert(t *testing.T) { - key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) + key, _, _, _, err := ParseAuthorizedKey(testdata.SSHCertificates["rsa-user-testcertificate"]) if err != nil { t.Fatalf("ParseAuthorizedKey: %v", err) } @@ -113,7 +114,7 @@ func TestValidateCert(t *testing.T) { return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) } - if err := checker.CheckCert("user", validCert); err != nil { + if err := checker.CheckCert("testcertificate", validCert); err != nil { t.Errorf("Unable to validate certificate: %v", err) } invalidCert := &Certificate{ @@ -122,7 +123,7 @@ func TestValidateCert(t *testing.T) { ValidBefore: CertTimeInfinity, Signature: &Signature{}, } - if err := checker.CheckCert("user", invalidCert); err == nil { + if err := checker.CheckCert("testcertificate", invalidCert); err == nil { t.Error("Invalid cert signature passed validation") } } @@ -184,10 +185,30 @@ func TestHostKeyCert(t *testing.T) { } for _, test := range []struct { - addr string - succeed bool + addr string + succeed bool + certSignerAlgorithms []string // Empty means no algorithm restrictions. + clientHostKeyAlgorithms []string }{ {addr: "hostname:22", succeed: true}, + { + addr: "hostname:22", + succeed: true, + certSignerAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}, + clientHostKeyAlgorithms: []string{CertAlgoRSASHA512v01}, + }, + { + addr: "hostname:22", + succeed: false, + certSignerAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}, + clientHostKeyAlgorithms: []string{CertAlgoRSAv01}, + }, + { + addr: "hostname:22", + succeed: false, + certSignerAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}, + clientHostKeyAlgorithms: []string{KeyAlgoRSASHA512}, // Not a certificate algorithm. + }, {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22' {addr: "lasthost:22", succeed: false}, } { @@ -204,75 +225,79 @@ func TestHostKeyCert(t *testing.T) { conf := ServerConfig{ NoClientAuth: true, } - conf.AddHostKey(certSigner) + if len(test.certSignerAlgorithms) > 0 { + mas, err := NewSignerWithAlgorithms(certSigner.(AlgorithmSigner), test.certSignerAlgorithms) + if err != nil { + errc <- err + return + } + conf.AddHostKey(mas) + } else { + conf.AddHostKey(certSigner) + } _, _, _, err := NewServerConn(c1, &conf) errc <- err }() config := &ClientConfig{ - User: "user", - HostKeyCallback: checker.CheckHostKey, + User: "user", + HostKeyCallback: checker.CheckHostKey, + HostKeyAlgorithms: test.clientHostKeyAlgorithms, } _, _, _, err = NewClientConn(c2, test.addr, config) if (err == nil) != test.succeed { - t.Fatalf("NewClientConn(%q): %v", test.addr, err) + t.Errorf("NewClientConn(%q): %v", test.addr, err) } err = <-errc if (err == nil) != test.succeed { - t.Fatalf("NewServerConn(%q): %v", test.addr, err) + t.Errorf("NewServerConn(%q): %v", test.addr, err) } } } +type legacyRSASigner struct { + Signer +} + +func (s *legacyRSASigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + v, ok := s.Signer.(AlgorithmSigner) + if !ok { + return nil, fmt.Errorf("invalid signer") + } + return v.SignWithAlgorithm(rand, data, KeyAlgoRSA) +} + func TestCertTypes(t *testing.T) { + algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner) + if !ok { + t.Fatal("rsa test signer does not implement the AlgorithmSigner interface") + } + multiAlgoSignerSHA256, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256}) + if err != nil { + t.Fatalf("unable to create multi algorithm signer SHA256: %v", err) + } + // Algorithms are in order of preference, we expect rsa-sha2-512 to be used. + multiAlgoSignerSHA512, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256}) + if err != nil { + t.Fatalf("unable to create multi algorithm signer SHA512: %v", err) + } + var testVars = []struct { - name string - keys func() Signer + name string + signer Signer + algo string }{ - { - name: CertAlgoECDSA256v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"]) - return s - }, - }, - { - name: CertAlgoECDSA384v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"]) - return s - }, - }, - { - name: CertAlgoECDSA521v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"]) - return s - }, - }, - { - name: CertAlgoED25519v01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"]) - return s - }, - }, - { - name: CertAlgoRSAv01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"]) - return s - }, - }, - { - name: CertAlgoDSAv01, - keys: func() Signer { - s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"]) - return s - }, - }, + {CertAlgoECDSA256v01, testSigners["ecdsap256"], ""}, + {CertAlgoECDSA384v01, testSigners["ecdsap384"], ""}, + {CertAlgoECDSA521v01, testSigners["ecdsap521"], ""}, + {CertAlgoED25519v01, testSigners["ed25519"], ""}, + {CertAlgoRSAv01, testSigners["rsa"], KeyAlgoRSASHA256}, + {"legacyRSASigner", &legacyRSASigner{testSigners["rsa"]}, KeyAlgoRSA}, + {"multiAlgoRSASignerSHA256", multiAlgoSignerSHA256, KeyAlgoRSASHA256}, + {"multiAlgoRSASignerSHA512", multiAlgoSignerSHA512, KeyAlgoRSASHA512}, + {InsecureCertAlgoDSAv01, testSigners["dsa"], ""}, } k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -304,7 +329,7 @@ func TestCertTypes(t *testing.T) { go NewServerConn(c1, conf) - priv := m.keys() + priv := m.signer if err != nil { t.Fatalf("error generating ssh pubkey: %v", err) } @@ -313,13 +338,19 @@ func TestCertTypes(t *testing.T) { CertType: UserCert, Key: priv.PublicKey(), } - cert.SignCert(rand.Reader, priv) + if err := cert.SignCert(rand.Reader, priv); err != nil { + t.Fatalf("error signing certificate: %v", err) + } certSigner, err := NewCertSigner(cert, priv) if err != nil { t.Fatalf("error generating cert signer: %v", err) } + if m.algo != "" && cert.Signature.Format != m.algo { + t.Errorf("expected %q signature format, got %q", m.algo, cert.Signature.Format) + } + config := &ClientConfig{ User: "user", HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil }, @@ -333,3 +364,74 @@ func TestCertTypes(t *testing.T) { }) } } + +func TestCertSignWithMultiAlgorithmSigner(t *testing.T) { + type testcase struct { + sigAlgo string + algorithms []string + } + cases := []testcase{ + { + sigAlgo: KeyAlgoRSA, + algorithms: []string{KeyAlgoRSA, KeyAlgoRSASHA512}, + }, + { + sigAlgo: KeyAlgoRSASHA256, + algorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSA, KeyAlgoRSASHA512}, + }, + { + sigAlgo: KeyAlgoRSASHA512, + algorithms: []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256}, + }, + } + + cert := &Certificate{ + Key: testPublicKeys["rsa"], + ValidBefore: CertTimeInfinity, + CertType: UserCert, + } + + for _, c := range cases { + t.Run(c.sigAlgo, func(t *testing.T) { + signer, err := NewSignerWithAlgorithms(testSigners["rsa"].(AlgorithmSigner), c.algorithms) + if err != nil { + t.Fatalf("NewSignerWithAlgorithms error: %v", err) + } + if err := cert.SignCert(rand.Reader, signer); err != nil { + t.Fatalf("SignCert error: %v", err) + } + if cert.Signature.Format != c.sigAlgo { + t.Fatalf("got signature format %q, want %q", cert.Signature.Format, c.sigAlgo) + } + }) + } +} + +func TestCertSignWithCertificate(t *testing.T) { + cert := &Certificate{ + Key: testPublicKeys["rsa"], + ValidBefore: CertTimeInfinity, + CertType: UserCert, + } + if err := cert.SignCert(rand.Reader, testSigners["ecdsa"]); err != nil { + t.Fatalf("SignCert: %v", err) + } + signer, err := NewSignerWithAlgorithms(testSigners["rsa"].(AlgorithmSigner), []string{KeyAlgoRSASHA256}) + if err != nil { + t.Fatal(err) + } + certSigner, err := NewCertSigner(cert, signer) + if err != nil { + t.Fatalf("NewCertSigner: %v", err) + } + + cert1 := &Certificate{ + Key: testPublicKeys["ecdsa"], + ValidBefore: CertTimeInfinity, + CertType: UserCert, + } + + if err := cert1.SignCert(rand.Reader, certSigner); err == nil { + t.Fatal("successfully signed a certificate using another certificate, it is expected to fail") + } +} diff --git a/ssh/channel.go b/ssh/channel.go index c0834c00df..cc0bb7ab64 100644 --- a/ssh/channel.go +++ b/ssh/channel.go @@ -187,9 +187,11 @@ type channel struct { pending *buffer extPending *buffer - // windowMu protects myWindow, the flow-control window. - windowMu sync.Mutex - myWindow uint32 + // windowMu protects myWindow, the flow-control window, and myConsumed, + // the number of bytes consumed since we last increased myWindow + windowMu sync.Mutex + myWindow uint32 + myConsumed uint32 // writeMu serializes calls to mux.conn.writePacket() and // protects sentClose and packetPool. This mutex must be @@ -332,14 +334,24 @@ func (ch *channel) handleData(packet []byte) error { return nil } -func (c *channel) adjustWindow(n uint32) error { +func (c *channel) adjustWindow(adj uint32) error { c.windowMu.Lock() - // Since myWindow is managed on our side, and can never exceed - // the initial window setting, we don't worry about overflow. - c.myWindow += uint32(n) + // Since myConsumed and myWindow are managed on our side, and can never + // exceed the initial window setting, we don't worry about overflow. + c.myConsumed += adj + var sendAdj uint32 + if (channelWindowSize-c.myWindow > 3*c.maxIncomingPayload) || + (c.myWindow < channelWindowSize/2) { + sendAdj = c.myConsumed + c.myConsumed = 0 + c.myWindow += sendAdj + } c.windowMu.Unlock() + if sendAdj == 0 { + return nil + } return c.sendMessage(windowAdjustMsg{ - AdditionalBytes: uint32(n), + AdditionalBytes: sendAdj, }) } diff --git a/ssh/cipher.go b/ssh/cipher.go index a65a923be3..7554ed57a9 100644 --- a/ssh/cipher.go +++ b/ssh/cipher.go @@ -8,6 +8,7 @@ import ( "crypto/aes" "crypto/cipher" "crypto/des" + "crypto/fips140" "crypto/rc4" "crypto/subtle" "encoding/binary" @@ -15,11 +16,10 @@ import ( "fmt" "hash" "io" - "io/ioutil" - "math/bits" + "slices" - "golang.org/x/crypto/internal/chacha20" - "golang.org/x/crypto/poly1305" + "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/poly1305" ) const ( @@ -60,11 +60,11 @@ func newRC4(key, iv []byte) (cipher.Stream, error) { type cipherMode struct { keySize int ivSize int - create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) + create func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) } -func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { - return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { + return func(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { stream, err := createFunc(key, iv) if err != nil { return nil, err @@ -95,40 +95,41 @@ func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, } // cipherModes documents properties of supported ciphers. Ciphers not included -// are not supported and will not be negotiated, even if explicitly requested in -// ClientConfig.Crypto.Ciphers. -var cipherModes = map[string]*cipherMode{ - // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms - // are defined in the order specified in the RFC. - "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, - "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, - "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, - - // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. - // They are defined in the order specified in the RFC. - "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, - "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, - - // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. - // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and - // RC4) has problems with weak keys, and should be used with caution." - // RFC4345 introduces improved versions of Arcfour. - "arcfour": {16, 0, streamCipherMode(0, newRC4)}, - - // AEAD ciphers - gcmCipherID: {16, 12, newGCMCipher}, - chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, - +// are not supported and will not be negotiated, even if explicitly configured. +// When FIPS mode is enabled, only FIPS-approved algorithms are included. +var cipherModes = map[string]*cipherMode{} + +func init() { + cipherModes[CipherAES128CTR] = &cipherMode{16, aes.BlockSize, streamCipherMode(0, newAESCTR)} + cipherModes[CipherAES192CTR] = &cipherMode{24, aes.BlockSize, streamCipherMode(0, newAESCTR)} + cipherModes[CipherAES256CTR] = &cipherMode{32, aes.BlockSize, streamCipherMode(0, newAESCTR)} + // Use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, + // we'll wire it up to NewGCMForSSH in Go 1.26. + // + // For now it means we'll work with fips140=on but not fips140=only. + cipherModes[CipherAES128GCM] = &cipherMode{16, 12, newGCMCipher} + cipherModes[CipherAES256GCM] = &cipherMode{32, 12, newGCMCipher} + + if fips140.Enabled() { + defaultCiphers = slices.DeleteFunc(defaultCiphers, func(algo string) bool { + _, ok := cipherModes[algo] + return !ok + }) + return + } + + cipherModes[CipherChaCha20Poly1305] = &cipherMode{64, 0, newChaCha20Cipher} + // Insecure ciphers not included in the default configuration. + cipherModes[InsecureCipherRC4128] = &cipherMode{16, 0, streamCipherMode(1536, newRC4)} + cipherModes[InsecureCipherRC4256] = &cipherMode{32, 0, streamCipherMode(1536, newRC4)} + cipherModes[InsecureCipherRC4] = &cipherMode{16, 0, streamCipherMode(0, newRC4)} // CBC mode is insecure and so is not included in the default config. - // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely + // (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely // needed, it's possible to specify a custom Config to enable it. // You should expect that an active attacker can recover plaintext if // you do. - aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, - - // 3des-cbc is insecure and is not included in the default - // config. - tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, + cipherModes[InsecureCipherAES128CBC] = &cipherMode{16, aes.BlockSize, newAESCBCCipher} + cipherModes[InsecureCipherTripleDESCBC] = &cipherMode{24, des.BlockSize, newTripleDESCBCCipher} } // prefixLen is the length of the packet prefix that contains the packet length @@ -308,7 +309,7 @@ type gcmCipher struct { buf []byte } -func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { +func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs DirectionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err @@ -395,6 +396,10 @@ func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) } c.incIV() + if len(plain) == 0 { + return nil, errors.New("ssh: empty packet") + } + padding := plain[0] if padding < 4 { // padding is a byte, so it automatically satisfies @@ -426,7 +431,7 @@ type cbcCipher struct { oracleCamouflage uint32 } -func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { cbc := &cbcCipher{ mac: macModes[algs.MAC].new(macKey), decrypter: cipher.NewCBCDecrypter(c, iv), @@ -440,7 +445,7 @@ func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorith return cbc, nil } -func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newAESCBCCipher(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err @@ -454,7 +459,7 @@ func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCi return cbc, nil } -func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newTripleDESCBCCipher(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { c, err := des.NewTripleDESCipher(key) if err != nil { return nil, err @@ -494,7 +499,7 @@ func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) // data, to make distinguishing between // failing MAC and failing length check more // difficult. - io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage)) + io.CopyN(io.Discard, r, int64(c.oracleCamouflage)) } } return p, err @@ -632,22 +637,20 @@ func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader return nil } -const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" - // chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com // AEAD, which is described here: // -// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 +// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 // -// the methods here also implement padding, which RFC4253 Section 6 +// the methods here also implement padding, which RFC 4253 Section 6 // also requires of stream ciphers. type chacha20Poly1305Cipher struct { - lengthKey [8]uint32 - contentKey [8]uint32 + lengthKey [32]byte + contentKey [32]byte buf []byte } -func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { +func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs DirectionAlgorithms) (packetCipher, error) { if len(key) != 64 { panic(len(key)) } @@ -656,21 +659,21 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA buf: make([]byte, 256), } - for i := range c.contentKey { - c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4]) - } - for i := range c.lengthKey { - c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4]) - } + copy(c.contentKey[:], key[:32]) + copy(c.lengthKey[:], key[32:]) return c, nil } func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { - nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} - s := chacha20.New(c.contentKey, nonce) - var polyKey [32]byte + nonce := make([]byte, 12) + binary.BigEndian.PutUint32(nonce[8:], seqNum) + s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) + if err != nil { + return nil, err + } + var polyKey, discardBuf [32]byte s.XORKeyStream(polyKey[:], polyKey[:]) - s.Advance() // skip next 32 bytes + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes encryptedLength := c.buf[:4] if _, err := io.ReadFull(r, encryptedLength); err != nil { @@ -678,7 +681,11 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([ } var lenBytes [4]byte - chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength) + ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) + if err != nil { + return nil, err + } + ls.XORKeyStream(lenBytes[:], encryptedLength) length := binary.BigEndian.Uint32(lenBytes[:]) if length > maxPacket { @@ -707,6 +714,10 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([ plain := c.buf[4:contentEnd] s.XORKeyStream(plain, plain) + if len(plain) == 0 { + return nil, errors.New("ssh: empty packet") + } + padding := plain[0] if padding < 4 { // padding is a byte, so it automatically satisfies @@ -724,11 +735,15 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([ } func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { - nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} - s := chacha20.New(c.contentKey, nonce) - var polyKey [32]byte + nonce := make([]byte, 12) + binary.BigEndian.PutUint32(nonce[8:], seqNum) + s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) + if err != nil { + return err + } + var polyKey, discardBuf [32]byte s.XORKeyStream(polyKey[:], polyKey[:]) - s.Advance() // skip next 32 bytes + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes // There is no blocksize, so fall back to multiple of 8 byte // padding, as described in RFC 4253, Sec 6. @@ -748,7 +763,11 @@ func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, r } binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) - chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4]) + ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) + if err != nil { + return err + } + ls.XORKeyStream(c.buf, c.buf[:4]) c.buf[4] = byte(padding) copy(c.buf[5:], payload) packetEnd := 5 + len(payload) + padding diff --git a/ssh/cipher_test.go b/ssh/cipher_test.go index 70a2b5b5cd..ac6da50429 100644 --- a/ssh/cipher_test.go +++ b/ssh/cipher_test.go @@ -8,7 +8,12 @@ import ( "bytes" "crypto" "crypto/rand" + "encoding/binary" + "io" "testing" + + "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/poly1305" ) func TestDefaultCiphersExist(t *testing.T) { @@ -17,7 +22,7 @@ func TestDefaultCiphersExist(t *testing.T) { t.Errorf("supported cipher %q is unknown", cipherAlgo) } } - for _, cipherAlgo := range preferredCiphers { + for _, cipherAlgo := range defaultCiphers { if _, ok := cipherModes[cipherAlgo]; !ok { t.Errorf("preferred cipher %q is unknown", cipherAlgo) } @@ -25,8 +30,8 @@ func TestDefaultCiphersExist(t *testing.T) { } func TestPacketCiphers(t *testing.T) { - defaultMac := "hmac-sha2-256" - defaultCipher := "aes128-ctr" + defaultMac := HMACSHA256 + defaultCipher := CipherAES128CTR for cipher := range cipherModes { t.Run("cipher="+cipher, func(t *testing.T) { testPacketCipher(t, cipher, defaultMac) }) @@ -39,10 +44,10 @@ func TestPacketCiphers(t *testing.T) { func testPacketCipher(t *testing.T, cipher, mac string) { kr := &kexResult{Hash: crypto.SHA1} - algs := directionAlgorithms{ + algs := DirectionAlgorithms{ Cipher: cipher, MAC: mac, - Compression: "none", + compression: compressionNone, } client, err := newPacketCipher(clientKeys, algs, kr) if err != nil { @@ -72,10 +77,10 @@ func testPacketCipher(t *testing.T, cipher, mac string) { func TestCBCOracleCounterMeasure(t *testing.T) { kr := &kexResult{Hash: crypto.SHA1} - algs := directionAlgorithms{ - Cipher: aes128cbcID, - MAC: "hmac-sha1", - Compression: "none", + algs := DirectionAlgorithms{ + Cipher: InsecureCipherAES128CBC, + MAC: HMACSHA1, + compression: compressionNone, } client, err := newPacketCipher(clientKeys, algs, kr) if err != nil { @@ -129,3 +134,98 @@ func TestCBCOracleCounterMeasure(t *testing.T) { lastRead = bytesRead } } + +func TestCVE202143565(t *testing.T) { + tests := []struct { + cipher string + constructPacket func(packetCipher) io.Reader + }{ + { + cipher: CipherAES128GCM, + constructPacket: func(client packetCipher) io.Reader { + internalCipher := client.(*gcmCipher) + b := &bytes.Buffer{} + prefix := [4]byte{} + if _, err := b.Write(prefix[:]); err != nil { + t.Fatal(err) + } + internalCipher.buf = internalCipher.aead.Seal(internalCipher.buf[:0], internalCipher.iv, []byte{}, prefix[:]) + if _, err := b.Write(internalCipher.buf); err != nil { + t.Fatal(err) + } + internalCipher.incIV() + + return b + }, + }, + { + cipher: CipherChaCha20Poly1305, + constructPacket: func(client packetCipher) io.Reader { + internalCipher := client.(*chacha20Poly1305Cipher) + b := &bytes.Buffer{} + + nonce := make([]byte, 12) + s, err := chacha20.NewUnauthenticatedCipher(internalCipher.contentKey[:], nonce) + if err != nil { + t.Fatal(err) + } + var polyKey, discardBuf [32]byte + s.XORKeyStream(polyKey[:], polyKey[:]) + s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes + + internalCipher.buf = make([]byte, 4+poly1305.TagSize) + binary.BigEndian.PutUint32(internalCipher.buf, 0) + ls, err := chacha20.NewUnauthenticatedCipher(internalCipher.lengthKey[:], nonce) + if err != nil { + t.Fatal(err) + } + ls.XORKeyStream(internalCipher.buf, internalCipher.buf[:4]) + if _, err := io.ReadFull(rand.Reader, internalCipher.buf[4:4]); err != nil { + t.Fatal(err) + } + + s.XORKeyStream(internalCipher.buf[4:], internalCipher.buf[4:4]) + + var tag [poly1305.TagSize]byte + poly1305.Sum(&tag, internalCipher.buf[:4], &polyKey) + + copy(internalCipher.buf[4:], tag[:]) + + if _, err := b.Write(internalCipher.buf); err != nil { + t.Fatal(err) + } + + return b + }, + }, + } + + for _, tc := range tests { + mac := HMACSHA256 + + kr := &kexResult{Hash: crypto.SHA1} + algs := DirectionAlgorithms{ + Cipher: tc.cipher, + MAC: mac, + compression: compressionNone, + } + client, err := newPacketCipher(clientKeys, algs, kr) + if err != nil { + t.Fatalf("newPacketCipher(client, %q, %q): %v", tc.cipher, mac, err) + } + server, err := newPacketCipher(clientKeys, algs, kr) + if err != nil { + t.Fatalf("newPacketCipher(client, %q, %q): %v", tc.cipher, mac, err) + } + + b := tc.constructPacket(client) + + wantErr := "ssh: empty packet" + _, err = server.readCipherPacket(0, b) + if err == nil { + t.Fatalf("readCipherPacket(%q, %q): didn't fail with empty packet", tc.cipher, mac) + } else if err.Error() != wantErr { + t.Fatalf("readCipherPacket(%q, %q): unexpected error, got %q, want %q", tc.cipher, mac, err, wantErr) + } + } +} diff --git a/ssh/client.go b/ssh/client.go index 7b00bff1ca..33079789bc 100644 --- a/ssh/client.go +++ b/ssh/client.go @@ -77,12 +77,12 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan } conn := &connection{ - sshConn: sshConn{conn: c}, + sshConn: sshConn{conn: c, user: fullConf.User}, } if err := conn.clientHandshake(addr, &fullConf); err != nil { c.Close() - return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) + return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %w", err) } conn.mux = newMux(conn.transport) return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil @@ -110,17 +110,22 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e } c.sessionID = c.transport.getSessionID() + c.algorithms = c.transport.getAlgorithms() return c.clientAuthenticate(config) } -// verifyHostKeySignature verifies the host key obtained in the key -// exchange. -func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { +// verifyHostKeySignature verifies the host key obtained in the key exchange. +// algo is the negotiated algorithm, and may be a certificate type. +func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error { sig, rest, ok := parseSignatureBody(result.Signature) if len(rest) > 0 || !ok { return errors.New("ssh: signature parse error") } + if a := underlyingAlgo(algo); sig.Format != a { + return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a) + } + return hostKey.Verify(result.H, sig) } @@ -224,11 +229,11 @@ type ClientConfig struct { // be used for the connection. If empty, a reasonable default is used. ClientVersion string - // HostKeyAlgorithms lists the key types that the client will - // accept from the server as host key, in order of + // HostKeyAlgorithms lists the public key algorithms that the client will + // accept from the server for host key authentication, in order of // preference. If empty, a reasonable default is used. Any - // string returned from PublicKey.Type method may be used, or - // any of the CertAlgoXxxx and KeyAlgoXxxx constants. + // string returned from a PublicKey.Type method may be used, or + // any of the CertAlgo and KeyAlgo constants. HostKeyAlgorithms []string // Timeout is the maximum amount of time for the TCP connection to establish. diff --git a/ssh/client_auth.go b/ssh/client_auth.go index 0590070e22..3127e49903 100644 --- a/ssh/client_auth.go +++ b/ssh/client_auth.go @@ -9,6 +9,8 @@ import ( "errors" "fmt" "io" + "slices" + "strings" ) type authResult int @@ -29,6 +31,33 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { if err != nil { return err } + // The server may choose to send a SSH_MSG_EXT_INFO at this point (if we + // advertised willingness to receive one, which we always do) or not. See + // RFC 8308, Section 2.4. + extensions := make(map[string][]byte) + if len(packet) > 0 && packet[0] == msgExtInfo { + var extInfo extInfoMsg + if err := Unmarshal(packet, &extInfo); err != nil { + return err + } + payload := extInfo.Payload + for i := uint32(0); i < extInfo.NumExtensions; i++ { + name, rest, ok := parseString(payload) + if !ok { + return parseError(msgExtInfo) + } + value, rest, ok := parseString(rest) + if !ok { + return parseError(msgExtInfo) + } + extensions[string(name)] = value + payload = rest + } + packet, err = c.transport.readPacket() + if err != nil { + return err + } + } var serviceAccept serviceAcceptMsg if err := Unmarshal(packet, &serviceAccept); err != nil { return err @@ -36,20 +65,28 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { // during the authentication phase the client first attempts the "none" method // then any untried methods suggested by the server. - tried := make(map[string]bool) + var tried []string var lastMethods []string sessionID := c.transport.getSessionID() for auth := AuthMethod(new(noneAuth)); auth != nil; { - ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand) + ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions) if err != nil { - return err + // On disconnect, return error immediately + if _, ok := err.(*disconnectMsg); ok { + return err + } + // We return the error later if there is no other method left to + // try. + ok = authFailure } if ok == authSuccess { // success return nil } else if ok == authFailure { - tried[auth.method()] = true + if m := auth.method(); !slices.Contains(tried, m) { + tried = append(tried, m) + } } if methods == nil { methods = lastMethods @@ -61,7 +98,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { findNext: for _, a := range config.Auth { candidateMethod := a.method() - if tried[candidateMethod] { + if slices.Contains(tried, candidateMethod) { continue } for _, meth := range methods { @@ -71,17 +108,14 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { } } } - } - return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried)) -} -func keys(m map[string]bool) []string { - s := make([]string, 0, len(m)) - - for key := range m { - s = append(s, key) + if auth == nil && err != nil { + // We have an error and there are no other authentication methods to + // try, so we return it. + return err + } } - return s + return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried) } // An AuthMethod represents an instance of an RFC 4252 authentication method. @@ -91,7 +125,7 @@ type AuthMethod interface { // If authentication is not successful, a []string of alternative // method names is returned. If the slice is nil, it will be ignored // and the previous set of possible methods will be reused. - auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error) + auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) // method returns the RFC 4252 method name. method() string @@ -100,7 +134,7 @@ type AuthMethod interface { // "none" authentication, RFC 4252 section 5.2. type noneAuth int -func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { +func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { if err := c.writePacket(Marshal(&userAuthRequestMsg{ User: user, Service: serviceSSH, @@ -120,7 +154,7 @@ func (n *noneAuth) method() string { // a function call, e.g. by prompting the user. type passwordCallback func() (password string, err error) -func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { +func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { type passwordAuthMsg struct { User string `sshtype:"50"` Service string @@ -187,7 +221,77 @@ func (cb publicKeyCallback) method() string { return "publickey" } -func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { +func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiAlgorithmSigner, string, error) { + var as MultiAlgorithmSigner + keyFormat := signer.PublicKey().Type() + + // If the signer implements MultiAlgorithmSigner we use the algorithms it + // support, if it implements AlgorithmSigner we assume it supports all + // algorithms, otherwise only the key format one. + switch s := signer.(type) { + case MultiAlgorithmSigner: + as = s + case AlgorithmSigner: + as = &multiAlgorithmSigner{ + AlgorithmSigner: s, + supportedAlgorithms: algorithmsForKeyFormat(underlyingAlgo(keyFormat)), + } + default: + as = &multiAlgorithmSigner{ + AlgorithmSigner: algorithmSignerWrapper{signer}, + supportedAlgorithms: []string{underlyingAlgo(keyFormat)}, + } + } + + getFallbackAlgo := func() (string, error) { + // Fallback to use if there is no "server-sig-algs" extension or a + // common algorithm cannot be found. We use the public key format if the + // MultiAlgorithmSigner supports it, otherwise we return an error. + if !slices.Contains(as.Algorithms(), underlyingAlgo(keyFormat)) { + return "", fmt.Errorf("ssh: no common public key signature algorithm, server only supports %q for key type %q, signer only supports %v", + underlyingAlgo(keyFormat), keyFormat, as.Algorithms()) + } + return keyFormat, nil + } + + extPayload, ok := extensions["server-sig-algs"] + if !ok { + // If there is no "server-sig-algs" extension use the fallback + // algorithm. + algo, err := getFallbackAlgo() + return as, algo, err + } + + // The server-sig-algs extension only carries underlying signature + // algorithm, but we are trying to select a protocol-level public key + // algorithm, which might be a certificate type. Extend the list of server + // supported algorithms to include the corresponding certificate algorithms. + serverAlgos := strings.Split(string(extPayload), ",") + for _, algo := range serverAlgos { + if certAlgo, ok := certificateAlgo(algo); ok { + serverAlgos = append(serverAlgos, certAlgo) + } + } + + // Filter algorithms based on those supported by MultiAlgorithmSigner. + var keyAlgos []string + for _, algo := range algorithmsForKeyFormat(keyFormat) { + if slices.Contains(as.Algorithms(), underlyingAlgo(algo)) { + keyAlgos = append(keyAlgos, algo) + } + } + + algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos, true) + if err != nil { + // If there is no overlap, return the fallback algorithm to support + // servers that fail to list all supported algorithms. + algo, err := getFallbackAlgo() + return as, algo, err + } + return as, algo, nil +} + +func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { // Authentication is performed by sending an enquiry to test if a key is // acceptable to the remote. If the key is acceptable, the client will // attempt to authenticate with the valid key. If not the client will repeat @@ -198,22 +302,50 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand return authFailure, nil, err } var methods []string - for _, signer := range signers { - ok, err := validateKey(signer.PublicKey(), user, c) + var errSigAlgo error + + origSignersLen := len(signers) + for idx := 0; idx < len(signers); idx++ { + signer := signers[idx] + pub := signer.PublicKey() + as, algo, err := pickSignatureAlgorithm(signer, extensions) + if err != nil && errSigAlgo == nil { + // If we cannot negotiate a signature algorithm store the first + // error so we can return it to provide a more meaningful message if + // no other signers work. + errSigAlgo = err + continue + } + ok, err := validateKey(pub, algo, user, c) if err != nil { return authFailure, nil, err } + // OpenSSH 7.2-7.7 advertises support for rsa-sha2-256 and rsa-sha2-512 + // in the "server-sig-algs" extension but doesn't support these + // algorithms for certificate authentication, so if the server rejects + // the key try to use the obtained algorithm as if "server-sig-algs" had + // not been implemented if supported from the algorithm signer. + if !ok && idx < origSignersLen && isRSACert(algo) && algo != CertAlgoRSAv01 { + if slices.Contains(as.Algorithms(), KeyAlgoRSA) { + // We retry using the compat algorithm after all signers have + // been tried normally. + signers = append(signers, &multiAlgorithmSigner{ + AlgorithmSigner: as, + supportedAlgorithms: []string{KeyAlgoRSA}, + }) + } + } if !ok { continue } - pub := signer.PublicKey() pubKey := pub.Marshal() - sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{ + data := buildDataSignedForAuth(session, userAuthRequestMsg{ User: user, Service: serviceSSH, Method: cb.method(), - }, []byte(pub.Type()), pubKey)) + }, algo, pubKey) + sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) if err != nil { return authFailure, nil, err } @@ -227,7 +359,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand Service: serviceSSH, Method: cb.method(), HasSig: true, - Algoname: pub.Type(), + Algoname: algo, PubKey: pubKey, Sig: sig, } @@ -245,33 +377,23 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand // contain the "publickey" method, do not attempt to authenticate with any // other keys. According to RFC 4252 Section 7, the latter can occur when // additional authentication methods are required. - if success == authSuccess || !containsMethod(methods, cb.method()) { + if success == authSuccess || !slices.Contains(methods, cb.method()) { return success, methods, err } } - return authFailure, methods, nil -} - -func containsMethod(methods []string, method string) bool { - for _, m := range methods { - if m == method { - return true - } - } - - return false + return authFailure, methods, errSigAlgo } // validateKey validates the key provided is acceptable to the server. -func validateKey(key PublicKey, user string, c packetConn) (bool, error) { +func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) { pubKey := key.Marshal() msg := publickeyAuthMsg{ User: user, Service: serviceSSH, Method: "publickey", HasSig: false, - Algoname: key.Type(), + Algoname: algo, PubKey: pubKey, } if err := c.writePacket(Marshal(&msg)); err != nil { @@ -283,7 +405,6 @@ func validateKey(key PublicKey, user string, c packetConn) (bool, error) { func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { pubKey := key.Marshal() - algoname := key.Type() for { packet, err := c.readPacket() @@ -300,14 +421,22 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { if err := Unmarshal(packet, &msg); err != nil { return false, err } - if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) { + // According to RFC 4252 Section 7 the algorithm in + // SSH_MSG_USERAUTH_PK_OK should match that of the request but some + // servers send the key type instead. OpenSSH allows any algorithm + // that matches the public key, so we do the same. + // https://github.com/openssh/openssh-portable/blob/86bdd385/sshconnect2.c#L709 + if !slices.Contains(algorithmsForKeyFormat(key.Type()), msg.Algo) { + return false, nil + } + if !bytes.Equal(msg.PubKey, pubKey) { return false, nil } return true, nil case msgUserAuthFailure: return false, nil default: - return false, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0]) } } } @@ -328,6 +457,7 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet // along with a list of remaining authentication methods to try next and // an error if an unexpected response was received. func handleAuthResponse(c packetConn) (authResult, []string, error) { + gotMsgExtInfo := false for { packet, err := c.readPacket() if err != nil { @@ -339,6 +469,12 @@ func handleAuthResponse(c packetConn) (authResult, []string, error) { if err := handleBannerResponse(c, packet); err != nil { return authFailure, nil, err } + case msgExtInfo: + // Ignore post-authentication RFC 8308 extensions, once. + if gotMsgExtInfo { + return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + gotMsgExtInfo = true case msgUserAuthFailure: var msg userAuthFailureMsg if err := Unmarshal(packet, &msg); err != nil { @@ -378,10 +514,10 @@ func handleBannerResponse(c packetConn, packet []byte) error { // disabling echoing (e.g. for passwords), and return all the answers. // Challenge may be called multiple times in a single session. After // successful authentication, the server may send a challenge with no -// questions, for which the user and instruction messages should be +// questions, for which the name and instruction messages should be // printed. RFC 4256 section 3.3 details how the UI should behave for // both CLI and GUI environments. -type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error) +type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error) // KeyboardInteractive returns an AuthMethod using a prompt/response // sequence controlled by the server. @@ -393,7 +529,7 @@ func (cb KeyboardInteractiveChallenge) method() string { return "keyboard-interactive" } -func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { +func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { type initiateMsg struct { User string `sshtype:"50"` Service string @@ -410,6 +546,8 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe return authFailure, nil, err } + gotMsgExtInfo := false + gotUserAuthInfoRequest := false for { packet, err := c.readPacket() if err != nil { @@ -423,6 +561,13 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe return authFailure, nil, err } continue + case msgExtInfo: + // Ignore post-authentication RFC 8308 extensions, once. + if gotMsgExtInfo { + return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + } + gotMsgExtInfo = true + continue case msgUserAuthInfoRequest: // OK case msgUserAuthFailure: @@ -433,6 +578,9 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe if msg.PartialSuccess { return authPartialSuccess, msg.Methods, nil } + if !gotUserAuthInfoRequest { + return authFailure, msg.Methods, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + } return authFailure, msg.Methods, nil case msgUserAuthSuccess: return authSuccess, nil, nil @@ -444,6 +592,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe if err := Unmarshal(packet, &msg); err != nil { return authFailure, nil, err } + gotUserAuthInfoRequest = true // Manually unpack the prompt/echo pairs. rest := msg.Prompts @@ -463,13 +612,13 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") } - answers, err := cb(msg.User, msg.Instruction, prompts, echos) + answers, err := cb(msg.Name, msg.Instruction, prompts, echos) if err != nil { return authFailure, nil, err } if len(answers) != len(prompts) { - return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") + return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts)) } responseLength := 1 + 4 for _, a := range answers { @@ -495,9 +644,9 @@ type retryableAuthMethod struct { maxTries int } -func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) { +func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) { for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { - ok, methods, err = r.authMethod.auth(session, user, c, rand) + ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions) if ok != authFailure || err != nil { // either success, partial success or error terminate return ok, methods, err } @@ -540,7 +689,7 @@ type gssAPIWithMICCallback struct { target string } -func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { +func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { m := &userAuthRequestMsg{ User: user, Service: serviceSSH, diff --git a/ssh/client_auth_test.go b/ssh/client_auth_test.go index 63a8e22487..a183c2183e 100644 --- a/ssh/client_auth_test.go +++ b/ssh/client_auth_test.go @@ -13,6 +13,8 @@ import ( "log" "net" "os" + "runtime" + "slices" "strings" "testing" ) @@ -37,7 +39,7 @@ func tryAuth(t *testing.T, config *ClientConfig) error { return err } -// tryAuth runs a handshake with a given config against an SSH server +// tryAuthWithGSSAPIWithMICConfig runs a handshake with a given config against an SSH server // with a given GSSAPIWithMICConfig and config serverConfig. Returns both client and server side errors. func tryAuthWithGSSAPIWithMICConfig(t *testing.T, clientConfig *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) error { err, _ := tryAuthBothSides(t, clientConfig, gssAPIWithMICConfig) @@ -104,11 +106,61 @@ func tryAuthBothSides(t *testing.T, config *ClientConfig, gssAPIWithMICConfig *G return err, serverAuthErrors } +type loggingAlgorithmSigner struct { + used []string + AlgorithmSigner +} + +func (l *loggingAlgorithmSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + l.used = append(l.used, "[Sign]") + return l.AlgorithmSigner.Sign(rand, data) +} + +func (l *loggingAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + l.used = append(l.used, algorithm) + return l.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm) +} + func TestClientAuthPublicKey(t *testing.T) { + signer := &loggingAlgorithmSigner{AlgorithmSigner: testSigners["rsa"].(AlgorithmSigner)} config := &ClientConfig{ User: "testuser", Auth: []AuthMethod{ - PublicKeys(testSigners["rsa"]), + PublicKeys(signer), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } + if len(signer.used) != 1 || signer.used[0] != KeyAlgoRSASHA256 { + t.Errorf("unexpected Sign/SignWithAlgorithm calls: %q", signer.used) + } +} + +// TestClientAuthNoSHA2 tests a ssh-rsa Signer that doesn't implement AlgorithmSigner. +func TestClientAuthNoSHA2(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(&legacyRSASigner{testSigners["rsa"]}), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +// TestClientAuthThirdKey checks that the third configured can succeed. If we +// were to do three attempts for each key (rsa-sha2-256, rsa-sha2-512, ssh-rsa), +// we'd hit the six maximum attempts before reaching it. +func TestClientAuthThirdKey(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa-openssh-format"], + testSigners["rsa-openssh-format"], testSigners["rsa"]), }, HostKeyCallback: InsecureIgnoreHostKey(), } @@ -273,6 +325,9 @@ func TestMethodInvalidAlgorithm(t *testing.T) { } func TestClientHMAC(t *testing.T) { + supportedAlgos := SupportedAlgorithms() + insecureAlgos := InsecureAlgorithms() + supportedMACs := append(supportedAlgos.MACs, insecureAlgos.MACs...) for _, mac := range supportedMACs { config := &ClientConfig{ User: "testuser", @@ -298,7 +353,7 @@ func TestClientUnsupportedCipher(t *testing.T) { PublicKeys(), }, Config: Config{ - Ciphers: []string{"aes128-cbc"}, // not currently supported + Ciphers: []string{"unsupported-cipher"}, // not currently supported }, } if err := tryAuth(t, config); err == nil { @@ -590,17 +645,28 @@ func TestClientAuthMaxAuthTries(t *testing.T) { defer c1.Close() defer c2.Close() - go newServer(c1, serverConfig) - _, _, _, err = NewClientConn(c2, "", clientConfig) - if tries > 2 { - if err == nil { + errCh := make(chan error, 1) + + go func() { + _, err := newServer(c1, serverConfig) + errCh <- err + }() + _, _, _, cliErr := NewClientConn(c2, "", clientConfig) + srvErr := <-errCh + + if tries > serverConfig.MaxAuthTries { + if cliErr == nil { t.Fatalf("client: got no error, want %s", expectedErr) - } else if err.Error() != expectedErr.Error() { + } else if cliErr.Error() != expectedErr.Error() { t.Fatalf("client: got %s, want %s", err, expectedErr) } + var authErr *ServerAuthError + if !errors.As(srvErr, &authErr) { + t.Errorf("expected ServerAuthError, got: %v", srvErr) + } } else { - if err != nil { - t.Fatalf("client: got %s, want no error", err) + if cliErr != nil { + t.Fatalf("client: got %s, want no error", cliErr) } } } @@ -639,7 +705,15 @@ func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) { if err := tryAuth(t, invalidConfig); err == nil { t.Fatalf("client: got no error, want %s", expectedErr) } else if err.Error() != expectedErr.Error() { - t.Fatalf("client: got %s, want %s", err, expectedErr) + // On Windows we can see a WSAECONNABORTED error + // if the client writes another authentication request + // before the client goroutine reads the disconnection + // message. See issue 50805. + if runtime.GOOS == "windows" && strings.Contains(err.Error(), "wsarecv: An established connection was aborted") { + // OK. + } else { + t.Fatalf("client: got %s, want %s", err, expectedErr) + } } } @@ -896,3 +970,419 @@ func TestAuthMethodGSSAPIWithMIC(t *testing.T) { } } } + +func TestCompatibleAlgoAndSignatures(t *testing.T) { + type testcase struct { + algo string + sigFormat string + compatible bool + } + testcases := []*testcase{ + { + KeyAlgoRSA, + KeyAlgoRSA, + true, + }, + { + KeyAlgoRSA, + KeyAlgoRSASHA256, + true, + }, + { + KeyAlgoRSA, + KeyAlgoRSASHA512, + true, + }, + { + KeyAlgoRSASHA256, + KeyAlgoRSA, + true, + }, + { + KeyAlgoRSASHA512, + KeyAlgoRSA, + true, + }, + { + KeyAlgoRSASHA512, + KeyAlgoRSASHA256, + true, + }, + { + KeyAlgoRSASHA256, + KeyAlgoRSASHA512, + true, + }, + { + KeyAlgoRSASHA512, + KeyAlgoRSASHA512, + true, + }, + { + CertAlgoRSAv01, + KeyAlgoRSA, + true, + }, + { + CertAlgoRSAv01, + KeyAlgoRSASHA256, + true, + }, + { + CertAlgoRSAv01, + KeyAlgoRSASHA512, + true, + }, + { + CertAlgoRSASHA256v01, + KeyAlgoRSASHA512, + true, + }, + { + CertAlgoRSASHA512v01, + KeyAlgoRSASHA512, + true, + }, + { + CertAlgoRSASHA512v01, + KeyAlgoRSASHA256, + true, + }, + { + CertAlgoRSASHA256v01, + CertAlgoRSAv01, + true, + }, + { + CertAlgoRSAv01, + CertAlgoRSASHA512v01, + true, + }, + { + KeyAlgoECDSA256, + KeyAlgoRSA, + false, + }, + { + KeyAlgoECDSA256, + KeyAlgoECDSA521, + false, + }, + { + KeyAlgoECDSA256, + KeyAlgoECDSA256, + true, + }, + { + KeyAlgoECDSA256, + KeyAlgoED25519, + false, + }, + { + KeyAlgoED25519, + KeyAlgoED25519, + true, + }, + } + + for _, c := range testcases { + if isAlgoCompatible(c.algo, c.sigFormat) != c.compatible { + t.Errorf("algorithm %q, signature format %q, expected compatible to be %t", c.algo, c.sigFormat, c.compatible) + } + } +} + +func TestPickSignatureAlgorithm(t *testing.T) { + type testcase struct { + name string + extensions map[string][]byte + } + cases := []testcase{ + { + name: "server with empty server-sig-algs", + extensions: map[string][]byte{ + "server-sig-algs": []byte(``), + }, + }, + { + name: "server with no server-sig-algs", + extensions: nil, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + signer, ok := testSigners["rsa"].(MultiAlgorithmSigner) + if !ok { + t.Fatalf("rsa test signer does not implement the MultiAlgorithmSigner interface") + } + // The signer supports the public key algorithm which is then returned. + _, algo, err := pickSignatureAlgorithm(signer, c.extensions) + if err != nil { + t.Fatalf("got %v, want no error", err) + } + if algo != signer.PublicKey().Type() { + t.Fatalf("got algo %q, want %q", algo, signer.PublicKey().Type()) + } + // Test a signer that uses a certificate algorithm as the public key + // type. + cert := &Certificate{ + CertType: UserCert, + Key: signer.PublicKey(), + } + cert.SignCert(rand.Reader, signer) + + certSigner, err := NewCertSigner(cert, signer) + if err != nil { + t.Fatalf("error generating cert signer: %v", err) + } + // The signer supports the public key algorithm and the + // public key format is a certificate type so the certificate + // algorithm matching the key format must be returned + _, algo, err = pickSignatureAlgorithm(certSigner, c.extensions) + if err != nil { + t.Fatalf("got %v, want no error", err) + } + if algo != certSigner.PublicKey().Type() { + t.Fatalf("got algo %q, want %q", algo, certSigner.PublicKey().Type()) + } + signer, err = NewSignerWithAlgorithms(signer.(AlgorithmSigner), []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256}) + if err != nil { + t.Fatalf("unable to create signer with algorithms: %v", err) + } + // The signer does not support the public key algorithm so an error + // is returned. + _, _, err = pickSignatureAlgorithm(signer, c.extensions) + if err == nil { + t.Fatal("got no error, no common public key signature algorithm error expected") + } + }) + } +} + +// configurablePublicKeyCallback is a public key callback that allows to +// configure the signature algorithm and format. This way we can emulate the +// behavior of buggy clients. +type configurablePublicKeyCallback struct { + signer AlgorithmSigner + signatureAlgo string + signatureFormat string +} + +func (cb configurablePublicKeyCallback) method() string { + return "publickey" +} + +func (cb configurablePublicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { + pub := cb.signer.PublicKey() + + ok, err := validateKey(pub, cb.signatureAlgo, user, c) + if err != nil { + return authFailure, nil, err + } + if !ok { + return authFailure, nil, fmt.Errorf("invalid public key") + } + + pubKey := pub.Marshal() + data := buildDataSignedForAuth(session, userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + }, cb.signatureAlgo, pubKey) + sign, err := cb.signer.SignWithAlgorithm(rand, data, underlyingAlgo(cb.signatureFormat)) + if err != nil { + return authFailure, nil, err + } + + s := Marshal(sign) + sig := make([]byte, stringLength(len(s))) + marshalString(sig, s) + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + HasSig: true, + Algoname: cb.signatureAlgo, + PubKey: pubKey, + Sig: sig, + } + p := Marshal(&msg) + if err := c.writePacket(p); err != nil { + return authFailure, nil, err + } + var success authResult + success, methods, err := handleAuthResponse(c) + if err != nil { + return authFailure, nil, err + } + if success == authSuccess || !slices.Contains(methods, cb.method()) { + return success, methods, err + } + + return authFailure, methods, nil +} + +func TestPublicKeyAndAlgoCompatibility(t *testing.T) { + cert := &Certificate{ + Key: testPublicKeys["rsa"], + ValidBefore: CertTimeInfinity, + CertType: UserCert, + } + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + certSigner, err := NewCertSigner(cert, testSigners["rsa"]) + if err != nil { + t.Fatalf("NewCertSigner: %v", err) + } + + clientConfig := &ClientConfig{ + User: "user", + HostKeyCallback: InsecureIgnoreHostKey(), + Auth: []AuthMethod{ + configurablePublicKeyCallback{ + signer: certSigner.(AlgorithmSigner), + signatureAlgo: KeyAlgoRSASHA256, + signatureFormat: KeyAlgoRSASHA256, + }, + }, + } + if err := tryAuth(t, clientConfig); err == nil { + t.Error("cert login passed with incompatible public key type and algorithm") + } +} + +func TestClientAuthGPGAgentCompat(t *testing.T) { + clientConfig := &ClientConfig{ + User: "testuser", + HostKeyCallback: InsecureIgnoreHostKey(), + Auth: []AuthMethod{ + // algorithm rsa-sha2-512 and signature format ssh-rsa. + configurablePublicKeyCallback{ + signer: testSigners["rsa"].(AlgorithmSigner), + signatureAlgo: KeyAlgoRSASHA512, + signatureFormat: KeyAlgoRSA, + }, + }, + } + if err := tryAuth(t, clientConfig); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +func TestCertAuthOpenSSHCompat(t *testing.T) { + cert := &Certificate{ + Key: testPublicKeys["rsa"], + ValidBefore: CertTimeInfinity, + CertType: UserCert, + } + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + certSigner, err := NewCertSigner(cert, testSigners["rsa"]) + if err != nil { + t.Fatalf("NewCertSigner: %v", err) + } + + clientConfig := &ClientConfig{ + User: "user", + HostKeyCallback: InsecureIgnoreHostKey(), + Auth: []AuthMethod{ + // algorithm ssh-rsa-cert-v01@openssh.com and signature format + // rsa-sha2-256. + configurablePublicKeyCallback{ + signer: certSigner.(AlgorithmSigner), + signatureAlgo: CertAlgoRSAv01, + signatureFormat: KeyAlgoRSASHA256, + }, + }, + } + if err := tryAuth(t, clientConfig); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +func TestKeyboardInteractiveAuthEarlyFail(t *testing.T) { + const maxAuthTries = 2 + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + // Start testserver + serverConfig := &ServerConfig{ + MaxAuthTries: maxAuthTries, + KeyboardInteractiveCallback: func(c ConnMetadata, + client KeyboardInteractiveChallenge) (*Permissions, error) { + // Fail keyboard-interactive authentication early before + // any prompt is sent to client. + return nil, errors.New("keyboard-interactive auth failed") + }, + PasswordCallback: func(c ConnMetadata, + pass []byte) (*Permissions, error) { + if string(pass) == clientPassword { + return nil, nil + } + return nil, errors.New("password auth failed") + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + serverDone := make(chan struct{}) + go func() { + defer func() { serverDone <- struct{}{} }() + conn, chans, reqs, err := NewServerConn(c2, serverConfig) + if err != nil { + return + } + _ = conn.Close() + + discarderDone := make(chan struct{}) + go func() { + defer func() { discarderDone <- struct{}{} }() + DiscardRequests(reqs) + }() + for newChannel := range chans { + newChannel.Reject(Prohibited, + "testserver not accepting requests") + } + + <-discarderDone + }() + + // Connect to testserver, expect KeyboardInteractive() to be not called, + // PasswordCallback() to be called and connection to succeed. + passwordCallbackCalled := false + clientConfig := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + RetryableAuthMethod(KeyboardInteractive(func(name, + instruction string, questions []string, + echos []bool) ([]string, error) { + t.Errorf("unexpected call to KeyboardInteractive()") + return []string{clientPassword}, nil + }), maxAuthTries), + RetryableAuthMethod(PasswordCallback(func() (secret string, + err error) { + t.Logf("PasswordCallback()") + passwordCallbackCalled = true + return clientPassword, nil + }), maxAuthTries), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + conn, _, _, err := NewClientConn(c1, "", clientConfig) + if err != nil { + t.Errorf("unexpected NewClientConn() error: %v", err) + } + if conn != nil { + conn.Close() + } + + // Wait for server to finish. + <-serverDone + + if !passwordCallbackCalled { + t.Errorf("expected PasswordCallback() to be called") + } +} diff --git a/ssh/client_test.go b/ssh/client_test.go index 81f9599e1d..d583900bf5 100644 --- a/ssh/client_test.go +++ b/ssh/client_test.go @@ -5,6 +5,11 @@ package ssh import ( + "bytes" + "crypto/rand" + "errors" + "fmt" + "net" "strings" "testing" ) @@ -116,6 +121,45 @@ func TestHostKeyCheck(t *testing.T) { } } +func TestVerifyHostKeySignature(t *testing.T) { + for _, tt := range []struct { + key string + signAlgo string + verifyAlgo string + wantError string + }{ + {"rsa", KeyAlgoRSA, KeyAlgoRSA, ""}, + {"rsa", KeyAlgoRSASHA256, KeyAlgoRSASHA256, ""}, + {"rsa", KeyAlgoRSA, KeyAlgoRSASHA512, `ssh: invalid signature algorithm "ssh-rsa", expected "rsa-sha2-512"`}, + {"ed25519", KeyAlgoED25519, KeyAlgoED25519, ""}, + } { + key := testSigners[tt.key].PublicKey() + s, ok := testSigners[tt.key].(AlgorithmSigner) + if !ok { + t.Fatalf("needed an AlgorithmSigner") + } + sig, err := s.SignWithAlgorithm(rand.Reader, []byte("test"), tt.signAlgo) + if err != nil { + t.Fatalf("couldn't sign: %q", err) + } + + b := bytes.Buffer{} + writeString(&b, []byte(sig.Format)) + writeString(&b, sig.Blob) + + result := kexResult{Signature: b.Bytes(), H: []byte("test")} + + err = verifyHostKeySignature(key, tt.verifyAlgo, &result) + if err != nil { + if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { + t.Errorf("got error %q, expecting %q", err.Error(), tt.wantError) + } + } else if tt.wantError != "" { + t.Errorf("succeeded, but want error string %q", tt.wantError) + } + } +} + func TestBannerCallback(t *testing.T) { c1, c2, err := netPipe() if err != nil { @@ -164,3 +208,160 @@ func TestBannerCallback(t *testing.T) { t.Fatalf("got %s; want %s", receivedBanner, expected) } } + +func TestNewClientConn(t *testing.T) { + errHostKeyMismatch := errors.New("host key mismatch") + + for _, tt := range []struct { + name string + user string + simulateHostKeyMismatch HostKeyCallback + }{ + { + name: "good user field for ConnMetadata", + user: "testuser", + }, + { + name: "empty user field for ConnMetadata", + user: "", + }, + { + name: "host key mismatch", + user: "testuser", + simulateHostKeyMismatch: func(hostname string, remote net.Addr, key PublicKey) error { + return fmt.Errorf("%w: %s", errHostKeyMismatch, bytes.TrimSpace(MarshalAuthorizedKey(key))) + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + go NewServerConn(c1, serverConf) + + clientConf := &ClientConfig{ + User: tt.user, + Auth: []AuthMethod{ + Password("testpw"), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + if tt.simulateHostKeyMismatch != nil { + clientConf.HostKeyCallback = tt.simulateHostKeyMismatch + } + + clientConn, _, _, err := NewClientConn(c2, "", clientConf) + if err != nil { + if tt.simulateHostKeyMismatch != nil && errors.Is(err, errHostKeyMismatch) { + return + } + t.Fatal(err) + } + + if userGot := clientConn.User(); userGot != tt.user { + t.Errorf("got user %q; want user %q", userGot, tt.user) + } + }) + } +} + +func TestUnsupportedAlgorithm(t *testing.T) { + for _, tt := range []struct { + name string + config Config + wantError string + }{ + { + "unsupported KEX", + Config{ + KeyExchanges: []string{"unsupported"}, + }, + "no common algorithm", + }, + { + "unsupported and supported KEXs", + Config{ + KeyExchanges: []string{"unsupported", KeyExchangeCurve25519}, + }, + "", + }, + { + "unsupported cipher", + Config{ + Ciphers: []string{"unsupported"}, + }, + "no common algorithm", + }, + { + "unsupported and supported ciphers", + Config{ + Ciphers: []string{"unsupported", CipherChaCha20Poly1305}, + }, + "", + }, + { + "unsupported MAC", + Config{ + MACs: []string{"unsupported"}, + // MAC is used for non AAED ciphers. + Ciphers: []string{CipherAES256CTR}, + }, + "no common algorithm", + }, + { + "unsupported and supported MACs", + Config{ + MACs: []string{"unsupported", HMACSHA256ETM}, + // MAC is used for non AAED ciphers. + Ciphers: []string{CipherAES256CTR}, + }, + "", + }, + } { + t.Run(tt.name, func(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + Config: tt.config, + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + go NewServerConn(c1, serverConf) + + clientConf := &ClientConfig{ + User: "testuser", + Config: tt.config, + Auth: []AuthMethod{ + Password("testpw"), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + _, _, _, err = NewClientConn(c2, "", clientConf) + if err != nil { + if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { + t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) + } + } else if tt.wantError != "" { + t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) + } + }) + } +} diff --git a/ssh/common.go b/ssh/common.go index 290382d059..2e44e9c9ec 100644 --- a/ssh/common.go +++ b/ssh/common.go @@ -6,10 +6,12 @@ package ssh import ( "crypto" + "crypto/fips140" "crypto/rand" "fmt" "io" "math" + "slices" "sync" _ "crypto/sha1" @@ -24,82 +26,354 @@ const ( serviceSSH = "ssh-connection" ) -// supportedCiphers lists ciphers we support but might not recommend. -var supportedCiphers = []string{ - "aes128-ctr", "aes192-ctr", "aes256-ctr", - "aes128-gcm@openssh.com", - chacha20Poly1305ID, - "arcfour256", "arcfour128", "arcfour", - aes128cbcID, - tripledescbcID, +// The ciphers currently or previously implemented by this library, to use in +// [Config.Ciphers]. For a list, see the [Algorithms.Ciphers] returned by +// [SupportedAlgorithms] or [InsecureAlgorithms]. +const ( + CipherAES128GCM = "aes128-gcm@openssh.com" + CipherAES256GCM = "aes256-gcm@openssh.com" + CipherChaCha20Poly1305 = "chacha20-poly1305@openssh.com" + CipherAES128CTR = "aes128-ctr" + CipherAES192CTR = "aes192-ctr" + CipherAES256CTR = "aes256-ctr" + InsecureCipherAES128CBC = "aes128-cbc" + InsecureCipherTripleDESCBC = "3des-cbc" + InsecureCipherRC4 = "arcfour" + InsecureCipherRC4128 = "arcfour128" + InsecureCipherRC4256 = "arcfour256" +) + +// The key exchanges currently or previously implemented by this library, to use +// in [Config.KeyExchanges]. For a list, see the +// [Algorithms.KeyExchanges] returned by [SupportedAlgorithms] or +// [InsecureAlgorithms]. +const ( + InsecureKeyExchangeDH1SHA1 = "diffie-hellman-group1-sha1" + InsecureKeyExchangeDH14SHA1 = "diffie-hellman-group14-sha1" + KeyExchangeDH14SHA256 = "diffie-hellman-group14-sha256" + KeyExchangeDH16SHA512 = "diffie-hellman-group16-sha512" + KeyExchangeECDHP256 = "ecdh-sha2-nistp256" + KeyExchangeECDHP384 = "ecdh-sha2-nistp384" + KeyExchangeECDHP521 = "ecdh-sha2-nistp521" + KeyExchangeCurve25519 = "curve25519-sha256" + InsecureKeyExchangeDHGEXSHA1 = "diffie-hellman-group-exchange-sha1" + KeyExchangeDHGEXSHA256 = "diffie-hellman-group-exchange-sha256" + // KeyExchangeMLKEM768X25519 is supported from Go 1.24. + KeyExchangeMLKEM768X25519 = "mlkem768x25519-sha256" + + // An alias for KeyExchangeCurve25519SHA256. This kex ID will be added if + // KeyExchangeCurve25519SHA256 is requested for backward compatibility with + // OpenSSH versions up to 7.2. + keyExchangeCurve25519LibSSH = "curve25519-sha256@libssh.org" +) + +// The message authentication code (MAC) currently or previously implemented by +// this library, to use in [Config.MACs]. For a list, see the +// [Algorithms.MACs] returned by [SupportedAlgorithms] or +// [InsecureAlgorithms]. +const ( + HMACSHA256ETM = "hmac-sha2-256-etm@openssh.com" + HMACSHA512ETM = "hmac-sha2-512-etm@openssh.com" + HMACSHA256 = "hmac-sha2-256" + HMACSHA512 = "hmac-sha2-512" + HMACSHA1 = "hmac-sha1" + InsecureHMACSHA196 = "hmac-sha1-96" +) + +var ( + // supportedKexAlgos specifies key-exchange algorithms implemented by this + // package in preference order, excluding those with security issues. + supportedKexAlgos = []string{ + KeyExchangeMLKEM768X25519, + KeyExchangeCurve25519, + KeyExchangeECDHP256, + KeyExchangeECDHP384, + KeyExchangeECDHP521, + KeyExchangeDH14SHA256, + KeyExchangeDH16SHA512, + KeyExchangeDHGEXSHA256, + } + // defaultKexAlgos specifies the default preference for key-exchange + // algorithms in preference order. + defaultKexAlgos = []string{ + KeyExchangeMLKEM768X25519, + KeyExchangeCurve25519, + KeyExchangeECDHP256, + KeyExchangeECDHP384, + KeyExchangeECDHP521, + KeyExchangeDH14SHA256, + InsecureKeyExchangeDH14SHA1, + } + // insecureKexAlgos specifies key-exchange algorithms implemented by this + // package and which have security issues. + insecureKexAlgos = []string{ + InsecureKeyExchangeDH14SHA1, + InsecureKeyExchangeDH1SHA1, + InsecureKeyExchangeDHGEXSHA1, + } + // supportedCiphers specifies cipher algorithms implemented by this package + // in preference order, excluding those with security issues. + supportedCiphers = []string{ + CipherAES128GCM, + CipherAES256GCM, + CipherChaCha20Poly1305, + CipherAES128CTR, + CipherAES192CTR, + CipherAES256CTR, + } + // defaultCiphers specifies the default preference for ciphers algorithms + // in preference order. + defaultCiphers = supportedCiphers + // insecureCiphers specifies cipher algorithms implemented by this + // package and which have security issues. + insecureCiphers = []string{ + InsecureCipherAES128CBC, + InsecureCipherTripleDESCBC, + InsecureCipherRC4256, + InsecureCipherRC4128, + InsecureCipherRC4, + } + // supportedMACs specifies MAC algorithms implemented by this package in + // preference order, excluding those with security issues. + supportedMACs = []string{ + HMACSHA256ETM, + HMACSHA512ETM, + HMACSHA256, + HMACSHA512, + HMACSHA1, + } + // defaultMACs specifies the default preference for MAC algorithms in + // preference order. + defaultMACs = []string{ + HMACSHA256ETM, + HMACSHA512ETM, + HMACSHA256, + HMACSHA512, + HMACSHA1, + InsecureHMACSHA196, + } + // insecureMACs specifies MAC algorithms implemented by this + // package and which have security issues. + insecureMACs = []string{ + InsecureHMACSHA196, + } + // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. + // methods of authenticating servers) implemented by this package in + // preference order, excluding those with security issues. + supportedHostKeyAlgos = []string{ + CertAlgoRSASHA256v01, + CertAlgoRSASHA512v01, + CertAlgoECDSA256v01, + CertAlgoECDSA384v01, + CertAlgoECDSA521v01, + CertAlgoED25519v01, + KeyAlgoRSASHA256, + KeyAlgoRSASHA512, + KeyAlgoECDSA256, + KeyAlgoECDSA384, + KeyAlgoECDSA521, + KeyAlgoED25519, + } + // defaultHostKeyAlgos specifies the default preference for host-key + // algorithms in preference order. + defaultHostKeyAlgos = []string{ + CertAlgoRSASHA256v01, + CertAlgoRSASHA512v01, + CertAlgoRSAv01, + InsecureCertAlgoDSAv01, + CertAlgoECDSA256v01, + CertAlgoECDSA384v01, + CertAlgoECDSA521v01, + CertAlgoED25519v01, + KeyAlgoECDSA256, + KeyAlgoECDSA384, + KeyAlgoECDSA521, + KeyAlgoRSASHA256, + KeyAlgoRSASHA512, + KeyAlgoRSA, + InsecureKeyAlgoDSA, + KeyAlgoED25519, + } + // insecureHostKeyAlgos specifies host-key algorithms implemented by this + // package and which have security issues. + insecureHostKeyAlgos = []string{ + KeyAlgoRSA, + InsecureKeyAlgoDSA, + CertAlgoRSAv01, + InsecureCertAlgoDSAv01, + } + // supportedPubKeyAuthAlgos specifies the supported client public key + // authentication algorithms. Note that this doesn't include certificate + // types since those use the underlying algorithm. Order is irrelevant. + supportedPubKeyAuthAlgos = []string{ + KeyAlgoED25519, + KeyAlgoSKED25519, + KeyAlgoSKECDSA256, + KeyAlgoECDSA256, + KeyAlgoECDSA384, + KeyAlgoECDSA521, + KeyAlgoRSASHA256, + KeyAlgoRSASHA512, + } + + // defaultPubKeyAuthAlgos specifies the preferred client public key + // authentication algorithms. This list is sent to the client if it supports + // the server-sig-algs extension. Order is irrelevant. + defaultPubKeyAuthAlgos = []string{ + KeyAlgoED25519, + KeyAlgoSKED25519, + KeyAlgoSKECDSA256, + KeyAlgoECDSA256, + KeyAlgoECDSA384, + KeyAlgoECDSA521, + KeyAlgoRSASHA256, + KeyAlgoRSASHA512, + KeyAlgoRSA, + InsecureKeyAlgoDSA, + } + // insecurePubKeyAuthAlgos specifies client public key authentication + // algorithms implemented by this package and which have security issues. + insecurePubKeyAuthAlgos = []string{ + KeyAlgoRSA, + InsecureKeyAlgoDSA, + } +) + +// NegotiatedAlgorithms defines algorithms negotiated between client and server. +type NegotiatedAlgorithms struct { + KeyExchange string + HostKey string + Read DirectionAlgorithms + Write DirectionAlgorithms } -// preferredCiphers specifies the default preference for ciphers. -var preferredCiphers = []string{ - "aes128-gcm@openssh.com", - chacha20Poly1305ID, - "aes128-ctr", "aes192-ctr", "aes256-ctr", +// Algorithms defines a set of algorithms that can be configured in the client +// or server config for negotiation during a handshake. +type Algorithms struct { + KeyExchanges []string + Ciphers []string + MACs []string + HostKeys []string + PublicKeyAuths []string } -// supportedKexAlgos specifies the supported key-exchange algorithms in -// preference order. -var supportedKexAlgos = []string{ - kexAlgoCurve25519SHA256, - // P384 and P521 are not constant-time yet, but since we don't - // reuse ephemeral keys, using them for ECDH should be OK. - kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, - kexAlgoDH14SHA1, kexAlgoDH1SHA1, +func init() { + if fips140.Enabled() { + defaultHostKeyAlgos = slices.DeleteFunc(defaultHostKeyAlgos, func(algo string) bool { + _, err := hashFunc(underlyingAlgo(algo)) + return err != nil + }) + defaultPubKeyAuthAlgos = slices.DeleteFunc(defaultPubKeyAuthAlgos, func(algo string) bool { + _, err := hashFunc(underlyingAlgo(algo)) + return err != nil + }) + } } -// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden -// for the server half. -var serverForbiddenKexAlgos = map[string]struct{}{ - kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests - kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests +func hashFunc(format string) (crypto.Hash, error) { + switch format { + case KeyAlgoRSASHA256, KeyAlgoECDSA256, KeyAlgoSKED25519, KeyAlgoSKECDSA256: + return crypto.SHA256, nil + case KeyAlgoECDSA384: + return crypto.SHA384, nil + case KeyAlgoRSASHA512, KeyAlgoECDSA521: + return crypto.SHA512, nil + case KeyAlgoED25519: + // KeyAlgoED25519 doesn't pre-hash. + return 0, nil + case KeyAlgoRSA, InsecureKeyAlgoDSA: + if fips140.Enabled() { + return 0, fmt.Errorf("ssh: hash algorithm for format %q not allowed in FIPS 140 mode", format) + } + return crypto.SHA1, nil + default: + return 0, fmt.Errorf("ssh: hash algorithm for format %q not mapped", format) + } } -// preferredKexAlgos specifies the default preference for key-exchange algorithms -// in preference order. -var preferredKexAlgos = []string{ - kexAlgoCurve25519SHA256, - kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, - kexAlgoDH14SHA1, +// SupportedAlgorithms returns algorithms currently implemented by this package, +// excluding those with security issues, which are returned by +// InsecureAlgorithms. The algorithms listed here are in preference order. +func SupportedAlgorithms() Algorithms { + return Algorithms{ + Ciphers: slices.Clone(supportedCiphers), + MACs: slices.Clone(supportedMACs), + KeyExchanges: slices.Clone(supportedKexAlgos), + HostKeys: slices.Clone(supportedHostKeyAlgos), + PublicKeyAuths: slices.Clone(supportedPubKeyAuthAlgos), + } } -// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods -// of authenticating servers) in preference order. -var supportedHostKeyAlgos = []string{ - CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, - CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, +// InsecureAlgorithms returns algorithms currently implemented by this package +// and which have security issues. +func InsecureAlgorithms() Algorithms { + return Algorithms{ + KeyExchanges: slices.Clone(insecureKexAlgos), + Ciphers: slices.Clone(insecureCiphers), + MACs: slices.Clone(insecureMACs), + HostKeys: slices.Clone(insecureHostKeyAlgos), + PublicKeyAuths: slices.Clone(insecurePubKeyAuthAlgos), + } +} - KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, - KeyAlgoRSA, KeyAlgoDSA, +var supportedCompressions = []string{compressionNone} - KeyAlgoED25519, +// algorithmsForKeyFormat returns the supported signature algorithms for a given +// public key format (PublicKey.Type), in order of preference. See RFC 8332, +// Section 2. See also the note in sendKexInit on backwards compatibility. +func algorithmsForKeyFormat(keyFormat string) []string { + switch keyFormat { + case KeyAlgoRSA: + return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA} + case CertAlgoRSAv01: + return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01} + default: + return []string{keyFormat} + } } -// supportedMACs specifies a default set of MAC algorithms in preference order. -// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed -// because they have reached the end of their useful life. -var supportedMACs = []string{ - "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", +// keyFormatForAlgorithm returns the key format corresponding to the given +// signature algorithm. It returns an empty string if the signature algorithm is +// invalid or unsupported. +func keyFormatForAlgorithm(sigAlgo string) string { + switch sigAlgo { + case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512: + return KeyAlgoRSA + case CertAlgoRSAv01, CertAlgoRSASHA256v01, CertAlgoRSASHA512v01: + return CertAlgoRSAv01 + case KeyAlgoED25519, + KeyAlgoSKED25519, + KeyAlgoSKECDSA256, + KeyAlgoECDSA256, + KeyAlgoECDSA384, + KeyAlgoECDSA521, + InsecureKeyAlgoDSA, + InsecureCertAlgoDSAv01, + CertAlgoECDSA256v01, + CertAlgoECDSA384v01, + CertAlgoECDSA521v01, + CertAlgoSKECDSA256v01, + CertAlgoED25519v01, + CertAlgoSKED25519v01: + return sigAlgo + default: + return "" + } } -var supportedCompressions = []string{compressionNone} +// isRSA returns whether algo is a supported RSA algorithm, including certificate +// algorithms. +func isRSA(algo string) bool { + algos := algorithmsForKeyFormat(KeyAlgoRSA) + return slices.Contains(algos, underlyingAlgo(algo)) +} -// hashFuncs keeps the mapping of supported algorithms to their respective -// hashes needed for signature verification. -var hashFuncs = map[string]crypto.Hash{ - KeyAlgoRSA: crypto.SHA1, - KeyAlgoDSA: crypto.SHA1, - KeyAlgoECDSA256: crypto.SHA256, - KeyAlgoECDSA384: crypto.SHA384, - KeyAlgoECDSA521: crypto.SHA512, - CertAlgoRSAv01: crypto.SHA1, - CertAlgoDSAv01: crypto.SHA1, - CertAlgoECDSA256v01: crypto.SHA256, - CertAlgoECDSA384v01: crypto.SHA384, - CertAlgoECDSA521v01: crypto.SHA512, +func isRSACert(algo string) bool { + _, ok := certKeyAlgoNames[algo] + if !ok { + return false + } + return isRSA(algo) } // unexpectedMessageError results when the SSH message that we received didn't @@ -113,7 +387,7 @@ func parseError(tag uint8) error { return fmt.Errorf("ssh: parse error in message type %d", tag) } -func findCommon(what string, client []string, server []string) (common string, err error) { +func findCommon(what string, client []string, server []string, isClient bool) (string, error) { for _, c := range client { for _, s := range server { if c == s { @@ -121,82 +395,111 @@ func findCommon(what string, client []string, server []string) (common string, e } } } - return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) + err := &AlgorithmNegotiationError{ + What: what, + } + if isClient { + err.SupportedAlgorithms = client + err.RequestedAlgorithms = server + } else { + err.SupportedAlgorithms = server + err.RequestedAlgorithms = client + } + return "", err +} + +// AlgorithmNegotiationError defines the error returned if the client and the +// server cannot agree on an algorithm for key exchange, host key, cipher, MAC. +type AlgorithmNegotiationError struct { + What string + // RequestedAlgorithms lists the algorithms supported by the peer. + RequestedAlgorithms []string + // SupportedAlgorithms lists the algorithms supported on our side. + SupportedAlgorithms []string +} + +func (a *AlgorithmNegotiationError) Error() string { + return fmt.Sprintf("ssh: no common algorithm for %s; we offered: %v, peer offered: %v", + a.What, a.SupportedAlgorithms, a.RequestedAlgorithms) } -// directionAlgorithms records algorithm choices in one direction (either read or write) -type directionAlgorithms struct { +// DirectionAlgorithms defines the algorithms negotiated in one direction +// (either read or write). +type DirectionAlgorithms struct { Cipher string MAC string - Compression string + compression string } // rekeyBytes returns a rekeying intervals in bytes. -func (a *directionAlgorithms) rekeyBytes() int64 { - // According to RFC4344 block ciphers should rekey after +func (a *DirectionAlgorithms) rekeyBytes() int64 { + // According to RFC 4344 block ciphers should rekey after // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is // 128. switch a.Cipher { - case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID: + case CipherAES128CTR, CipherAES192CTR, CipherAES256CTR, CipherAES128GCM, CipherAES256GCM, InsecureCipherAES128CBC: return 16 * (1 << 32) } - // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data. + // For others, stick with RFC 4253 recommendation to rekey after 1 Gb of data. return 1 << 30 } -type algorithms struct { - kex string - hostKey string - w directionAlgorithms - r directionAlgorithms +var aeadCiphers = map[string]bool{ + CipherAES128GCM: true, + CipherAES256GCM: true, + CipherChaCha20Poly1305: true, } -func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { - result := &algorithms{} +func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *NegotiatedAlgorithms, err error) { + result := &NegotiatedAlgorithms{} - result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) + result.KeyExchange, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos, isClient) if err != nil { return } - result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) + result.HostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos, isClient) if err != nil { return } - stoc, ctos := &result.w, &result.r + stoc, ctos := &result.Write, &result.Read if isClient { ctos, stoc = stoc, ctos } - ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) + ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer, isClient) if err != nil { return } - stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) + stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient, isClient) if err != nil { return } - ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) - if err != nil { - return + if !aeadCiphers[ctos.Cipher] { + ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer, isClient) + if err != nil { + return + } } - stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) - if err != nil { - return + if !aeadCiphers[stoc.Cipher] { + stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient, isClient) + if err != nil { + return + } } - ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) + ctos.compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer, isClient) if err != nil { return } - stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) + stoc.compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient, isClient) if err != nil { return } @@ -221,16 +524,16 @@ type Config struct { // unspecified, a size suitable for the chosen cipher is used. RekeyThreshold uint64 - // The allowed key exchanges algorithms. If unspecified then a - // default set of algorithms is used. + // The allowed key exchanges algorithms. If unspecified then a default set + // of algorithms is used. Unsupported values are silently ignored. KeyExchanges []string - // The allowed cipher algorithms. If unspecified then a sensible - // default is used. + // The allowed cipher algorithms. If unspecified then a sensible default is + // used. Unsupported values are silently ignored. Ciphers []string - // The allowed MAC algorithms. If unspecified then a sensible default - // is used. + // The allowed MAC algorithms. If unspecified then a sensible default is + // used. Unsupported values are silently ignored. MACs []string } @@ -242,24 +545,43 @@ func (c *Config) SetDefaults() { c.Rand = rand.Reader } if c.Ciphers == nil { - c.Ciphers = preferredCiphers + c.Ciphers = defaultCiphers } var ciphers []string for _, c := range c.Ciphers { if cipherModes[c] != nil { - // reject the cipher if we have no cipherModes definition + // Ignore the cipher if we have no cipherModes definition. ciphers = append(ciphers, c) } } c.Ciphers = ciphers if c.KeyExchanges == nil { - c.KeyExchanges = preferredKexAlgos + c.KeyExchanges = defaultKexAlgos } + var kexs []string + for _, k := range c.KeyExchanges { + if kexAlgoMap[k] != nil { + // Ignore the KEX if we have no kexAlgoMap definition. + kexs = append(kexs, k) + if k == KeyExchangeCurve25519 && !slices.Contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) { + kexs = append(kexs, keyExchangeCurve25519LibSSH) + } + } + } + c.KeyExchanges = kexs if c.MACs == nil { - c.MACs = supportedMACs + c.MACs = defaultMACs + } + var macs []string + for _, m := range c.MACs { + if macModes[m] != nil { + // Ignore the MAC if we have no macModes definition. + macs = append(macs, m) + } } + c.MACs = macs if c.RekeyThreshold == 0 { // cipher specific default @@ -272,8 +594,9 @@ func (c *Config) SetDefaults() { } // buildDataSignedForAuth returns the data that is signed in order to prove -// possession of a private key. See RFC 4252, section 7. -func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { +// possession of a private key. See RFC 4252, section 7. algo is the advertised +// algorithm, and may be a certificate type. +func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte { data := struct { Session []byte Type byte @@ -281,7 +604,7 @@ func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubK Service string Method string Sign bool - Algo []byte + Algo string PubKey []byte }{ sessionID, diff --git a/ssh/common_test.go b/ssh/common_test.go index 96744dcf0f..80aa2df73b 100644 --- a/ssh/common_test.go +++ b/ssh/common_test.go @@ -5,7 +5,9 @@ package ssh import ( + "maps" "reflect" + "slices" "testing" ) @@ -51,42 +53,42 @@ func TestFindAgreedAlgorithms(t *testing.T) { } } - initDirAlgs := func(a *directionAlgorithms) { + initDirAlgs := func(a *DirectionAlgorithms) { if a.Cipher == "" { a.Cipher = "cipher1" } if a.MAC == "" { a.MAC = "mac1" } - if a.Compression == "" { - a.Compression = "compression1" + if a.compression == "" { + a.compression = "compression1" } } - initAlgs := func(a *algorithms) { - if a.kex == "" { - a.kex = "kex1" + initAlgs := func(a *NegotiatedAlgorithms) { + if a.KeyExchange == "" { + a.KeyExchange = "kex1" } - if a.hostKey == "" { - a.hostKey = "hostkey1" + if a.HostKey == "" { + a.HostKey = "hostkey1" } - initDirAlgs(&a.r) - initDirAlgs(&a.w) + initDirAlgs(&a.Read) + initDirAlgs(&a.Write) } type testcase struct { name string clientIn, serverIn kexInitMsg - wantClient, wantServer algorithms + wantClient, wantServer NegotiatedAlgorithms wantErr bool } cases := []testcase{ - testcase{ + { name: "standard", }, - testcase{ + { name: "no common hostkey", serverIn: kexInitMsg{ ServerHostKeyAlgos: []string{"hostkey2"}, @@ -94,7 +96,7 @@ func TestFindAgreedAlgorithms(t *testing.T) { wantErr: true, }, - testcase{ + { name: "no common kex", serverIn: kexInitMsg{ KexAlgos: []string{"kex2"}, @@ -102,7 +104,7 @@ func TestFindAgreedAlgorithms(t *testing.T) { wantErr: true, }, - testcase{ + { name: "no common cipher", serverIn: kexInitMsg{ CiphersClientServer: []string{"cipher2"}, @@ -110,7 +112,7 @@ func TestFindAgreedAlgorithms(t *testing.T) { wantErr: true, }, - testcase{ + { name: "client decides cipher", serverIn: kexInitMsg{ CiphersClientServer: []string{"cipher1", "cipher2"}, @@ -120,19 +122,19 @@ func TestFindAgreedAlgorithms(t *testing.T) { CiphersClientServer: []string{"cipher2", "cipher1"}, CiphersServerClient: []string{"cipher3", "cipher2"}, }, - wantClient: algorithms{ - r: directionAlgorithms{ + wantClient: NegotiatedAlgorithms{ + Read: DirectionAlgorithms{ Cipher: "cipher3", }, - w: directionAlgorithms{ + Write: DirectionAlgorithms{ Cipher: "cipher2", }, }, - wantServer: algorithms{ - w: directionAlgorithms{ + wantServer: NegotiatedAlgorithms{ + Write: DirectionAlgorithms{ Cipher: "cipher3", }, - r: directionAlgorithms{ + Read: DirectionAlgorithms{ Cipher: "cipher2", }, }, @@ -174,3 +176,21 @@ func TestFindAgreedAlgorithms(t *testing.T) { }) } } + +func TestKeyFormatAlgorithms(t *testing.T) { + supportedAlgos := SupportedAlgorithms() + insecureAlgos := InsecureAlgorithms() + algoritms := append(supportedAlgos.PublicKeyAuths, insecureAlgos.PublicKeyAuths...) + algoritms = append(algoritms, slices.Collect(maps.Keys(certKeyAlgoNames))...) + + for _, algo := range algoritms { + keyFormat := keyFormatForAlgorithm(algo) + if keyFormat == "" { + t.Errorf("got empty key format for algorithm %q", algo) + } + if !slices.Contains(algorithmsForKeyFormat(keyFormat), algo) { + t.Errorf("algorithms for key format %q, does not contain %q", keyFormat, algo) + } + + } +} diff --git a/ssh/connection.go b/ssh/connection.go index fd6b0681b5..613a71a7b3 100644 --- a/ssh/connection.go +++ b/ssh/connection.go @@ -52,7 +52,7 @@ type Conn interface { // SendRequest sends a global request, and returns the // reply. If wantReply is true, it returns the response status - // and payload. See also RFC4254, section 4. + // and payload. See also RFC 4254, section 4. SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) // OpenChannel tries to open an channel. If the request is @@ -74,6 +74,13 @@ type Conn interface { // Disconnect } +// AlgorithmsConnMetadata is a ConnMetadata that can return the algorithms +// negotiated between client and server. +type AlgorithmsConnMetadata interface { + ConnMetadata + Algorithms() NegotiatedAlgorithms +} + // DiscardRequests consumes and rejects all requests from the // passed-in channel. func DiscardRequests(in <-chan *Request) { @@ -97,7 +104,7 @@ func (c *connection) Close() error { return c.sshConn.conn.Close() } -// sshconn provides net.Conn metadata, but disallows direct reads and +// sshConn provides net.Conn metadata, but disallows direct reads and // writes. type sshConn struct { conn net.Conn @@ -106,6 +113,7 @@ type sshConn struct { sessionID []byte clientVersion []byte serverVersion []byte + algorithms NegotiatedAlgorithms } func dup(src []byte) []byte { @@ -141,3 +149,7 @@ func (c *sshConn) ClientVersion() []byte { func (c *sshConn) ServerVersion() []byte { return dup(c.serverVersion) } + +func (c *sshConn) Algorithms() NegotiatedAlgorithms { + return c.algorithms +} diff --git a/ssh/doc.go b/ssh/doc.go index 67b7322c05..5b4de9effc 100644 --- a/ssh/doc.go +++ b/ssh/doc.go @@ -12,10 +12,23 @@ the multiplexed nature of SSH is exposed to users that wish to support others. References: - [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD - [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 + + [PROTOCOL]: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD + [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD + [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 + [SSH-CERTS]: https://datatracker.ietf.org/doc/html/draft-miller-ssh-cert-01 + [FIPS 140-3 mode]: https://go.dev/doc/security/fips140 This package does not fall under the stability promise of the Go language itself, so its API may be changed when pressing needs arise. + +# FIPS 140-3 mode + +When the program is in [FIPS 140-3 mode], this package behaves as if only SP +800-140C and SP 800-140D approved cipher suites, signature algorithms, +certificate public key types and sizes, and key exchange and derivation +algorithms were implemented. Others are silently ignored and not negotiated, or +rejected. This set may depend on the algorithms supported by the FIPS 140-3 Go +Cryptographic Module selected with GOFIPS140, and may change across Go versions. */ -package ssh // import "golang.org/x/crypto/ssh" +package ssh diff --git a/ssh/example_test.go b/ssh/example_test.go index 4fe26b0bb6..653f2c8f50 100644 --- a/ssh/example_test.go +++ b/ssh/example_test.go @@ -7,14 +7,16 @@ package ssh_test import ( "bufio" "bytes" + "crypto/rand" + "crypto/rsa" "fmt" - "io/ioutil" "log" "net" "net/http" "os" "path/filepath" "strings" + "sync" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/terminal" @@ -24,7 +26,7 @@ func ExampleNewServerConn() { // Public key authentication is done by comparing // the public key of a received connection // with the entries in the authorized_keys file. - authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys") + authorizedKeysBytes, err := os.ReadFile("authorized_keys") if err != nil { log.Fatalf("Failed to load authorized_keys, err: %v", err) } @@ -67,7 +69,7 @@ func ExampleNewServerConn() { }, } - privateBytes, err := ioutil.ReadFile("id_rsa") + privateBytes, err := os.ReadFile("id_rsa") if err != nil { log.Fatal("Failed to load private key: ", err) } @@ -76,7 +78,6 @@ func ExampleNewServerConn() { if err != nil { log.Fatal("Failed to parse private key: ", err) } - config.AddHostKey(private) // Once a ServerConfig has been configured, connections can be @@ -98,8 +99,15 @@ func ExampleNewServerConn() { } log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"]) + var wg sync.WaitGroup + defer wg.Wait() + // The incoming Request channel must be serviced. - go ssh.DiscardRequests(reqs) + wg.Add(1) + go func() { + ssh.DiscardRequests(reqs) + wg.Done() + }() // Service the incoming Channel channel. for newChannel := range chans { @@ -119,16 +127,22 @@ func ExampleNewServerConn() { // Sessions have out-of-band requests such as "shell", // "pty-req" and "env". Here we handle only the // "shell" request. + wg.Add(1) go func(in <-chan *ssh.Request) { for req := range in { req.Reply(req.Type == "shell", nil) } + wg.Done() }(requests) term := terminal.NewTerminal(channel, "> ") + wg.Add(1) go func() { - defer channel.Close() + defer func() { + channel.Close() + wg.Done() + }() for { line, err := term.ReadLine() if err != nil { @@ -140,6 +154,105 @@ func ExampleNewServerConn() { } } +func ExampleServerConfig() { + // Minimal ServerConfig with SHA-1 algorithms disabled and supporting only + // public key authentication. + + // The algorithms returned by ssh.SupportedAlgorithms() are different from + // the default ones and do not include algorithms that are considered + // insecure, such as those using SHA-1, returned by + // ssh.InsecureAlgorithms(). + algorithms := ssh.SupportedAlgorithms() + + // Public key authentication is done by comparing + // the public key of a received connection + // with the entries in the authorized_keys file. + authorizedKeysBytes, err := os.ReadFile("authorized_keys") + if err != nil { + log.Fatalf("Failed to load authorized_keys, err: %v", err) + } + + authorizedKeysMap := map[string]bool{} + for len(authorizedKeysBytes) > 0 { + pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes) + if err != nil { + log.Fatal(err) + } + + authorizedKeysMap[string(pubKey.Marshal())] = true + authorizedKeysBytes = rest + } + + config := &ssh.ServerConfig{ + Config: ssh.Config{ + KeyExchanges: algorithms.KeyExchanges, + Ciphers: algorithms.Ciphers, + MACs: algorithms.MACs, + }, + // The configured PublicKeyAuthAlgorithms do not contain SHA-1 based + // signature formats, so if the client attempts to use them the + // authentication will fail before calling the defined callback. + PublicKeyAuthAlgorithms: algorithms.PublicKeyAuths, + PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { + if authorizedKeysMap[string(pubKey.Marshal())] { + return &ssh.Permissions{ + // Record the public key used for authentication. + Extensions: map[string]string{ + "pubkey-fp": ssh.FingerprintSHA256(pubKey), + }, + }, nil + } + return nil, fmt.Errorf("unknown public key for %q", c.User()) + }, + } + + privateBytes, err := os.ReadFile("id_rsa") + if err != nil { + log.Fatal("Failed to load private key: ", err) + } + + private, err := ssh.ParsePrivateKey(privateBytes) + if err != nil { + log.Fatal("Failed to parse private key: ", err) + } + // Restrict host key algorithms to disable ssh-rsa. + signer, err := ssh.NewSignerWithAlgorithms(private.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512}) + if err != nil { + log.Fatal("Failed to create private key with restricted algorithms: ", err) + } + config.AddHostKey(signer) +} + +func ExampleServerConfig_AddHostKey() { + // Minimal ServerConfig supporting only password authentication. + config := &ssh.ServerConfig{ + PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { + // Should use constant-time compare (or better, salt+hash) in + // a production setting. + if c.User() == "testuser" && string(pass) == "tiger" { + return nil, nil + } + return nil, fmt.Errorf("password rejected for %q", c.User()) + }, + } + + privateBytes, err := os.ReadFile("id_rsa") + if err != nil { + log.Fatal("Failed to load private key: ", err) + } + + private, err := ssh.ParsePrivateKey(privateBytes) + if err != nil { + log.Fatal("Failed to parse private key: ", err) + } + // Restrict host key algorithms to disable ssh-rsa. + signer, err := ssh.NewSignerWithAlgorithms(private.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512}) + if err != nil { + log.Fatal("Failed to create private key with restricted algorithms: ", err) + } + config.AddHostKey(signer) +} + func ExampleClientConfig_HostKeyCallback() { // Every client must provide a host key check. Here is a // simple-minded parse of OpenSSH's known_hosts file @@ -198,6 +311,7 @@ func ExampleDial() { if err != nil { log.Fatal("Failed to dial: ", err) } + defer client.Close() // Each ClientConn can support multiple interactive sessions, // represented by a Session. @@ -217,6 +331,47 @@ func ExampleDial() { fmt.Println(b.String()) } +func ExampleClientConfig() { + var hostKey ssh.PublicKey + key, err := os.ReadFile("/home/user/.ssh/id_rsa") + if err != nil { + log.Fatalf("unable to read private key: %v", err) + } + + // Create the Signer for this private key. + signer, err := ssh.ParsePrivateKey(key) + if err != nil { + log.Fatalf("unable to parse private key: %v", err) + } + + // Minimal ClientConfig with SHA-1 algorithms disabled. + // The algorithms returned by ssh.SupportedAlgorithms() are different from + // the default ones and do not include algorithms that are considered + // insecure, such as those using SHA-1, returned by + // ssh.InsecureAlgorithms(). + algorithms := ssh.SupportedAlgorithms() + config := &ssh.ClientConfig{ + Config: ssh.Config{ + KeyExchanges: algorithms.KeyExchanges, + Ciphers: algorithms.Ciphers, + MACs: algorithms.MACs, + }, + User: "username", + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), + }, + HostKeyCallback: ssh.FixedHostKey(hostKey), + // We should check that hostKey algorithm is included in + // algorithms.HostKeys. + HostKeyAlgorithms: algorithms.HostKeys, + } + client, err := ssh.Dial("tcp", "yourserver.com:22", config) + if err != nil { + log.Fatal("Failed to dial: ", err) + } + defer client.Close() +} + func ExamplePublicKeys() { var hostKey ssh.PublicKey // A public key may be used to authenticate against the remote @@ -224,7 +379,7 @@ func ExamplePublicKeys() { // // If you have an encrypted private key, the crypto/x509 package // can be used to decrypt it. - key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa") + key, err := os.ReadFile("/home/user/.ssh/id_rsa") if err != nil { log.Fatalf("unable to read private key: %v", err) } @@ -318,3 +473,38 @@ func ExampleSession_RequestPty() { log.Fatal("failed to start shell: ", err) } } + +func ExampleCertificate_SignCert() { + // Sign a certificate with a specific algorithm. + privateKey, err := rsa.GenerateKey(rand.Reader, 3072) + if err != nil { + log.Fatal("unable to generate RSA key: ", err) + } + publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + log.Fatal("unable to get RSA public key: ", err) + } + caKey, err := rsa.GenerateKey(rand.Reader, 3072) + if err != nil { + log.Fatal("unable to generate CA key: ", err) + } + signer, err := ssh.NewSignerFromKey(caKey) + if err != nil { + log.Fatal("unable to generate signer from key: ", err) + } + mas, err := ssh.NewSignerWithAlgorithms(signer.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256}) + if err != nil { + log.Fatal("unable to create signer with algorithms: ", err) + } + certificate := ssh.Certificate{ + Key: publicKey, + CertType: ssh.UserCert, + } + if err := certificate.SignCert(rand.Reader, mas); err != nil { + log.Fatal("unable to sign certificate: ", err) + } + // Save the public key to a file and check that rsa-sha-256 is used for + // signing: + // ssh-keygen -L -f + fmt.Println(string(ssh.MarshalAuthorizedKey(&certificate))) +} diff --git a/ssh/handshake.go b/ssh/handshake.go index 2b10b05a49..4be3cbb6de 100644 --- a/ssh/handshake.go +++ b/ssh/handshake.go @@ -5,12 +5,13 @@ package ssh import ( - "crypto/rand" "errors" "fmt" "io" "log" "net" + "slices" + "strings" "sync" ) @@ -24,6 +25,11 @@ const debugHandshake = false // quickly. const chanSize = 16 +// maxPendingPackets sets the maximum number of packets to queue while waiting +// for KEX to complete. This limits the total pending data to maxPendingPackets +// * maxPacket bytes, which is ~16.8MB. +const maxPendingPackets = 64 + // keyingTransport is a packet based transport that supports key // changes. It need not be thread-safe. It should pass through // msgNewKeys in both directions. @@ -33,7 +39,17 @@ type keyingTransport interface { // prepareKeyChange sets up a key change. The key change for a // direction will be effected if a msgNewKeys message is sent // or received. - prepareKeyChange(*algorithms, *kexResult) error + prepareKeyChange(*NegotiatedAlgorithms, *kexResult) error + + // setStrictMode sets the strict KEX mode, notably triggering + // sequence number resets on sending or receiving msgNewKeys. + // If the sequence number is already > 1 when setStrictMode + // is called, an error is returned. + setStrictMode() error + + // setInitialKEXDone indicates to the transport that the initial key exchange + // was completed + setInitialKEXDone() } // handshakeTransport implements rekeying on top of a keyingTransport @@ -50,6 +66,10 @@ type handshakeTransport struct { // connection. hostKeys []Signer + // publicKeyAuthAlgorithms is non-empty if we are the server. In that case, + // it contains the supported client public key authentication algorithms. + publicKeyAuthAlgorithms []string + // hostKeyAlgorithms is non-empty if we are the client. In that case, // we accept these key types from the server as host key. hostKeyAlgorithms []string @@ -58,11 +78,22 @@ type handshakeTransport struct { incoming chan []byte readError error - mu sync.Mutex + mu sync.Mutex + // Condition for the above mutex. It is used to notify a completed key + // exchange or a write failure. Writes can wait for this condition while a + // key exchange is in progress. + writeCond *sync.Cond writeError error sentInitPacket []byte sentInitMsg *kexInitMsg - pendingPackets [][]byte // Used when a key exchange is in progress. + // Used to queue writes when a key exchange is in progress. The length is + // limited by pendingPacketsSize. Once full, writes will block until the key + // exchange is completed or an error occurs. If not empty, it is emptied + // all at once when the key exchange is completed in kexLoop. + pendingPackets [][]byte + writePacketsLeft uint32 + writeBytesLeft int64 + userAuthComplete bool // whether the user authentication phase is complete // If the read loop wants to schedule a kex, it pings this // channel, and the write loop will send out a kex @@ -71,7 +102,8 @@ type handshakeTransport struct { // If the other side requests or confirms a kex, its kexInit // packet is sent here for the write loop to find it. - startKex chan *pendingKex + startKex chan *pendingKex + kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits // data for host key checking hostKeyCallback HostKeyCallback @@ -84,16 +116,18 @@ type handshakeTransport struct { bannerCallback BannerCallback // Algorithms agreed in the last key exchange. - algorithms *algorithms + algorithms *NegotiatedAlgorithms + // Counters exclusively owned by readLoop. readPacketsLeft uint32 readBytesLeft int64 - writePacketsLeft uint32 - writeBytesLeft int64 - // The session ID or nil if first kex did not complete yet. sessionID []byte + + // strictMode indicates if the other side of the handshake indicated + // that we should be following the strict KEX protocol restrictions. + strictMode bool } type pendingKex struct { @@ -108,10 +142,12 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, clientVersion: clientVersion, incoming: make(chan []byte, chanSize), requestKex: make(chan struct{}, 1), - startKex: make(chan *pendingKex, 1), + startKex: make(chan *pendingKex), + kexLoopDone: make(chan struct{}), config: config, } + t.writeCond = sync.NewCond(&t.mu) t.resetReadThresholds() t.resetWriteThresholds() @@ -129,7 +165,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt if config.HostKeyAlgorithms != nil { t.hostKeyAlgorithms = config.HostKeyAlgorithms } else { - t.hostKeyAlgorithms = supportedHostKeyAlgos + t.hostKeyAlgorithms = defaultHostKeyAlgos } go t.readLoop() go t.kexLoop() @@ -139,6 +175,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) t.hostKeys = config.hostKeys + t.publicKeyAuthAlgorithms = config.PublicKeyAuthAlgorithms go t.readLoop() go t.kexLoop() return t @@ -148,6 +185,10 @@ func (t *handshakeTransport) getSessionID() []byte { return t.sessionID } +func (t *handshakeTransport) getAlgorithms() NegotiatedAlgorithms { + return *t.algorithms +} + // waitSession waits for the session to be established. This should be // the first thing to call after instantiating handshakeTransport. func (t *handshakeTransport) waitSession() error { @@ -201,7 +242,10 @@ func (t *handshakeTransport) readLoop() { close(t.incoming) break } - if p[0] == msgIgnore || p[0] == msgDebug { + // If this is the first kex, and strict KEX mode is enabled, + // we don't ignore any messages, as they may be used to manipulate + // the packet sequence numbers. + if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) { continue } t.incoming <- p @@ -234,6 +278,7 @@ func (t *handshakeTransport) recordWriteError(err error) { defer t.mu.Unlock() if t.writeError == nil && err != nil { t.writeError = err + t.writeCond.Broadcast() } } @@ -250,7 +295,7 @@ func (t *handshakeTransport) resetWriteThresholds() { if t.config.RekeyThreshold > 0 { t.writeBytesLeft = int64(t.config.RekeyThreshold) } else if t.algorithms != nil { - t.writeBytesLeft = t.algorithms.w.rekeyBytes() + t.writeBytesLeft = t.algorithms.Write.rekeyBytes() } else { t.writeBytesLeft = 1 << 30 } @@ -337,19 +382,22 @@ write: } } t.pendingPackets = t.pendingPackets[:0] + // Unblock writePacket if waiting for KEX. + t.writeCond.Broadcast() t.mu.Unlock() } + // Unblock reader. + t.conn.Close() + // drain startKex channel. We don't service t.requestKex // because nobody does blocking sends there. - go func() { - for init := range t.startKex { - init.done <- t.writeError - } - }() + for request := range t.startKex { + request.done <- t.getWriteError() + } - // Unblock reader. - t.conn.Close() + // Mark that the loop is done so that Close can return. + close(t.kexLoopDone) } // The protocol uses uint32 for packet counters, so we can't let them @@ -364,7 +412,7 @@ func (t *handshakeTransport) resetReadThresholds() { if t.config.RekeyThreshold > 0 { t.readBytesLeft = int64(t.config.RekeyThreshold) } else if t.algorithms != nil { - t.readBytesLeft = t.algorithms.r.rekeyBytes() + t.readBytesLeft = t.algorithms.Read.rekeyBytes() } else { t.readBytesLeft = 1 << 30 } @@ -432,6 +480,11 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) { return successPacket, nil } +const ( + kexStrictClient = "kex-strict-c-v00@openssh.com" + kexStrictServer = "kex-strict-s-v00@openssh.com" +) + // sendKexInit sends a key change message. func (t *handshakeTransport) sendKexInit() error { t.mu.Lock() @@ -445,7 +498,6 @@ func (t *handshakeTransport) sendKexInit() error { } msg := &kexInitMsg{ - KexAlgos: t.config.KeyExchanges, CiphersClientServer: t.config.Ciphers, CiphersServerClient: t.config.Ciphers, MACsClientServer: t.config.MACs, @@ -453,16 +505,59 @@ func (t *handshakeTransport) sendKexInit() error { CompressionClientServer: supportedCompressions, CompressionServerClient: supportedCompressions, } - io.ReadFull(rand.Reader, msg.Cookie[:]) + io.ReadFull(t.config.Rand, msg.Cookie[:]) - if len(t.hostKeys) > 0 { + // We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm, + // and possibly to add the ext-info extension algorithm. Since the slice may be the + // user owned KeyExchanges, we create our own slice in order to avoid using user + // owned memory by mistake. + msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info + msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) + + isServer := len(t.hostKeys) > 0 + if isServer { for _, k := range t.hostKeys { - msg.ServerHostKeyAlgos = append( - msg.ServerHostKeyAlgos, k.PublicKey().Type()) + // If k is a MultiAlgorithmSigner, we restrict the signature + // algorithms. If k is a AlgorithmSigner, presume it supports all + // signature algorithms associated with the key format. If k is not + // an AlgorithmSigner, we can only assume it only supports the + // algorithms that matches the key format. (This means that Sign + // can't pick a different default). + keyFormat := k.PublicKey().Type() + + switch s := k.(type) { + case MultiAlgorithmSigner: + for _, algo := range algorithmsForKeyFormat(keyFormat) { + if slices.Contains(s.Algorithms(), underlyingAlgo(algo)) { + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo) + } + } + case AlgorithmSigner: + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...) + default: + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat) + } + } + + if t.sessionID == nil { + msg.KexAlgos = append(msg.KexAlgos, kexStrictServer) } } else { msg.ServerHostKeyAlgos = t.hostKeyAlgorithms + + // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what + // algorithms the server supports for public key authentication. See RFC + // 8308, Section 2.1. + // + // We also send the strict KEX mode extension algorithm, in order to opt + // into the strict KEX mode. + if firstKeyExchange := t.sessionID == nil; firstKeyExchange { + msg.KexAlgos = append(msg.KexAlgos, "ext-info-c") + msg.KexAlgos = append(msg.KexAlgos, kexStrictClient) + } + } + packet := Marshal(msg) // writePacket destroys the contents, so save a copy. @@ -479,26 +574,44 @@ func (t *handshakeTransport) sendKexInit() error { return nil } +var errSendBannerPhase = errors.New("ssh: SendAuthBanner outside of authentication phase") + func (t *handshakeTransport) writePacket(p []byte) error { + t.mu.Lock() + defer t.mu.Unlock() + switch p[0] { case msgKexInit: return errors.New("ssh: only handshakeTransport can send kexInit") case msgNewKeys: return errors.New("ssh: only handshakeTransport can send newKeys") + case msgUserAuthBanner: + if t.userAuthComplete { + return errSendBannerPhase + } + case msgUserAuthSuccess: + t.userAuthComplete = true } - t.mu.Lock() - defer t.mu.Unlock() if t.writeError != nil { return t.writeError } if t.sentInitMsg != nil { - // Copy the packet so the writer can reuse the buffer. - cp := make([]byte, len(p)) - copy(cp, p) - t.pendingPackets = append(t.pendingPackets, cp) - return nil + if len(t.pendingPackets) < maxPendingPackets { + // Copy the packet so the writer can reuse the buffer. + cp := make([]byte, len(p)) + copy(cp, p) + t.pendingPackets = append(t.pendingPackets, cp) + return nil + } + for t.sentInitMsg != nil { + // Block and wait for KEX to complete or an error. + t.writeCond.Wait() + if t.writeError != nil { + return t.writeError + } + } } if t.writeBytesLeft > 0 { @@ -515,13 +628,23 @@ func (t *handshakeTransport) writePacket(p []byte) error { if err := t.pushPacket(p); err != nil { t.writeError = err + t.writeCond.Broadcast() } return nil } func (t *handshakeTransport) Close() error { - return t.conn.Close() + // Close the connection. This should cause the readLoop goroutine to wake up + // and close t.startKex, which will shut down kexLoop if running. + err := t.conn.Close() + + // Wait for the kexLoop goroutine to complete. + // At that point we know that the readLoop goroutine is complete too, + // because kexLoop itself waits for readLoop to close the startKex channel. + <-t.kexLoopDone + + return err } func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { @@ -557,6 +680,13 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { return err } + if t.sessionID == nil && ((isClient && slices.Contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && slices.Contains(clientInit.KexAlgos, kexStrictClient))) { + t.strictMode = true + if err := t.conn.setStrictMode(); err != nil { + return err + } + } + // We don't send FirstKexFollows, but we handle receiving it. // // RFC 4253 section 7 defines the kex and the agreement method for @@ -575,23 +705,24 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { } } - kex, ok := kexAlgoMap[t.algorithms.kex] + kex, ok := kexAlgoMap[t.algorithms.KeyExchange] if !ok { - return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex) + return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.KeyExchange) } var result *kexResult if len(t.hostKeys) > 0 { - result, err = t.server(kex, t.algorithms, &magics) + result, err = t.server(kex, &magics) } else { - result, err = t.client(kex, t.algorithms, &magics) + result, err = t.client(kex, &magics) } if err != nil { return err } - if t.sessionID == nil { + firstKeyExchange := t.sessionID == nil + if firstKeyExchange { t.sessionID = result.H } result.SessionID = t.sessionID @@ -602,28 +733,97 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { return err } + + // On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO + // message with the server-sig-algs extension if the client supports it. See + // RFC 8308, Sections 2.4 and 3.1, and [PROTOCOL], Section 1.9. + if !isClient && firstKeyExchange && slices.Contains(clientInit.KexAlgos, "ext-info-c") { + supportedPubKeyAuthAlgosList := strings.Join(t.publicKeyAuthAlgorithms, ",") + extInfo := &extInfoMsg{ + NumExtensions: 2, + Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)+4+16+4+1), + } + extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs")) + extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...) + extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList)) + extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...) + extInfo.Payload = appendInt(extInfo.Payload, len("ping@openssh.com")) + extInfo.Payload = append(extInfo.Payload, "ping@openssh.com"...) + extInfo.Payload = appendInt(extInfo.Payload, 1) + extInfo.Payload = append(extInfo.Payload, "0"...) + if err := t.conn.writePacket(Marshal(extInfo)); err != nil { + return err + } + } + if packet, err := t.conn.readPacket(); err != nil { return err } else if packet[0] != msgNewKeys { return unexpectedMessageError(msgNewKeys, packet[0]) } + if firstKeyExchange { + // Indicates to the transport that the first key exchange is completed + // after receiving SSH_MSG_NEWKEYS. + t.conn.setInitialKEXDone() + } + return nil } -func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { - var hostKey Signer - for _, k := range t.hostKeys { - if algs.hostKey == k.PublicKey().Type() { - hostKey = k +// algorithmSignerWrapper is an AlgorithmSigner that only supports the default +// key format algorithm. +// +// This is technically a violation of the AlgorithmSigner interface, but it +// should be unreachable given where we use this. Anyway, at least it returns an +// error instead of panicing or producing an incorrect signature. +type algorithmSignerWrapper struct { + Signer +} + +func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + if algorithm != underlyingAlgo(a.PublicKey().Type()) { + return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm") + } + return a.Sign(rand, data) +} + +func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner { + for _, k := range hostKeys { + if s, ok := k.(MultiAlgorithmSigner); ok { + if !slices.Contains(s.Algorithms(), underlyingAlgo(algo)) { + continue + } + } + + if algo == k.PublicKey().Type() { + return algorithmSignerWrapper{k} } + + k, ok := k.(AlgorithmSigner) + if !ok { + continue + } + for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) { + if algo == a { + return k + } + } + } + return nil +} + +func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { + hostKey := pickHostKey(t.hostKeys, t.algorithms.HostKey) + if hostKey == nil { + return nil, errors.New("ssh: internal error: negotiated unsupported signature type") } - r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey) + r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.HostKey) return r, err } -func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { +func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { result, err := kex.Client(t.conn, t.config.Rand, magics) if err != nil { return nil, err @@ -634,7 +834,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics * return nil, err } - if err := verifyHostKeySignature(hostKey, result); err != nil { + if err := verifyHostKeySignature(hostKey, t.algorithms.HostKey, result); err != nil { return nil, err } diff --git a/ssh/handshake_test.go b/ssh/handshake_test.go index 02fbe83821..56f230cae9 100644 --- a/ssh/handshake_test.go +++ b/ssh/handshake_test.go @@ -148,6 +148,7 @@ func TestHandshakeBasic(t *testing.T) { clientDone := make(chan int, 0) gotHalf := make(chan int, 0) const N = 20 + errorCh := make(chan error, 1) go func() { defer close(clientDone) @@ -158,7 +159,9 @@ func TestHandshakeBasic(t *testing.T) { for i := 0; i < N; i++ { p := []byte{msgRequestSuccess, byte(i)} if err := trC.writePacket(p); err != nil { - t.Fatalf("sendPacket: %v", err) + errorCh <- err + trC.Close() + return } if (i % 10) == 5 { <-gotHalf @@ -177,16 +180,15 @@ func TestHandshakeBasic(t *testing.T) { checker.waitCall <- 1 } } + errorCh <- nil }() // Server checks that client messages come in cleanly i := 0 - err = nil for ; i < N; i++ { - var p []byte - p, err = trS.readPacket() - if err != nil { - break + p, err := trS.readPacket() + if err != nil && err != io.EOF { + t.Fatalf("server error: %v", err) } if (i % 10) == 5 { gotHalf <- 1 @@ -198,8 +200,8 @@ func TestHandshakeBasic(t *testing.T) { } } <-clientDone - if err != nil && err != io.EOF { - t.Fatalf("server error: %v", err) + if err := <-errorCh; err != nil { + t.Fatalf("sendPacket: %v", err) } if i != N { t.Errorf("received %d messages, want 10.", i) @@ -345,16 +347,16 @@ func TestHandshakeAutoRekeyRead(t *testing.T) { // While we read out the packet, a key change will be // initiated. - done := make(chan int, 1) + errorCh := make(chan error, 1) go func() { - defer close(done) - if _, err := trC.readPacket(); err != nil { - t.Fatalf("readPacket(client): %v", err) - } - + _, err := trC.readPacket() + errorCh <- err }() - <-done + if err := <-errorCh; err != nil { + t.Fatalf("readPacket(client): %v", err) + } + <-sync.called } @@ -365,7 +367,7 @@ type errorKeyingTransport struct { readLeft, writeLeft int } -func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { +func (n *errorKeyingTransport) prepareKeyChange(*NegotiatedAlgorithms, *kexResult) error { return nil } @@ -393,6 +395,10 @@ func (n *errorKeyingTransport) readPacket() ([]byte, error) { return n.packetConn.readPacket() } +func (n *errorKeyingTransport) setStrictMode() error { return nil } + +func (n *errorKeyingTransport) setInitialKEXDone() {} + func TestHandshakeErrorHandlingRead(t *testing.T) { for i := 0; i < 20; i++ { testHandshakeErrorHandlingN(t, i, -1, false) @@ -421,8 +427,8 @@ func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) { // handshakeTransport deadlocks, the go runtime will detect it and // panic. func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) { - if runtime.GOOS == "js" && runtime.GOARCH == "wasm" { - t.Skip("skipping on js/wasm; see golang.org/issue/32840") + if (runtime.GOOS == "js" || runtime.GOOS == "wasip1") && runtime.GOARCH == "wasm" { + t.Skipf("skipping on %s/wasm; see golang.org/issue/32840", runtime.GOOS) } msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)}) @@ -533,10 +539,230 @@ func TestDisconnect(t *testing.T) { } } +type mockKeyingTransport struct { + packetConn + kexInitAllowed chan struct{} + kexInitSent chan struct{} +} + +func (n *mockKeyingTransport) prepareKeyChange(*NegotiatedAlgorithms, *kexResult) error { + return nil +} + +func (n *mockKeyingTransport) writePacket(packet []byte) error { + if packet[0] == msgKexInit { + <-n.kexInitAllowed + n.kexInitSent <- struct{}{} + } + return n.packetConn.writePacket(packet) +} + +func (n *mockKeyingTransport) readPacket() ([]byte, error) { + return n.packetConn.readPacket() +} + +func (n *mockKeyingTransport) setStrictMode() error { return nil } + +func (n *mockKeyingTransport) setInitialKEXDone() {} + +func TestHandshakePendingPacketsWait(t *testing.T) { + a, b := memPipe() + + trS := &mockKeyingTransport{ + packetConn: a, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trS.kexInitAllowed <- struct{}{} + + trC := &mockKeyingTransport{ + packetConn: b, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trC.kexInitAllowed <- struct{}{} + + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + } + clientConf.SetDefaults() + + v := []byte("version") + client := newClientTransport(trC, v, v, clientConf, "addr", nil) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + server := newServerTransport(trS, v, v, serverConf) + + if err := server.waitSession(); err != nil { + t.Fatalf("server.waitSession: %v", err) + } + if err := client.waitSession(); err != nil { + t.Fatalf("client.waitSession: %v", err) + } + + <-trC.kexInitSent + <-trS.kexInitSent + + // Allow and request new KEX server side. + trS.kexInitAllowed <- struct{}{} + server.requestKeyExchange() + // Wait until the KEX init is sent. + <-trS.kexInitSent + // The client is not allowed to respond to the KEX, so writes will be + // blocked on the server side once the packets queue is full. + for i := 0; i < maxPendingPackets; i++ { + p := []byte{msgRequestSuccess, byte(i)} + if err := server.writePacket(p); err != nil { + t.Errorf("unexpected write error: %v", err) + } + } + // The packets queue is now full, the next write will block. + server.mu.Lock() + if len(server.pendingPackets) != maxPendingPackets { + t.Errorf("unexpected pending packets size; got: %d, want: %d", len(server.pendingPackets), maxPendingPackets) + } + server.mu.Unlock() + + writeDone := make(chan struct{}) + go func() { + defer close(writeDone) + + p := []byte{msgRequestSuccess, byte(65)} + // This write will block until KEX completes. + err := server.writePacket(p) + if err != nil { + t.Errorf("unexpected write error: %v", err) + } + }() + + // Consume packets on the client side + readDone := make(chan bool) + go func() { + defer close(readDone) + + for { + if _, err := client.readPacket(); err != nil { + if err != io.EOF { + t.Errorf("unexpected read error: %v", err) + } + break + } + } + }() + + // Allow the client to reply to the KEX and so unblock the write goroutine. + trC.kexInitAllowed <- struct{}{} + <-trC.kexInitSent + <-writeDone + // Close the client to unblock the read goroutine. + client.Close() + <-readDone + server.Close() +} + +func TestHandshakePendingPacketsError(t *testing.T) { + a, b := memPipe() + + trS := &mockKeyingTransport{ + packetConn: a, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trS.kexInitAllowed <- struct{}{} + + trC := &mockKeyingTransport{ + packetConn: b, + kexInitAllowed: make(chan struct{}, 2), + kexInitSent: make(chan struct{}, 2), + } + // Allow the first KEX. + trC.kexInitAllowed <- struct{}{} + + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + } + clientConf.SetDefaults() + + v := []byte("version") + client := newClientTransport(trC, v, v, clientConf, "addr", nil) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + server := newServerTransport(trS, v, v, serverConf) + + if err := server.waitSession(); err != nil { + t.Fatalf("server.waitSession: %v", err) + } + if err := client.waitSession(); err != nil { + t.Fatalf("client.waitSession: %v", err) + } + + <-trC.kexInitSent + <-trS.kexInitSent + + // Allow and request new KEX server side. + trS.kexInitAllowed <- struct{}{} + server.requestKeyExchange() + // Wait until the KEX init is sent. + <-trS.kexInitSent + // The client is not allowed to respond to the KEX, so writes will be + // blocked on the server side once the packets queue is full. + for i := 0; i < maxPendingPackets; i++ { + p := []byte{msgRequestSuccess, byte(i)} + if err := server.writePacket(p); err != nil { + t.Errorf("unexpected write error: %v", err) + } + } + // The packets queue is now full, the next write will block. + writeDone := make(chan struct{}) + go func() { + defer close(writeDone) + + p := []byte{msgRequestSuccess, byte(65)} + // This write will block until KEX completes. + err := server.writePacket(p) + if err != io.EOF { + t.Errorf("unexpected write error: %v", err) + } + }() + + // Consume packets on the client side + readDone := make(chan bool) + go func() { + defer close(readDone) + + for { + if _, err := client.readPacket(); err != nil { + if err != io.EOF { + t.Errorf("unexpected read error: %v", err) + } + break + } + } + }() + + // Close the server to unblock the write after an error + server.Close() + <-writeDone + // Unblock the pending write and close the client to unblock the read + // goroutine. + trC.kexInitAllowed <- struct{}{} + client.Close() + <-readDone +} + func TestHandshakeRekeyDefault(t *testing.T) { clientConf := &ClientConfig{ Config: Config{ - Ciphers: []string{"aes128-ctr"}, + Ciphers: []string{CipherAES128CTR}, }, HostKeyCallback: InsecureIgnoreHostKey(), } @@ -560,3 +786,581 @@ func TestHandshakeRekeyDefault(t *testing.T) { t.Errorf("got rekey after %dG write, want 64G", wgb) } } + +func TestHandshakeAEADCipherNoMAC(t *testing.T) { + for _, cipher := range []string{CipherChaCha20Poly1305, CipherAES128GCM} { + checker := &syncChecker{ + called: make(chan int, 1), + } + clientConf := &ClientConfig{ + Config: Config{ + Ciphers: []string{cipher}, + MACs: []string{}, + }, + HostKeyCallback: checker.Check, + } + trC, trS, err := handshakePair(clientConf, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + defer trC.Close() + defer trS.Close() + + <-checker.called + } +} + +// TestNoSHA2Support tests a host key Signer that is not an AlgorithmSigner and +// therefore can't do SHA-2 signatures. Ensures the server does not advertise +// support for them in this case. +func TestNoSHA2Support(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + } + serverConf.AddHostKey(&legacyRSASigner{testSigners["rsa"]}) + go func() { + _, _, _, err := NewServerConn(c1, serverConf) + if err != nil { + t.Error(err) + } + }() + + clientConf := &ClientConfig{ + User: "test", + Auth: []AuthMethod{Password("testpw")}, + HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), + } + + if _, _, _, err := NewClientConn(c2, "", clientConf); err != nil { + t.Fatal(err) + } +} + +func TestMultiAlgoSignerHandshake(t *testing.T) { + algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner) + if !ok { + t.Fatal("rsa test signer does not implement the AlgorithmSigner interface") + } + multiAlgoSigner, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}) + if err != nil { + t.Fatalf("unable to create multi algorithm signer: %v", err) + } + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + } + serverConf.AddHostKey(multiAlgoSigner) + go NewServerConn(c1, serverConf) + + clientConf := &ClientConfig{ + User: "test", + Auth: []AuthMethod{Password("testpw")}, + HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), + HostKeyAlgorithms: []string{KeyAlgoRSASHA512}, + } + + if _, _, _, err := NewClientConn(c2, "", clientConf); err != nil { + t.Fatal(err) + } +} + +func TestMultiAlgoSignerNoCommonHostKeyAlgo(t *testing.T) { + algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner) + if !ok { + t.Fatal("rsa test signer does not implement the AlgorithmSigner interface") + } + multiAlgoSigner, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}) + if err != nil { + t.Fatalf("unable to create multi algorithm signer: %v", err) + } + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + // ssh-rsa is disabled server side + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + } + serverConf.AddHostKey(multiAlgoSigner) + go NewServerConn(c1, serverConf) + + // the client only supports ssh-rsa + clientConf := &ClientConfig{ + User: "test", + Auth: []AuthMethod{Password("testpw")}, + HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), + HostKeyAlgorithms: []string{KeyAlgoRSA}, + } + + _, _, _, err = NewClientConn(c2, "", clientConf) + if err == nil { + t.Fatal("succeeded connecting with no common hostkey algorithm") + } +} + +func TestPickIncompatibleHostKeyAlgo(t *testing.T) { + algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner) + if !ok { + t.Fatal("rsa test signer does not implement the AlgorithmSigner interface") + } + multiAlgoSigner, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}) + if err != nil { + t.Fatalf("unable to create multi algorithm signer: %v", err) + } + signer := pickHostKey([]Signer{multiAlgoSigner}, KeyAlgoRSA) + if signer != nil { + t.Fatal("incompatible signer returned") + } +} + +func TestStrictKEXResetSeqFirstKEX(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("see golang.org/issue/7237") + } + + checker := &syncChecker{ + waitCall: make(chan int, 10), + called: make(chan int, 10), + } + + checker.waitCall <- 1 + trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + <-checker.called + + t.Cleanup(func() { + trC.Close() + trS.Close() + }) + + // Throw away the msgExtInfo packet sent during the handshake by the server + _, err = trC.readPacket() + if err != nil { + t.Fatalf("readPacket failed: %s", err) + } + + // close the handshake transports before checking the sequence number to + // avoid races. + trC.Close() + trS.Close() + + // check that the sequence number counters. We reset after msgNewKeys, but + // then the server immediately writes msgExtInfo, and we close the + // transports so we expect read 2, write 0 on the client and read 1, write 1 + // on the server. + if trC.conn.(*transport).reader.seqNum != 2 || trC.conn.(*transport).writer.seqNum != 0 || + trS.conn.(*transport).reader.seqNum != 1 || trS.conn.(*transport).writer.seqNum != 1 { + t.Errorf( + "unexpected sequence counters:\nclient: reader %d (expected 2), writer %d (expected 0)\nserver: reader %d (expected 1), writer %d (expected 1)", + trC.conn.(*transport).reader.seqNum, + trC.conn.(*transport).writer.seqNum, + trS.conn.(*transport).reader.seqNum, + trS.conn.(*transport).writer.seqNum, + ) + } +} + +func TestStrictKEXResetSeqSuccessiveKEX(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("see golang.org/issue/7237") + } + + checker := &syncChecker{ + waitCall: make(chan int, 10), + called: make(chan int, 10), + } + + checker.waitCall <- 1 + trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + <-checker.called + + t.Cleanup(func() { + trC.Close() + trS.Close() + }) + + // Throw away the msgExtInfo packet sent during the handshake by the server + _, err = trC.readPacket() + if err != nil { + t.Fatalf("readPacket failed: %s", err) + } + + // write and read five packets on either side to bump the sequence numbers + for i := 0; i < 5; i++ { + if err := trC.writePacket([]byte{msgRequestSuccess}); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + if _, err := trS.readPacket(); err != nil { + t.Fatalf("readPacket failed: %s", err) + } + if err := trS.writePacket([]byte{msgRequestSuccess}); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + if _, err := trC.readPacket(); err != nil { + t.Fatalf("readPacket failed: %s", err) + } + } + + // Request a key exchange, which should cause the sequence numbers to reset + checker.waitCall <- 1 + trC.requestKeyExchange() + <-checker.called + + // write a packet on the client, and then read it, to verify the key change has actually happened, since + // the HostKeyCallback is called _during_ the handshake, so isn't actually indicative of the handshake + // finishing. + dummyPacket := []byte{99} + if err := trS.writePacket(dummyPacket); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + if p, err := trC.readPacket(); err != nil { + t.Fatalf("readPacket failed: %s", err) + } else if !bytes.Equal(p, dummyPacket) { + t.Fatalf("unexpected packet: got %x, want %x", p, dummyPacket) + } + + // close the handshake transports before checking the sequence number to + // avoid races. + trC.Close() + trS.Close() + + if trC.conn.(*transport).reader.seqNum != 2 || trC.conn.(*transport).writer.seqNum != 0 || + trS.conn.(*transport).reader.seqNum != 1 || trS.conn.(*transport).writer.seqNum != 1 { + t.Errorf( + "unexpected sequence counters:\nclient: reader %d (expected 2), writer %d (expected 0)\nserver: reader %d (expected 1), writer %d (expected 1)", + trC.conn.(*transport).reader.seqNum, + trC.conn.(*transport).writer.seqNum, + trS.conn.(*transport).reader.seqNum, + trS.conn.(*transport).writer.seqNum, + ) + } +} + +func TestSeqNumIncrease(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("see golang.org/issue/7237") + } + + checker := &syncChecker{ + waitCall: make(chan int, 10), + called: make(chan int, 10), + } + + checker.waitCall <- 1 + trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + <-checker.called + + t.Cleanup(func() { + trC.Close() + trS.Close() + }) + + // Throw away the msgExtInfo packet sent during the handshake by the server + _, err = trC.readPacket() + if err != nil { + t.Fatalf("readPacket failed: %s", err) + } + + // write and read five packets on either side to bump the sequence numbers + for i := 0; i < 5; i++ { + if err := trC.writePacket([]byte{msgRequestSuccess}); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + if _, err := trS.readPacket(); err != nil { + t.Fatalf("readPacket failed: %s", err) + } + if err := trS.writePacket([]byte{msgRequestSuccess}); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + if _, err := trC.readPacket(); err != nil { + t.Fatalf("readPacket failed: %s", err) + } + } + + // close the handshake transports before checking the sequence number to + // avoid races. + trC.Close() + trS.Close() + + if trC.conn.(*transport).reader.seqNum != 7 || trC.conn.(*transport).writer.seqNum != 5 || + trS.conn.(*transport).reader.seqNum != 6 || trS.conn.(*transport).writer.seqNum != 6 { + t.Errorf( + "unexpected sequence counters:\nclient: reader %d (expected 7), writer %d (expected 5)\nserver: reader %d (expected 6), writer %d (expected 6)", + trC.conn.(*transport).reader.seqNum, + trC.conn.(*transport).writer.seqNum, + trS.conn.(*transport).reader.seqNum, + trS.conn.(*transport).writer.seqNum, + ) + } +} + +func TestStrictKEXUnexpectedMsg(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("see golang.org/issue/7237") + } + + // Check that unexpected messages during the handshake cause failure + _, _, err := handshakePair(&ClientConfig{HostKeyCallback: func(hostname string, remote net.Addr, key PublicKey) error { return nil }}, "addr", true) + if err == nil { + t.Fatal("handshake should fail when there are unexpected messages during the handshake") + } + + trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: func(hostname string, remote net.Addr, key PublicKey) error { return nil }}, "addr", false) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + + // Check that ignore/debug pacekts are still ignored outside of the handshake + if err := trC.writePacket([]byte{msgIgnore}); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + if err := trC.writePacket([]byte{msgDebug}); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + dummyPacket := []byte{99} + if err := trC.writePacket(dummyPacket); err != nil { + t.Fatalf("writePacket failed: %s", err) + } + + if p, err := trS.readPacket(); err != nil { + t.Fatalf("readPacket failed: %s", err) + } else if !bytes.Equal(p, dummyPacket) { + t.Fatalf("unexpected packet: got %x, want %x", p, dummyPacket) + } +} + +func TestStrictKEXMixed(t *testing.T) { + // Test that we still support a mixed connection, where one side sends kex-strict but the other + // side doesn't. + + a, b, err := netPipe() + if err != nil { + t.Fatalf("netPipe failed: %s", err) + } + + var trC, trS keyingTransport + + trC = newTransport(a, rand.Reader, true) + trS = newTransport(b, rand.Reader, false) + trS = addNoiseTransport(trS) + + clientConf := &ClientConfig{HostKeyCallback: func(hostname string, remote net.Addr, key PublicKey) error { return nil }} + clientConf.SetDefaults() + + v := []byte("version") + client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr()) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + + transport := newHandshakeTransport(trS, &serverConf.Config, []byte("version"), []byte("version")) + transport.hostKeys = serverConf.hostKeys + transport.publicKeyAuthAlgorithms = serverConf.PublicKeyAuthAlgorithms + + readOneFailure := make(chan error, 1) + go func() { + if _, err := transport.readOnePacket(true); err != nil { + readOneFailure <- err + } + }() + + // Basically sendKexInit, but without the kex-strict extension algorithm + msg := &kexInitMsg{ + KexAlgos: transport.config.KeyExchanges, + CiphersClientServer: transport.config.Ciphers, + CiphersServerClient: transport.config.Ciphers, + MACsClientServer: transport.config.MACs, + MACsServerClient: transport.config.MACs, + CompressionClientServer: supportedCompressions, + CompressionServerClient: supportedCompressions, + ServerHostKeyAlgos: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA}, + } + packet := Marshal(msg) + // writePacket destroys the contents, so save a copy. + packetCopy := make([]byte, len(packet)) + copy(packetCopy, packet) + if err := transport.pushPacket(packetCopy); err != nil { + t.Fatalf("pushPacket: %s", err) + } + transport.sentInitMsg = msg + transport.sentInitPacket = packet + + if err := transport.getWriteError(); err != nil { + t.Fatalf("getWriteError failed: %s", err) + } + var request *pendingKex + select { + case err = <-readOneFailure: + t.Fatalf("server readOnePacket failed: %s", err) + case request = <-transport.startKex: + break + } + + // We expect the following calls to fail if the side which does not support + // kex-strict sends unexpected/ignored packets during the handshake, even if + // the other side does support kex-strict. + + if err := transport.enterKeyExchange(request.otherInit); err != nil { + t.Fatalf("enterKeyExchange failed: %s", err) + } + if err := client.waitSession(); err != nil { + t.Fatalf("client.waitSession: %v", err) + } +} + +func TestNegotiatedAlgorithms(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + var serverAlgorithms NegotiatedAlgorithms + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if algorithmConn, ok := conn.(AlgorithmsConnMetadata); ok { + serverAlgorithms = algorithmConn.Algorithms() + return &Permissions{}, nil + } + return nil, errors.New("server conn does not implement AlgorithmsConnMetadata") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + go NewServerConn(c1, serverConf) + + clientConf := &ClientConfig{ + User: "test", + Auth: []AuthMethod{Password("testpw")}, + HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), + } + + if conn, _, _, err := NewClientConn(c2, "", clientConf); err != nil { + t.Fatal(err) + } else { + if algorithmConn, ok := conn.(AlgorithmsConnMetadata); ok { + clientAlgorithms := algorithmConn.Algorithms() + if clientAlgorithms.HostKey == "" { + t.Fatal("negotiated client host key is empty") + } + if clientAlgorithms.KeyExchange == "" { + t.Fatal("negotiated client KEX is empty") + } + if clientAlgorithms.Read.Cipher == "" { + t.Fatal("negotiated client read cipher is empty") + } + if clientAlgorithms.Write.Cipher == "" { + t.Fatal("negotiated client write cipher is empty") + } + if !reflect.DeepEqual(clientAlgorithms, serverAlgorithms) { + t.Fatalf("negotiated client algorithms: %+v differs from negotiated server algorithms: %+v", + clientAlgorithms, serverAlgorithms) + } + } else { + t.Fatal("client conn does not implement AlgorithmsConnMetadata") + } + } +} + +func TestAlgorithmNegotiationError(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + Config: Config{ + Ciphers: []string{CipherAES128CTR, CipherAES256CTR}, + }, + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + srvErrCh := make(chan error, 1) + go func() { + _, _, _, err := NewServerConn(c1, serverConf) + srvErrCh <- err + }() + + clientConf := &ClientConfig{ + Config: Config{ + Ciphers: []string{CipherAES128GCM, CipherAES256GCM}, + }, + User: "test", + Auth: []AuthMethod{Password("testpw")}, + HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), + } + + _, _, _, err = NewClientConn(c2, "", clientConf) + if err == nil { + t.Fatal("client connection succeeded expected algorithm negotiation error") + } + var negotiationError *AlgorithmNegotiationError + if !errors.As(err, &negotiationError) { + t.Fatalf("expected algorithm negotiation error, got %v", err) + } + expectedErrorString := fmt.Sprintf("ssh: handshake failed: ssh: no common algorithm for client to server cipher; we offered: %v, peer offered: %v", + clientConf.Ciphers, serverConf.Ciphers) + if err.Error() != expectedErrorString { + t.Fatalf("expected error string %q, got %q", expectedErrorString, err.Error()) + } + if !reflect.DeepEqual(negotiationError.RequestedAlgorithms, serverConf.Ciphers) { + t.Fatalf("expected requested algorithms %v, got %v", serverConf.Ciphers, negotiationError.RequestedAlgorithms) + } + if !reflect.DeepEqual(negotiationError.SupportedAlgorithms, clientConf.Ciphers) { + t.Fatalf("expected supported algorithms %v, got %v", clientConf.Ciphers, negotiationError.SupportedAlgorithms) + } + err = <-srvErrCh + negotiationError = nil + if !errors.As(err, &negotiationError) { + t.Fatalf("expected algorithm negotiation error, got %v", err) + } + expectedErrorString = fmt.Sprintf("ssh: no common algorithm for client to server cipher; we offered: %v, peer offered: %v", + serverConf.Ciphers, clientConf.Ciphers) + if err.Error() != expectedErrorString { + t.Fatalf("expected error string %q, got %q", expectedErrorString, err.Error()) + } + if !reflect.DeepEqual(negotiationError.RequestedAlgorithms, clientConf.Ciphers) { + t.Fatalf("expected requested algorithms %v, got %v", clientConf.Ciphers, negotiationError.RequestedAlgorithms) + } + if !reflect.DeepEqual(negotiationError.SupportedAlgorithms, serverConf.Ciphers) { + t.Fatalf("expected supported algorithms %v, got %v", serverConf.Ciphers, negotiationError.SupportedAlgorithms) + } +} diff --git a/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go new file mode 100644 index 0000000000..af81d26654 --- /dev/null +++ b/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go @@ -0,0 +1,93 @@ +// Copyright 2014 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 bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD. +// +// See https://flak.tedunangst.com/post/bcrypt-pbkdf and +// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c. +package bcrypt_pbkdf + +import ( + "crypto/sha512" + "errors" + "golang.org/x/crypto/blowfish" +) + +const blockSize = 32 + +// Key derives a key from the password, salt and rounds count, returning a +// []byte of length keyLen that can be used as cryptographic key. +func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) { + if rounds < 1 { + return nil, errors.New("bcrypt_pbkdf: number of rounds is too small") + } + if len(password) == 0 { + return nil, errors.New("bcrypt_pbkdf: empty password") + } + if len(salt) == 0 || len(salt) > 1<<20 { + return nil, errors.New("bcrypt_pbkdf: bad salt length") + } + if keyLen > 1024 { + return nil, errors.New("bcrypt_pbkdf: keyLen is too large") + } + + numBlocks := (keyLen + blockSize - 1) / blockSize + key := make([]byte, numBlocks*blockSize) + + h := sha512.New() + h.Write(password) + shapass := h.Sum(nil) + + shasalt := make([]byte, 0, sha512.Size) + cnt, tmp := make([]byte, 4), make([]byte, blockSize) + for block := 1; block <= numBlocks; block++ { + h.Reset() + h.Write(salt) + cnt[0] = byte(block >> 24) + cnt[1] = byte(block >> 16) + cnt[2] = byte(block >> 8) + cnt[3] = byte(block) + h.Write(cnt) + bcryptHash(tmp, shapass, h.Sum(shasalt)) + + out := make([]byte, blockSize) + copy(out, tmp) + for i := 2; i <= rounds; i++ { + h.Reset() + h.Write(tmp) + bcryptHash(tmp, shapass, h.Sum(shasalt)) + for j := 0; j < len(out); j++ { + out[j] ^= tmp[j] + } + } + + for i, v := range out { + key[i*numBlocks+(block-1)] = v + } + } + return key[:keyLen], nil +} + +var magic = []byte("OxychromaticBlowfishSwatDynamite") + +func bcryptHash(out, shapass, shasalt []byte) { + c, err := blowfish.NewSaltedCipher(shapass, shasalt) + if err != nil { + panic(err) + } + for i := 0; i < 64; i++ { + blowfish.ExpandKey(shasalt, c) + blowfish.ExpandKey(shapass, c) + } + copy(out, magic) + for i := 0; i < 32; i += 8 { + for j := 0; j < 64; j++ { + c.Encrypt(out[i:i+8], out[i:i+8]) + } + } + // Swap bytes due to different endianness. + for i := 0; i < 32; i += 4 { + out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3] + } +} diff --git a/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go b/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go new file mode 100644 index 0000000000..20b7889bce --- /dev/null +++ b/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go @@ -0,0 +1,97 @@ +// Copyright 2014 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 bcrypt_pbkdf + +import ( + "bytes" + "testing" +) + +// Test vectors generated by the reference implementation from OpenBSD. +var golden = []struct { + rounds int + password, salt, result []byte +}{ + { + 12, + []byte("password"), + []byte("salt"), + []byte{ + 0x1a, 0xe4, 0x2c, 0x05, 0xd4, 0x87, 0xbc, 0x02, 0xf6, + 0x49, 0x21, 0xa4, 0xeb, 0xe4, 0xea, 0x93, 0xbc, 0xac, + 0xfe, 0x13, 0x5f, 0xda, 0x99, 0x97, 0x4c, 0x06, 0xb7, + 0xb0, 0x1f, 0xae, 0x14, 0x9a, + }, + }, + { + 3, + []byte("passwordy\x00PASSWORD\x00"), + []byte("salty\x00SALT\x00"), + []byte{ + 0x7f, 0x31, 0x0b, 0xd3, 0xe7, 0x8c, 0x32, 0x80, 0xc5, + 0x9c, 0xe4, 0x59, 0x52, 0x11, 0xa2, 0x92, 0x8e, 0x8d, + 0x4e, 0xc7, 0x44, 0xc1, 0xed, 0x2e, 0xfc, 0x9f, 0x76, + 0x4e, 0x33, 0x88, 0xe0, 0xad, + }, + }, + { + // See http://thread.gmane.org/gmane.os.openbsd.bugs/20542 + 8, + []byte("секретное слово"), + []byte("посолить немножко"), + []byte{ + 0x8d, 0xf4, 0x3f, 0xc6, 0xfe, 0x13, 0x1f, 0xc4, 0x7f, + 0x0c, 0x9e, 0x39, 0x22, 0x4b, 0xd9, 0x4c, 0x70, 0xb6, + 0xfc, 0xc8, 0xee, 0x81, 0x35, 0xfa, 0xdd, 0xf6, 0x11, + 0x56, 0xe6, 0xcb, 0x27, 0x33, 0xea, 0x76, 0x5f, 0x31, + 0x5a, 0x3e, 0x1e, 0x4a, 0xfc, 0x35, 0xbf, 0x86, 0x87, + 0xd1, 0x89, 0x25, 0x4c, 0x1e, 0x05, 0xa6, 0xfe, 0x80, + 0xc0, 0x61, 0x7f, 0x91, 0x83, 0xd6, 0x72, 0x60, 0xd6, + 0xa1, 0x15, 0xc6, 0xc9, 0x4e, 0x36, 0x03, 0xe2, 0x30, + 0x3f, 0xbb, 0x43, 0xa7, 0x6a, 0x64, 0x52, 0x3f, 0xfd, + 0xa6, 0x86, 0xb1, 0xd4, 0x51, 0x85, 0x43, + }, + }, +} + +func TestKey(t *testing.T) { + for i, v := range golden { + k, err := Key(v.password, v.salt, v.rounds, len(v.result)) + if err != nil { + t.Errorf("%d: %s", i, err) + continue + } + if !bytes.Equal(k, v.result) { + t.Errorf("%d: expected\n%x\n, got\n%x\n", i, v.result, k) + } + } +} + +func TestBcryptHash(t *testing.T) { + good := []byte{ + 0x87, 0x90, 0x48, 0x70, 0xee, 0xf9, 0xde, 0xdd, 0xf8, 0xe7, + 0x61, 0x1a, 0x14, 0x01, 0x06, 0xe6, 0xaa, 0xf1, 0xa3, 0x63, + 0xd9, 0xa2, 0xc5, 0x04, 0xdb, 0x35, 0x64, 0x43, 0x72, 0x1e, + 0xb5, 0x55, + } + var pass, salt [64]byte + var result [32]byte + for i := 0; i < 64; i++ { + pass[i] = byte(i) + salt[i] = byte(i + 64) + } + bcryptHash(result[:], pass[:], salt[:]) + if !bytes.Equal(result[:], good) { + t.Errorf("expected %x, got %x", good, result) + } +} + +func BenchmarkKey(b *testing.B) { + pass := []byte("password") + salt := []byte("salt") + for i := 0; i < b.N; i++ { + Key(pass, salt, 10, 32) + } +} diff --git a/ssh/kex.go b/ssh/kex.go index 16072004b1..5f7fdd8514 100644 --- a/ssh/kex.go +++ b/ssh/kex.go @@ -8,30 +8,31 @@ import ( "crypto" "crypto/ecdsa" "crypto/elliptic" + "crypto/fips140" "crypto/rand" - "crypto/subtle" "encoding/binary" "errors" "fmt" "io" "math/big" + "slices" "golang.org/x/crypto/curve25519" ) const ( - kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" - kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" - kexAlgoECDH256 = "ecdh-sha2-nistp256" - kexAlgoECDH384 = "ecdh-sha2-nistp384" - kexAlgoECDH521 = "ecdh-sha2-nistp521" - kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" - - // For the following kex only the client half contains a production - // ready implementation. The server half only consists of a minimal - // implementation to satisfy the automated tests. - kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1" - kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256" + // This is the group called diffie-hellman-group1-sha1 in RFC 4253 and + // Oakley Group 2 in RFC 2409. + oakleyGroup2 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF" + // This is the group called diffie-hellman-group14-sha1 in RFC 4253 and + // Oakley Group 14 in RFC 3526. + oakleyGroup14 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF" + // This is the group called diffie-hellman-group15-sha512 in RFC 8268 and + // Oakley Group 15 in RFC 3526. + oakleyGroup15 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" + // This is the group called diffie-hellman-group16-sha512 in RFC 8268 and + // Oakley Group 16 in RFC 3526. + oakleyGroup16 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF" ) // kexResult captures the outcome of a key exchange. @@ -75,8 +76,9 @@ func (m *handshakeMagics) write(w io.Writer) { // kexAlgorithm abstracts different key exchange algorithms. type kexAlgorithm interface { // Server runs server-side key agreement, signing the result - // with a hostkey. - Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) + // with a hostkey. algo is the negotiated algorithm, and may + // be a certificate type. + Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error) // Client runs the client-side key agreement. Caller is // responsible for verifying the host key signature. @@ -86,6 +88,7 @@ type kexAlgorithm interface { // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. type dhGroup struct { g, p, pMinus1 *big.Int + hashFunc crypto.Hash } func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { @@ -96,8 +99,6 @@ func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, } func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { - hashFunc := crypto.SHA1 - var x *big.Int for { var err error @@ -132,7 +133,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha return nil, err } - h := hashFunc.New() + h := group.hashFunc.New() magics.write(h) writeString(h, kexDHReply.HostKey) writeInt(h, X) @@ -146,12 +147,11 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha K: K, HostKey: kexDHReply.HostKey, Signature: kexDHReply.Signature, - Hash: crypto.SHA1, + Hash: group.hashFunc, }, nil } -func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { - hashFunc := crypto.SHA1 +func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { packet, err := c.readPacket() if err != nil { return @@ -179,7 +179,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha hostKeyBytes := priv.PublicKey().Marshal() - h := hashFunc.New() + h := group.hashFunc.New() magics.write(h) writeString(h, hostKeyBytes) writeInt(h, kexDHInit.X) @@ -193,7 +193,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha // H is already a hash, but the hostkey signing will apply its // own key-specific hash algorithm. - sig, err := signAndMarshal(priv, randSource, H) + sig, err := signAndMarshal(priv, randSource, H, algo) if err != nil { return nil, err } @@ -211,8 +211,8 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha K: K, HostKey: hostKeyBytes, Signature: sig, - Hash: crypto.SHA1, - }, nil + Hash: group.hashFunc, + }, err } // ecdh performs Elliptic Curve Diffie-Hellman key exchange as @@ -314,7 +314,7 @@ func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { return true } -func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { +func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { packet, err := c.readPacket() if err != nil { return nil, err @@ -359,7 +359,7 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p // H is already a hash, but the hostkey signing will apply its // own key-specific hash algorithm. - sig, err := signAndMarshal(priv, rand, H) + sig, err := signAndMarshal(priv, rand, H, algo) if err != nil { return nil, err } @@ -384,39 +384,81 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p }, nil } +// ecHash returns the hash to match the given elliptic curve, see RFC +// 5656, section 6.2.1 +func ecHash(curve elliptic.Curve) crypto.Hash { + bitSize := curve.Params().BitSize + switch { + case bitSize <= 256: + return crypto.SHA256 + case bitSize <= 384: + return crypto.SHA384 + } + return crypto.SHA512 +} + +// kexAlgoMap defines the supported KEXs. KEXs not included are not supported +// and will not be negotiated, even if explicitly configured. When FIPS mode is +// enabled, only FIPS-approved algorithms are included. var kexAlgoMap = map[string]kexAlgorithm{} func init() { - // This is the group called diffie-hellman-group1-sha1 in RFC - // 4253 and Oakley Group 2 in RFC 2409. - p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) - kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ - g: new(big.Int).SetInt64(2), - p: p, - pMinus1: new(big.Int).Sub(p, bigOne), + // mlkem768x25519-sha256 we'll work with fips140=on but not fips140=only + // until Go 1.26. + kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{} + kexAlgoMap[KeyExchangeECDHP521] = &ecdh{elliptic.P521()} + kexAlgoMap[KeyExchangeECDHP384] = &ecdh{elliptic.P384()} + kexAlgoMap[KeyExchangeECDHP256] = &ecdh{elliptic.P256()} + + if fips140.Enabled() { + defaultKexAlgos = slices.DeleteFunc(defaultKexAlgos, func(algo string) bool { + _, ok := kexAlgoMap[algo] + return !ok + }) + return } - // This is the group called diffie-hellman-group14-sha1 in RFC - // 4253 and Oakley Group 14 in RFC 3526. - p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + p, _ := new(big.Int).SetString(oakleyGroup2, 16) + kexAlgoMap[InsecureKeyExchangeDH1SHA1] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + pMinus1: new(big.Int).Sub(p, bigOne), + hashFunc: crypto.SHA1, + } - kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ + p, _ = new(big.Int).SetString(oakleyGroup14, 16) + group14 := &dhGroup{ g: new(big.Int).SetInt64(2), p: p, pMinus1: new(big.Int).Sub(p, bigOne), } - kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} - kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} - kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} - kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} - kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} - kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} + kexAlgoMap[InsecureKeyExchangeDH14SHA1] = &dhGroup{ + g: group14.g, p: group14.p, pMinus1: group14.pMinus1, + hashFunc: crypto.SHA1, + } + kexAlgoMap[KeyExchangeDH14SHA256] = &dhGroup{ + g: group14.g, p: group14.p, pMinus1: group14.pMinus1, + hashFunc: crypto.SHA256, + } + + p, _ = new(big.Int).SetString(oakleyGroup16, 16) + + kexAlgoMap[KeyExchangeDH16SHA512] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + pMinus1: new(big.Int).Sub(p, bigOne), + hashFunc: crypto.SHA512, + } + + kexAlgoMap[KeyExchangeCurve25519] = &curve25519sha256{} + kexAlgoMap[keyExchangeCurve25519LibSSH] = &curve25519sha256{} + kexAlgoMap[InsecureKeyExchangeDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} + kexAlgoMap[KeyExchangeDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} } -// curve25519sha256 implements the curve25519-sha256@libssh.org key -// agreement protocol, as described in -// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt +// curve25519sha256 implements the curve25519-sha256 (formerly known as +// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731. type curve25519sha256 struct{} type curve25519KeyPair struct { @@ -428,15 +470,17 @@ func (kp *curve25519KeyPair) generate(rand io.Reader) error { if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { return err } - curve25519.ScalarBaseMult(&kp.pub, &kp.priv) + p, err := curve25519.X25519(kp.priv[:], curve25519.Basepoint) + if err != nil { + return fmt.Errorf("curve25519: %w", err) + } + if len(p) != 32 { + return fmt.Errorf("curve25519: internal error: X25519 returned %d bytes, expected 32", len(p)) + } + copy(kp.pub[:], p) return nil } -// curve25519Zeros is just an array of 32 zero bytes so that we have something -// convenient to compare against in order to reject curve25519 points with the -// wrong order. -var curve25519Zeros [32]byte - func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { var kp curve25519KeyPair if err := kp.generate(rand); err != nil { @@ -459,11 +503,9 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh return nil, errors.New("ssh: peer's curve25519 public value has wrong length") } - var servPub, secret [32]byte - copy(servPub[:], reply.EphemeralPubKey) - curve25519.ScalarMult(&secret, &kp.priv, &servPub) - if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { - return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + secret, err := curve25519.X25519(kp.priv[:], reply.EphemeralPubKey) + if err != nil { + return nil, fmt.Errorf("ssh: peer's curve25519 public value is not valid: %w", err) } h := crypto.SHA256.New() @@ -486,7 +528,7 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh }, nil } -func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { +func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { packet, err := c.readPacket() if err != nil { return @@ -505,11 +547,9 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh return nil, err } - var clientPub, secret [32]byte - copy(clientPub[:], kexInit.ClientPubKey) - curve25519.ScalarMult(&secret, &kp.priv, &clientPub) - if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { - return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + secret, err := curve25519.X25519(kp.priv[:], kexInit.ClientPubKey) + if err != nil { + return nil, fmt.Errorf("ssh: peer's curve25519 public value is not valid: %w", err) } hostKeyBytes := priv.PublicKey().Marshal() @@ -527,7 +567,7 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh H := h.Sum(nil) - sig, err := signAndMarshal(priv, rand, H) + sig, err := signAndMarshal(priv, rand, H, algo) if err != nil { return nil, err } @@ -553,31 +593,21 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh // diffie-hellman-group-exchange-sha256 key agreement protocols, // as described in RFC 4419 type dhGEXSHA struct { - g, p *big.Int hashFunc crypto.Hash } -const numMRTests = 64 - const ( dhGroupExchangeMinimumBits = 2048 dhGroupExchangePreferredBits = 2048 dhGroupExchangeMaximumBits = 8192 ) -func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { - if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 { - return nil, fmt.Errorf("ssh: DH parameter out of bounds") - } - return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil -} - func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { // Send GexRequest kexDHGexRequest := kexDHGexRequestMsg{ - MinBits: dhGroupExchangeMinimumBits, - PreferedBits: dhGroupExchangePreferredBits, - MaxBits: dhGroupExchangeMaximumBits, + MinBits: dhGroupExchangeMinimumBits, + PreferredBits: dhGroupExchangePreferredBits, + MaxBits: dhGroupExchangeMaximumBits, } if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil { return nil, err @@ -589,40 +619,29 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak return nil, err } - var kexDHGexGroup kexDHGexGroupMsg - if err = Unmarshal(packet, &kexDHGexGroup); err != nil { + var msg kexDHGexGroupMsg + if err = Unmarshal(packet, &msg); err != nil { return nil, err } // reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits - if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits { - return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen()) + if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits { + return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen()) } - gex.p = kexDHGexGroup.P - gex.g = kexDHGexGroup.G - - // Check if p is safe by verifing that p and (p-1)/2 are primes - one := big.NewInt(1) - var pHalf = &big.Int{} - pHalf.Rsh(gex.p, 1) - if !gex.p.ProbablyPrime(numMRTests) || !pHalf.ProbablyPrime(numMRTests) { - return nil, fmt.Errorf("ssh: server provided gex p is not safe") - } - - // Check if g is safe by verifing that g > 1 and g < p - 1 - var pMinusOne = &big.Int{} - pMinusOne.Sub(gex.p, one) - if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 { + // Check if g is safe by verifying that 1 < g < p-1 + pMinusOne := new(big.Int).Sub(msg.P, bigOne) + if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 { return nil, fmt.Errorf("ssh: server provided gex g is not safe") } // Send GexInit + pHalf := new(big.Int).Rsh(msg.P, 1) x, err := rand.Int(randSource, pHalf) if err != nil { return nil, err } - X := new(big.Int).Exp(gex.g, x, gex.p) + X := new(big.Int).Exp(msg.G, x, msg.P) kexDHGexInit := kexDHGexInitMsg{ X: X, } @@ -641,13 +660,13 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak return nil, err } - kInt, err := gex.diffieHellman(kexDHGexReply.Y, x) - if err != nil { - return nil, err + if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") } + kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P) - // Check if k is safe by verifing that k > 1 and k < p - 1 - if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 { + // Check if k is safe by verifying that k > 1 and k < p - 1 + if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 { return nil, fmt.Errorf("ssh: derived k is not safe") } @@ -657,8 +676,8 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) - writeInt(h, gex.p) - writeInt(h, gex.g) + writeInt(h, msg.P) + writeInt(h, msg.G) writeInt(h, X) writeInt(h, kexDHGexReply.Y) K := make([]byte, intLength(kInt)) @@ -675,9 +694,7 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak } // Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. -// -// This is a minimal implementation to satisfy the automated tests. -func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { +func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { // Receive GexRequest packet, err := c.readPacket() if err != nil { @@ -687,36 +704,37 @@ func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshak if err = Unmarshal(packet, &kexDHGexRequest); err != nil { return } - - // smoosh the user's preferred size into our own limits - if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits { - kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits - } - if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits { - kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits - } - // fix min/max if they're inconsistent. technically, we could just pout - // and hang up, but there's no harm in giving them the benefit of the - // doubt and just picking a bitsize for them. - if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits { - kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits - } - if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits { - kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits + // We check that the request received is valid and that the MaxBits + // requested are at least equal to our supported minimum. This is the same + // check done in OpenSSH: + // https://github.com/openssh/openssh-portable/blob/80a2f64b/kexgexs.c#L94 + // + // Furthermore, we also check that the required MinBits are less than or + // equal to 4096 because we can use up to Oakley Group 16. + if kexDHGexRequest.MaxBits < kexDHGexRequest.MinBits || kexDHGexRequest.PreferredBits < kexDHGexRequest.MinBits || + kexDHGexRequest.MaxBits < kexDHGexRequest.PreferredBits || kexDHGexRequest.MaxBits < dhGroupExchangeMinimumBits || + kexDHGexRequest.MinBits > 4096 { + return nil, fmt.Errorf("ssh: DH GEX request out of range, min: %d, max: %d, preferred: %d", kexDHGexRequest.MinBits, + kexDHGexRequest.MaxBits, kexDHGexRequest.PreferredBits) } - // Send GexGroup - // This is the group called diffie-hellman-group14-sha1 in RFC - // 4253 and Oakley Group 14 in RFC 3526. - p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) - gex.p = p - gex.g = big.NewInt(2) + var p *big.Int + // We hardcode sending Oakley Group 14 (2048 bits), Oakley Group 15 (3072 + // bits) or Oakley Group 16 (4096 bits), based on the requested max size. + if kexDHGexRequest.MaxBits < 3072 { + p, _ = new(big.Int).SetString(oakleyGroup14, 16) + } else if kexDHGexRequest.MaxBits < 4096 { + p, _ = new(big.Int).SetString(oakleyGroup15, 16) + } else { + p, _ = new(big.Int).SetString(oakleyGroup16, 16) + } - kexDHGexGroup := kexDHGexGroupMsg{ - P: gex.p, - G: gex.g, + g := big.NewInt(2) + msg := &kexDHGexGroupMsg{ + P: p, + G: g, } - if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil { + if err := c.writePacket(Marshal(msg)); err != nil { return nil, err } @@ -730,30 +748,30 @@ func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshak return } - var pHalf = &big.Int{} - pHalf.Rsh(gex.p, 1) + pHalf := new(big.Int).Rsh(p, 1) y, err := rand.Int(randSource, pHalf) if err != nil { return } + Y := new(big.Int).Exp(g, y, p) - Y := new(big.Int).Exp(gex.g, y, gex.p) - kInt, err := gex.diffieHellman(kexDHGexInit.X, y) - if err != nil { - return nil, err + pMinusOne := new(big.Int).Sub(p, bigOne) + if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") } + kInt := new(big.Int).Exp(kexDHGexInit.X, y, p) hostKeyBytes := priv.PublicKey().Marshal() h := gex.hashFunc.New() magics.write(h) writeString(h, hostKeyBytes) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) - writeInt(h, gex.p) - writeInt(h, gex.g) + binary.Write(h, binary.BigEndian, kexDHGexRequest.MinBits) + binary.Write(h, binary.BigEndian, kexDHGexRequest.PreferredBits) + binary.Write(h, binary.BigEndian, kexDHGexRequest.MaxBits) + writeInt(h, p) + writeInt(h, g) writeInt(h, kexDHGexInit.X) writeInt(h, Y) @@ -765,7 +783,7 @@ func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshak // H is already a hash, but the hostkey signing will apply its // own key-specific hash algorithm. - sig, err := signAndMarshal(priv, randSource, H) + sig, err := signAndMarshal(priv, randSource, H, algo) if err != nil { return nil, err } diff --git a/ssh/kex_test.go b/ssh/kex_test.go index 12ca0acd31..cb7f66a509 100644 --- a/ssh/kex_test.go +++ b/ssh/kex_test.go @@ -8,10 +8,16 @@ package ssh import ( "crypto/rand" + "fmt" "reflect" + "sync" "testing" ) +// Runs multiple key exchanges concurrent to detect potential data races with +// kex obtained from the global kexAlgoMap. +// This test needs to be executed using the race detector in order to detect +// race conditions. func TestKexes(t *testing.T) { type kexResultErr struct { result *kexResult @@ -19,32 +25,82 @@ func TestKexes(t *testing.T) { } for name, kex := range kexAlgoMap { - a, b := memPipe() - - s := make(chan kexResultErr, 1) - c := make(chan kexResultErr, 1) - var magics handshakeMagics - go func() { - r, e := kex.Client(a, rand.Reader, &magics) - a.Close() - c <- kexResultErr{r, e} - }() - go func() { - r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"]) - b.Close() - s <- kexResultErr{r, e} - }() - - clientRes := <-c - serverRes := <-s - if clientRes.err != nil { - t.Errorf("client: %v", clientRes.err) - } - if serverRes.err != nil { - t.Errorf("server: %v", serverRes.err) - } - if !reflect.DeepEqual(clientRes.result, serverRes.result) { - t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) - } + t.Run(name, func(t *testing.T) { + wg := sync.WaitGroup{} + for i := 0; i < 3; i++ { + wg.Add(1) + go func() { + defer wg.Done() + a, b := memPipe() + + s := make(chan kexResultErr, 1) + c := make(chan kexResultErr, 1) + var magics handshakeMagics + go func() { + r, e := kex.Client(a, rand.Reader, &magics) + a.Close() + c <- kexResultErr{r, e} + }() + go func() { + r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"].(AlgorithmSigner), testSigners["ecdsa"].PublicKey().Type()) + b.Close() + s <- kexResultErr{r, e} + }() + + clientRes := <-c + serverRes := <-s + if clientRes.err != nil { + t.Errorf("client: %v", clientRes.err) + } + if serverRes.err != nil { + t.Errorf("server: %v", serverRes.err) + } + if !reflect.DeepEqual(clientRes.result, serverRes.result) { + t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) + } + }() + } + wg.Wait() + }) + } +} + +func BenchmarkKexes(b *testing.B) { + type kexResultErr struct { + result *kexResult + err error + } + + for name, kex := range kexAlgoMap { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + t1, t2 := memPipe() + + s := make(chan kexResultErr, 1) + c := make(chan kexResultErr, 1) + var magics handshakeMagics + + go func() { + r, e := kex.Client(t1, rand.Reader, &magics) + t1.Close() + c <- kexResultErr{r, e} + }() + go func() { + r, e := kex.Server(t2, rand.Reader, &magics, testSigners["ecdsa"].(AlgorithmSigner), testSigners["ecdsa"].PublicKey().Type()) + t2.Close() + s <- kexResultErr{r, e} + }() + + clientRes := <-c + serverRes := <-s + + if clientRes.err != nil { + panic(fmt.Sprintf("client: %v", clientRes.err)) + } + if serverRes.err != nil { + panic(fmt.Sprintf("server: %v", serverRes.err)) + } + } + }) } } diff --git a/ssh/keys.go b/ssh/keys.go index 969804794f..a035956fcc 100644 --- a/ssh/keys.go +++ b/ssh/keys.go @@ -7,45 +7,64 @@ package ssh import ( "bytes" "crypto" + "crypto/aes" + "crypto/cipher" "crypto/dsa" "crypto/ecdsa" + "crypto/ed25519" "crypto/elliptic" "crypto/md5" + "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/asn1" "encoding/base64" + "encoding/binary" "encoding/hex" "encoding/pem" "errors" "fmt" "io" "math/big" + "slices" "strings" - "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf" ) -// These constants represent the algorithm names for key types supported by this -// package. +// Public key algorithms names. These values can appear in PublicKey.Type, +// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner +// arguments. const ( - KeyAlgoRSA = "ssh-rsa" - KeyAlgoDSA = "ssh-dss" - KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" - KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" - KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" - KeyAlgoED25519 = "ssh-ed25519" + KeyAlgoRSA = "ssh-rsa" + // Deprecated: DSA is only supported at insecure key sizes, and was removed + // from major implementations. + KeyAlgoDSA = InsecureKeyAlgoDSA + // Deprecated: DSA is only supported at insecure key sizes, and was removed + // from major implementations. + InsecureKeyAlgoDSA = "ssh-dss" + KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" + KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" + KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" + KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" + KeyAlgoED25519 = "ssh-ed25519" + KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com" + + // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not + // public key formats, so they can't appear as a PublicKey.Type. The + // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. + KeyAlgoRSASHA256 = "rsa-sha2-256" + KeyAlgoRSASHA512 = "rsa-sha2-512" ) -// These constants represent non-default signature algorithms that are supported -// as algorithm parameters to AlgorithmSigner.SignWithAlgorithm methods. See -// [PROTOCOL.agent] section 4.5.1 and -// https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-10 const ( - SigAlgoRSA = "ssh-rsa" - SigAlgoRSASHA2256 = "rsa-sha2-256" - SigAlgoRSASHA2512 = "rsa-sha2-512" + // Deprecated: use KeyAlgoRSA. + SigAlgoRSA = KeyAlgoRSA + // Deprecated: use KeyAlgoRSASHA256. + SigAlgoRSASHA2256 = KeyAlgoRSASHA256 + // Deprecated: use KeyAlgoRSASHA512. + SigAlgoRSASHA2512 = KeyAlgoRSASHA512 ) // parsePubKey parses a public key of the given algorithm. @@ -54,19 +73,28 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err switch algo { case KeyAlgoRSA: return parseRSA(in) - case KeyAlgoDSA: + case InsecureKeyAlgoDSA: return parseDSA(in) case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: return parseECDSA(in) + case KeyAlgoSKECDSA256: + return parseSKECDSA(in) case KeyAlgoED25519: return parseED25519(in) - case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01: - cert, err := parseCert(in, certToPrivAlgo(algo)) + case KeyAlgoSKED25519: + return parseSKEd25519(in) + case CertAlgoRSAv01, InsecureCertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: + cert, err := parseCert(in, certKeyAlgoNames[algo]) if err != nil { return nil, nil, err } return cert, nil, nil } + if keyFormat := keyFormatForAlgorithm(algo); keyFormat != "" { + return nil, nil, fmt.Errorf("ssh: signature algorithm %q isn't a key format; key is malformed and should be re-encoded with type %q", + algo, keyFormat) + } + return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo) } @@ -169,9 +197,10 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey return "", nil, nil, "", nil, io.EOF } -// ParseAuthorizedKeys parses a public key from an authorized_keys -// file used in OpenSSH according to the sshd(8) manual page. +// ParseAuthorizedKey parses a public key from an authorized_keys file used in +// OpenSSH according to the sshd(8) manual page. Invalid lines are ignored. func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { + var lastErr error for len(in) > 0 { end := bytes.IndexByte(in, '\n') if end != -1 { @@ -200,6 +229,8 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { return out, comment, options, rest, nil + } else { + lastErr = err } // No key type recognised. Maybe there's an options field at @@ -242,16 +273,22 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { options = candidateOptions return out, comment, options, rest, nil + } else { + lastErr = err } in = rest continue } + if lastErr != nil { + return nil, "", nil, nil, fmt.Errorf("ssh: no key found; last parsing error for ignored line: %w", lastErr) + } + return nil, "", nil, nil, errors.New("ssh: no key found") } -// ParsePublicKey parses an SSH public key formatted for use in +// ParsePublicKey parses an SSH public key or certificate formatted for use in // the SSH wire protocol according to RFC 4253, section 6.6. func ParsePublicKey(in []byte) (out PublicKey, err error) { algo, in, ok := parseString(in) @@ -280,18 +317,33 @@ func MarshalAuthorizedKey(key PublicKey) []byte { return b.Bytes() } -// PublicKey is an abstraction of different types of public keys. +// MarshalPrivateKey returns a PEM block with the private key serialized in the +// OpenSSH format. +func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error) { + return marshalOpenSSHPrivateKey(key, comment, unencryptedOpenSSHMarshaler) +} + +// MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted +// private key serialized in the OpenSSH format. +func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error) { + return marshalOpenSSHPrivateKey(key, comment, passphraseProtectedOpenSSHMarshaler(passphrase)) +} + +// PublicKey represents a public key using an unspecified algorithm. +// +// Some PublicKeys provided by this package also implement CryptoPublicKey. type PublicKey interface { - // Type returns the key's type, e.g. "ssh-rsa". + // Type returns the key format name, e.g. "ssh-rsa". Type() string - // Marshal returns the serialized key data in SSH wire format, - // with the name prefix. To unmarshal the returned data, use - // the ParsePublicKey function. + // Marshal returns the serialized key data in SSH wire format, with the name + // prefix. To unmarshal the returned data, use the ParsePublicKey function. Marshal() []byte - // Verify that sig is a signature on the given data using this - // key. This function will hash the data appropriately first. + // Verify that sig is a signature on the given data using this key. This + // method will hash the data appropriately first. sig.Format is allowed to + // be any signature algorithm compatible with the key type, the caller + // should check if it has more stringent requirements. Verify(data []byte, sig *Signature) error } @@ -302,28 +354,104 @@ type CryptoPublicKey interface { } // A Signer can create signatures that verify against a public key. +// +// Some Signers provided by this package also implement MultiAlgorithmSigner. type Signer interface { - // PublicKey returns an associated PublicKey instance. + // PublicKey returns the associated PublicKey. PublicKey() PublicKey - // Sign returns raw signature for the given data. This method - // will apply the hash specified for the keytype to the data. + // Sign returns a signature for the given data. This method will hash the + // data appropriately first. The signature algorithm is expected to match + // the key format returned by the PublicKey.Type method (and not to be any + // alternative algorithm supported by the key format). Sign(rand io.Reader, data []byte) (*Signature, error) } -// A AlgorithmSigner is a Signer that also supports specifying a specific -// algorithm to use for signing. +// An AlgorithmSigner is a Signer that also supports specifying an algorithm to +// use for signing. +// +// An AlgorithmSigner can't advertise the algorithms it supports, unless it also +// implements MultiAlgorithmSigner, so it should be prepared to be invoked with +// every algorithm supported by the public key format. type AlgorithmSigner interface { Signer - // SignWithAlgorithm is like Signer.Sign, but allows specification of a - // non-default signing algorithm. See the SigAlgo* constants in this - // package for signature algorithms supported by this package. Callers may - // pass an empty string for the algorithm in which case the AlgorithmSigner - // will use its default algorithm. + // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired + // signing algorithm. Callers may pass an empty string for the algorithm in + // which case the AlgorithmSigner will use a default algorithm. This default + // doesn't currently control any behavior in this package. SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) } +// MultiAlgorithmSigner is an AlgorithmSigner that also reports the algorithms +// supported by that signer. +type MultiAlgorithmSigner interface { + AlgorithmSigner + + // Algorithms returns the available algorithms in preference order. The list + // must not be empty, and it must not include certificate types. + Algorithms() []string +} + +// NewSignerWithAlgorithms returns a signer restricted to the specified +// algorithms. The algorithms must be set in preference order. The list must not +// be empty, and it must not include certificate types. An error is returned if +// the specified algorithms are incompatible with the public key type. +func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string) (MultiAlgorithmSigner, error) { + if len(algorithms) == 0 { + return nil, errors.New("ssh: please specify at least one valid signing algorithm") + } + var signerAlgos []string + supportedAlgos := algorithmsForKeyFormat(underlyingAlgo(signer.PublicKey().Type())) + if s, ok := signer.(*multiAlgorithmSigner); ok { + signerAlgos = s.Algorithms() + } else { + signerAlgos = supportedAlgos + } + + for _, algo := range algorithms { + if !slices.Contains(supportedAlgos, algo) { + return nil, fmt.Errorf("ssh: algorithm %q is not supported for key type %q", + algo, signer.PublicKey().Type()) + } + if !slices.Contains(signerAlgos, algo) { + return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", algo) + } + } + return &multiAlgorithmSigner{ + AlgorithmSigner: signer, + supportedAlgorithms: algorithms, + }, nil +} + +type multiAlgorithmSigner struct { + AlgorithmSigner + supportedAlgorithms []string +} + +func (s *multiAlgorithmSigner) Algorithms() []string { + return s.supportedAlgorithms +} + +func (s *multiAlgorithmSigner) isAlgorithmSupported(algorithm string) bool { + if algorithm == "" { + algorithm = underlyingAlgo(s.PublicKey().Type()) + } + for _, algo := range s.supportedAlgorithms { + if algorithm == algo { + return true + } + } + return false +} + +func (s *multiAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { + if !s.isAlgorithmSupported(algorithm) { + return nil, fmt.Errorf("ssh: algorithm %q is not supported: %v", algorithm, s.supportedAlgorithms) + } + return s.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm) +} + type rsaPublicKey rsa.PublicKey func (r *rsaPublicKey) Type() string { @@ -372,21 +500,60 @@ func (r *rsaPublicKey) Marshal() []byte { } func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { - var hash crypto.Hash - switch sig.Format { - case SigAlgoRSA: - hash = crypto.SHA1 - case SigAlgoRSASHA2256: - hash = crypto.SHA256 - case SigAlgoRSASHA2512: - hash = crypto.SHA512 - default: + supportedAlgos := algorithmsForKeyFormat(r.Type()) + if !slices.Contains(supportedAlgos, sig.Format) { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) } + hash, err := hashFunc(sig.Format) + if err != nil { + return err + } h := hash.New() h.Write(data) digest := h.Sum(nil) - return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, sig.Blob) + + // Signatures in PKCS1v15 must match the key's modulus in + // length. However with SSH, some signers provide RSA + // signatures which are missing the MSB 0's of the bignum + // represented. With ssh-rsa signatures, this is encouraged by + // the spec (even though e.g. OpenSSH will give the full + // length unconditionally). With rsa-sha2-* signatures, the + // verifier is allowed to support these, even though they are + // out of spec. See RFC 4253 Section 6.6 for ssh-rsa and RFC + // 8332 Section 3 for rsa-sha2-* details. + // + // In practice: + // * OpenSSH always allows "short" signatures: + // https://github.com/openssh/openssh-portable/blob/V_9_8_P1/ssh-rsa.c#L526 + // but always generates padded signatures: + // https://github.com/openssh/openssh-portable/blob/V_9_8_P1/ssh-rsa.c#L439 + // + // * PuTTY versions 0.81 and earlier will generate short + // signatures for all RSA signature variants. Note that + // PuTTY is embedded in other software, such as WinSCP and + // FileZilla. At the time of writing, a patch has been + // applied to PuTTY to generate padded signatures for + // rsa-sha2-*, but not yet released: + // https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=a5bcf3d384e1bf15a51a6923c3724cbbee022d8e + // + // * SSH.NET versions 2024.0.0 and earlier will generate short + // signatures for all RSA signature variants, fixed in 2024.1.0: + // https://github.com/sshnet/SSH.NET/releases/tag/2024.1.0 + // + // As a result, we pad these up to the key size by inserting + // leading 0's. + // + // Note that support for short signatures with rsa-sha2-* may + // be removed in the future due to such signatures not being + // allowed by the spec. + blob := sig.Blob + keySize := (*rsa.PublicKey)(r).Size() + if len(blob) < keySize { + padded := make([]byte, keySize) + copy(padded[keySize-len(blob):], blob) + blob = padded + } + return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, blob) } func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey { @@ -457,7 +624,11 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { if sig.Format != k.Type() { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) } - h := crypto.SHA1.New() + hash, err := hashFunc(sig.Format) + if err != nil { + return err + } + h := hash.New() h.Write(data) digest := h.Sum(nil) @@ -490,7 +661,11 @@ func (k *dsaPrivateKey) PublicKey() PublicKey { } func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { - return k.SignWithAlgorithm(rand, data, "") + return k.SignWithAlgorithm(rand, data, k.PublicKey().Type()) +} + +func (k *dsaPrivateKey) Algorithms() []string { + return []string{k.PublicKey().Type()} } func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { @@ -498,7 +673,11 @@ func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) } - h := crypto.SHA1.New() + hash, err := hashFunc(k.PublicKey().Type()) + if err != nil { + return nil, err + } + h := hash.New() h.Write(data) digest := h.Sum(nil) r, s, err := dsa.Sign(rand, k.PrivateKey, digest) @@ -553,9 +732,11 @@ func parseED25519(in []byte) (out PublicKey, rest []byte, err error) { return nil, nil, err } - key := ed25519.PublicKey(w.KeyBytes) + if l := len(w.KeyBytes); l != ed25519.PublicKeySize { + return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) + } - return (ed25519PublicKey)(key), w.Rest, nil + return ed25519PublicKey(w.KeyBytes), w.Rest, nil } func (k ed25519PublicKey) Marshal() []byte { @@ -573,9 +754,11 @@ func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error { if sig.Format != k.Type() { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) } + if l := len(k); l != ed25519.PublicKeySize { + return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) + } - edKey := (ed25519.PublicKey)(k) - if ok := ed25519.Verify(edKey, b, sig.Blob); !ok { + if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok { return errors.New("ssh: signature did not verify") } @@ -590,19 +773,6 @@ func supportedEllipticCurve(curve elliptic.Curve) bool { return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() } -// ecHash returns the hash to match the given elliptic curve, see RFC -// 5656, section 6.2.1 -func ecHash(curve elliptic.Curve) crypto.Hash { - bitSize := curve.Params().BitSize - switch { - case bitSize <= 256: - return crypto.SHA256 - case bitSize <= 384: - return crypto.SHA384 - } - return crypto.SHA512 -} - // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { var w struct { @@ -657,8 +827,11 @@ func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { if sig.Format != k.Type() { return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) } - - h := ecHash(k.Curve).New() + hash, err := hashFunc(sig.Format) + if err != nil { + return err + } + h := hash.New() h.Write(data) digest := h.Sum(nil) @@ -685,6 +858,239 @@ func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey { return (*ecdsa.PublicKey)(k) } +// skFields holds the additional fields present in U2F/FIDO2 signatures. +// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details. +type skFields struct { + // Flags contains U2F/FIDO2 flags such as 'user present' + Flags byte + // Counter is a monotonic signature counter which can be + // used to detect concurrent use of a private key, should + // it be extracted from hardware. + Counter uint32 +} + +type skECDSAPublicKey struct { + // application is a URL-like string, typically "ssh:" for SSH. + // see openssh/PROTOCOL.u2f for details. + application string + ecdsa.PublicKey +} + +func (k *skECDSAPublicKey) Type() string { + return KeyAlgoSKECDSA256 +} + +func (k *skECDSAPublicKey) nistID() string { + return "nistp256" +} + +func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + Curve string + KeyBytes []byte + Application string + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := new(skECDSAPublicKey) + key.application = w.Application + + if w.Curve != "nistp256" { + return nil, nil, errors.New("ssh: unsupported curve") + } + key.Curve = elliptic.P256() + + key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) + if key.X == nil || key.Y == nil { + return nil, nil, errors.New("ssh: invalid curve point") + } + + return key, w.Rest, nil +} + +func (k *skECDSAPublicKey) Marshal() []byte { + // See RFC 5656, section 3.1. + keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) + w := struct { + Name string + ID string + Key []byte + Application string + }{ + k.Type(), + k.nistID(), + keyBytes, + k.application, + } + + return Marshal(&w) +} + +func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + hash, err := hashFunc(sig.Format) + if err != nil { + return err + } + h := hash.New() + h.Write([]byte(k.application)) + appDigest := h.Sum(nil) + + h.Reset() + h.Write(data) + dataDigest := h.Sum(nil) + + var ecSig struct { + R *big.Int + S *big.Int + } + if err := Unmarshal(sig.Blob, &ecSig); err != nil { + return err + } + + var skf skFields + if err := Unmarshal(sig.Rest, &skf); err != nil { + return err + } + + blob := struct { + ApplicationDigest []byte `ssh:"rest"` + Flags byte + Counter uint32 + MessageDigest []byte `ssh:"rest"` + }{ + appDigest, + skf.Flags, + skf.Counter, + dataDigest, + } + + original := Marshal(blob) + + h.Reset() + h.Write(original) + digest := h.Sum(nil) + + if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +func (k *skECDSAPublicKey) CryptoPublicKey() crypto.PublicKey { + return &k.PublicKey +} + +type skEd25519PublicKey struct { + // application is a URL-like string, typically "ssh:" for SSH. + // see openssh/PROTOCOL.u2f for details. + application string + ed25519.PublicKey +} + +func (k *skEd25519PublicKey) Type() string { + return KeyAlgoSKED25519 +} + +func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + KeyBytes []byte + Application string + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + if l := len(w.KeyBytes); l != ed25519.PublicKeySize { + return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) + } + + key := new(skEd25519PublicKey) + key.application = w.Application + key.PublicKey = ed25519.PublicKey(w.KeyBytes) + + return key, w.Rest, nil +} + +func (k *skEd25519PublicKey) Marshal() []byte { + w := struct { + Name string + KeyBytes []byte + Application string + }{ + KeyAlgoSKED25519, + []byte(k.PublicKey), + k.application, + } + return Marshal(&w) +} + +func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + if l := len(k.PublicKey); l != ed25519.PublicKeySize { + return fmt.Errorf("invalid size %d for Ed25519 public key", l) + } + + hash, err := hashFunc(sig.Format) + if err != nil { + return err + } + h := hash.New() + h.Write([]byte(k.application)) + appDigest := h.Sum(nil) + + h.Reset() + h.Write(data) + dataDigest := h.Sum(nil) + + var edSig struct { + Signature []byte `ssh:"rest"` + } + + if err := Unmarshal(sig.Blob, &edSig); err != nil { + return err + } + + var skf skFields + if err := Unmarshal(sig.Rest, &skf); err != nil { + return err + } + + blob := struct { + ApplicationDigest []byte `ssh:"rest"` + Flags byte + Counter uint32 + MessageDigest []byte `ssh:"rest"` + }{ + appDigest, + skf.Flags, + skf.Counter, + dataDigest, + } + + original := Marshal(blob) + + if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok { + return errors.New("ssh: signature did not verify") + } + + return nil +} + +func (k *skEd25519PublicKey) CryptoPublicKey() crypto.PublicKey { + return k.PublicKey +} + // NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, // *ecdsa.PrivateKey or any other crypto.Signer and returns a // corresponding Signer instance. ECDSA keys must use P-256, P-384 or @@ -730,44 +1136,26 @@ func (s *wrappedSigner) PublicKey() PublicKey { } func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { - return s.SignWithAlgorithm(rand, data, "") + return s.SignWithAlgorithm(rand, data, s.pubKey.Type()) +} + +func (s *wrappedSigner) Algorithms() []string { + return algorithmsForKeyFormat(s.pubKey.Type()) } func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { - var hashFunc crypto.Hash - - if _, ok := s.pubKey.(*rsaPublicKey); ok { - // RSA keys support a few hash functions determined by the requested signature algorithm - switch algorithm { - case "", SigAlgoRSA: - algorithm = SigAlgoRSA - hashFunc = crypto.SHA1 - case SigAlgoRSASHA2256: - hashFunc = crypto.SHA256 - case SigAlgoRSASHA2512: - hashFunc = crypto.SHA512 - default: - return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) - } - } else { - // The only supported algorithm for all other key types is the same as the type of the key - if algorithm == "" { - algorithm = s.pubKey.Type() - } else if algorithm != s.pubKey.Type() { - return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) - } + if algorithm == "" { + algorithm = s.pubKey.Type() + } - switch key := s.pubKey.(type) { - case *dsaPublicKey: - hashFunc = crypto.SHA1 - case *ecdsaPublicKey: - hashFunc = ecHash(key.Curve) - case ed25519PublicKey: - default: - return nil, fmt.Errorf("ssh: unsupported key type %T", key) - } + if !slices.Contains(s.Algorithms(), algorithm) { + return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type()) } + hashFunc, err := hashFunc(algorithm) + if err != nil { + return nil, err + } var digest []byte if hashFunc != 0 { h := hashFunc.New() @@ -830,14 +1218,18 @@ func NewPublicKey(key interface{}) (PublicKey, error) { case *dsa.PublicKey: return (*dsaPublicKey)(key), nil case ed25519.PublicKey: - return (ed25519PublicKey)(key), nil + if l := len(key); l != ed25519.PublicKeySize { + return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) + } + return ed25519PublicKey(key), nil default: return nil, fmt.Errorf("ssh: unsupported key type %T", key) } } // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports -// the same keys as ParseRawPrivateKey. +// the same keys as ParseRawPrivateKey. If the private key is encrypted, it +// will return a PassphraseMissingError. func ParsePrivateKey(pemBytes []byte) (Signer, error) { key, err := ParseRawPrivateKey(pemBytes) if err != nil { @@ -850,8 +1242,8 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) { // ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private // key and passphrase. It supports the same keys as // ParseRawPrivateKeyWithPassphrase. -func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) { - key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase) +func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) { + key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase) if err != nil { return nil, err } @@ -867,8 +1259,21 @@ func encryptedBlock(block *pem.Block) bool { return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") } -// ParseRawPrivateKey returns a private key from a PEM encoded private key. It -// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. +// A PassphraseMissingError indicates that parsing this private key requires a +// passphrase. Use ParsePrivateKeyWithPassphrase. +type PassphraseMissingError struct { + // PublicKey will be set if the private key format includes an unencrypted + // public key along with the encrypted private key. + PublicKey PublicKey +} + +func (*PassphraseMissingError) Error() string { + return "ssh: this private key is passphrase protected" +} + +// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports +// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH +// formats. If the private key is encrypted, it will return a PassphraseMissingError. func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { block, _ := pem.Decode(pemBytes) if block == nil { @@ -876,7 +1281,7 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { } if encryptedBlock(block) { - return nil, errors.New("ssh: cannot decode encrypted private keys") + return nil, &PassphraseMissingError{} } switch block.Type { @@ -890,47 +1295,58 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { case "DSA PRIVATE KEY": return ParseDSAPrivateKey(block.Bytes) case "OPENSSH PRIVATE KEY": - return parseOpenSSHPrivateKey(block.Bytes) + return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey) default: return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) } } // ParseRawPrivateKeyWithPassphrase returns a private key decrypted with -// passphrase from a PEM encoded private key. If wrong passphrase, return -// x509.IncorrectPasswordError. -func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) { +// passphrase from a PEM encoded private key. If the passphrase is wrong, it +// will return x509.IncorrectPasswordError. +func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) { block, _ := pem.Decode(pemBytes) if block == nil { return nil, errors.New("ssh: no key found") } - buf := block.Bytes - if encryptedBlock(block) { - if x509.IsEncryptedPEMBlock(block) { - var err error - buf, err = x509.DecryptPEMBlock(block, passPhrase) - if err != nil { - if err == x509.IncorrectPasswordError { - return nil, err - } - return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err) - } + if block.Type == "OPENSSH PRIVATE KEY" { + return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase)) + } + + if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) { + return nil, errors.New("ssh: not an encrypted key") + } + + buf, err := x509.DecryptPEMBlock(block, passphrase) + if err != nil { + if err == x509.IncorrectPasswordError { + return nil, err } + return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err) } + var result interface{} + switch block.Type { case "RSA PRIVATE KEY": - return x509.ParsePKCS1PrivateKey(buf) + result, err = x509.ParsePKCS1PrivateKey(buf) case "EC PRIVATE KEY": - return x509.ParseECPrivateKey(buf) + result, err = x509.ParseECPrivateKey(buf) case "DSA PRIVATE KEY": - return ParseDSAPrivateKey(buf) - case "OPENSSH PRIVATE KEY": - return parseOpenSSHPrivateKey(buf) + result, err = ParseDSAPrivateKey(buf) default: - return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) + err = fmt.Errorf("ssh: unsupported key type %q", block.Type) + } + // Because of deficiencies in the format, DecryptPEMBlock does not always + // detect an incorrect password. In these cases decrypted DER bytes is + // random noise. If the parsing of the key returns an asn1.StructuralError + // we return x509.IncorrectPasswordError. + if _, ok := err.(asn1.StructuralError); ok { + return nil, x509.IncorrectPasswordError } + + return result, err } // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as @@ -965,70 +1381,199 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { }, nil } -// Implemented based on the documentation at -// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key -func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) { - const magic = "openssh-key-v1\x00" - if len(key) < len(magic) || string(key[:len(magic)]) != magic { - return nil, errors.New("ssh: invalid openssh private key format") +func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { + if kdfName != "none" || cipherName != "none" { + return nil, &PassphraseMissingError{} + } + if kdfOpts != "" { + return nil, errors.New("ssh: invalid openssh private key") } - remaining := key[len(magic):] + return privKeyBlock, nil +} - var w struct { - CipherName string - KdfName string - KdfOpts string - NumKeys uint32 - PubKey []byte - PrivKeyBlock []byte +func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc { + return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { + if kdfName == "none" || cipherName == "none" { + return nil, errors.New("ssh: key is not password protected") + } + if kdfName != "bcrypt" { + return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt") + } + + var opts struct { + Salt string + Rounds uint32 + } + if err := Unmarshal([]byte(kdfOpts), &opts); err != nil { + return nil, err + } + + k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16) + if err != nil { + return nil, err + } + key, iv := k[:32], k[32:] + + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + switch cipherName { + case "aes256-ctr": + ctr := cipher.NewCTR(c, iv) + ctr.XORKeyStream(privKeyBlock, privKeyBlock) + case "aes256-cbc": + if len(privKeyBlock)%c.BlockSize() != 0 { + return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size") + } + cbc := cipher.NewCBCDecrypter(c, iv) + cbc.CryptBlocks(privKeyBlock, privKeyBlock) + default: + return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc") + } + + return privKeyBlock, nil } +} - if err := Unmarshal(remaining, &w); err != nil { - return nil, err +func unencryptedOpenSSHMarshaler(privKeyBlock []byte) ([]byte, string, string, string, error) { + key := generateOpenSSHPadding(privKeyBlock, 8) + return key, "none", "none", "", nil +} + +func passphraseProtectedOpenSSHMarshaler(passphrase []byte) openSSHEncryptFunc { + return func(privKeyBlock []byte) ([]byte, string, string, string, error) { + salt := make([]byte, 16) + if _, err := rand.Read(salt); err != nil { + return nil, "", "", "", err + } + + opts := struct { + Salt []byte + Rounds uint32 + }{salt, 16} + + // Derive key to encrypt the private key block. + k, err := bcrypt_pbkdf.Key(passphrase, salt, int(opts.Rounds), 32+aes.BlockSize) + if err != nil { + return nil, "", "", "", err + } + + // Add padding matching the block size of AES. + keyBlock := generateOpenSSHPadding(privKeyBlock, aes.BlockSize) + + // Encrypt the private key using the derived secret. + + dst := make([]byte, len(keyBlock)) + key, iv := k[:32], k[32:] + block, err := aes.NewCipher(key) + if err != nil { + return nil, "", "", "", err + } + + stream := cipher.NewCTR(block, iv) + stream.XORKeyStream(dst, keyBlock) + + return dst, "aes256-ctr", "bcrypt", string(Marshal(opts)), nil } +} + +const privateKeyAuthMagic = "openssh-key-v1\x00" - if w.KdfName != "none" || w.CipherName != "none" { - return nil, errors.New("ssh: cannot decode encrypted private keys") +type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error) +type openSSHEncryptFunc func(PrivKeyBlock []byte) (ProtectedKeyBlock []byte, cipherName, kdfName, kdfOptions string, err error) + +type openSSHEncryptedPrivateKey struct { + CipherName string + KdfName string + KdfOpts string + NumKeys uint32 + PubKey []byte + PrivKeyBlock []byte +} + +type openSSHPrivateKey struct { + Check1 uint32 + Check2 uint32 + Keytype string + Rest []byte `ssh:"rest"` +} + +type openSSHRSAPrivateKey struct { + N *big.Int + E *big.Int + D *big.Int + Iqmp *big.Int + P *big.Int + Q *big.Int + Comment string + Pad []byte `ssh:"rest"` +} + +type openSSHEd25519PrivateKey struct { + Pub []byte + Priv []byte + Comment string + Pad []byte `ssh:"rest"` +} + +type openSSHECDSAPrivateKey struct { + Curve string + Pub []byte + D *big.Int + Comment string + Pad []byte `ssh:"rest"` +} + +// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt +// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used +// as the decrypt function to parse an unencrypted private key. See +// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key. +func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) { + if len(key) < len(privateKeyAuthMagic) || string(key[:len(privateKeyAuthMagic)]) != privateKeyAuthMagic { + return nil, errors.New("ssh: invalid openssh private key format") } + remaining := key[len(privateKeyAuthMagic):] - pk1 := struct { - Check1 uint32 - Check2 uint32 - Keytype string - Rest []byte `ssh:"rest"` - }{} + var w openSSHEncryptedPrivateKey + if err := Unmarshal(remaining, &w); err != nil { + return nil, err + } + if w.NumKeys != 1 { + // We only support single key files, and so does OpenSSH. + // https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171 + return nil, errors.New("ssh: multi-key files are not supported") + } - if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil { + privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock) + if err != nil { + if err, ok := err.(*PassphraseMissingError); ok { + pub, errPub := ParsePublicKey(w.PubKey) + if errPub != nil { + return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub) + } + err.PublicKey = pub + } return nil, err } - if pk1.Check1 != pk1.Check2 { - return nil, errors.New("ssh: checkint mismatch") + var pk1 openSSHPrivateKey + if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 { + if w.CipherName != "none" { + return nil, x509.IncorrectPasswordError + } + return nil, errors.New("ssh: malformed OpenSSH key") } - // we only handle ed25519 and rsa keys currently switch pk1.Keytype { case KeyAlgoRSA: - // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 - key := struct { - N *big.Int - E *big.Int - D *big.Int - Iqmp *big.Int - P *big.Int - Q *big.Int - Comment string - Pad []byte `ssh:"rest"` - }{} - + var key openSSHRSAPrivateKey if err := Unmarshal(pk1.Rest, &key); err != nil { return nil, err } - for i, b := range key.Pad { - if int(b) != i+1 { - return nil, errors.New("ssh: padding not as expected") - } + if err := checkOpenSSHKeyPadding(key.Pad); err != nil { + return nil, err } pk := &rsa.PrivateKey{ @@ -1048,13 +1593,7 @@ func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) { return pk, nil case KeyAlgoED25519: - key := struct { - Pub []byte - Priv []byte - Comment string - Pad []byte `ssh:"rest"` - }{} - + var key openSSHEd25519PrivateKey if err := Unmarshal(pk1.Rest, &key); err != nil { return nil, err } @@ -1063,20 +1602,203 @@ func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) { return nil, errors.New("ssh: private key unexpected length") } - for i, b := range key.Pad { - if int(b) != i+1 { - return nil, errors.New("ssh: padding not as expected") - } + if err := checkOpenSSHKeyPadding(key.Pad); err != nil { + return nil, err } pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) copy(pk, key.Priv) return &pk, nil + case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: + var key openSSHECDSAPrivateKey + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + if err := checkOpenSSHKeyPadding(key.Pad); err != nil { + return nil, err + } + + var curve elliptic.Curve + switch key.Curve { + case "nistp256": + curve = elliptic.P256() + case "nistp384": + curve = elliptic.P384() + case "nistp521": + curve = elliptic.P521() + default: + return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve) + } + + X, Y := elliptic.Unmarshal(curve, key.Pub) + if X == nil || Y == nil { + return nil, errors.New("ssh: failed to unmarshal public key") + } + + if key.D.Cmp(curve.Params().N) >= 0 { + return nil, errors.New("ssh: scalar is out of range") + } + + x, y := curve.ScalarBaseMult(key.D.Bytes()) + if x.Cmp(X) != 0 || y.Cmp(Y) != 0 { + return nil, errors.New("ssh: public key does not match private key") + } + + return &ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: curve, + X: X, + Y: Y, + }, + D: key.D, + }, nil default: return nil, errors.New("ssh: unhandled key type") } } +func marshalOpenSSHPrivateKey(key crypto.PrivateKey, comment string, encrypt openSSHEncryptFunc) (*pem.Block, error) { + var w openSSHEncryptedPrivateKey + var pk1 openSSHPrivateKey + + // Random check bytes. + var check uint32 + if err := binary.Read(rand.Reader, binary.BigEndian, &check); err != nil { + return nil, err + } + + pk1.Check1 = check + pk1.Check2 = check + w.NumKeys = 1 + + // Use a []byte directly on ed25519 keys. + if k, ok := key.(*ed25519.PrivateKey); ok { + key = *k + } + + switch k := key.(type) { + case *rsa.PrivateKey: + E := new(big.Int).SetInt64(int64(k.PublicKey.E)) + // Marshal public key: + // E and N are in reversed order in the public and private key. + pubKey := struct { + KeyType string + E *big.Int + N *big.Int + }{ + KeyAlgoRSA, + E, k.PublicKey.N, + } + w.PubKey = Marshal(pubKey) + + // Marshal private key. + key := openSSHRSAPrivateKey{ + N: k.PublicKey.N, + E: E, + D: k.D, + Iqmp: k.Precomputed.Qinv, + P: k.Primes[0], + Q: k.Primes[1], + Comment: comment, + } + pk1.Keytype = KeyAlgoRSA + pk1.Rest = Marshal(key) + case ed25519.PrivateKey: + pub := make([]byte, ed25519.PublicKeySize) + priv := make([]byte, ed25519.PrivateKeySize) + copy(pub, k[32:]) + copy(priv, k) + + // Marshal public key. + pubKey := struct { + KeyType string + Pub []byte + }{ + KeyAlgoED25519, pub, + } + w.PubKey = Marshal(pubKey) + + // Marshal private key. + key := openSSHEd25519PrivateKey{ + Pub: pub, + Priv: priv, + Comment: comment, + } + pk1.Keytype = KeyAlgoED25519 + pk1.Rest = Marshal(key) + case *ecdsa.PrivateKey: + var curve, keyType string + switch name := k.Curve.Params().Name; name { + case "P-256": + curve = "nistp256" + keyType = KeyAlgoECDSA256 + case "P-384": + curve = "nistp384" + keyType = KeyAlgoECDSA384 + case "P-521": + curve = "nistp521" + keyType = KeyAlgoECDSA521 + default: + return nil, errors.New("ssh: unhandled elliptic curve " + name) + } + + pub := elliptic.Marshal(k.Curve, k.PublicKey.X, k.PublicKey.Y) + + // Marshal public key. + pubKey := struct { + KeyType string + Curve string + Pub []byte + }{ + keyType, curve, pub, + } + w.PubKey = Marshal(pubKey) + + // Marshal private key. + key := openSSHECDSAPrivateKey{ + Curve: curve, + Pub: pub, + D: k.D, + Comment: comment, + } + pk1.Keytype = keyType + pk1.Rest = Marshal(key) + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", k) + } + + var err error + // Add padding and encrypt the key if necessary. + w.PrivKeyBlock, w.CipherName, w.KdfName, w.KdfOpts, err = encrypt(Marshal(pk1)) + if err != nil { + return nil, err + } + + b := Marshal(w) + block := &pem.Block{ + Type: "OPENSSH PRIVATE KEY", + Bytes: append([]byte(privateKeyAuthMagic), b...), + } + return block, nil +} + +func checkOpenSSHKeyPadding(pad []byte) error { + for i, b := range pad { + if int(b) != i+1 { + return errors.New("ssh: padding not as expected") + } + } + return nil +} + +func generateOpenSSHPadding(block []byte, blockSize int) []byte { + for i, l := 0, len(block); (l+i)%blockSize != 0; i++ { + block = append(block, byte(i+1)) + } + return block +} + // FingerprintLegacyMD5 returns the user presentation of the key's // fingerprint as described by RFC 4716 section 4. func FingerprintLegacyMD5(pubKey PublicKey) string { diff --git a/ssh/keys_test.go b/ssh/keys_test.go index 3847b3bf3e..661e3cb31c 100644 --- a/ssh/keys_test.go +++ b/ssh/keys_test.go @@ -8,19 +8,21 @@ import ( "bytes" "crypto/dsa" "crypto/ecdsa" + "crypto/ed25519" "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" + "encoding/hex" "encoding/pem" + "errors" "fmt" "io" "reflect" "strings" "testing" - "golang.org/x/crypto/ed25519" "golang.org/x/crypto/ssh/testdata" ) @@ -57,6 +59,17 @@ func TestKeyMarshalParse(t *testing.T) { } } +func TestParsePublicKeyWithSigningAlgoAsKeyFormat(t *testing.T) { + key := []byte(`rsa-sha2-256 AAAADHJzYS1zaGEyLTI1NgAAAAMBAAEAAAEBAJ7qMyjLXEJCCJmRknuCLo0uPi5GrPY5pQYr84lhlN8Gor5KVL2LKYCW4e70r5xzj7SrHHSCft1FMlYg1KDO9xrprJh733kQqAPWETmSuH0EfRtGtcH6EarKyVxk6As076/yNiiMKVBtG0RPa1L7FviTfcYK4vnCCVrbv3RmA5CCzuG5BSMbRLxzVb4Ri3p8jhxYT8N4QGe/2yqvJLys5vQ9szpZR3tcFp3DJIVZhBRfR6LnoY23XZniAAMQaUVBX86dXQ++dNwAwZSXSt9Og+AniOCiBYqhNVa5n3DID/H7YtEtG+CbZr3r2KD3fv8AfSLRar4XOp8rsRdD31h/kr8=`) + _, _, _, _, err := ParseAuthorizedKey(key) + if err == nil { + t.Fatal("parsing a public key using a signature algorithm as the key format succeeded unexpectedly") + } + if !strings.Contains(err.Error(), `signature algorithm "rsa-sha2-256" isn't a key format`) { + t.Errorf(`got %v, expected 'signature algorithm "rsa-sha2-256" isn't a key format'`, err) + } +} + func TestUnsupportedCurves(t *testing.T) { raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) if err != nil { @@ -110,9 +123,9 @@ func TestKeySignVerify(t *testing.T) { } func TestKeySignWithAlgorithmVerify(t *testing.T) { - for _, priv := range testSigners { - if algorithmSigner, ok := priv.(AlgorithmSigner); !ok { - t.Errorf("Signers constructed by ssh package should always implement the AlgorithmSigner interface: %T", priv) + for k, priv := range testSigners { + if algorithmSigner, ok := priv.(MultiAlgorithmSigner); !ok { + t.Errorf("Signers %q constructed by ssh package should always implement the MultiAlgorithmSigner interface: %T", k, priv) } else { pub := priv.PublicKey() data := []byte("sign me") @@ -144,7 +157,7 @@ func TestKeySignWithAlgorithmVerify(t *testing.T) { // RSA keys are the only ones which currently support more than one signing algorithm if pub.Type() == KeyAlgoRSA { - for _, algorithm := range []string{SigAlgoRSA, SigAlgoRSASHA2256, SigAlgoRSASHA2512} { + for _, algorithm := range []string{KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512} { signWithAlgTestCase(algorithm, algorithm) } } @@ -152,6 +165,44 @@ func TestKeySignWithAlgorithmVerify(t *testing.T) { } } +func TestKeySignWithShortSignature(t *testing.T) { + signer := testSigners["rsa"].(AlgorithmSigner) + pub := signer.PublicKey() + // Note: data obtained by empirically trying until a result + // starting with 0 appeared + tests := []struct { + algorithm string + data []byte + }{ + { + algorithm: KeyAlgoRSA, + data: []byte("sign me92"), + }, + { + algorithm: KeyAlgoRSASHA256, + data: []byte("sign me294"), + }, + { + algorithm: KeyAlgoRSASHA512, + data: []byte("sign me60"), + }, + } + + for _, tt := range tests { + sig, err := signer.SignWithAlgorithm(rand.Reader, tt.data, tt.algorithm) + if err != nil { + t.Fatalf("Sign(%T): %v", signer, err) + } + if sig.Blob[0] != 0 { + t.Errorf("%s: Expected signature with a leading 0", tt.algorithm) + } + sig.Blob = sig.Blob[1:] + if err := pub.Verify(tt.data, sig); err != nil { + t.Errorf("publicKey.Verify(%s): %v", tt.algorithm, err) + } + } +} + func TestParseRSAPrivateKey(t *testing.T) { key := testPrivateKeys["rsa"] @@ -178,44 +229,55 @@ func TestParseECPrivateKey(t *testing.T) { } } -// See Issue https://github.com/golang/go/issues/6650. -func TestParseEncryptedPrivateKeysFails(t *testing.T) { - const wantSubstring = "encrypted" - for i, tt := range testdata.PEMEncryptedKeys { - _, err := ParsePrivateKey(tt.PEMBytes) - if err == nil { - t.Errorf("#%d key %s: ParsePrivateKey successfully parsed, expected an error", i, tt.Name) - continue - } - - if !strings.Contains(err.Error(), wantSubstring) { - t.Errorf("#%d key %s: got error %q, want substring %q", i, tt.Name, err, wantSubstring) - } - } -} - -// Parse encrypted private keys with passphrase func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) { data := []byte("sign me") for _, tt := range testdata.PEMEncryptedKeys { - s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) - if err != nil { - t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err) - continue - } - sig, err := s.Sign(rand.Reader, data) - if err != nil { - t.Fatalf("dsa.Sign: %v", err) - } - if err := s.PublicKey().Verify(data, sig); err != nil { - t.Errorf("Verify failed: %v", err) - } + t.Run(tt.Name, func(t *testing.T) { + _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect")) + if err != x509.IncorrectPasswordError { + t.Errorf("got %v want IncorrectPasswordError", err) + } + + s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) + if err != nil { + t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err) + } + + sig, err := s.Sign(rand.Reader, data) + if err != nil { + t.Fatalf("Signer.Sign: %v", err) + } + if err := s.PublicKey().Verify(data, sig); err != nil { + t.Errorf("Verify failed: %v", err) + } + + _, err = ParsePrivateKey(tt.PEMBytes) + if err == nil { + t.Fatalf("ParsePrivateKey succeeded, expected an error") + } + + if err, ok := err.(*PassphraseMissingError); !ok { + t.Errorf("got error %q, want PassphraseMissingError", err) + } else if tt.IncludesPublicKey { + if err.PublicKey == nil { + t.Fatalf("expected PassphraseMissingError.PublicKey not to be nil") + } + got, want := err.PublicKey.Marshal(), s.PublicKey().Marshal() + if !bytes.Equal(got, want) { + t.Errorf("error field %q doesn't match signer public key %q", got, want) + } + } + }) } +} - tt := testdata.PEMEncryptedKeys[0] - _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect")) - if err != x509.IncorrectPasswordError { - t.Fatalf("got %v want IncorrectPasswordError", err) +func TestParseEncryptedPrivateKeysWithIncorrectPassphrase(t *testing.T) { + pem := testdata.PEMEncryptedKeys[0].PEMBytes + for i := 0; i < 4096; i++ { + _, err := ParseRawPrivateKeyWithPassphrase(pem, []byte(fmt.Sprintf("%d", i))) + if !errors.Is(err, x509.IncorrectPasswordError) { + t.Fatalf("expected error: %v, got: %v", x509.IncorrectPasswordError, err) + } } } @@ -279,6 +341,74 @@ func TestMarshalParsePublicKey(t *testing.T) { } } +func TestMarshalPrivateKey(t *testing.T) { + tests := []struct { + name string + }{ + {"rsa-openssh-format"}, + {"ed25519"}, + {"p256-openssh-format"}, + {"p384-openssh-format"}, + {"p521-openssh-format"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expected, ok := testPrivateKeys[tt.name] + if !ok { + t.Fatalf("cannot find key %s", tt.name) + } + + block, err := MarshalPrivateKey(expected, "test@golang.org") + if err != nil { + t.Fatalf("cannot marshal %s: %v", tt.name, err) + } + + key, err := ParseRawPrivateKey(pem.EncodeToMemory(block)) + if err != nil { + t.Fatalf("cannot parse %s: %v", tt.name, err) + } + + if !reflect.DeepEqual(expected, key) { + t.Errorf("unexpected marshaled key %s", tt.name) + } + }) + } +} + +func TestMarshalPrivateKeyWithPassphrase(t *testing.T) { + tests := []struct { + name string + }{ + {"rsa-openssh-format"}, + {"ed25519"}, + {"p256-openssh-format"}, + {"p384-openssh-format"}, + {"p521-openssh-format"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expected, ok := testPrivateKeys[tt.name] + if !ok { + t.Fatalf("cannot find key %s", tt.name) + } + + block, err := MarshalPrivateKeyWithPassphrase(expected, "test@golang.org", []byte("test-passphrase")) + if err != nil { + t.Fatalf("cannot marshal %s: %v", tt.name, err) + } + + key, err := ParseRawPrivateKeyWithPassphrase(pem.EncodeToMemory(block), []byte("test-passphrase")) + if err != nil { + t.Fatalf("cannot parse %s: %v", tt.name, err) + } + + if !reflect.DeepEqual(expected, key) { + t.Errorf("unexpected marshaled key %s", tt.name) + } + }) + } +} + type testAuthResult struct { pubKey PublicKey options []string @@ -529,7 +659,7 @@ func TestKnownHostsParsing(t *testing.T) { func TestFingerprintLegacyMD5(t *testing.T) { pub, _ := getTestKey() fingerprint := FingerprintLegacyMD5(pub) - want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa + want := "b7:ef:d3:d5:89:29:52:96:9f:df:47:41:4d:15:37:f4" // ssh-keygen -lf -E md5 rsa if fingerprint != want { t.Errorf("got fingerprint %q want %q", fingerprint, want) } @@ -538,7 +668,7 @@ func TestFingerprintLegacyMD5(t *testing.T) { func TestFingerprintSHA256(t *testing.T) { pub, _ := getTestKey() fingerprint := FingerprintSHA256(pub) - want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa + want := "SHA256:fi5+D7UmDZDE9Q2sAVvvlpcQSIakN4DERdINgXd2AnE" // ssh-keygen -lf rsa if fingerprint != want { t.Errorf("got fingerprint %q want %q", fingerprint, want) } @@ -572,3 +702,149 @@ func TestInvalidKeys(t *testing.T) { } } } + +func TestSKKeys(t *testing.T) { + for _, d := range testdata.SKData { + pk, _, _, _, err := ParseAuthorizedKey(d.PubKey) + if err != nil { + t.Fatalf("parseAuthorizedKey returned error: %v", err) + } + + sigBuf := make([]byte, hex.DecodedLen(len(d.HexSignature))) + if _, err := hex.Decode(sigBuf, d.HexSignature); err != nil { + t.Fatalf("hex.Decode() failed: %v", err) + } + + dataBuf := make([]byte, hex.DecodedLen(len(d.HexData))) + if _, err := hex.Decode(dataBuf, d.HexData); err != nil { + t.Fatalf("hex.Decode() failed: %v", err) + } + + sig, _, ok := parseSignature(sigBuf) + if !ok { + t.Fatalf("parseSignature(%v) failed", sigBuf) + } + + // Test that good data and signature pass verification + if err := pk.Verify(dataBuf, sig); err != nil { + t.Errorf("%s: PublicKey.Verify(%v, %v) failed: %v", d.Name, dataBuf, sig, err) + } + + // Invalid data being passed in + invalidData := []byte("INVALID DATA") + if err := pk.Verify(invalidData, sig); err == nil { + t.Errorf("%s with invalid data: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, invalidData, sig) + } + + // Change byte in blob to corrup signature + sig.Blob[5] = byte('A') + // Corrupted data being passed in + if err := pk.Verify(dataBuf, sig); err == nil { + t.Errorf("%s with corrupted signature: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, dataBuf, sig) + } + } +} + +func TestNewSignerWithAlgos(t *testing.T) { + algorithSigner, ok := testSigners["rsa"].(AlgorithmSigner) + if !ok { + t.Fatal("rsa test signer does not implement the AlgorithmSigner interface") + } + _, err := NewSignerWithAlgorithms(algorithSigner, nil) + if err == nil { + t.Error("signer with algos created with no algorithms") + } + + _, err = NewSignerWithAlgorithms(algorithSigner, []string{KeyAlgoED25519}) + if err == nil { + t.Error("signer with algos created with invalid algorithms") + } + + _, err = NewSignerWithAlgorithms(algorithSigner, []string{CertAlgoRSASHA256v01}) + if err == nil { + t.Error("signer with algos created with certificate algorithms") + } + + mas, err := NewSignerWithAlgorithms(algorithSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}) + if err != nil { + t.Errorf("unable to create signer with valid algorithms: %v", err) + } + + _, err = NewSignerWithAlgorithms(mas, []string{KeyAlgoRSA}) + if err == nil { + t.Error("signer with algos created with restricted algorithms") + } +} + +func TestCryptoPublicKey(t *testing.T) { + for _, priv := range testSigners { + p1 := priv.PublicKey() + key, ok := p1.(CryptoPublicKey) + if !ok { + continue + } + p2, err := NewPublicKey(key.CryptoPublicKey()) + if err != nil { + t.Fatalf("NewPublicKey(CryptoPublicKey) failed for %s, got: %v", p1.Type(), err) + } + if !reflect.DeepEqual(p1, p2) { + t.Errorf("got %#v in NewPublicKey, want %#v", p2, p1) + } + } + for _, d := range testdata.SKData { + p1, _, _, _, err := ParseAuthorizedKey(d.PubKey) + if err != nil { + t.Fatalf("parseAuthorizedKey returned error: %v", err) + } + k1, ok := p1.(CryptoPublicKey) + if !ok { + t.Fatalf("%T does not implement CryptoPublicKey", p1) + } + + var p2 PublicKey + switch pub := k1.CryptoPublicKey().(type) { + case *ecdsa.PublicKey: + p2 = &skECDSAPublicKey{ + application: "ssh:", + PublicKey: *pub, + } + case ed25519.PublicKey: + p2 = &skEd25519PublicKey{ + application: "ssh:", + PublicKey: pub, + } + default: + t.Fatalf("unexpected type %T from CryptoPublicKey()", pub) + } + if !reflect.DeepEqual(p1, p2) { + t.Errorf("got %#v, want %#v", p2, p1) + } + } +} + +func TestParseCertWithCertSignatureKey(t *testing.T) { + certBytes := []byte(`-----BEGIN SSH CERTIFICATE----- +AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIPSp27hvNSB0 +IotJnVhjC4zxNgNS8BHlUCxD0VJi4D/eAAAAIIJMi1e5qfx+IFuKD/p/Ssqcb3os +CpOw/4wBs1pQ53zwAAAAAAAAAAEAAAACAAAAAAAAABMAAAAPZm9vLmV4YW1wbGUu +Y29tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0AAAAgc3NoLWVkMjU1 +MTktY2VydC12MDFAb3BlbnNzaC5jb20AAAAg+sNYhCO35mQT1UBMpmMk8ey+culd +IU8vBlPEl4B07swAAAAggiv+RLnboS4znGCVl/n1jDg2uD0h15tW4s/04eS2mLQA +AAAAAAAAAQAAAAIAAAAAAAAAEwAAAA9mb28uZXhhbXBsZS5jb20AAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCV2wETgLKL +Kt0bRl3YUnd/ZYSlq0xJMbn4Jj3cdPWykQAAAFMAAAALc3NoLWVkMjU1MTkAAABA +WOdbRGEzyRAhiIK227CLUQD5caXYMV8FvSIB7toEE2M/8HnWdG9H3Rsg/v3unruQ +JrQldnuPJNe7KOP2+zvUDgAAAFMAAAALc3NoLWVkMjU1MTkAAABAm3bIPp85ZpIe +D+izJcUqlcAOri7HO8bULFNHT6LVegvB06xQ5TLwMlrxWUF4cafl1tSe8JQck4a6 +cLYUOHfQDw== +-----END SSH CERTIFICATE----- + `) + block, _ := pem.Decode(certBytes) + if block == nil { + t.Fatal("invalid test certificate") + } + + if _, err := ParsePublicKey(block.Bytes); err == nil { + t.Fatal("parsing an SSH certificate using another certificate as signature key succeeded; expected failure") + } +} diff --git a/ssh/knownhosts/knownhosts.go b/ssh/knownhosts/knownhosts.go index 260cfe58c6..1ebd7e6da2 100644 --- a/ssh/knownhosts/knownhosts.go +++ b/ssh/knownhosts/knownhosts.go @@ -142,7 +142,7 @@ func keyEq(a, b ssh.PublicKey) bool { return bytes.Equal(a.Marshal(), b.Marshal()) } -// IsAuthorityForHost can be used as a callback in ssh.CertChecker +// IsHostAuthority can be used as a callback in ssh.CertChecker func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool { h, p, err := net.SplitHostPort(address) if err != nil { @@ -302,8 +302,8 @@ func (k *KnownKey) String() string { // applications can offer an interactive prompt to the user. type KeyError struct { // Want holds the accepted host keys. For each key algorithm, - // there can be one hostkey. If Want is empty, the host is - // unknown. If Want is non-empty, there was a mismatch, which + // there can be multiple hostkeys. If Want is empty, the host + // is unknown. If Want is non-empty, there was a mismatch, which // can signify a MITM attack. Want []KnownKey } @@ -358,34 +358,20 @@ func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { // is just a key for the IP address, but not for the // hostname? - // Algorithm => key. - knownKeys := map[string]KnownKey{} - for _, l := range db.lines { - if l.match(a) { - typ := l.knownKey.Key.Type() - if _, ok := knownKeys[typ]; !ok { - knownKeys[typ] = l.knownKey - } - } - } - keyErr := &KeyError{} - for _, v := range knownKeys { - keyErr.Want = append(keyErr.Want, v) - } - // Unknown remote host. - if len(knownKeys) == 0 { - return keyErr - } + for _, l := range db.lines { + if !l.match(a) { + continue + } - // If the remote host starts using a different, unknown key type, we - // also interpret that as a mismatch. - if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { - return keyErr + keyErr.Want = append(keyErr.Want, l.knownKey) + if keyEq(l.knownKey.Key, remoteKey) { + return nil + } } - return nil + return keyErr } // The Read function parses file contents. @@ -435,20 +421,26 @@ func New(files ...string) (ssh.HostKeyCallback, error) { return certChecker.CheckHostKey, nil } -// Normalize normalizes an address into the form used in known_hosts +// Normalize normalizes an address into the form used in known_hosts. Supports +// IPv4, hostnames, bracketed IPv6. Any other non-standard formats are returned +// with minimal transformation. func Normalize(address string) string { + const defaultSSHPort = "22" + host, port, err := net.SplitHostPort(address) if err != nil { host = address - port = "22" + port = defaultSSHPort + } + + if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") { + host = host[1 : len(host)-1] } - entry := host - if port != "22" { - entry = "[" + entry + "]:" + port - } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { - entry = "[" + entry + "]" + + if port == defaultSSHPort { + return host } - return entry + return "[" + host + "]:" + port } // Line returns a line to add append to the known_hosts files. diff --git a/ssh/knownhosts/knownhosts_test.go b/ssh/knownhosts/knownhosts_test.go index 464dd59249..552a556110 100644 --- a/ssh/knownhosts/knownhosts_test.go +++ b/ssh/knownhosts/knownhosts_test.go @@ -201,17 +201,6 @@ func TestHostNamePrecedence(t *testing.T) { } } -func TestDBOrderingPrecedenceKeyType(t *testing.T) { - str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) - db := testDB(t, str) - - if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil { - t.Errorf("check succeeded") - } else if _, ok := err.(*KeyError); !ok { - t.Errorf("got %T, want *KeyError", err) - } -} - func TestNegate(t *testing.T) { str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) db := testDB(t, str) @@ -247,7 +236,7 @@ func TestLine(t *testing.T) { "server.org": "server.org " + edKeyStr, "server.org:22": "server.org " + edKeyStr, "server.org:23": "[server.org]:23 " + edKeyStr, - "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr, + "[c629:1ec4:102:304:102:304:102:304]:22": "c629:1ec4:102:304:102:304:102:304 " + edKeyStr, "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr, } { if got := Line([]string{in}, edKey); got != want { @@ -321,14 +310,25 @@ func testHostHash(t *testing.T, hostname, encoded string) { func TestNormalize(t *testing.T) { for in, want := range map[string]string{ - "127.0.0.1:22": "127.0.0.1", - "[127.0.0.1]:22": "127.0.0.1", - "[127.0.0.1]:23": "[127.0.0.1]:23", - "127.0.0.1:23": "[127.0.0.1]:23", - "[a.b.c]:22": "a.b.c", - "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]", - "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]", - "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23", + "127.0.0.1": "127.0.0.1", + "127.0.0.1:22": "127.0.0.1", + "[127.0.0.1]:22": "127.0.0.1", + "[127.0.0.1]:23": "[127.0.0.1]:23", + "127.0.0.1:23": "[127.0.0.1]:23", + "[a.b.c]:22": "a.b.c", + "[a.b.c]:23": "[a.b.c]:23", + "abcd::abcd:abcd:abcd": "abcd::abcd:abcd:abcd", + "[abcd::abcd:abcd:abcd]": "abcd::abcd:abcd:abcd", + "[abcd::abcd:abcd:abcd]:22": "abcd::abcd:abcd:abcd", + "[abcd::abcd:abcd:abcd]:23": "[abcd::abcd:abcd:abcd]:23", + "2001:db8::1": "2001:db8::1", + "2001:db8::1:22": "2001:db8::1:22", + "[2001:db8::1]:22": "2001:db8::1", + "2001:db8::1:2200": "2001:db8::1:2200", + "a.b.c.d.com:2200": "[a.b.c.d.com]:2200", + "2001::db8:1": "2001::db8:1", + "2001::db8:1:22": "2001::db8:1:22", + "2001::db8:1:2200": "2001::db8:1:2200", } { got := Normalize(in) if got != want { @@ -354,3 +354,16 @@ func TestHashedHostkeyCheck(t *testing.T) { t.Errorf("got error %v, want %v", got, want) } } + +func TestIssue36126(t *testing.T) { + str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) + db := testDB(t, str) + + if err := db.check("server.org:22", testAddr, edKey); err != nil { + t.Errorf("should have passed the check, got %v", err) + } + + if err := db.check("server.org:22", testAddr, alternateEdKey); err != nil { + t.Errorf("should have passed the check, got %v", err) + } +} diff --git a/ssh/mac.go b/ssh/mac.go index c07a06285e..87d626fbbf 100644 --- a/ssh/mac.go +++ b/ssh/mac.go @@ -7,10 +7,13 @@ package ssh // Message authentication support import ( + "crypto/fips140" "crypto/hmac" "crypto/sha1" "crypto/sha256" + "crypto/sha512" "hash" + "slices" ) type macMode struct { @@ -45,17 +48,37 @@ func (t truncatingMAC) Size() int { func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } -var macModes = map[string]*macMode{ - "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { +// macModes defines the supported MACs. MACs not included are not supported +// and will not be negotiated, even if explicitly configured. When FIPS mode is +// enabled, only FIPS-approved algorithms are included. +var macModes = map[string]*macMode{} + +func init() { + macModes[HMACSHA512ETM] = &macMode{64, true, func(key []byte) hash.Hash { + return hmac.New(sha512.New, key) + }} + macModes[HMACSHA256ETM] = &macMode{32, true, func(key []byte) hash.Hash { return hmac.New(sha256.New, key) - }}, - "hmac-sha2-256": {32, false, func(key []byte) hash.Hash { + }} + macModes[HMACSHA512] = &macMode{64, false, func(key []byte) hash.Hash { + return hmac.New(sha512.New, key) + }} + macModes[HMACSHA256] = &macMode{32, false, func(key []byte) hash.Hash { return hmac.New(sha256.New, key) - }}, - "hmac-sha1": {20, false, func(key []byte) hash.Hash { + }} + + if fips140.Enabled() { + defaultMACs = slices.DeleteFunc(defaultMACs, func(algo string) bool { + _, ok := macModes[algo] + return !ok + }) + return + } + + macModes[HMACSHA1] = &macMode{20, false, func(key []byte) hash.Hash { return hmac.New(sha1.New, key) - }}, - "hmac-sha1-96": {20, false, func(key []byte) hash.Hash { + }} + macModes[InsecureHMACSHA196] = &macMode{20, false, func(key []byte) hash.Hash { return truncatingMAC{12, hmac.New(sha1.New, key)} - }}, + }} } diff --git a/ssh/mempipe_test.go b/ssh/mempipe_test.go index 8697cd6140..f27339c51a 100644 --- a/ssh/mempipe_test.go +++ b/ssh/mempipe_test.go @@ -13,9 +13,10 @@ import ( // An in-memory packetConn. It is safe to call Close and writePacket // from different goroutines. type memTransport struct { - eof bool - pending [][]byte - write *memTransport + eof bool + pending [][]byte + write *memTransport + writeCount uint64 sync.Mutex *sync.Cond } @@ -63,9 +64,16 @@ func (t *memTransport) writePacket(p []byte) error { copy(c, p) t.write.pending = append(t.write.pending, c) t.write.Cond.Signal() + t.writeCount++ return nil } +func (t *memTransport) getWriteCount() uint64 { + t.write.Lock() + defer t.write.Unlock() + return t.writeCount +} + func memPipe() (a, b packetConn) { t1 := memTransport{} t2 := memTransport{} @@ -81,6 +89,9 @@ func TestMemPipe(t *testing.T) { if err := a.writePacket([]byte{42}); err != nil { t.Fatalf("writePacket: %v", err) } + if wc := a.(*memTransport).getWriteCount(); wc != 1 { + t.Fatalf("got %v, want 1", wc) + } if err := a.Close(); err != nil { t.Fatal("Close: ", err) } @@ -95,6 +106,9 @@ func TestMemPipe(t *testing.T) { if err != io.EOF { t.Fatalf("got %v, %v, want EOF", p, err) } + if wc := b.(*memTransport).getWriteCount(); wc != 0 { + t.Fatalf("got %v, want 0", wc) + } } func TestDoubleClose(t *testing.T) { diff --git a/ssh/messages.go b/ssh/messages.go index ac41a4168b..ab22c3d38d 100644 --- a/ssh/messages.go +++ b/ssh/messages.go @@ -68,7 +68,7 @@ type kexInitMsg struct { // See RFC 4253, section 8. -// Diffie-Helman +// Diffie-Hellman const msgKexDHInit = 30 type kexDHInitMsg struct { @@ -122,9 +122,9 @@ type kexDHGexReplyMsg struct { const msgKexDHGexRequest = 34 type kexDHGexRequestMsg struct { - MinBits uint32 `sshtype:"34"` - PreferedBits uint32 - MaxBits uint32 + MinBits uint32 `sshtype:"34"` + PreferredBits uint32 + MaxBits uint32 } // See RFC 4253, section 10. @@ -141,6 +141,14 @@ type serviceAcceptMsg struct { Service string `sshtype:"6"` } +// See RFC 8308, section 2.3 +const msgExtInfo = 7 + +type extInfoMsg struct { + NumExtensions uint32 `sshtype:"7"` + Payload []byte `ssh:"rest"` +} + // See RFC 4252, section 5. const msgUserAuthRequest = 50 @@ -180,11 +188,11 @@ const msgUserAuthInfoRequest = 60 const msgUserAuthInfoResponse = 61 type userAuthInfoRequestMsg struct { - User string `sshtype:"60"` - Instruction string - DeprecatedLanguage string - NumPrompts uint32 - Prompts []byte `ssh:"rest"` + Name string `sshtype:"60"` + Instruction string + Language string + NumPrompts uint32 + Prompts []byte `ssh:"rest"` } // See RFC 4254, section 5.1. @@ -341,6 +349,20 @@ type userAuthGSSAPIError struct { LanguageTag string } +// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9 +const msgPing = 192 + +type pingMsg struct { + Data string `sshtype:"192"` +} + +// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9 +const msgPong = 193 + +type pongMsg struct { + Data string `sshtype:"193"` +} + // typeTags returns the possible type bytes for the given reflect.Type, which // should be a struct. The possible values are separated by a '|' character. func typeTags(structType reflect.Type) (tags []byte) { @@ -770,7 +792,7 @@ func marshalString(to []byte, s []byte) []byte { return to[len(s):] } -var bigIntType = reflect.TypeOf((*big.Int)(nil)) +var bigIntType = reflect.TypeFor[*big.Int]() // Decode a packet into its corresponding message. func decode(packet []byte) (interface{}, error) { @@ -782,6 +804,8 @@ func decode(packet []byte) (interface{}, error) { msg = new(serviceRequestMsg) case msgServiceAccept: msg = new(serviceAcceptMsg) + case msgExtInfo: + msg = new(extInfoMsg) case msgKexInit: msg = new(kexInitMsg) case msgKexDHInit: @@ -794,6 +818,8 @@ func decode(packet []byte) (interface{}, error) { return new(userAuthSuccessMsg), nil case msgUserAuthFailure: msg = new(userAuthFailureMsg) + case msgUserAuthBanner: + msg = new(userAuthBannerMsg) case msgUserAuthPubKeyOk: msg = new(userAuthPubKeyOkMsg) case msgGlobalRequest: @@ -843,6 +869,7 @@ var packetTypeNames = map[byte]string{ msgDisconnect: "disconnectMsg", msgServiceRequest: "serviceRequestMsg", msgServiceAccept: "serviceAcceptMsg", + msgExtInfo: "extInfoMsg", msgKexInit: "kexInitMsg", msgKexDHInit: "kexDHInitMsg", msgKexDHReply: "kexDHReplyMsg", diff --git a/ssh/messages_test.go b/ssh/messages_test.go index e79076412a..ed346285bf 100644 --- a/ssh/messages_test.go +++ b/ssh/messages_test.go @@ -206,6 +206,62 @@ func TestMarshalMultiTag(t *testing.T) { } } +func TestDecode(t *testing.T) { + rnd := rand.New(rand.NewSource(0)) + kexInit := new(kexInitMsg).Generate(rnd, 10).Interface() + kexDHInit := new(kexDHInitMsg).Generate(rnd, 10).Interface() + kexDHReply := new(kexDHReplyMsg) + kexDHReply.Y = randomInt(rnd) + // Note: userAuthSuccessMsg can't be tested directly since it + // doesn't have a field for sshtype. So it's tested separately + // at the end. + decodeMessageTypes := []interface{}{ + new(disconnectMsg), + new(serviceRequestMsg), + new(serviceAcceptMsg), + new(extInfoMsg), + kexInit, + kexDHInit, + kexDHReply, + new(userAuthRequestMsg), + new(userAuthFailureMsg), + new(userAuthBannerMsg), + new(userAuthPubKeyOkMsg), + new(globalRequestMsg), + new(globalRequestSuccessMsg), + new(globalRequestFailureMsg), + new(channelOpenMsg), + new(channelDataMsg), + new(channelOpenConfirmMsg), + new(channelOpenFailureMsg), + new(windowAdjustMsg), + new(channelEOFMsg), + new(channelCloseMsg), + new(channelRequestMsg), + new(channelRequestSuccessMsg), + new(channelRequestFailureMsg), + new(userAuthGSSAPIToken), + new(userAuthGSSAPIMIC), + new(userAuthGSSAPIErrTok), + new(userAuthGSSAPIError), + } + for _, msg := range decodeMessageTypes { + decoded, err := decode(Marshal(msg)) + if err != nil { + t.Errorf("error decoding %T", msg) + } else if reflect.TypeOf(msg) != reflect.TypeOf(decoded) { + t.Errorf("error decoding %T, unexpected %T", msg, decoded) + } + } + + userAuthSuccess, err := decode([]byte{msgUserAuthSuccess}) + if err != nil { + t.Errorf("error decoding userAuthSuccessMsg") + } else if _, ok := userAuthSuccess.(*userAuthSuccessMsg); !ok { + t.Errorf("error decoding userAuthSuccessMsg, unexpected %T", userAuthSuccess) + } +} + func randomBytes(out []byte, rand *rand.Rand) { for i := 0; i < len(out); i++ { out[i] = byte(rand.Int31()) diff --git a/ssh/mlkem.go b/ssh/mlkem.go new file mode 100644 index 0000000000..ddc0ed1fc0 --- /dev/null +++ b/ssh/mlkem.go @@ -0,0 +1,168 @@ +// Copyright 2024 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 ssh + +import ( + "crypto" + "crypto/mlkem" + "crypto/sha256" + "errors" + "fmt" + "io" + + "golang.org/x/crypto/curve25519" +) + +// mlkem768WithCurve25519sha256 implements the hybrid ML-KEM768 with +// curve25519-sha256 key exchange method, as described by +// draft-kampanakis-curdle-ssh-pq-ke-05 section 2.3.3. +type mlkem768WithCurve25519sha256 struct{} + +func (kex *mlkem768WithCurve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + var c25519kp curve25519KeyPair + if err := c25519kp.generate(rand); err != nil { + return nil, err + } + + seed := make([]byte, mlkem.SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { + return nil, err + } + + mlkemDk, err := mlkem.NewDecapsulationKey768(seed) + if err != nil { + return nil, err + } + + hybridKey := append(mlkemDk.EncapsulationKey().Bytes(), c25519kp.pub[:]...) + if err := c.writePacket(Marshal(&kexECDHInitMsg{hybridKey})); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + + if len(reply.EphemeralPubKey) != mlkem.CiphertextSize768+32 { + return nil, errors.New("ssh: peer's mlkem768x25519 public value has wrong length") + } + + // Perform KEM decapsulate operation to obtain shared key from ML-KEM. + mlkem768Secret, err := mlkemDk.Decapsulate(reply.EphemeralPubKey[:mlkem.CiphertextSize768]) + if err != nil { + return nil, err + } + + // Complete Curve25519 ECDH to obtain its shared key. + c25519Secret, err := curve25519.X25519(c25519kp.priv[:], reply.EphemeralPubKey[mlkem.CiphertextSize768:]) + if err != nil { + return nil, fmt.Errorf("ssh: peer's mlkem768x25519 public value is not valid: %w", err) + } + // Compute actual shared key. + h := sha256.New() + h.Write(mlkem768Secret) + h.Write(c25519Secret) + secret := h.Sum(nil) + + h.Reset() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, hybridKey) + writeString(h, reply.EphemeralPubKey) + + K := make([]byte, stringLength(len(secret))) + marshalString(K, secret) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: crypto.SHA256, + }, nil +} + +func (kex *mlkem768WithCurve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (*kexResult, error) { + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexInit kexECDHInitMsg + if err = Unmarshal(packet, &kexInit); err != nil { + return nil, err + } + + if len(kexInit.ClientPubKey) != mlkem.EncapsulationKeySize768+32 { + return nil, errors.New("ssh: peer's ML-KEM768/curve25519 public value has wrong length") + } + + encapsulationKey, err := mlkem.NewEncapsulationKey768(kexInit.ClientPubKey[:mlkem.EncapsulationKeySize768]) + if err != nil { + return nil, fmt.Errorf("ssh: peer's ML-KEM768 encapsulation key is not valid: %w", err) + } + // Perform KEM encapsulate operation to obtain ciphertext and shared key. + mlkem768Secret, mlkem768Ciphertext := encapsulationKey.Encapsulate() + + // Perform server side of Curve25519 ECDH to obtain server public value and + // shared key. + var c25519kp curve25519KeyPair + if err := c25519kp.generate(rand); err != nil { + return nil, err + } + c25519Secret, err := curve25519.X25519(c25519kp.priv[:], kexInit.ClientPubKey[mlkem.EncapsulationKeySize768:]) + if err != nil { + return nil, fmt.Errorf("ssh: peer's ML-KEM768/curve25519 public value is not valid: %w", err) + } + hybridKey := append(mlkem768Ciphertext, c25519kp.pub[:]...) + + // Compute actual shared key. + h := sha256.New() + h.Write(mlkem768Secret) + h.Write(c25519Secret) + secret := h.Sum(nil) + + hostKeyBytes := priv.PublicKey().Marshal() + + h.Reset() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexInit.ClientPubKey) + writeString(h, hybridKey) + + K := make([]byte, stringLength(len(secret))) + marshalString(K, secret) + h.Write(K) + + H := h.Sum(nil) + + sig, err := signAndMarshal(priv, rand, H, algo) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: hybridKey, + HostKey: hostKeyBytes, + Signature: sig, + } + if err := c.writePacket(Marshal(&reply)); err != nil { + return nil, err + } + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: crypto.SHA256, + }, nil +} diff --git a/ssh/mux.go b/ssh/mux.go index f19016270e..d2d24c635d 100644 --- a/ssh/mux.go +++ b/ssh/mux.go @@ -231,6 +231,12 @@ func (m *mux) onePacket() error { return m.handleChannelOpen(packet) case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: return m.handleGlobalPacket(packet) + case msgPing: + var msg pingMsg + if err := Unmarshal(packet, &msg); err != nil { + return fmt.Errorf("failed to unmarshal ping@openssh.com message: %w", err) + } + return m.sendMessage(pongMsg(msg)) } // assume a channel packet. @@ -240,7 +246,7 @@ func (m *mux) onePacket() error { id := binary.BigEndian.Uint32(packet[1:]) ch := m.chanList.getChan(id) if ch == nil { - return fmt.Errorf("ssh: invalid channel %d", id) + return m.handleUnknownChannelPacket(id, packet) } return ch.handlePacket(packet) @@ -328,3 +334,24 @@ func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) } } + +func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) error { + msg, err := decode(packet) + if err != nil { + return err + } + + switch msg := msg.(type) { + // RFC 4254 section 5.4 says unrecognized channel requests should + // receive a failure response. + case *channelRequestMsg: + if msg.WantReply { + return m.sendMessage(channelRequestFailureMsg{ + PeersID: msg.PeersID, + }) + } + return nil + default: + return fmt.Errorf("ssh: invalid channel %d", id) + } +} diff --git a/ssh/mux_test.go b/ssh/mux_test.go index 94596ec2d7..21f0ac3e32 100644 --- a/ssh/mux_test.go +++ b/ssh/mux_test.go @@ -5,8 +5,9 @@ package ssh import ( + "errors" + "fmt" "io" - "io/ioutil" "sync" "testing" ) @@ -29,14 +30,21 @@ func channelPair(t *testing.T) (*channel, *channel, *mux) { go func() { newCh, ok := <-s.incomingChannels if !ok { - t.Fatalf("No incoming channel") + t.Error("no incoming channel") + close(res) + return } if newCh.ChannelType() != "chan" { - t.Fatalf("got type %q want chan", newCh.ChannelType()) + t.Errorf("got type %q want chan", newCh.ChannelType()) + newCh.Reject(Prohibited, fmt.Sprintf("got type %q want chan", newCh.ChannelType())) + close(res) + return } ch, _, err := newCh.Accept() if err != nil { - t.Fatalf("Accept %v", err) + t.Errorf("accept: %v", err) + close(res) + return } res <- ch.(*channel) }() @@ -45,8 +53,12 @@ func channelPair(t *testing.T) (*channel, *channel, *mux) { if err != nil { t.Fatalf("OpenChannel: %v", err) } + w := <-res + if w == nil { + t.Fatal("unable to get write channel") + } - return <-res, ch, c + return w, ch, c } // Test that stderr and stdout can be addressed from different @@ -72,16 +84,16 @@ func TestMuxChannelExtendedThreadSafety(t *testing.T) { rd.Add(2) go func() { - c, err := ioutil.ReadAll(reader) + c, err := io.ReadAll(reader) if string(c) != magic { - t.Fatalf("stdout read got %q, want %q (error %s)", c, magic, err) + t.Errorf("stdout read got %q, want %q (error %s)", c, magic, err) } rd.Done() }() go func() { - c, err := ioutil.ReadAll(reader.Stderr()) + c, err := io.ReadAll(reader.Stderr()) if string(c) != magic { - t.Fatalf("stderr read got %q, want %q (error %s)", c, magic, err) + t.Errorf("stderr read got %q, want %q (error %s)", c, magic, err) } rd.Done() }() @@ -99,14 +111,20 @@ func TestMuxReadWrite(t *testing.T) { magic := "hello world" magicExt := "hello stderr" + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) go func() { + defer wg.Done() _, err := s.Write([]byte(magic)) if err != nil { - t.Fatalf("Write: %v", err) + t.Errorf("Write: %v", err) + return } _, err = s.Extended(1).Write([]byte(magicExt)) if err != nil { - t.Fatalf("Write: %v", err) + t.Errorf("Write: %v", err) + return } }() @@ -137,13 +155,15 @@ func TestMuxChannelOverflow(t *testing.T) { defer writer.Close() defer mux.Close() - wDone := make(chan int, 1) + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) go func() { + defer wg.Done() if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { t.Errorf("could not fill window: %v", err) } writer.Write(make([]byte, 1)) - wDone <- 1 }() writer.remoteWin.waitWriterBlocked() @@ -160,7 +180,40 @@ func TestMuxChannelOverflow(t *testing.T) { if _, err := reader.SendRequest("hello", true, nil); err == nil { t.Errorf("SendRequest succeeded.") } - <-wDone +} + +func TestMuxChannelReadUnblock(t *testing.T) { + reader, writer, mux := channelPair(t) + defer reader.Close() + defer writer.Close() + defer mux.Close() + + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) + go func() { + defer wg.Done() + if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { + t.Errorf("could not fill window: %v", err) + } + if _, err := writer.Write(make([]byte, 1)); err != nil { + t.Errorf("Write: %v", err) + } + writer.Close() + }() + + writer.remoteWin.waitWriterBlocked() + + buf := make([]byte, 32768) + for { + _, err := reader.Read(buf) + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("Read: %v", err) + } + } } func TestMuxChannelCloseWriteUnblock(t *testing.T) { @@ -169,20 +222,21 @@ func TestMuxChannelCloseWriteUnblock(t *testing.T) { defer writer.Close() defer mux.Close() - wDone := make(chan int, 1) + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) go func() { + defer wg.Done() if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { t.Errorf("could not fill window: %v", err) } if _, err := writer.Write(make([]byte, 1)); err != io.EOF { t.Errorf("got %v, want EOF for unblock write", err) } - wDone <- 1 }() writer.remoteWin.waitWriterBlocked() reader.Close() - <-wDone } func TestMuxConnectionCloseWriteUnblock(t *testing.T) { @@ -191,20 +245,21 @@ func TestMuxConnectionCloseWriteUnblock(t *testing.T) { defer writer.Close() defer mux.Close() - wDone := make(chan int, 1) + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) go func() { + defer wg.Done() if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { t.Errorf("could not fill window: %v", err) } if _, err := writer.Write(make([]byte, 1)); err != io.EOF { t.Errorf("got %v, want EOF for unblock write", err) } - wDone <- 1 }() writer.remoteWin.waitWriterBlocked() mux.Close() - <-wDone } func TestMuxReject(t *testing.T) { @@ -212,13 +267,21 @@ func TestMuxReject(t *testing.T) { defer server.Close() defer client.Close() + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) go func() { + defer wg.Done() + ch, ok := <-server.incomingChannels if !ok { - t.Fatalf("Accept") + t.Error("cannot accept channel") + return } if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" { - t.Fatalf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) + t.Errorf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) + ch.Reject(RejectionReason(UnknownChannelType), UnknownChannelType.String()) + return } ch.Reject(RejectionReason(42), "message") }() @@ -249,6 +312,7 @@ func TestMuxChannelRequest(t *testing.T) { var received int var wg sync.WaitGroup + t.Cleanup(wg.Wait) wg.Add(1) go func() { for r := range server.incomingRequests { @@ -277,7 +341,6 @@ func TestMuxChannelRequest(t *testing.T) { } if ok { t.Errorf("SendRequest(no): %v", ok) - } client.Close() @@ -288,15 +351,251 @@ func TestMuxChannelRequest(t *testing.T) { } } +func TestMuxUnknownChannelRequests(t *testing.T) { + clientPipe, serverPipe := memPipe() + client := newMux(clientPipe) + defer serverPipe.Close() + defer client.Close() + + kDone := make(chan error, 1) + go func() { + // Ignore unknown channel messages that don't want a reply. + err := serverPipe.writePacket(Marshal(channelRequestMsg{ + PeersID: 1, + Request: "keepalive@openssh.com", + WantReply: false, + RequestSpecificData: []byte{}, + })) + if err != nil { + kDone <- fmt.Errorf("send: %w", err) + return + } + + // Send a keepalive, which should get a channel failure message + // in response. + err = serverPipe.writePacket(Marshal(channelRequestMsg{ + PeersID: 2, + Request: "keepalive@openssh.com", + WantReply: true, + RequestSpecificData: []byte{}, + })) + if err != nil { + kDone <- fmt.Errorf("send: %w", err) + return + } + + packet, err := serverPipe.readPacket() + if err != nil { + kDone <- fmt.Errorf("read packet: %w", err) + return + } + decoded, err := decode(packet) + if err != nil { + kDone <- fmt.Errorf("decode failed: %w", err) + return + } + + switch msg := decoded.(type) { + case *channelRequestFailureMsg: + if msg.PeersID != 2 { + kDone <- fmt.Errorf("received response to wrong message: %v", msg) + return + + } + default: + kDone <- fmt.Errorf("unexpected channel message: %v", msg) + return + } + + kDone <- nil + + // Receive and respond to the keepalive to confirm the mux is + // still processing requests. + packet, err = serverPipe.readPacket() + if err != nil { + kDone <- fmt.Errorf("read packet: %w", err) + return + } + if packet[0] != msgGlobalRequest { + kDone <- errors.New("expected global request") + return + } + + err = serverPipe.writePacket(Marshal(globalRequestFailureMsg{ + Data: []byte{}, + })) + if err != nil { + kDone <- fmt.Errorf("failed to send failure msg: %w", err) + return + } + + close(kDone) + }() + + // Wait for the server to send the keepalive message and receive back a + // response. + if err := <-kDone; err != nil { + t.Fatal(err) + } + + // Confirm client hasn't closed. + if _, _, err := client.SendRequest("keepalive@golang.org", true, nil); err != nil { + t.Fatalf("failed to send keepalive: %v", err) + } + + // Wait for the server to shut down. + if err := <-kDone; err != nil { + t.Fatal(err) + } +} + +func TestMuxClosedChannel(t *testing.T) { + clientPipe, serverPipe := memPipe() + client := newMux(clientPipe) + defer serverPipe.Close() + defer client.Close() + + kDone := make(chan error, 1) + go func() { + // Open the channel. + packet, err := serverPipe.readPacket() + if err != nil { + kDone <- fmt.Errorf("read packet: %w", err) + return + } + if packet[0] != msgChannelOpen { + kDone <- errors.New("expected chan open") + return + } + + var openMsg channelOpenMsg + if err := Unmarshal(packet, &openMsg); err != nil { + kDone <- fmt.Errorf("unmarshal: %w", err) + return + } + + // Send back the opened channel confirmation. + err = serverPipe.writePacket(Marshal(channelOpenConfirmMsg{ + PeersID: openMsg.PeersID, + MyID: 0, + MyWindow: 0, + MaxPacketSize: channelMaxPacket, + })) + if err != nil { + kDone <- fmt.Errorf("send: %w", err) + return + } + + // Close the channel. + err = serverPipe.writePacket(Marshal(channelCloseMsg{ + PeersID: openMsg.PeersID, + })) + if err != nil { + kDone <- fmt.Errorf("send: %w", err) + return + } + + // Send a keepalive message on the channel we just closed. + err = serverPipe.writePacket(Marshal(channelRequestMsg{ + PeersID: openMsg.PeersID, + Request: "keepalive@openssh.com", + WantReply: true, + RequestSpecificData: []byte{}, + })) + if err != nil { + kDone <- fmt.Errorf("send: %w", err) + return + } + + // Receive the channel closed response. + packet, err = serverPipe.readPacket() + if err != nil { + kDone <- fmt.Errorf("read packet: %w", err) + return + } + if packet[0] != msgChannelClose { + kDone <- errors.New("expected channel close") + return + } + + // Receive the keepalive response failure. + packet, err = serverPipe.readPacket() + if err != nil { + kDone <- fmt.Errorf("read packet: %w", err) + return + } + if packet[0] != msgChannelFailure { + kDone <- errors.New("expected channel failure") + return + } + kDone <- nil + + // Receive and respond to the keepalive to confirm the mux is + // still processing requests. + packet, err = serverPipe.readPacket() + if err != nil { + kDone <- fmt.Errorf("read packet: %w", err) + return + } + if packet[0] != msgGlobalRequest { + kDone <- errors.New("expected global request") + return + } + + err = serverPipe.writePacket(Marshal(globalRequestFailureMsg{ + Data: []byte{}, + })) + if err != nil { + kDone <- fmt.Errorf("failed to send failure msg: %w", err) + return + } + + close(kDone) + }() + + // Open a channel. + ch, err := client.openChannel("chan", nil) + if err != nil { + t.Fatalf("OpenChannel: %v", err) + } + defer ch.Close() + + // Wait for the server to close the channel and send the keepalive. + <-kDone + + // Make sure the channel closed. + if _, ok := <-ch.incomingRequests; ok { + t.Fatalf("channel not closed") + } + + // Confirm client hasn't closed + if _, _, err := client.SendRequest("keepalive@golang.org", true, nil); err != nil { + t.Fatalf("failed to send keepalive: %v", err) + } + + // Wait for the server to shut down. + <-kDone +} + func TestMuxGlobalRequest(t *testing.T) { + var sawPeek bool + var wg sync.WaitGroup + defer func() { + wg.Wait() + if !sawPeek { + t.Errorf("never saw 'peek' request") + } + }() + clientMux, serverMux := muxPair() defer serverMux.Close() defer clientMux.Close() - var seen bool + wg.Add(1) go func() { + defer wg.Done() for r := range serverMux.incomingRequests { - seen = seen || r.Type == "peek" + sawPeek = sawPeek || r.Type == "peek" if r.WantReply { err := r.Reply(r.Type == "yes", append([]byte(r.Type), r.Payload...)) @@ -326,10 +625,6 @@ func TestMuxGlobalRequest(t *testing.T) { t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v", ok, data, err) } - - if !seen { - t.Errorf("never saw 'peek' request") - } } func TestMuxGlobalRequestUnblock(t *testing.T) { @@ -456,7 +751,7 @@ func TestZeroWindowAdjust(t *testing.T) { }() want := "helloworld" - c, _ := ioutil.ReadAll(b) + c, _ := io.ReadAll(b) if string(c) != want { t.Errorf("got %q want %q", c, want) } @@ -479,7 +774,13 @@ func TestMuxMaxPacketSize(t *testing.T) { t.Errorf("could not send packet") } - go a.SendRequest("hello", false, nil) + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) + go func() { + a.SendRequest("hello", false, nil) + wg.Done() + }() _, ok := <-b.incomingRequests if ok { @@ -487,6 +788,43 @@ func TestMuxMaxPacketSize(t *testing.T) { } } +func TestMuxChannelWindowDeferredUpdates(t *testing.T) { + s, c, mux := channelPair(t) + cTransport := mux.conn.(*memTransport) + defer s.Close() + defer c.Close() + defer mux.Close() + + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + + data := make([]byte, 1024) + + wg.Add(1) + go func() { + defer wg.Done() + _, err := s.Write(data) + if err != nil { + t.Errorf("Write: %v", err) + return + } + }() + cWritesInit := cTransport.getWriteCount() + buf := make([]byte, 1) + for i := 0; i < len(data); i++ { + n, err := c.Read(buf) + if n != len(buf) || err != nil { + t.Fatalf("Read: %v, %v", n, err) + } + } + cWrites := cTransport.getWriteCount() - cWritesInit + // reading 1 KiB should not cause any window updates to be sent, but allow + // for some unexpected writes + if cWrites > 30 { + t.Fatalf("reading 1 KiB from channel caused %v writes", cWrites) + } +} + // Don't ship code with debug=true. func TestDebug(t *testing.T) { if debugMux { diff --git a/ssh/server.go b/ssh/server.go index 7a5a1d7ad3..064dcbaf5a 100644 --- a/ssh/server.go +++ b/ssh/server.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "net" + "slices" "strings" ) @@ -43,6 +44,9 @@ type Permissions struct { // pass data from the authentication callbacks to the server // application layer. Extensions map[string]string + + // ExtraData allows to store user defined data. + ExtraData map[any]any } type GSSAPIWithMICConfig struct { @@ -59,17 +63,53 @@ type GSSAPIWithMICConfig struct { Server GSSAPIServer } +// SendAuthBanner implements [ServerPreAuthConn]. +func (s *connection) SendAuthBanner(msg string) error { + return s.transport.writePacket(Marshal(&userAuthBannerMsg{ + Message: msg, + })) +} + +func (*connection) unexportedMethodForFutureProofing() {} + +// ServerPreAuthConn is the interface available on an incoming server +// connection before authentication has completed. +type ServerPreAuthConn interface { + unexportedMethodForFutureProofing() // permits growing ServerPreAuthConn safely later, ala testing.TB + + ConnMetadata + + // SendAuthBanner sends a banner message to the client. + // It returns an error once the authentication phase has ended. + SendAuthBanner(string) error +} + // ServerConfig holds server specific configuration data. type ServerConfig struct { // Config contains configuration shared between client and server. Config + // PublicKeyAuthAlgorithms specifies the supported client public key + // authentication algorithms. Note that this should not include certificate + // types since those use the underlying algorithm. This list is sent to the + // client if it supports the server-sig-algs extension. Order is irrelevant. + // If unspecified then a default set of algorithms is used. + PublicKeyAuthAlgorithms []string + hostKeys []Signer // NoClientAuth is true if clients are allowed to connect without // authenticating. + // To determine NoClientAuth at runtime, set NoClientAuth to true + // and the optional NoClientAuthCallback to a non-nil value. NoClientAuth bool + // NoClientAuthCallback, if non-nil, is called when a user + // attempts to authenticate with auth method "none". + // NoClientAuth must also be set to true for this be used, or + // this func is unused. + NoClientAuthCallback func(ConnMetadata) (*Permissions, error) + // MaxAuthTries specifies the maximum number of authentication attempts // permitted per connection. If set to a negative number, the number of // attempts are unlimited. If set to zero, the number of attempts are limited @@ -90,6 +130,21 @@ type ServerConfig struct { // Permissions.Extensions entry. PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + // VerifiedPublicKeyCallback, if non-nil, is called after a client + // successfully confirms having control over a key that was previously + // approved by PublicKeyCallback. The permissions object passed to the + // callback is the one returned by PublicKeyCallback for the given public + // key and its ownership is transferred to the callback. The returned + // Permissions object can be the same object, optionally modified, or a + // completely new object. If VerifiedPublicKeyCallback is non-nil, + // PublicKeyCallback is not allowed to return a PartialSuccessError, which + // can instead be returned by VerifiedPublicKeyCallback. + // + // VerifiedPublicKeyCallback does not affect which authentication methods + // are included in the list of methods that can be attempted by the client. + VerifiedPublicKeyCallback func(conn ConnMetadata, key PublicKey, permissions *Permissions, + signatureAlgorithm string) (*Permissions, error) + // KeyboardInteractiveCallback, if non-nil, is called when // keyboard-interactive authentication is selected (RFC // 4256). The client object's Challenge function should be @@ -103,6 +158,12 @@ type ServerConfig struct { // attempts. AuthLogCallback func(conn ConnMetadata, method string, err error) + // PreAuthConnCallback, if non-nil, is called upon receiving a new connection + // before any authentication has started. The provided ServerPreAuthConn + // can be used at any time before authentication is complete, including + // after this callback has returned. + PreAuthConnCallback func(ServerPreAuthConn) + // ServerVersion is the version identification string to announce in // the public handshake. // If empty, a reasonable default is used. @@ -120,7 +181,7 @@ type ServerConfig struct { } // AddHostKey adds a private key as a host key. If an existing host -// key exists with the same algorithm, it is overwritten. Each server +// key exists with the same public key format, it is replaced. Each server // config must have at least one host key. func (s *ServerConfig) AddHostKey(key Signer) { for i, k := range s.hostKeys { @@ -134,7 +195,7 @@ func (s *ServerConfig) AddHostKey(key Signer) { } // cachedPubKey contains the results of querying whether a public key is -// acceptable for a user. +// acceptable for a user. This is a FIFO cache. type cachedPubKey struct { user string pubKeyData []byte @@ -142,7 +203,13 @@ type cachedPubKey struct { perms *Permissions } -const maxCachedPubKeys = 16 +// maxCachedPubKeys is the number of cache entries we store. +// +// Due to consistent misuse of the PublicKeyCallback API, we have reduced this +// to 1, such that the only key in the cache is the most recently seen one. This +// forces the behavior that the last call to PublicKeyCallback will always be +// with the key that is used for authentication. +const maxCachedPubKeys = 1 // pubKeyCache caches tests for public keys. Since SSH clients // will query whether a public key is acceptable before attempting to @@ -164,9 +231,10 @@ func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { // add adds the given tuple to the cache. func (c *pubKeyCache) add(candidate cachedPubKey) { - if len(c.keys) < maxCachedPubKeys { - c.keys = append(c.keys, candidate) + if len(c.keys) >= maxCachedPubKeys { + c.keys = c.keys[1:] } + c.keys = append(c.keys, candidate) } // ServerConn is an authenticated SSH connection, as seen from the @@ -193,10 +261,14 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha if fullConf.MaxAuthTries == 0 { fullConf.MaxAuthTries = 6 } - // Check if the config contains any unsupported key exchanges - for _, kex := range fullConf.KeyExchanges { - if _, ok := serverForbiddenKexAlgos[kex]; ok { - return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex) + if len(fullConf.PublicKeyAuthAlgorithms) == 0 { + fullConf.PublicKeyAuthAlgorithms = defaultPubKeyAuthAlgos + } else { + for _, algo := range fullConf.PublicKeyAuthAlgorithms { + if !slices.Contains(SupportedAlgorithms().PublicKeyAuths, algo) && !slices.Contains(InsecureAlgorithms().PublicKeyAuths, algo) { + c.Close() + return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo) + } } } @@ -212,9 +284,10 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha } // signAndMarshal signs the data with the appropriate algorithm, -// and serializes the result in SSH wire format. -func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { - sig, err := k.Sign(rand, data) +// and serializes the result in SSH wire format. algo is the negotiate +// algorithm and may be a certificate type. +func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) { + sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) if err != nil { return nil, err } @@ -254,6 +327,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) // We just did the key change, so the session ID is established. s.sessionID = s.transport.getSessionID() + s.algorithms = s.transport.getAlgorithms() var packet []byte if packet, err = s.transport.readPacket(); err != nil { @@ -282,15 +356,6 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) return perms, err } -func isAcceptableAlgo(algo string) bool { - switch algo { - case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519, - CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01: - return true - } - return false -} - func checkSourceAddress(addr net.Addr, sourceAddrs string) error { if addr == nil { return errors.New("ssh: no address known for client, but source-address match required") @@ -321,7 +386,7 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error { return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) } -func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection, +func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, token []byte, s *connection, sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) { gssAPIServer := gssapiConfig.Server defer gssAPIServer.DeleteSecContext() @@ -331,7 +396,7 @@ func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *c outToken []byte needContinue bool ) - outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken) + outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(token) if err != nil { return err, nil, nil } @@ -353,6 +418,7 @@ func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *c if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { return nil, nil, err } + token = userAuthGSSAPITokenReq.Token } packet, err := s.transport.readPacket() if err != nil { @@ -370,6 +436,25 @@ func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *c return authErr, perms, nil } +// isAlgoCompatible checks if the signature format is compatible with the +// selected algorithm taking into account edge cases that occur with old +// clients. +func isAlgoCompatible(algo, sigFormat string) bool { + // Compatibility for old clients. + // + // For certificate authentication with OpenSSH 7.2-7.7 signature format can + // be rsa-sha2-256 or rsa-sha2-512 for the algorithm + // ssh-rsa-cert-v01@openssh.com. + // + // With gpg-agent < 2.2.6 the algorithm can be rsa-sha2-256 or rsa-sha2-512 + // for signature format ssh-rsa. + if isRSA(algo) && isRSA(sigFormat) { + return true + } + // Standard case: the underlying algorithm must match the signature format. + return underlyingAlgo(algo) == sigFormat +} + // ServerAuthError represents server authentication errors and is // sometimes returned by NewServerConn. It appends any authentication // errors that may occur, and is returned if all of the authentication @@ -388,6 +473,35 @@ func (l ServerAuthError) Error() string { return "[" + strings.Join(errs, ", ") + "]" } +// ServerAuthCallbacks defines server-side authentication callbacks. +type ServerAuthCallbacks struct { + // PasswordCallback behaves like [ServerConfig.PasswordCallback]. + PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) + + // PublicKeyCallback behaves like [ServerConfig.PublicKeyCallback]. + PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // KeyboardInteractiveCallback behaves like [ServerConfig.KeyboardInteractiveCallback]. + KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) + + // GSSAPIWithMICConfig behaves like [ServerConfig.GSSAPIWithMICConfig]. + GSSAPIWithMICConfig *GSSAPIWithMICConfig +} + +// PartialSuccessError can be returned by any of the [ServerConfig] +// authentication callbacks to indicate to the client that authentication has +// partially succeeded, but further steps are required. +type PartialSuccessError struct { + // Next defines the authentication callbacks to apply to further steps. The + // available methods communicated to the client are based on the non-nil + // ServerAuthCallbacks fields. + Next ServerAuthCallbacks +} + +func (p *PartialSuccessError) Error() string { + return "ssh: authenticated with partial success" +} + // ErrNoAuth is the error value returned if no // authentication method has been passed yet. This happens as a normal // part of the authentication loop, since the client first tries @@ -395,14 +509,46 @@ func (l ServerAuthError) Error() string { // It is returned in ServerAuthError.Errors from NewServerConn. var ErrNoAuth = errors.New("ssh: no auth passed yet") +// BannerError is an error that can be returned by authentication handlers in +// ServerConfig to send a banner message to the client. +type BannerError struct { + Err error + Message string +} + +func (b *BannerError) Unwrap() error { + return b.Err +} + +func (b *BannerError) Error() string { + if b.Err == nil { + return b.Message + } + return b.Err.Error() +} + func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { + if config.PreAuthConnCallback != nil { + config.PreAuthConnCallback(s) + } + sessionID := s.transport.getSessionID() var cache pubKeyCache var perms *Permissions authFailures := 0 + noneAuthCount := 0 var authErrs []error - var displayedBanner bool + var calledBannerCallback bool + partialSuccessReturned := false + // Set the initial authentication callbacks from the config. They can be + // changed if a PartialSuccessError is returned. + authConfig := ServerAuthCallbacks{ + PasswordCallback: config.PasswordCallback, + PublicKeyCallback: config.PublicKeyCallback, + KeyboardInteractiveCallback: config.KeyboardInteractiveCallback, + GSSAPIWithMICConfig: config.GSSAPIWithMICConfig, + } userAuthLoop: for { @@ -415,8 +561,8 @@ userAuthLoop: if err := s.transport.writePacket(Marshal(discMsg)); err != nil { return nil, err } - - return nil, discMsg + authErrs = append(authErrs, discMsg) + return nil, &ServerAuthError{Errors: authErrs} } var userAuthReq userAuthRequestMsg @@ -433,16 +579,17 @@ userAuthLoop: return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) } + if s.user != userAuthReq.User && partialSuccessReturned { + return nil, fmt.Errorf("ssh: client changed the user after a partial success authentication, previous user %q, current user %q", + s.user, userAuthReq.User) + } + s.user = userAuthReq.User - if !displayedBanner && config.BannerCallback != nil { - displayedBanner = true - msg := config.BannerCallback(s) - if msg != "" { - bannerMsg := &userAuthBannerMsg{ - Message: msg, - } - if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { + if !calledBannerCallback && config.BannerCallback != nil { + calledBannerCallback = true + if msg := config.BannerCallback(s); msg != "" { + if err := s.SendAuthBanner(msg); err != nil { return nil, err } } @@ -453,16 +600,18 @@ userAuthLoop: switch userAuthReq.Method { case "none": - if config.NoClientAuth { - authErr = nil - } - - // allow initial attempt of 'none' without penalty - if authFailures == 0 { - authFailures-- + noneAuthCount++ + // We don't allow none authentication after a partial success + // response. + if config.NoClientAuth && !partialSuccessReturned { + if config.NoClientAuthCallback != nil { + perms, authErr = config.NoClientAuthCallback(s) + } else { + authErr = nil + } } case "password": - if config.PasswordCallback == nil { + if authConfig.PasswordCallback == nil { authErr = errors.New("ssh: password auth not configured") break } @@ -476,17 +625,17 @@ userAuthLoop: return nil, parseError(msgUserAuthRequest) } - perms, authErr = config.PasswordCallback(s, password) + perms, authErr = authConfig.PasswordCallback(s, password) case "keyboard-interactive": - if config.KeyboardInteractiveCallback == nil { + if authConfig.KeyboardInteractiveCallback == nil { authErr = errors.New("ssh: keyboard-interactive auth not configured") break } prompter := &sshClientKeyboardInteractive{s} - perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) + perms, authErr = authConfig.KeyboardInteractiveCallback(s, prompter.Challenge) case "publickey": - if config.PublicKeyCallback == nil { + if authConfig.PublicKeyCallback == nil { authErr = errors.New("ssh: publickey auth not configured") break } @@ -501,7 +650,7 @@ userAuthLoop: return nil, parseError(msgUserAuthRequest) } algo := string(algoBytes) - if !isAcceptableAlgo(algo) { + if !slices.Contains(config.PublicKeyAuthAlgorithms, underlyingAlgo(algo)) { authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) break } @@ -520,11 +669,21 @@ userAuthLoop: if !ok { candidate.user = s.user candidate.pubKeyData = pubKeyData - candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) - if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { - candidate.result = checkSourceAddress( + candidate.perms, candidate.result = authConfig.PublicKeyCallback(s, pubKey) + _, isPartialSuccessError := candidate.result.(*PartialSuccessError) + if isPartialSuccessError && config.VerifiedPublicKeyCallback != nil { + return nil, errors.New("ssh: invalid library usage: PublicKeyCallback must not return partial success when VerifiedPublicKeyCallback is defined") + } + + if (candidate.result == nil || isPartialSuccessError) && + candidate.perms != nil && + candidate.perms.CriticalOptions != nil && + candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { + if err := checkSourceAddress( s.RemoteAddr(), - candidate.perms.CriticalOptions[sourceAddressCriticalOption]) + candidate.perms.CriticalOptions[sourceAddressCriticalOption]); err != nil { + candidate.result = err + } } cache.add(candidate) } @@ -536,8 +695,8 @@ userAuthLoop: if len(payload) > 0 { return nil, parseError(msgUserAuthRequest) } - - if candidate.result == nil { + _, isPartialSuccessError := candidate.result.(*PartialSuccessError) + if candidate.result == nil || isPartialSuccessError { okMsg := userAuthPubKeyOkMsg{ Algo: algo, PubKey: pubKeyData, @@ -553,16 +712,31 @@ userAuthLoop: if !ok || len(payload) > 0 { return nil, parseError(msgUserAuthRequest) } + // Ensure the declared public key algo is compatible with the + // decoded one. This check will ensure we don't accept e.g. + // ssh-rsa-cert-v01@openssh.com algorithm with ssh-rsa public + // key type. The algorithm and public key type must be + // consistent: both must be certificate algorithms, or neither. + if !slices.Contains(algorithmsForKeyFormat(pubKey.Type()), algo) { + authErr = fmt.Errorf("ssh: public key type %q not compatible with selected algorithm %q", + pubKey.Type(), algo) + break + } // Ensure the public key algo and signature algo // are supported. Compare the private key // algorithm name that corresponds to algo with // sig.Format. This is usually the same, but // for certs, the names differ. - if !isAcceptableAlgo(sig.Format) { + if !slices.Contains(config.PublicKeyAuthAlgorithms, sig.Format) { authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format) break } - signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData) + if !isAlgoCompatible(algo, sig.Format) { + authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo) + break + } + + signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData) if err := pubKey.Verify(signedData, sig); err != nil { return nil, err @@ -570,9 +744,19 @@ userAuthLoop: authErr = candidate.result perms = candidate.perms + if authErr == nil && config.VerifiedPublicKeyCallback != nil { + // Only call VerifiedPublicKeyCallback after the key has been accepted + // and successfully verified. If authErr is non-nil, the key is not + // considered verified and the callback must not run. + perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo) + } } case "gssapi-with-mic": - gssapiConfig := config.GSSAPIWithMICConfig + if authConfig.GSSAPIWithMICConfig == nil { + authErr = errors.New("ssh: gssapi-with-mic auth not configured") + break + } + gssapiConfig := authConfig.GSSAPIWithMICConfig userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload) if err != nil { return nil, parseError(msgUserAuthRequest) @@ -624,29 +808,83 @@ userAuthLoop: config.AuthLogCallback(s, userAuthReq.Method, authErr) } + var bannerErr *BannerError + if errors.As(authErr, &bannerErr) { + if bannerErr.Message != "" { + if err := s.SendAuthBanner(bannerErr.Message); err != nil { + return nil, err + } + } + } + if authErr == nil { break userAuthLoop } - authFailures++ - var failureMsg userAuthFailureMsg - if config.PasswordCallback != nil { + + if partialSuccess, ok := authErr.(*PartialSuccessError); ok { + // After a partial success error we don't allow changing the user + // name and execute the NoClientAuthCallback. + partialSuccessReturned = true + + // In case a partial success is returned, the server may send + // a new set of authentication methods. + authConfig = partialSuccess.Next + + // Reset pubkey cache, as the new PublicKeyCallback might + // accept a different set of public keys. + cache = pubKeyCache{} + + // Send back a partial success message to the user. + failureMsg.PartialSuccess = true + } else { + // Allow initial attempt of 'none' without penalty. + if authFailures > 0 || userAuthReq.Method != "none" || noneAuthCount != 1 { + authFailures++ + } + if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries { + // If we have hit the max attempts, don't bother sending the + // final SSH_MSG_USERAUTH_FAILURE message, since there are + // no more authentication methods which can be attempted, + // and this message may cause the client to re-attempt + // authentication while we send the disconnect message. + // Continue, and trigger the disconnect at the start of + // the loop. + // + // The SSH specification is somewhat confusing about this, + // RFC 4252 Section 5.1 requires each authentication failure + // be responded to with a respective SSH_MSG_USERAUTH_FAILURE + // message, but Section 4 says the server should disconnect + // after some number of attempts, but it isn't explicit which + // message should take precedence (i.e. should there be a failure + // message than a disconnect message, or if we are going to + // disconnect, should we only send that message.) + // + // Either way, OpenSSH disconnects immediately after the last + // failed authentication attempt, and given they are typically + // considered the golden implementation it seems reasonable + // to match that behavior. + continue + } + } + + if authConfig.PasswordCallback != nil { failureMsg.Methods = append(failureMsg.Methods, "password") } - if config.PublicKeyCallback != nil { + if authConfig.PublicKeyCallback != nil { failureMsg.Methods = append(failureMsg.Methods, "publickey") } - if config.KeyboardInteractiveCallback != nil { + if authConfig.KeyboardInteractiveCallback != nil { failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") } - if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil && - config.GSSAPIWithMICConfig.AllowLogin != nil { + if authConfig.GSSAPIWithMICConfig != nil && authConfig.GSSAPIWithMICConfig.Server != nil && + authConfig.GSSAPIWithMICConfig.AllowLogin != nil { failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic") } if len(failureMsg.Methods) == 0 { - return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + return nil, errors.New("ssh: no authentication methods available") } if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil { @@ -666,7 +904,7 @@ type sshClientKeyboardInteractive struct { *connection } -func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) { +func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) { if len(questions) != len(echos) { return nil, errors.New("ssh: echos and questions must have equal length") } @@ -678,6 +916,7 @@ func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, quest } if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ + Name: name, Instruction: instruction, NumPrompts: uint32(len(questions)), Prompts: prompts, diff --git a/ssh/server_multi_auth_test.go b/ssh/server_multi_auth_test.go new file mode 100644 index 0000000000..3b39802437 --- /dev/null +++ b/ssh/server_multi_auth_test.go @@ -0,0 +1,412 @@ +// Copyright 2024 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 ssh + +import ( + "bytes" + "errors" + "fmt" + "strings" + "testing" +) + +func doClientServerAuth(t *testing.T, serverConfig *ServerConfig, clientConfig *ClientConfig) ([]error, error) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + var serverAuthErrors []error + + serverConfig.AddHostKey(testSigners["rsa"]) + serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) { + serverAuthErrors = append(serverAuthErrors, err) + } + go newServer(c1, serverConfig) + c, _, _, err := NewClientConn(c2, "", clientConfig) + if err == nil { + c.Close() + } + return serverAuthErrors, err +} + +func TestMultiStepAuth(t *testing.T) { + // This user can login with password, public key or public key + password. + username := "testuser" + // This user can login with public key + password only. + usernameSecondFactor := "testuser_second_factor" + errPwdAuthFailed := errors.New("password auth failed") + errWrongSequence := errors.New("wrong sequence") + + serverConfig := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if conn.User() == usernameSecondFactor { + return nil, errWrongSequence + } + if conn.User() == username && string(password) == clientPassword { + return nil, nil + } + return nil, errPwdAuthFailed + }, + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + if conn.User() == usernameSecondFactor { + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if string(password) == clientPassword { + return nil, nil + } + return nil, errPwdAuthFailed + }, + }, + } + } + return nil, nil + } + return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) + }, + } + + clientConfig := &ClientConfig{ + User: usernameSecondFactor, + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + serverAuthErrors, err := doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("client login error: %s", err) + } + + // The error sequence is: + // - no auth passed yet + // - partial success + // - nil + if len(serverAuthErrors) != 3 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok { + t.Fatalf("expected partial success error, got: %v", serverAuthErrors[1]) + } + // Now test a wrong sequence. + clientConfig.Auth = []AuthMethod{ + Password(clientPassword), + PublicKeys(testSigners["rsa"]), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err == nil { + t.Fatal("client login with wrong sequence must fail") + } + // The error sequence is: + // - no auth passed yet + // - wrong sequence + // - partial success + if len(serverAuthErrors) != 3 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if serverAuthErrors[1] != errWrongSequence { + t.Fatal("server not returned wrong sequence") + } + if _, ok := serverAuthErrors[2].(*PartialSuccessError); !ok { + t.Fatalf("expected partial success error, got: %v", serverAuthErrors[2]) + } + // Now test using a correct sequence but a wrong password before the right + // one. + n := 0 + passwords := []string{"WRONG", "WRONG", clientPassword} + clientConfig.Auth = []AuthMethod{ + PublicKeys(testSigners["rsa"]), + RetryableAuthMethod(PasswordCallback(func() (string, error) { + p := passwords[n] + n++ + return p, nil + }), 3), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("client login error: %s", err) + } + // The error sequence is: + // - no auth passed yet + // - partial success + // - wrong password + // - wrong password + // - nil + if len(serverAuthErrors) != 5 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + if serverAuthErrors[2] != errPwdAuthFailed { + t.Fatal("server not returned password authentication failed") + } + if serverAuthErrors[3] != errPwdAuthFailed { + t.Fatal("server not returned password authentication failed") + } + // Only password authentication should fail. + clientConfig.Auth = []AuthMethod{ + Password(clientPassword), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err == nil { + t.Fatal("client login with password only must fail") + } + // The error sequence is: + // - no auth passed yet + // - wrong sequence + if len(serverAuthErrors) != 2 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if serverAuthErrors[1] != errWrongSequence { + t.Fatal("server not returned wrong sequence") + } + + // Only public key authentication should fail. + clientConfig.Auth = []AuthMethod{ + PublicKeys(testSigners["rsa"]), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err == nil { + t.Fatal("client login with public key only must fail") + } + // The error sequence is: + // - no auth passed yet + // - partial success + if len(serverAuthErrors) != 2 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + + // Public key and wrong password. + clientConfig.Auth = []AuthMethod{ + PublicKeys(testSigners["rsa"]), + Password("WRONG"), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err == nil { + t.Fatal("client login with wrong password after public key must fail") + } + // The error sequence is: + // - no auth passed yet + // - partial success + // - password auth failed + if len(serverAuthErrors) != 3 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + if serverAuthErrors[2] != errPwdAuthFailed { + t.Fatal("server not returned password authentication failed") + } + + // Public key, public key again and then correct password. Public key + // authentication is attempted only once because the partial success error + // returns only "password" as the allowed authentication method. + clientConfig.Auth = []AuthMethod{ + PublicKeys(testSigners["rsa"]), + PublicKeys(testSigners["rsa"]), + Password(clientPassword), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("client login error: %s", err) + } + // The error sequence is: + // - no auth passed yet + // - partial success + // - nil + if len(serverAuthErrors) != 3 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + + // The unrestricted username can do anything + clientConfig = &ClientConfig{ + User: username, + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, err = doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("unrestricted client login error: %s", err) + } + + clientConfig = &ClientConfig{ + User: username, + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, err = doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("unrestricted client login error: %s", err) + } + + clientConfig = &ClientConfig{ + User: username, + Auth: []AuthMethod{ + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, err = doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("unrestricted client login error: %s", err) + } +} + +func TestDynamicAuthCallbacks(t *testing.T) { + user1 := "user1" + user2 := "user2" + errInvalidCredentials := errors.New("invalid credentials") + + serverConfig := &ServerConfig{ + NoClientAuth: true, + NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) { + switch conn.User() { + case user1: + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if conn.User() == user1 && string(password) == clientPassword { + return nil, nil + } + return nil, errInvalidCredentials + }, + }, + } + case user2: + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + if conn.User() == user2 { + return nil, nil + } + } + return nil, errInvalidCredentials + }, + }, + } + default: + return nil, errInvalidCredentials + } + }, + } + + clientConfig := &ClientConfig{ + User: user1, + Auth: []AuthMethod{ + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + serverAuthErrors, err := doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("client login error: %s", err) + } + // The error sequence is: + // - partial success + // - nil + if len(serverAuthErrors) != 2 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + + clientConfig = &ClientConfig{ + User: user2, + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("client login error: %s", err) + } + // The error sequence is: + // - partial success + // - nil + if len(serverAuthErrors) != 2 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + + // user1 cannot login with public key + clientConfig = &ClientConfig{ + User: user1, + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err == nil { + t.Fatal("user1 login with public key must fail") + } + if !strings.Contains(err.Error(), "no supported methods remain") { + t.Errorf("got %v, expected 'no supported methods remain'", err) + } + if len(serverAuthErrors) != 1 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } + // user2 cannot login with password + clientConfig = &ClientConfig{ + User: user2, + Auth: []AuthMethod{ + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig) + if err == nil { + t.Fatal("user2 login with password must fail") + } + if !strings.Contains(err.Error(), "no supported methods remain") { + t.Errorf("got %v, expected 'no supported methods remain'", err) + } + if len(serverAuthErrors) != 1 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok { + t.Fatal("server not returned partial success") + } +} diff --git a/ssh/server_test.go b/ssh/server_test.go new file mode 100644 index 0000000000..e1861931db --- /dev/null +++ b/ssh/server_test.go @@ -0,0 +1,852 @@ +// Copyright 2023 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 ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "reflect" + "strings" + "sync/atomic" + "testing" + "time" +) + +func TestClientAuthRestrictedPublicKeyAlgos(t *testing.T) { + for _, tt := range []struct { + name string + key Signer + wantError bool + }{ + {"rsa", testSigners["rsa"], false}, + {"dsa", testSigners["dsa"], true}, + {"ed25519", testSigners["ed25519"], true}, + } { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + serverConf := &ServerConfig{ + PublicKeyAuthAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}, + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + return nil, nil + }, + } + serverConf.AddHostKey(testSigners["ecdsap256"]) + + done := make(chan struct{}) + go func() { + defer close(done) + NewServerConn(c1, serverConf) + }() + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(tt.key), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + if !tt.wantError { + t.Errorf("%s: got unexpected error %q", tt.name, err.Error()) + } + } else if tt.wantError { + t.Errorf("%s: succeeded, but want error", tt.name) + } + <-done + } +} + +func TestMaxAuthTriesNoneMethod(t *testing.T) { + username := "testuser" + serverConfig := &ServerConfig{ + MaxAuthTries: 2, + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if conn.User() == username && string(password) == clientPassword { + return nil, nil + } + return nil, errors.New("invalid credentials") + }, + } + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + var serverAuthErrors []error + + serverConfig.AddHostKey(testSigners["rsa"]) + serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) { + serverAuthErrors = append(serverAuthErrors, err) + } + go newServer(c1, serverConfig) + + clientConfig := ClientConfig{ + User: username, + HostKeyCallback: InsecureIgnoreHostKey(), + } + clientConfig.SetDefaults() + // Our client will send 'none' auth only once, so we need to send the + // requests manually. + c := &connection{ + sshConn: sshConn{ + conn: c2, + user: username, + clientVersion: []byte(packageVersion), + }, + } + c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) + if err != nil { + t.Fatalf("unable to exchange version: %v", err) + } + c.transport = newClientTransport( + newTransport(c.sshConn.conn, clientConfig.Rand, true /* is client */), + c.clientVersion, c.serverVersion, &clientConfig, "", c.sshConn.RemoteAddr()) + if err := c.transport.waitSession(); err != nil { + t.Fatalf("unable to wait session: %v", err) + } + c.sessionID = c.transport.getSessionID() + if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { + t.Fatalf("unable to send ssh-userauth message: %v", err) + } + packet, err := c.transport.readPacket() + if err != nil { + t.Fatal(err) + } + if len(packet) > 0 && packet[0] == msgExtInfo { + packet, err = c.transport.readPacket() + if err != nil { + t.Fatal(err) + } + } + var serviceAccept serviceAcceptMsg + if err := Unmarshal(packet, &serviceAccept); err != nil { + t.Fatal(err) + } + for i := 0; i <= serverConfig.MaxAuthTries; i++ { + auth := new(noneAuth) + _, _, err := auth.auth(c.sessionID, clientConfig.User, c.transport, clientConfig.Rand, nil) + if i < serverConfig.MaxAuthTries { + if err != nil { + t.Fatal(err) + } + continue + } + if err == nil { + t.Fatal("client: got no error") + } else if !strings.Contains(err.Error(), "too many authentication failures") { + t.Fatalf("client: got unexpected error: %v", err) + } + } + if len(serverAuthErrors) != 3 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + for _, err := range serverAuthErrors { + if !errors.Is(err, ErrNoAuth) { + t.Errorf("go error: %v; want: %v", err, ErrNoAuth) + } + } +} + +func TestMaxAuthTriesFirstNoneAuthErrorIgnored(t *testing.T) { + username := "testuser" + serverConfig := &ServerConfig{ + MaxAuthTries: 1, + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if conn.User() == username && string(password) == clientPassword { + return nil, nil + } + return nil, errors.New("invalid credentials") + }, + } + clientConfig := &ClientConfig{ + User: username, + Auth: []AuthMethod{ + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + serverAuthErrors, err := doClientServerAuth(t, serverConfig, clientConfig) + if err != nil { + t.Fatalf("client login error: %s", err) + } + if len(serverAuthErrors) != 2 { + t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors) + } + if !errors.Is(serverAuthErrors[0], ErrNoAuth) { + t.Errorf("go error: %v; want: %v", serverAuthErrors[0], ErrNoAuth) + } + if serverAuthErrors[1] != nil { + t.Errorf("unexpected error: %v", serverAuthErrors[1]) + } +} + +func TestNewServerConnValidationErrors(t *testing.T) { + serverConf := &ServerConfig{ + PublicKeyAuthAlgorithms: []string{CertAlgoRSAv01}, + } + c := &markerConn{} + _, _, _, err := NewServerConn(c, serverConf) + if err == nil { + t.Fatal("NewServerConn with invalid public key auth algorithms succeeded") + } + if !c.isClosed() { + t.Fatal("NewServerConn with invalid public key auth algorithms left connection open") + } + if c.isUsed() { + t.Fatal("NewServerConn with invalid public key auth algorithms used connection") + } + + serverConf = &ServerConfig{ + Config: Config{ + KeyExchanges: []string{KeyExchangeDHGEXSHA256}, + }, + } + c = &markerConn{} + _, _, _, err = NewServerConn(c, serverConf) + if err == nil { + t.Fatal("NewServerConn with unsupported key exchange succeeded") + } + if !c.isClosed() { + t.Fatal("NewServerConn with unsupported key exchange left connection open") + } + if c.isUsed() { + t.Fatal("NewServerConn with unsupported key exchange used connection") + } +} + +func TestBannerError(t *testing.T) { + serverConfig := &ServerConfig{ + BannerCallback: func(ConnMetadata) string { + return "banner from BannerCallback" + }, + NoClientAuth: true, + NoClientAuthCallback: func(ConnMetadata) (*Permissions, error) { + err := &BannerError{ + Err: errors.New("error from NoClientAuthCallback"), + Message: "banner from NoClientAuthCallback", + } + return nil, fmt.Errorf("wrapped: %w", err) + }, + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + return nil, &BannerError{ + Err: errors.New("error from PublicKeyCallback"), + Message: "banner from PublicKeyCallback", + } + }, + KeyboardInteractiveCallback: func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) { + return nil, &BannerError{ + Err: nil, // make sure that a nil inner error is allowed + Message: "banner from KeyboardInteractiveCallback", + } + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + var banners []string + clientConfig := &ClientConfig{ + User: "test", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + KeyboardInteractive(func(name, instruction string, questions []string, echos []bool) ([]string, error) { + return []string{"letmein"}, nil + }), + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + BannerCallback: func(msg string) error { + banners = append(banners, msg) + return nil + }, + } + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + go newServer(c1, serverConfig) + c, _, _, err := NewClientConn(c2, "", clientConfig) + if err != nil { + t.Fatalf("client connection failed: %v", err) + } + defer c.Close() + + wantBanners := []string{ + "banner from BannerCallback", + "banner from NoClientAuthCallback", + "banner from PublicKeyCallback", + "banner from KeyboardInteractiveCallback", + } + if !reflect.DeepEqual(banners, wantBanners) { + t.Errorf("got banners:\n%q\nwant banners:\n%q", banners, wantBanners) + } +} + +func TestPublicKeyCallbackLastSeen(t *testing.T) { + var lastSeenKey PublicKey + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + serverConf := &ServerConfig{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + lastSeenKey = key + fmt.Printf("seen %#v\n", key) + if _, ok := key.(*dsaPublicKey); !ok { + return nil, errors.New("nope") + } + return nil, nil + }, + } + serverConf.AddHostKey(testSigners["ecdsap256"]) + + done := make(chan struct{}) + go func() { + defer close(done) + NewServerConn(c1, serverConf) + }() + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"], testSigners["dsa"], testSigners["ed25519"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + t.Fatal(err) + } + <-done + + expectedPublicKey := testSigners["dsa"].PublicKey().Marshal() + lastSeenMarshalled := lastSeenKey.Marshal() + if !bytes.Equal(lastSeenMarshalled, expectedPublicKey) { + t.Errorf("unexpected key: got %#v, want %#v", lastSeenKey, testSigners["dsa"].PublicKey()) + } +} + +func TestPreAuthConnAndBanners(t *testing.T) { + testDone := make(chan struct{}) + defer close(testDone) + + authConnc := make(chan ServerPreAuthConn, 1) + serverConfig := &ServerConfig{ + PreAuthConnCallback: func(c ServerPreAuthConn) { + t.Logf("got ServerPreAuthConn: %v", c) + authConnc <- c // for use later in the test + for _, s := range []string{"hello1", "hello2"} { + if err := c.SendAuthBanner(s); err != nil { + t.Errorf("failed to send banner %q: %v", s, err) + } + } + // Now start a goroutine to spam SendAuthBanner in hopes + // of hitting a race. + go func() { + for { + select { + case <-testDone: + return + default: + if err := c.SendAuthBanner("attempted-race"); err != nil && err != errSendBannerPhase { + t.Errorf("unexpected error from SendAuthBanner: %v", err) + } + time.Sleep(5 * time.Millisecond) + } + } + }() + }, + NoClientAuth: true, + NoClientAuthCallback: func(ConnMetadata) (*Permissions, error) { + t.Logf("got NoClientAuthCallback") + return &Permissions{}, nil + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + var banners []string + clientConfig := &ClientConfig{ + User: "test", + HostKeyCallback: InsecureIgnoreHostKey(), + BannerCallback: func(msg string) error { + if msg != "attempted-race" { + banners = append(banners, msg) + } + return nil + }, + } + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + go newServer(c1, serverConfig) + c, _, _, err := NewClientConn(c2, "", clientConfig) + if err != nil { + t.Fatalf("client connection failed: %v", err) + } + defer c.Close() + + wantBanners := []string{ + "hello1", + "hello2", + } + if !reflect.DeepEqual(banners, wantBanners) { + t.Errorf("got banners:\n%q\nwant banners:\n%q", banners, wantBanners) + } + + // Now that we're authenticated, verify that use of SendBanner + // is an error. + var bc ServerPreAuthConn + select { + case bc = <-authConnc: + default: + t.Fatal("expected ServerPreAuthConn") + } + if err := bc.SendAuthBanner("wrong-phase"); err == nil { + t.Error("unexpected success of SendAuthBanner after authentication") + } else if err != errSendBannerPhase { + t.Errorf("unexpected error: %v; want %v", err, errSendBannerPhase) + } +} + +func TestVerifiedPublicKeyCallback(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + extraKey := "extra" + extraDataString := "just a string" + + serverConf := &ServerConfig{ + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + if permissions != nil && permissions.ExtraData != nil { + if !reflect.DeepEqual(map[any]any{extraKey: extraDataString}, permissions.ExtraData) { + t.Errorf("expected extra data: %v; got: %v", extraDataString, permissions.ExtraData) + } + } else { + t.Error("expected extra data is missing") + } + if signatureAlgorithm != KeyAlgoRSASHA256 { + t.Errorf("expected signature algorithm: %q; got: %q", KeyAlgoRSASHA256, signatureAlgorithm) + } + return permissions, nil + }, + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + return &Permissions{ExtraData: map[any]any{extraKey: extraDataString}}, nil + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + done := make(chan struct{}) + go func() { + defer close(done) + conn, _, _, err := NewServerConn(c1, serverConf) + if err != nil { + t.Errorf("unexpected server error: %v", err) + } + if !reflect.DeepEqual(map[any]any{extraKey: extraDataString}, conn.Permissions.ExtraData) { + t.Errorf("expected extra data: %v; got: %v", extraDataString, conn.Permissions.ExtraData) + } + }() + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + t.Fatal(err) + } + <-done +} + +func TestVerifiedPublicCallbackPartialSuccess(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + return nil, errors.New("invalid credentials") + }, + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if string(password) == clientPassword { + return nil, nil + } + return nil, nil + }, + }, + } + } + return nil, errors.New("invalid credentials") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + go NewServerConn(c1, serverConf) + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + t.Fatalf("client login error: %s", err) + } +} + +func TestVerifiedPublicKeyCallbackPwdAndKey(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if string(password) == clientPassword { + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + return nil, errors.New("invalid credentials") + }, + }, + } + } + return nil, errors.New("invalid credentials") + + }, + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + return nil, errors.New("invalid credentials") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + Password(clientPassword), + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + go NewServerConn(c1, serverConf) + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + t.Fatalf("client login error: %s", err) + } +} + +func TestVerifiedPubKeyCallbackAuthMethods(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return nil, nil + }, + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + return nil, errors.New("invalid credentials") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + go NewServerConn(c1, serverConf) + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err == nil { + t.Fatal("client login succeed with only VerifiedPublicKeyCallback defined") + } +} + +func TestVerifiedPubKeyCallbackError(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + return nil, nil + }, + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + return nil, errors.New("invalid credentials") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + go NewServerConn(c1, serverConf) + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err == nil { + t.Fatal("client login succeed with VerifiedPublicKeyCallback returning an error") + } +} + +func TestVerifiedPublicCallbackPartialSuccessBadUsage(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + // Returning PartialSuccessError is not permitted when + // VerifiedPublicKeyCallback is defined. This callback is + // invoked for both query requests and real authentications, + // while VerifiedPublicKeyCallback is only triggered if the + // client has proven control of the key. + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if string(password) == clientPassword { + return nil, nil + } + return nil, nil + }, + }, + } + } + return nil, errors.New("invalid credentials") + }, + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, &PartialSuccessError{ + Next: ServerAuthCallbacks{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if string(password) == clientPassword { + return nil, nil + } + return nil, nil + }, + }, + } + } + return nil, errors.New("invalid credentials") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + go NewServerConn(c1, serverConf) + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err == nil { + t.Fatal("authentication succeeded with PartialSuccess returned from PublicKeyCallback and VerifiedPublicKeyCallback defined") + } +} + +func TestVerifiedPublicKeyCallbackOnError(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + var verifiedCallbackCalled bool + + serverConf := &ServerConfig{ + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + verifiedCallbackCalled = true + return nil, nil + }, + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + return nil, errors.New("invalid key") + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + + done := make(chan struct{}) + go func() { + defer close(done) + NewServerConn(c1, serverConf) + }() + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err == nil { + t.Fatal("authentication should fail") + } + <-done + if verifiedCallbackCalled { + t.Error("VerifiedPublicKeyCallback called after PublicKeyCallback returned an error") + } +} + +func TestVerifiedPublicKeyCallbackOnly(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + VerifiedPublicKeyCallback: func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error) { + return nil, nil + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + done := make(chan struct{}) + go func() { + defer close(done) + NewServerConn(c1, serverConf) + }() + + clientConf := ClientConfig{ + User: "user", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err == nil { + t.Fatal("authentication succeeded with only VerifiedPublicKeyCallback defined") + } + <-done +} + +type markerConn struct { + closed uint32 + used uint32 +} + +func (c *markerConn) isClosed() bool { + return atomic.LoadUint32(&c.closed) != 0 +} + +func (c *markerConn) isUsed() bool { + return atomic.LoadUint32(&c.used) != 0 +} + +func (c *markerConn) Close() error { + atomic.StoreUint32(&c.closed, 1) + return nil +} + +func (c *markerConn) Read(b []byte) (n int, err error) { + atomic.StoreUint32(&c.used, 1) + if atomic.LoadUint32(&c.closed) != 0 { + return 0, net.ErrClosed + } else { + return 0, io.EOF + } +} + +func (c *markerConn) Write(b []byte) (n int, err error) { + atomic.StoreUint32(&c.used, 1) + if atomic.LoadUint32(&c.closed) != 0 { + return 0, net.ErrClosed + } else { + return 0, io.ErrClosedPipe + } +} + +func (*markerConn) LocalAddr() net.Addr { return nil } +func (*markerConn) RemoteAddr() net.Addr { return nil } + +func (*markerConn) SetDeadline(t time.Time) error { return nil } +func (*markerConn) SetReadDeadline(t time.Time) error { return nil } +func (*markerConn) SetWriteDeadline(t time.Time) error { return nil } diff --git a/ssh/session.go b/ssh/session.go index d3321f6b78..acef62259f 100644 --- a/ssh/session.go +++ b/ssh/session.go @@ -13,7 +13,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "sync" ) @@ -85,6 +84,7 @@ const ( IXANY = 39 IXOFF = 40 IMAXBEL = 41 + IUTF8 = 42 // RFC 8160 ISIG = 50 ICANON = 51 XCASE = 52 @@ -123,7 +123,7 @@ type Session struct { // output and error. // // If either is nil, Run connects the corresponding file - // descriptor to an instance of ioutil.Discard. There is a + // descriptor to an instance of io.Discard. There is a // fixed amount of buffering that is shared for the two streams. // If either blocks it may eventually cause the remote // command to block. @@ -505,7 +505,7 @@ func (s *Session) stdout() { return } if s.Stdout == nil { - s.Stdout = ioutil.Discard + s.Stdout = io.Discard } s.copyFuncs = append(s.copyFuncs, func() error { _, err := io.Copy(s.Stdout, s.ch) @@ -518,7 +518,7 @@ func (s *Session) stderr() { return } if s.Stderr == nil { - s.Stderr = ioutil.Discard + s.Stderr = io.Discard } s.copyFuncs = append(s.copyFuncs, func() error { _, err := io.Copy(s.Stderr, s.ch.Stderr()) diff --git a/ssh/session_test.go b/ssh/session_test.go index 39853bfcd0..807a913e5a 100644 --- a/ssh/session_test.go +++ b/ssh/session_test.go @@ -11,9 +11,9 @@ import ( crypto_rand "crypto/rand" "errors" "io" - "io/ioutil" "math/rand" "net" + "sync" "testing" "golang.org/x/crypto/ssh/terminal" @@ -28,8 +28,14 @@ func dial(handler serverType, t *testing.T) *Client { t.Fatalf("netPipe: %v", err) } + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) go func() { - defer c1.Close() + defer func() { + c1.Close() + wg.Done() + }() conf := ServerConfig{ NoClientAuth: true, } @@ -37,9 +43,14 @@ func dial(handler serverType, t *testing.T) *Client { conn, chans, reqs, err := NewServerConn(c1, &conf) if err != nil { - t.Fatalf("Unable to handshake: %v", err) + t.Errorf("Unable to handshake: %v", err) + return } - go DiscardRequests(reqs) + wg.Add(1) + go func() { + DiscardRequests(reqs) + wg.Done() + }() for newCh := range chans { if newCh.ChannelType() != "session" { @@ -52,8 +63,10 @@ func dial(handler serverType, t *testing.T) *Client { t.Errorf("Accept: %v", err) continue } + wg.Add(1) go func() { handler(ch, inReqs, t) + wg.Done() }() } if err := conn.Wait(); err != io.EOF { @@ -338,8 +351,13 @@ func TestServerWindow(t *testing.T) { t.Fatal(err) } defer session.Close() - result := make(chan []byte) + serverStdin, err := session.StdinPipe() + if err != nil { + t.Fatalf("StdinPipe failed: %v", err) + } + + result := make(chan []byte) go func() { defer close(result) echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) @@ -355,10 +373,6 @@ func TestServerWindow(t *testing.T) { result <- echoedBuf.Bytes() }() - serverStdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("StdinPipe failed: %v", err) - } written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes) if err != nil { t.Errorf("failed to copy origBuf to serverStdin: %v", err) @@ -531,7 +545,7 @@ func sendSignal(signal string, ch Channel, t *testing.T) { func discardHandler(ch Channel, t *testing.T) { defer ch.Close() - io.Copy(ioutil.Discard, ch) + io.Copy(io.Discard, ch) } func echoHandler(ch Channel, in <-chan *Request, t *testing.T) { @@ -606,7 +620,7 @@ func TestClientWriteEOF(t *testing.T) { } stdin.Close() - res, err := ioutil.ReadAll(stdout) + res, err := io.ReadAll(stdout) if err != nil { t.Fatalf("Read failed: %v", err) } @@ -618,7 +632,7 @@ func TestClientWriteEOF(t *testing.T) { func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) { defer ch.Close() - data, err := ioutil.ReadAll(ch) + data, err := io.ReadAll(ch) if err != nil { t.Errorf("handler read error: %v", err) } @@ -648,30 +662,57 @@ func TestSessionID(t *testing.T) { User: "user", } + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + + srvErrCh := make(chan error, 1) + wg.Add(1) go func() { + defer wg.Done() conn, chans, reqs, err := NewServerConn(c1, serverConf) + srvErrCh <- err if err != nil { - t.Fatalf("server handshake: %v", err) + return } serverID <- conn.SessionID() - go DiscardRequests(reqs) + wg.Add(1) + go func() { + DiscardRequests(reqs) + wg.Done() + }() for ch := range chans { ch.Reject(Prohibited, "") } }() + cliErrCh := make(chan error, 1) + wg.Add(1) go func() { + defer wg.Done() conn, chans, reqs, err := NewClientConn(c2, "", clientConf) + cliErrCh <- err if err != nil { - t.Fatalf("client handshake: %v", err) + return } clientID <- conn.SessionID() - go DiscardRequests(reqs) + wg.Add(1) + go func() { + DiscardRequests(reqs) + wg.Done() + }() for ch := range chans { ch.Reject(Prohibited, "") } }() + if err := <-srvErrCh; err != nil { + t.Fatalf("server handshake: %v", err) + } + + if err := <-cliErrCh; err != nil { + t.Fatalf("client handshake: %v", err) + } + s := <-serverID c := <-clientID if bytes.Compare(s, c) != 0 { @@ -726,6 +767,8 @@ func TestHostKeyAlgorithms(t *testing.T) { serverConf.AddHostKey(testSigners["rsa"]) serverConf.AddHostKey(testSigners["ecdsa"]) + var wg sync.WaitGroup + t.Cleanup(wg.Wait) connect := func(clientConf *ClientConfig, want string) { var alg string clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error { @@ -739,7 +782,11 @@ func TestHostKeyAlgorithms(t *testing.T) { defer c1.Close() defer c2.Close() - go NewServerConn(c1, serverConf) + wg.Add(1) + go func() { + NewServerConn(c1, serverConf) + wg.Done() + }() _, _, _, err = NewClientConn(c2, "", clientConf) if err != nil { t.Fatalf("NewClientConn: %v", err) @@ -760,6 +807,12 @@ func TestHostKeyAlgorithms(t *testing.T) { clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} connect(clientConf, KeyAlgoRSA) + // Client asks for RSA-SHA2-512 explicitly. + clientConf.HostKeyAlgorithms = []string{KeyAlgoRSASHA512} + // We get back an "ssh-rsa" key but the verification happened + // with an RSA-SHA2-512 signature. + connect(clientConf, KeyAlgoRSA) + c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) @@ -767,10 +820,73 @@ func TestHostKeyAlgorithms(t *testing.T) { defer c1.Close() defer c2.Close() - go NewServerConn(c1, serverConf) + wg.Add(1) + go func() { + NewServerConn(c1, serverConf) + wg.Done() + }() clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"} _, _, _, err = NewClientConn(c2, "", clientConf) if err == nil { t.Fatal("succeeded connecting with unknown hostkey algorithm") } } + +func TestServerClientAuthCallback(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + userCh := make(chan string, 1) + + serverConf := &ServerConfig{ + NoClientAuth: true, + NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) { + userCh <- conn.User() + return nil, nil + }, + } + const someUsername = "some-username" + + serverConf.AddHostKey(testSigners["ecdsa"]) + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + User: someUsername, + } + + var wg sync.WaitGroup + t.Cleanup(wg.Wait) + wg.Add(1) + go func() { + defer wg.Done() + _, chans, reqs, err := NewServerConn(c1, serverConf) + if err != nil { + t.Errorf("server handshake: %v", err) + userCh <- "error" + return + } + wg.Add(1) + go func() { + DiscardRequests(reqs) + wg.Done() + }() + for ch := range chans { + ch.Reject(Prohibited, "") + } + }() + + conn, _, _, err := NewClientConn(c2, "", clientConf) + if err != nil { + t.Fatalf("client handshake: %v", err) + return + } + conn.Close() + + got := <-userCh + if got != someUsername { + t.Errorf("username = %q; want %q", got, someUsername) + } +} diff --git a/ssh/tcpip.go b/ssh/tcpip.go index 80d35f5ec1..93d844f035 100644 --- a/ssh/tcpip.go +++ b/ssh/tcpip.go @@ -5,6 +5,7 @@ package ssh import ( + "context" "errors" "fmt" "io" @@ -332,6 +333,40 @@ func (l *tcpListener) Addr() net.Addr { return l.laddr } +// DialContext initiates a connection to the addr from the remote host. +// +// The provided Context must be non-nil. If the context expires before the +// connection is complete, an error is returned. Once successfully connected, +// any expiration of the context will not affect the connection. +// +// See func Dial for additional information. +func (c *Client) DialContext(ctx context.Context, n, addr string) (net.Conn, error) { + if err := ctx.Err(); err != nil { + return nil, err + } + type connErr struct { + conn net.Conn + err error + } + ch := make(chan connErr) + go func() { + conn, err := c.Dial(n, addr) + select { + case ch <- connErr{conn, err}: + case <-ctx.Done(): + if conn != nil { + conn.Close() + } + } + }() + select { + case res := <-ch: + return res.conn, res.err + case <-ctx.Done(): + return nil, ctx.Err() + } +} + // Dial initiates a connection to the addr from the remote host. // The resulting connection has a zero LocalAddr() and RemoteAddr(). func (c *Client) Dial(n, addr string) (net.Conn, error) { @@ -424,7 +459,7 @@ func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel return nil, err } go DiscardRequests(in) - return ch, err + return ch, nil } type tcpChan struct { diff --git a/ssh/tcpip_test.go b/ssh/tcpip_test.go index f1265cb496..4d85114727 100644 --- a/ssh/tcpip_test.go +++ b/ssh/tcpip_test.go @@ -5,7 +5,10 @@ package ssh import ( + "context" + "net" "testing" + "time" ) func TestAutoPortListenBroken(t *testing.T) { @@ -18,3 +21,33 @@ func TestAutoPortListenBroken(t *testing.T) { t.Errorf("version %q marked as broken", works) } } + +func TestClientImplementsDialContext(t *testing.T) { + type ContextDialer interface { + DialContext(context.Context, string, string) (net.Conn, error) + } + // Belt and suspenders assertion, since package net does not + // declare a ContextDialer type. + var _ ContextDialer = &net.Dialer{} + var _ ContextDialer = &Client{} +} + +func TestClientDialContextWithCancel(t *testing.T) { + c := &Client{} + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, err := c.DialContext(ctx, "tcp", "localhost:1000") + if err != context.Canceled { + t.Errorf("DialContext: got nil error, expected %v", context.Canceled) + } +} + +func TestClientDialContextWithDeadline(t *testing.T) { + c := &Client{} + ctx, cancel := context.WithDeadline(context.Background(), time.Now()) + defer cancel() + _, err := c.DialContext(ctx, "tcp", "localhost:1000") + if err != context.DeadlineExceeded { + t.Errorf("DialContext: got nil error, expected %v", context.DeadlineExceeded) + } +} diff --git a/ssh/terminal/terminal.go b/ssh/terminal/terminal.go index 2f04ee5b5c..a4d1919a9e 100644 --- a/ssh/terminal/terminal.go +++ b/ssh/terminal/terminal.go @@ -2,965 +2,75 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Deprecated: this package moved to golang.org/x/term. package terminal import ( - "bytes" "io" - "strconv" - "sync" - "unicode/utf8" + + "golang.org/x/term" ) // EscapeCodes contains escape sequences that can be written to the terminal in // order to achieve different styles of text. -type EscapeCodes struct { - // Foreground colors - Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte - - // Reset all attributes - Reset []byte -} - -var vt100EscapeCodes = EscapeCodes{ - Black: []byte{keyEscape, '[', '3', '0', 'm'}, - Red: []byte{keyEscape, '[', '3', '1', 'm'}, - Green: []byte{keyEscape, '[', '3', '2', 'm'}, - Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, - Blue: []byte{keyEscape, '[', '3', '4', 'm'}, - Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, - Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, - White: []byte{keyEscape, '[', '3', '7', 'm'}, - - Reset: []byte{keyEscape, '[', '0', 'm'}, -} +type EscapeCodes = term.EscapeCodes // Terminal contains the state for running a VT100 terminal that is capable of // reading lines of input. -type Terminal struct { - // AutoCompleteCallback, if non-null, is called for each keypress with - // the full input line and the current position of the cursor (in - // bytes, as an index into |line|). If it returns ok=false, the key - // press is processed normally. Otherwise it returns a replacement line - // and the new cursor position. - AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) - - // Escape contains a pointer to the escape codes for this terminal. - // It's always a valid pointer, although the escape codes themselves - // may be empty if the terminal doesn't support them. - Escape *EscapeCodes - - // lock protects the terminal and the state in this object from - // concurrent processing of a key press and a Write() call. - lock sync.Mutex - - c io.ReadWriter - prompt []rune - - // line is the current line being entered. - line []rune - // pos is the logical position of the cursor in line - pos int - // echo is true if local echo is enabled - echo bool - // pasteActive is true iff there is a bracketed paste operation in - // progress. - pasteActive bool - - // cursorX contains the current X value of the cursor where the left - // edge is 0. cursorY contains the row number where the first row of - // the current line is 0. - cursorX, cursorY int - // maxLine is the greatest value of cursorY so far. - maxLine int - - termWidth, termHeight int - - // outBuf contains the terminal data to be sent. - outBuf []byte - // remainder contains the remainder of any partial key sequences after - // a read. It aliases into inBuf. - remainder []byte - inBuf [256]byte - - // history contains previously entered commands so that they can be - // accessed with the up and down keys. - history stRingBuffer - // historyIndex stores the currently accessed history entry, where zero - // means the immediately previous entry. - historyIndex int - // When navigating up and down the history it's possible to return to - // the incomplete, initial line. That value is stored in - // historyPending. - historyPending string -} +type Terminal = term.Terminal // NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is // a local terminal, that terminal must first have been put into raw mode. // prompt is a string that is written at the start of each input line (i.e. // "> "). func NewTerminal(c io.ReadWriter, prompt string) *Terminal { - return &Terminal{ - Escape: &vt100EscapeCodes, - c: c, - prompt: []rune(prompt), - termWidth: 80, - termHeight: 24, - echo: true, - historyIndex: -1, - } -} - -const ( - keyCtrlD = 4 - keyCtrlU = 21 - keyEnter = '\r' - keyEscape = 27 - keyBackspace = 127 - keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota - keyUp - keyDown - keyLeft - keyRight - keyAltLeft - keyAltRight - keyHome - keyEnd - keyDeleteWord - keyDeleteLine - keyClearScreen - keyPasteStart - keyPasteEnd -) - -var ( - crlf = []byte{'\r', '\n'} - pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} - pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} -) - -// bytesToKey tries to parse a key sequence from b. If successful, it returns -// the key and the remainder of the input. Otherwise it returns utf8.RuneError. -func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { - if len(b) == 0 { - return utf8.RuneError, nil - } - - if !pasteActive { - switch b[0] { - case 1: // ^A - return keyHome, b[1:] - case 5: // ^E - return keyEnd, b[1:] - case 8: // ^H - return keyBackspace, b[1:] - case 11: // ^K - return keyDeleteLine, b[1:] - case 12: // ^L - return keyClearScreen, b[1:] - case 23: // ^W - return keyDeleteWord, b[1:] - case 14: // ^N - return keyDown, b[1:] - case 16: // ^P - return keyUp, b[1:] - } - } - - if b[0] != keyEscape { - if !utf8.FullRune(b) { - return utf8.RuneError, b - } - r, l := utf8.DecodeRune(b) - return r, b[l:] - } - - if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { - switch b[2] { - case 'A': - return keyUp, b[3:] - case 'B': - return keyDown, b[3:] - case 'C': - return keyRight, b[3:] - case 'D': - return keyLeft, b[3:] - case 'H': - return keyHome, b[3:] - case 'F': - return keyEnd, b[3:] - } - } - - if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { - switch b[5] { - case 'C': - return keyAltRight, b[6:] - case 'D': - return keyAltLeft, b[6:] - } - } - - if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { - return keyPasteStart, b[6:] - } - - if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { - return keyPasteEnd, b[6:] - } - - // If we get here then we have a key that we don't recognise, or a - // partial sequence. It's not clear how one should find the end of a - // sequence without knowing them all, but it seems that [a-zA-Z~] only - // appears at the end of a sequence. - for i, c := range b[0:] { - if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { - return keyUnknown, b[i+1:] - } - } - - return utf8.RuneError, b -} - -// queue appends data to the end of t.outBuf -func (t *Terminal) queue(data []rune) { - t.outBuf = append(t.outBuf, []byte(string(data))...) -} - -var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} -var space = []rune{' '} - -func isPrintable(key rune) bool { - isInSurrogateArea := key >= 0xd800 && key <= 0xdbff - return key >= 32 && !isInSurrogateArea -} - -// moveCursorToPos appends data to t.outBuf which will move the cursor to the -// given, logical position in the text. -func (t *Terminal) moveCursorToPos(pos int) { - if !t.echo { - return - } - - x := visualLength(t.prompt) + pos - y := x / t.termWidth - x = x % t.termWidth - - up := 0 - if y < t.cursorY { - up = t.cursorY - y - } - - down := 0 - if y > t.cursorY { - down = y - t.cursorY - } - - left := 0 - if x < t.cursorX { - left = t.cursorX - x - } - - right := 0 - if x > t.cursorX { - right = x - t.cursorX - } - - t.cursorX = x - t.cursorY = y - t.move(up, down, left, right) -} - -func (t *Terminal) move(up, down, left, right int) { - m := []rune{} - - // 1 unit up can be expressed as ^[[A or ^[A - // 5 units up can be expressed as ^[[5A - - if up == 1 { - m = append(m, keyEscape, '[', 'A') - } else if up > 1 { - m = append(m, keyEscape, '[') - m = append(m, []rune(strconv.Itoa(up))...) - m = append(m, 'A') - } - - if down == 1 { - m = append(m, keyEscape, '[', 'B') - } else if down > 1 { - m = append(m, keyEscape, '[') - m = append(m, []rune(strconv.Itoa(down))...) - m = append(m, 'B') - } - - if right == 1 { - m = append(m, keyEscape, '[', 'C') - } else if right > 1 { - m = append(m, keyEscape, '[') - m = append(m, []rune(strconv.Itoa(right))...) - m = append(m, 'C') - } - - if left == 1 { - m = append(m, keyEscape, '[', 'D') - } else if left > 1 { - m = append(m, keyEscape, '[') - m = append(m, []rune(strconv.Itoa(left))...) - m = append(m, 'D') - } - - t.queue(m) -} - -func (t *Terminal) clearLineToRight() { - op := []rune{keyEscape, '[', 'K'} - t.queue(op) -} - -const maxLineLength = 4096 - -func (t *Terminal) setLine(newLine []rune, newPos int) { - if t.echo { - t.moveCursorToPos(0) - t.writeLine(newLine) - for i := len(newLine); i < len(t.line); i++ { - t.writeLine(space) - } - t.moveCursorToPos(newPos) - } - t.line = newLine - t.pos = newPos -} - -func (t *Terminal) advanceCursor(places int) { - t.cursorX += places - t.cursorY += t.cursorX / t.termWidth - if t.cursorY > t.maxLine { - t.maxLine = t.cursorY - } - t.cursorX = t.cursorX % t.termWidth - - if places > 0 && t.cursorX == 0 { - // Normally terminals will advance the current position - // when writing a character. But that doesn't happen - // for the last character in a line. However, when - // writing a character (except a new line) that causes - // a line wrap, the position will be advanced two - // places. - // - // So, if we are stopping at the end of a line, we - // need to write a newline so that our cursor can be - // advanced to the next line. - t.outBuf = append(t.outBuf, '\r', '\n') - } -} - -func (t *Terminal) eraseNPreviousChars(n int) { - if n == 0 { - return - } - - if t.pos < n { - n = t.pos - } - t.pos -= n - t.moveCursorToPos(t.pos) - - copy(t.line[t.pos:], t.line[n+t.pos:]) - t.line = t.line[:len(t.line)-n] - if t.echo { - t.writeLine(t.line[t.pos:]) - for i := 0; i < n; i++ { - t.queue(space) - } - t.advanceCursor(n) - t.moveCursorToPos(t.pos) - } -} - -// countToLeftWord returns then number of characters from the cursor to the -// start of the previous word. -func (t *Terminal) countToLeftWord() int { - if t.pos == 0 { - return 0 - } - - pos := t.pos - 1 - for pos > 0 { - if t.line[pos] != ' ' { - break - } - pos-- - } - for pos > 0 { - if t.line[pos] == ' ' { - pos++ - break - } - pos-- - } - - return t.pos - pos -} - -// countToRightWord returns then number of characters from the cursor to the -// start of the next word. -func (t *Terminal) countToRightWord() int { - pos := t.pos - for pos < len(t.line) { - if t.line[pos] == ' ' { - break - } - pos++ - } - for pos < len(t.line) { - if t.line[pos] != ' ' { - break - } - pos++ - } - return pos - t.pos -} - -// visualLength returns the number of visible glyphs in s. -func visualLength(runes []rune) int { - inEscapeSeq := false - length := 0 - - for _, r := range runes { - switch { - case inEscapeSeq: - if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { - inEscapeSeq = false - } - case r == '\x1b': - inEscapeSeq = true - default: - length++ - } - } - - return length -} - -// handleKey processes the given key and, optionally, returns a line of text -// that the user has entered. -func (t *Terminal) handleKey(key rune) (line string, ok bool) { - if t.pasteActive && key != keyEnter { - t.addKeyToLine(key) - return - } - - switch key { - case keyBackspace: - if t.pos == 0 { - return - } - t.eraseNPreviousChars(1) - case keyAltLeft: - // move left by a word. - t.pos -= t.countToLeftWord() - t.moveCursorToPos(t.pos) - case keyAltRight: - // move right by a word. - t.pos += t.countToRightWord() - t.moveCursorToPos(t.pos) - case keyLeft: - if t.pos == 0 { - return - } - t.pos-- - t.moveCursorToPos(t.pos) - case keyRight: - if t.pos == len(t.line) { - return - } - t.pos++ - t.moveCursorToPos(t.pos) - case keyHome: - if t.pos == 0 { - return - } - t.pos = 0 - t.moveCursorToPos(t.pos) - case keyEnd: - if t.pos == len(t.line) { - return - } - t.pos = len(t.line) - t.moveCursorToPos(t.pos) - case keyUp: - entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) - if !ok { - return "", false - } - if t.historyIndex == -1 { - t.historyPending = string(t.line) - } - t.historyIndex++ - runes := []rune(entry) - t.setLine(runes, len(runes)) - case keyDown: - switch t.historyIndex { - case -1: - return - case 0: - runes := []rune(t.historyPending) - t.setLine(runes, len(runes)) - t.historyIndex-- - default: - entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) - if ok { - t.historyIndex-- - runes := []rune(entry) - t.setLine(runes, len(runes)) - } - } - case keyEnter: - t.moveCursorToPos(len(t.line)) - t.queue([]rune("\r\n")) - line = string(t.line) - ok = true - t.line = t.line[:0] - t.pos = 0 - t.cursorX = 0 - t.cursorY = 0 - t.maxLine = 0 - case keyDeleteWord: - // Delete zero or more spaces and then one or more characters. - t.eraseNPreviousChars(t.countToLeftWord()) - case keyDeleteLine: - // Delete everything from the current cursor position to the - // end of line. - for i := t.pos; i < len(t.line); i++ { - t.queue(space) - t.advanceCursor(1) - } - t.line = t.line[:t.pos] - t.moveCursorToPos(t.pos) - case keyCtrlD: - // Erase the character under the current position. - // The EOF case when the line is empty is handled in - // readLine(). - if t.pos < len(t.line) { - t.pos++ - t.eraseNPreviousChars(1) - } - case keyCtrlU: - t.eraseNPreviousChars(t.pos) - case keyClearScreen: - // Erases the screen and moves the cursor to the home position. - t.queue([]rune("\x1b[2J\x1b[H")) - t.queue(t.prompt) - t.cursorX, t.cursorY = 0, 0 - t.advanceCursor(visualLength(t.prompt)) - t.setLine(t.line, t.pos) - default: - if t.AutoCompleteCallback != nil { - prefix := string(t.line[:t.pos]) - suffix := string(t.line[t.pos:]) - - t.lock.Unlock() - newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) - t.lock.Lock() - - if completeOk { - t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) - return - } - } - if !isPrintable(key) { - return - } - if len(t.line) == maxLineLength { - return - } - t.addKeyToLine(key) - } - return -} - -// addKeyToLine inserts the given key at the current position in the current -// line. -func (t *Terminal) addKeyToLine(key rune) { - if len(t.line) == cap(t.line) { - newLine := make([]rune, len(t.line), 2*(1+len(t.line))) - copy(newLine, t.line) - t.line = newLine - } - t.line = t.line[:len(t.line)+1] - copy(t.line[t.pos+1:], t.line[t.pos:]) - t.line[t.pos] = key - if t.echo { - t.writeLine(t.line[t.pos:]) - } - t.pos++ - t.moveCursorToPos(t.pos) -} - -func (t *Terminal) writeLine(line []rune) { - for len(line) != 0 { - remainingOnLine := t.termWidth - t.cursorX - todo := len(line) - if todo > remainingOnLine { - todo = remainingOnLine - } - t.queue(line[:todo]) - t.advanceCursor(visualLength(line[:todo])) - line = line[todo:] - } -} - -// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n. -func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) { - for len(buf) > 0 { - i := bytes.IndexByte(buf, '\n') - todo := len(buf) - if i >= 0 { - todo = i - } - - var nn int - nn, err = w.Write(buf[:todo]) - n += nn - if err != nil { - return n, err - } - buf = buf[todo:] - - if i >= 0 { - if _, err = w.Write(crlf); err != nil { - return n, err - } - n++ - buf = buf[1:] - } - } - - return n, nil -} - -func (t *Terminal) Write(buf []byte) (n int, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - if t.cursorX == 0 && t.cursorY == 0 { - // This is the easy case: there's nothing on the screen that we - // have to move out of the way. - return writeWithCRLF(t.c, buf) - } - - // We have a prompt and possibly user input on the screen. We - // have to clear it first. - t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) - t.cursorX = 0 - t.clearLineToRight() - - for t.cursorY > 0 { - t.move(1 /* up */, 0, 0, 0) - t.cursorY-- - t.clearLineToRight() - } - - if _, err = t.c.Write(t.outBuf); err != nil { - return - } - t.outBuf = t.outBuf[:0] - - if n, err = writeWithCRLF(t.c, buf); err != nil { - return - } - - t.writeLine(t.prompt) - if t.echo { - t.writeLine(t.line) - } - - t.moveCursorToPos(t.pos) - - if _, err = t.c.Write(t.outBuf); err != nil { - return - } - t.outBuf = t.outBuf[:0] - return -} - -// ReadPassword temporarily changes the prompt and reads a password, without -// echo, from the terminal. -func (t *Terminal) ReadPassword(prompt string) (line string, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - oldPrompt := t.prompt - t.prompt = []rune(prompt) - t.echo = false - - line, err = t.readLine() - - t.prompt = oldPrompt - t.echo = true - - return -} - -// ReadLine returns a line of input from the terminal. -func (t *Terminal) ReadLine() (line string, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - return t.readLine() -} - -func (t *Terminal) readLine() (line string, err error) { - // t.lock must be held at this point - - if t.cursorX == 0 && t.cursorY == 0 { - t.writeLine(t.prompt) - t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - } - - lineIsPasted := t.pasteActive - - for { - rest := t.remainder - lineOk := false - for !lineOk { - var key rune - key, rest = bytesToKey(rest, t.pasteActive) - if key == utf8.RuneError { - break - } - if !t.pasteActive { - if key == keyCtrlD { - if len(t.line) == 0 { - return "", io.EOF - } - } - if key == keyPasteStart { - t.pasteActive = true - if len(t.line) == 0 { - lineIsPasted = true - } - continue - } - } else if key == keyPasteEnd { - t.pasteActive = false - continue - } - if !t.pasteActive { - lineIsPasted = false - } - line, lineOk = t.handleKey(key) - } - if len(rest) > 0 { - n := copy(t.inBuf[:], rest) - t.remainder = t.inBuf[:n] - } else { - t.remainder = nil - } - t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - if lineOk { - if t.echo { - t.historyIndex = -1 - t.history.Add(line) - } - if lineIsPasted { - err = ErrPasteIndicator - } - return - } - - // t.remainder is a slice at the beginning of t.inBuf - // containing a partial key sequence - readBuf := t.inBuf[len(t.remainder):] - var n int - - t.lock.Unlock() - n, err = t.c.Read(readBuf) - t.lock.Lock() - - if err != nil { - return - } - - t.remainder = t.inBuf[:n+len(t.remainder)] - } -} - -// SetPrompt sets the prompt to be used when reading subsequent lines. -func (t *Terminal) SetPrompt(prompt string) { - t.lock.Lock() - defer t.lock.Unlock() - - t.prompt = []rune(prompt) -} - -func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { - // Move cursor to column zero at the start of the line. - t.move(t.cursorY, 0, t.cursorX, 0) - t.cursorX, t.cursorY = 0, 0 - t.clearLineToRight() - for t.cursorY < numPrevLines { - // Move down a line - t.move(0, 1, 0, 0) - t.cursorY++ - t.clearLineToRight() - } - // Move back to beginning. - t.move(t.cursorY, 0, 0, 0) - t.cursorX, t.cursorY = 0, 0 - - t.queue(t.prompt) - t.advanceCursor(visualLength(t.prompt)) - t.writeLine(t.line) - t.moveCursorToPos(t.pos) -} - -func (t *Terminal) SetSize(width, height int) error { - t.lock.Lock() - defer t.lock.Unlock() - - if width == 0 { - width = 1 - } - - oldWidth := t.termWidth - t.termWidth, t.termHeight = width, height - - switch { - case width == oldWidth: - // If the width didn't change then nothing else needs to be - // done. - return nil - case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: - // If there is nothing on current line and no prompt printed, - // just do nothing - return nil - case width < oldWidth: - // Some terminals (e.g. xterm) will truncate lines that were - // too long when shinking. Others, (e.g. gnome-terminal) will - // attempt to wrap them. For the former, repainting t.maxLine - // works great, but that behaviour goes badly wrong in the case - // of the latter because they have doubled every full line. - - // We assume that we are working on a terminal that wraps lines - // and adjust the cursor position based on every previous line - // wrapping and turning into two. This causes the prompt on - // xterms to move upwards, which isn't great, but it avoids a - // huge mess with gnome-terminal. - if t.cursorX >= t.termWidth { - t.cursorX = t.termWidth - 1 - } - t.cursorY *= 2 - t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) - case width > oldWidth: - // If the terminal expands then our position calculations will - // be wrong in the future because we think the cursor is - // |t.pos| chars into the string, but there will be a gap at - // the end of any wrapped line. - // - // But the position will actually be correct until we move, so - // we can move back to the beginning and repaint everything. - t.clearAndRepaintLinePlusNPrevious(t.maxLine) - } - - _, err := t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - return err -} - -type pasteIndicatorError struct{} - -func (pasteIndicatorError) Error() string { - return "terminal: ErrPasteIndicator not correctly handled" + return term.NewTerminal(c, prompt) } // ErrPasteIndicator may be returned from ReadLine as the error, in addition // to valid line data. It indicates that bracketed paste mode is enabled and // that the returned line consists only of pasted data. Programs may wish to // interpret pasted data more literally than typed data. -var ErrPasteIndicator = pasteIndicatorError{} +var ErrPasteIndicator = term.ErrPasteIndicator -// SetBracketedPasteMode requests that the terminal bracket paste operations -// with markers. Not all terminals support this but, if it is supported, then -// enabling this mode will stop any autocomplete callback from running due to -// pastes. Additionally, any lines that are completely pasted will be returned -// from ReadLine with the error set to ErrPasteIndicator. -func (t *Terminal) SetBracketedPasteMode(on bool) { - if on { - io.WriteString(t.c, "\x1b[?2004h") - } else { - io.WriteString(t.c, "\x1b[?2004l") - } -} +// State contains the state of a terminal. +type State = term.State -// stRingBuffer is a ring buffer of strings. -type stRingBuffer struct { - // entries contains max elements. - entries []string - max int - // head contains the index of the element most recently added to the ring. - head int - // size contains the number of elements in the ring. - size int +// IsTerminal returns whether the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + return term.IsTerminal(fd) } -func (s *stRingBuffer) Add(a string) { - if s.entries == nil { - const defaultNumEntries = 100 - s.entries = make([]string, defaultNumEntries) - s.max = defaultNumEntries - } +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + return term.ReadPassword(fd) +} - s.head = (s.head + 1) % s.max - s.entries[s.head] = a - if s.size < s.max { - s.size++ - } +// MakeRaw puts the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + return term.MakeRaw(fd) } -// NthPreviousEntry returns the value passed to the nth previous call to Add. -// If n is zero then the immediately prior value is returned, if one, then the -// next most recent, and so on. If such an element doesn't exist then ok is -// false. -func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { - if n >= s.size { - return "", false - } - index := s.head - n - if index < 0 { - index += s.max - } - return s.entries[index], true +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, oldState *State) error { + return term.Restore(fd, oldState) } -// readPasswordLine reads from reader until it finds \n or io.EOF. -// The slice returned does not include the \n. -// readPasswordLine also ignores any \r it finds. -func readPasswordLine(reader io.Reader) ([]byte, error) { - var buf [1]byte - var ret []byte +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + return term.GetState(fd) +} - for { - n, err := reader.Read(buf[:]) - if n > 0 { - switch buf[0] { - case '\n': - return ret, nil - case '\r': - // remove \r from passwords on Windows - default: - ret = append(ret, buf[0]) - } - continue - } - if err != nil { - if err == io.EOF && len(ret) > 0 { - return ret, nil - } - return ret, err - } - } +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + return term.GetSize(fd) } diff --git a/ssh/terminal/terminal_test.go b/ssh/terminal/terminal_test.go deleted file mode 100644 index 4e7a0c658f..0000000000 --- a/ssh/terminal/terminal_test.go +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2011 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 aix darwin dragonfly freebsd linux,!appengine netbsd openbsd windows plan9 solaris - -package terminal - -import ( - "bytes" - "io" - "os" - "runtime" - "testing" -) - -type MockTerminal struct { - toSend []byte - bytesPerRead int - received []byte -} - -func (c *MockTerminal) Read(data []byte) (n int, err error) { - n = len(data) - if n == 0 { - return - } - if n > len(c.toSend) { - n = len(c.toSend) - } - if n == 0 { - return 0, io.EOF - } - if c.bytesPerRead > 0 && n > c.bytesPerRead { - n = c.bytesPerRead - } - copy(data, c.toSend[:n]) - c.toSend = c.toSend[n:] - return -} - -func (c *MockTerminal) Write(data []byte) (n int, err error) { - c.received = append(c.received, data...) - return len(data), nil -} - -func TestClose(t *testing.T) { - c := &MockTerminal{} - ss := NewTerminal(c, "> ") - line, err := ss.ReadLine() - if line != "" { - t.Errorf("Expected empty line but got: %s", line) - } - if err != io.EOF { - t.Errorf("Error should have been EOF but got: %s", err) - } -} - -var keyPressTests = []struct { - in string - line string - err error - throwAwayLines int -}{ - { - err: io.EOF, - }, - { - in: "\r", - line: "", - }, - { - in: "foo\r", - line: "foo", - }, - { - in: "a\x1b[Cb\r", // right - line: "ab", - }, - { - in: "a\x1b[Db\r", // left - line: "ba", - }, - { - in: "a\177b\r", // backspace - line: "b", - }, - { - in: "\x1b[A\r", // up - }, - { - in: "\x1b[B\r", // down - }, - { - in: "\016\r", // ^P - }, - { - in: "\014\r", // ^N - }, - { - in: "line\x1b[A\x1b[B\r", // up then down - line: "line", - }, - { - in: "line1\rline2\x1b[A\r", // recall previous line. - line: "line1", - throwAwayLines: 1, - }, - { - // recall two previous lines and append. - in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r", - line: "line1xxx", - throwAwayLines: 2, - }, - { - // Ctrl-A to move to beginning of line followed by ^K to kill - // line. - in: "a b \001\013\r", - line: "", - }, - { - // Ctrl-A to move to beginning of line, Ctrl-E to move to end, - // finally ^K to kill nothing. - in: "a b \001\005\013\r", - line: "a b ", - }, - { - in: "\027\r", - line: "", - }, - { - in: "a\027\r", - line: "", - }, - { - in: "a \027\r", - line: "", - }, - { - in: "a b\027\r", - line: "a ", - }, - { - in: "a b \027\r", - line: "a ", - }, - { - in: "one two thr\x1b[D\027\r", - line: "one two r", - }, - { - in: "\013\r", - line: "", - }, - { - in: "a\013\r", - line: "a", - }, - { - in: "ab\x1b[D\013\r", - line: "a", - }, - { - in: "Ξεσκεπάζω\r", - line: "Ξεσκεπάζω", - }, - { - in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace. - line: "", - throwAwayLines: 1, - }, - { - in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter. - line: "£", - throwAwayLines: 1, - }, - { - // Ctrl-D at the end of the line should be ignored. - in: "a\004\r", - line: "a", - }, - { - // a, b, left, Ctrl-D should erase the b. - in: "ab\x1b[D\004\r", - line: "a", - }, - { - // a, b, c, d, left, left, ^U should erase to the beginning of - // the line. - in: "abcd\x1b[D\x1b[D\025\r", - line: "cd", - }, - { - // Bracketed paste mode: control sequences should be returned - // verbatim in paste mode. - in: "abc\x1b[200~de\177f\x1b[201~\177\r", - line: "abcde\177", - }, - { - // Enter in bracketed paste mode should still work. - in: "abc\x1b[200~d\refg\x1b[201~h\r", - line: "efgh", - throwAwayLines: 1, - }, - { - // Lines consisting entirely of pasted data should be indicated as such. - in: "\x1b[200~a\r", - line: "a", - err: ErrPasteIndicator, - }, -} - -func TestKeyPresses(t *testing.T) { - for i, test := range keyPressTests { - for j := 1; j < len(test.in); j++ { - c := &MockTerminal{ - toSend: []byte(test.in), - bytesPerRead: j, - } - ss := NewTerminal(c, "> ") - for k := 0; k < test.throwAwayLines; k++ { - _, err := ss.ReadLine() - if err != nil { - t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err) - } - } - line, err := ss.ReadLine() - if line != test.line { - t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line) - break - } - if err != test.err { - t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err) - break - } - } - } -} - -var renderTests = []struct { - in string - received string - err error -}{ - { - // Cursor move after keyHome (left 4) then enter (right 4, newline) - in: "abcd\x1b[H\r", - received: "> abcd\x1b[4D\x1b[4C\r\n", - }, - { - // Write, home, prepend, enter. Prepends rewrites the line. - in: "cdef\x1b[Hab\r", - received: "> cdef" + // Initial input - "\x1b[4Da" + // Move cursor back, insert first char - "cdef" + // Copy over original string - "\x1b[4Dbcdef" + // Repeat for second char with copy - "\x1b[4D" + // Put cursor back in position to insert again - "\x1b[4C\r\n", // Put cursor at the end of the line and newline. - }, -} - -func TestRender(t *testing.T) { - for i, test := range renderTests { - for j := 1; j < len(test.in); j++ { - c := &MockTerminal{ - toSend: []byte(test.in), - bytesPerRead: j, - } - ss := NewTerminal(c, "> ") - _, err := ss.ReadLine() - if err != test.err { - t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err) - break - } - if test.received != string(c.received) { - t.Errorf("Results rendered from test %d (%d bytes per read) was '%s', expected '%s'", i, j, c.received, test.received) - break - } - } - } -} - -func TestPasswordNotSaved(t *testing.T) { - c := &MockTerminal{ - toSend: []byte("password\r\x1b[A\r"), - bytesPerRead: 1, - } - ss := NewTerminal(c, "> ") - pw, _ := ss.ReadPassword("> ") - if pw != "password" { - t.Fatalf("failed to read password, got %s", pw) - } - line, _ := ss.ReadLine() - if len(line) > 0 { - t.Fatalf("password was saved in history") - } -} - -var setSizeTests = []struct { - width, height int -}{ - {40, 13}, - {80, 24}, - {132, 43}, -} - -func TestTerminalSetSize(t *testing.T) { - for _, setSize := range setSizeTests { - c := &MockTerminal{ - toSend: []byte("password\r\x1b[A\r"), - bytesPerRead: 1, - } - ss := NewTerminal(c, "> ") - ss.SetSize(setSize.width, setSize.height) - pw, _ := ss.ReadPassword("Password: ") - if pw != "password" { - t.Fatalf("failed to read password, got %s", pw) - } - if string(c.received) != "Password: \r\n" { - t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received) - } - } -} - -func TestReadPasswordLineEnd(t *testing.T) { - var tests = []struct { - input string - want string - }{ - {"\n", ""}, - {"\r\n", ""}, - {"test\r\n", "test"}, - {"testtesttesttes\n", "testtesttesttes"}, - {"testtesttesttes\r\n", "testtesttesttes"}, - {"testtesttesttesttest\n", "testtesttesttesttest"}, - {"testtesttesttesttest\r\n", "testtesttesttesttest"}, - } - for _, test := range tests { - buf := new(bytes.Buffer) - if _, err := buf.WriteString(test.input); err != nil { - t.Fatal(err) - } - - have, err := readPasswordLine(buf) - if err != nil { - t.Errorf("readPasswordLine(%q) failed: %v", test.input, err) - continue - } - if string(have) != test.want { - t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want) - continue - } - - if _, err = buf.WriteString(test.input); err != nil { - t.Fatal(err) - } - have, err = readPasswordLine(buf) - if err != nil { - t.Errorf("readPasswordLine(%q) failed: %v", test.input, err) - continue - } - if string(have) != test.want { - t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want) - continue - } - } -} - -func TestMakeRawState(t *testing.T) { - fd := int(os.Stdout.Fd()) - if !IsTerminal(fd) { - t.Skip("stdout is not a terminal; skipping test") - } - - st, err := GetState(fd) - if err != nil { - t.Fatalf("failed to get terminal state from GetState: %s", err) - } - - if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { - t.Skip("MakeRaw not allowed on iOS; skipping test") - } - - defer Restore(fd, st) - raw, err := MakeRaw(fd) - if err != nil { - t.Fatalf("failed to get terminal state from MakeRaw: %s", err) - } - - if *st != *raw { - t.Errorf("states do not match; was %v, expected %v", raw, st) - } -} - -func TestOutputNewlines(t *testing.T) { - // \n should be changed to \r\n in terminal output. - buf := new(bytes.Buffer) - term := NewTerminal(buf, ">") - - term.Write([]byte("1\n2\n")) - output := string(buf.Bytes()) - const expected = "1\r\n2\r\n" - - if output != expected { - t.Errorf("incorrect output: was %q, expected %q", output, expected) - } -} diff --git a/ssh/terminal/util.go b/ssh/terminal/util.go deleted file mode 100644 index 3911040840..0000000000 --- a/ssh/terminal/util.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2011 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 aix darwin dragonfly freebsd linux,!appengine netbsd openbsd - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal // import "golang.org/x/crypto/ssh/terminal" - -import ( - "golang.org/x/sys/unix" -) - -// State contains the state of a terminal. -type State struct { - termios unix.Termios -} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - return err == nil -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, err - } - - oldState := State{termios: *termios} - - // This attempts to replicate the behaviour documented for cfmakeraw in - // the termios(3) manpage. - termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON - termios.Oflag &^= unix.OPOST - termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN - termios.Cflag &^= unix.CSIZE | unix.PARENB - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil { - return nil, err - } - - return &oldState, nil -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, err - } - - return &State{termios: *termios}, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios) -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) - if err != nil { - return -1, -1, err - } - return int(ws.Col), int(ws.Row), nil -} - -// passwordReader is an io.Reader that reads from a specific file descriptor. -type passwordReader int - -func (r passwordReader) Read(buf []byte) (int, error) { - return unix.Read(int(r), buf) -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, err - } - - newState := *termios - newState.Lflag &^= unix.ECHO - newState.Lflag |= unix.ICANON | unix.ISIG - newState.Iflag |= unix.ICRNL - if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil { - return nil, err - } - - defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) - - return readPasswordLine(passwordReader(fd)) -} diff --git a/ssh/terminal/util_aix.go b/ssh/terminal/util_aix.go deleted file mode 100644 index dfcd627859..0000000000 --- a/ssh/terminal/util_aix.go +++ /dev/null @@ -1,12 +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 aix - -package terminal - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TCGETS -const ioctlWriteTermios = unix.TCSETS diff --git a/ssh/terminal/util_bsd.go b/ssh/terminal/util_bsd.go deleted file mode 100644 index cb23a59049..0000000000 --- a/ssh/terminal/util_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 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 darwin dragonfly freebsd netbsd openbsd - -package terminal - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TIOCGETA -const ioctlWriteTermios = unix.TIOCSETA diff --git a/ssh/terminal/util_linux.go b/ssh/terminal/util_linux.go deleted file mode 100644 index 5fadfe8a1d..0000000000 --- a/ssh/terminal/util_linux.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2013 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 terminal - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TCGETS -const ioctlWriteTermios = unix.TCSETS diff --git a/ssh/terminal/util_plan9.go b/ssh/terminal/util_plan9.go deleted file mode 100644 index 9317ac7ede..0000000000 --- a/ssh/terminal/util_plan9.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal - -import ( - "fmt" - "runtime" -) - -type State struct{} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - return false -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} diff --git a/ssh/terminal/util_solaris.go b/ssh/terminal/util_solaris.go deleted file mode 100644 index 3d5f06a9f0..0000000000 --- a/ssh/terminal/util_solaris.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build solaris - -package terminal // import "golang.org/x/crypto/ssh/terminal" - -import ( - "golang.org/x/sys/unix" - "io" - "syscall" -) - -// State contains the state of a terminal. -type State struct { - termios unix.Termios -} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - _, err := unix.IoctlGetTermio(fd, unix.TCGETA) - return err == nil -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c - val, err := unix.IoctlGetTermios(fd, unix.TCGETS) - if err != nil { - return nil, err - } - oldState := *val - - newState := oldState - newState.Lflag &^= syscall.ECHO - newState.Lflag |= syscall.ICANON | syscall.ISIG - newState.Iflag |= syscall.ICRNL - err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState) - if err != nil { - return nil, err - } - - defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState) - - var buf [16]byte - var ret []byte - for { - n, err := syscall.Read(fd, buf[:]) - if err != nil { - return nil, err - } - if n == 0 { - if len(ret) == 0 { - return nil, io.EOF - } - break - } - if buf[n-1] == '\n' { - n-- - } - ret = append(ret, buf[:n]...) - if n < len(buf) { - break - } - } - - return ret, nil -} - -// MakeRaw puts the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -// see http://cr.illumos.org/~webrev/andy_js/1060/ -func MakeRaw(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) - if err != nil { - return nil, err - } - - oldState := State{termios: *termios} - - termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON - termios.Oflag &^= unix.OPOST - termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN - termios.Cflag &^= unix.CSIZE | unix.PARENB - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - - if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil { - return nil, err - } - - return &oldState, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, oldState *State) error { - return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios) -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) - if err != nil { - return nil, err - } - - return &State{termios: *termios}, nil -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) - if err != nil { - return 0, 0, err - } - return int(ws.Col), int(ws.Row), nil -} diff --git a/ssh/terminal/util_windows.go b/ssh/terminal/util_windows.go deleted file mode 100644 index 5cfdf8f3f0..0000000000 --- a/ssh/terminal/util_windows.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2011 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 windows - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal - -import ( - "os" - - "golang.org/x/sys/windows" -) - -type State struct { - mode uint32 -} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - var st uint32 - err := windows.GetConsoleMode(windows.Handle(fd), &st) - return err == nil -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - var st uint32 - if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { - return nil, err - } - raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) - if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { - return nil, err - } - return &State{st}, nil -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - var st uint32 - if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { - return nil, err - } - return &State{st}, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return windows.SetConsoleMode(windows.Handle(fd), state.mode) -} - -// GetSize returns the visible dimensions of the given terminal. -// -// These dimensions don't include any scrollback buffer height. -func GetSize(fd int) (width, height int, err error) { - var info windows.ConsoleScreenBufferInfo - if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { - return 0, 0, err - } - return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - var st uint32 - if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { - return nil, err - } - old := st - - st &^= (windows.ENABLE_ECHO_INPUT) - st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) - if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { - return nil, err - } - - defer windows.SetConsoleMode(windows.Handle(fd), old) - - var h windows.Handle - p, _ := windows.GetCurrentProcess() - if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { - return nil, err - } - - f := os.NewFile(uintptr(h), "stdin") - defer f.Close() - return readPasswordLine(f) -} diff --git a/ssh/test/agent_unix_test.go b/ssh/test/agent_unix_test.go index 5d320d0511..9257bfe1bc 100644 --- a/ssh/test/agent_unix_test.go +++ b/ssh/test/agent_unix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris package test @@ -16,25 +16,25 @@ import ( func TestAgentForward(t *testing.T) { server := newServer(t) - defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() keyring := agent.NewKeyring() - if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil { + if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["ecdsa"]}); err != nil { t.Fatalf("Error adding key: %s", err) } if err := keyring.Add(agent.AddedKey{ - PrivateKey: testPrivateKeys["dsa"], + PrivateKey: testPrivateKeys["ecdsa"], ConfirmBeforeUse: true, LifetimeSecs: 3600, }); err != nil { t.Fatalf("Error adding key with constraints: %s", err) } - pub := testPublicKeys["dsa"] + pub := testPublicKeys["ecdsa"] sess, err := conn.NewSession() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("NewSession: %v", err) } if err := agent.RequestAgentForwarding(sess); err != nil { diff --git a/ssh/test/banner_test.go b/ssh/test/banner_test.go deleted file mode 100644 index c3f0a08cb0..0000000000 --- a/ssh/test/banner_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 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 aix darwin dragonfly freebsd linux netbsd openbsd - -package test - -import ( - "testing" -) - -func TestBannerCallbackAgainstOpenSSH(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - - clientConf := clientConfig() - - var receivedBanner string - clientConf.BannerCallback = func(message string) error { - receivedBanner = message - return nil - } - - conn := server.Dial(clientConf) - defer conn.Close() - - expected := "Server Banner" - if receivedBanner != expected { - t.Fatalf("got %v; want %v", receivedBanner, expected) - } -} diff --git a/ssh/test/cert_test.go b/ssh/test/cert_test.go index 84ac31e733..9555a097b0 100644 --- a/ssh/test/cert_test.go +++ b/ssh/test/cert_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris package test @@ -17,10 +17,9 @@ import ( // Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly func TestCertLogin(t *testing.T) { s := newServer(t) - defer s.Shutdown() // Use a key different from the default. - clientKey := testSigners["dsa"] + clientKey := testSigners["ed25519"] caAuthKey := testSigners["ecdsa"] cert := &ssh.Certificate{ Key: clientKey.PublicKey(), diff --git a/ssh/test/dial_unix_test.go b/ssh/test/dial_unix_test.go index 8e1362c490..7d6fb2877f 100644 --- a/ssh/test/dial_unix_test.go +++ b/ssh/test/dial_unix_test.go @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !windows,!solaris,!js +//go:build !windows && !js && !wasip1 package test // direct-tcpip and direct-streamlocal functional tests import ( + "context" "fmt" "io" - "io/ioutil" "net" "strings" "testing" @@ -24,7 +24,6 @@ type dialTester interface { func testDial(t *testing.T, n, listenAddr string, x dialTester) { server := newServer(t) - defer server.Shutdown() sshConn := server.Dial(clientConfig()) defer sshConn.Close() @@ -48,13 +47,18 @@ func testDial(t *testing.T, n, listenAddr string, x dialTester) { } }() - conn, err := sshConn.Dial(n, l.Addr().String()) + ctx, cancel := context.WithCancel(context.Background()) + conn, err := sshConn.DialContext(ctx, n, l.Addr().String()) + // Canceling the context after dial should have no effect + // on the opened connection. + cancel() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("Dial: %v", err) } x.TestClientConn(t, conn) defer conn.Close() - b, err := ioutil.ReadAll(conn) + b, err := io.ReadAll(conn) if err != nil { t.Fatalf("ReadAll: %v", err) } diff --git a/ssh/test/doc.go b/ssh/test/doc.go index 198f0ca1e2..865781c819 100644 --- a/ssh/test/doc.go +++ b/ssh/test/doc.go @@ -4,4 +4,6 @@ // Package test contains integration tests for the // golang.org/x/crypto/ssh package. -package test // import "golang.org/x/crypto/ssh/test" +// +// Deprecated: this package is for internal use only. +package test diff --git a/ssh/test/forward_unix_test.go b/ssh/test/forward_unix_test.go index 2f5669a994..c10d1d02a6 100644 --- a/ssh/test/forward_unix_test.go +++ b/ssh/test/forward_unix_test.go @@ -2,16 +2,17 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris package test import ( "bytes" + "fmt" "io" - "io/ioutil" "math/rand" "net" + "runtime" "testing" "time" ) @@ -22,26 +23,32 @@ type closeWriter interface { func testPortForward(t *testing.T, n, listenAddr string) { server := newServer(t) - defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() sshListener, err := conn.Listen(n, listenAddr) if err != nil { + if runtime.GOOS == "darwin" && err == io.EOF { + t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959") + } t.Fatal(err) } + errCh := make(chan error, 1) + go func() { + defer close(errCh) sshConn, err := sshListener.Accept() if err != nil { - t.Fatalf("listen.Accept failed: %v", err) + errCh <- fmt.Errorf("listen.Accept failed: %v", err) + return } + defer sshConn.Close() _, err = io.Copy(sshConn, sshConn) if err != nil && err != io.EOF { - t.Fatalf("ssh client copy: %v", err) + errCh <- fmt.Errorf("ssh client copy: %v", err) } - sshConn.Close() }() forwardedAddr := sshListener.Addr().String() @@ -52,7 +59,7 @@ func testPortForward(t *testing.T, n, listenAddr string) { readChan := make(chan []byte) go func() { - data, _ := ioutil.ReadAll(netConn) + data, _ := io.ReadAll(netConn) readChan <- data }() @@ -76,12 +83,18 @@ func testPortForward(t *testing.T, n, listenAddr string) { t.Errorf("netConn.CloseWrite: %v", err) } + // Check for errors on server goroutine + err = <-errCh + if err != nil { + t.Fatalf("server: %v", err) + } + read := <-readChan if len(sent) != len(read) { t.Fatalf("got %d bytes, want %d", len(read), len(sent)) } - if bytes.Compare(sent, read) != 0 { + if !bytes.Equal(sent, read) { t.Fatalf("read back data does not match") } @@ -109,11 +122,13 @@ func TestPortForwardUnix(t *testing.T) { func testAcceptClose(t *testing.T, n, listenAddr string) { server := newServer(t) - defer server.Shutdown() conn := server.Dial(clientConfig()) sshListener, err := conn.Listen(n, listenAddr) if err != nil { + if runtime.GOOS == "darwin" && err == io.EOF { + t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959") + } t.Fatal(err) } @@ -151,11 +166,13 @@ func TestAcceptCloseUnix(t *testing.T) { // Check that listeners exit if the underlying client transport dies. func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) { server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) + client := server.Dial(clientConfig()) - sshListener, err := conn.Listen(n, listenAddr) + sshListener, err := client.Listen(n, listenAddr) if err != nil { + if runtime.GOOS == "darwin" && err == io.EOF { + t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959") + } t.Fatal(err) } @@ -173,14 +190,10 @@ func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) { // It would be even nicer if we closed the server side, but it // is more involved as the fd for that side is dup()ed. - server.clientConn.Close() + server.lastDialConn.Close() - select { - case <-time.After(1 * time.Second): - t.Errorf("timeout: listener did not close.") - case err := <-quit: - t.Logf("quit as expected (error %v)", err) - } + err = <-quit + t.Logf("quit as expected (error %v)", err) } func TestPortForwardConnectionCloseTCP(t *testing.T) { diff --git a/ssh/test/multi_auth_test.go b/ssh/test/multi_auth_test.go index f594d36e40..14cf1cce12 100644 --- a/ssh/test/multi_auth_test.go +++ b/ssh/test/multi_auth_test.go @@ -14,7 +14,7 @@ // not exist these tests will be skipped. See compile instructions // (for linux) in file ./sshd_test_pw.c. -// +build linux +//go:build linux package test @@ -76,27 +76,27 @@ func (ctx *multiAuthTestCtx) kbdIntCb(user, instruction string, questions []stri func TestMultiAuth(t *testing.T) { testCases := []multiAuthTestCase{ // Test password,publickey authentication, assert that password callback is called 1 time - multiAuthTestCase{ + { authMethods: []string{"password", "publickey"}, expectedPasswordCbs: 1, }, // Test keyboard-interactive,publickey authentication, assert that keyboard-interactive callback is called 1 time - multiAuthTestCase{ + { authMethods: []string{"keyboard-interactive", "publickey"}, expectedKbdIntCbs: 1, }, // Test publickey,password authentication, assert that password callback is called 1 time - multiAuthTestCase{ + { authMethods: []string{"publickey", "password"}, expectedPasswordCbs: 1, }, // Test publickey,keyboard-interactive authentication, assert that keyboard-interactive callback is called 1 time - multiAuthTestCase{ + { authMethods: []string{"publickey", "keyboard-interactive"}, expectedKbdIntCbs: 1, }, // Test password,password authentication, assert that password callback is called 2 times - multiAuthTestCase{ + { authMethods: []string{"password", "password"}, expectedPasswordCbs: 2, }, @@ -107,7 +107,6 @@ func TestMultiAuth(t *testing.T) { ctx := newMultiAuthTestCtx(t) server := newServerForConfig(t, "MultiAuth", map[string]string{"AuthMethods": strings.Join(testCase.authMethods, ",")}) - defer server.Shutdown() clientConfig := clientConfig() server.setTestPassword(clientConfig.User, ctx.password) diff --git a/ssh/test/recording_client_test.go b/ssh/test/recording_client_test.go new file mode 100644 index 0000000000..b744bd332e --- /dev/null +++ b/ssh/test/recording_client_test.go @@ -0,0 +1,504 @@ +// Copyright 2025 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 test + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" + "testing" + "time" + + "golang.org/x/crypto/internal/testenv" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/testdata" +) + +// serverPort contains the port that OpenSSH will listen on. OpenSSH can't take +// "0" as an argument here so we have to pick a number and hope that it's not in +// use on the machine. Since this only occurs when -update is given and thus +// when there's a human watching the test, this isn't too bad. +const serverPort = 24222 + +var ( + storeUsernameOnce sync.Once +) + +type clientTest struct { + // name is a freeform string identifying the test and the file in which + // the expected results will be stored. + name string + // config contains the client configuration to use for this test. + config *ssh.ClientConfig + // expectError defines the error string to check if the connection is + // expected to fail. + expectError string + // successCallback defines a callback to execute after the client connection + // is established. + successCallback func(t *testing.T, client *ssh.Client) +} + +// connFromCommand starts the reference server process, connects to it and +// returns a recordingConn for the connection. It must be closed before Waiting +// for child. +func (test *clientTest) connFromCommand(t *testing.T, config string) *recordingConn { + sshd, err := exec.LookPath("sshd") + if err != nil { + t.Skipf("sshd not found, skipping test: %v", err) + } + dir, err := os.MkdirTemp("", "sshtest") + if err != nil { + t.Fatal(err) + } + f, err := os.Create(filepath.Join(dir, "sshd_config")) + if err != nil { + t.Fatal(err) + } + if _, ok := configTmpl[config]; ok == false { + t.Fatal(fmt.Errorf("Invalid server config '%s'", config)) + } + configVars := map[string]string{ + "Dir": dir, + } + err = configTmpl[config].Execute(f, configVars) + if err != nil { + t.Fatal(err) + } + f.Close() + + writeFile(filepath.Join(dir, "banner"), []byte("Server Banner")) + + for k, v := range testdata.PEMBytes { + filename := "id_" + k + writeFile(filepath.Join(dir, filename), v) + writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) + } + + var authkeys bytes.Buffer + for k := range testdata.PEMBytes { + authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k])) + } + writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes()) + cmd := testenv.Command(t, sshd, "-D", "-e", "-f", f.Name(), "-p", strconv.Itoa(serverPort)) + cmd.Stdin = nil + var output bytes.Buffer + cmd.Stdout = &output + cmd.Stderr = &output + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + if err := os.RemoveAll(dir); err != nil { + t.Error(err) + } + // Don't check for errors; if it fails it's most + // likely "os: process already finished", and we don't + // care about that. Use os.Interrupt, so child + // processes are killed too. + cmd.Process.Signal(os.Interrupt) + cmd.Wait() + if t.Failed() { + t.Logf("OpenSSH output:\n\n%s", cmd.Stdout) + } + }) + var tcpConn net.Conn + for i := uint(0); i < 5; i++ { + tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: serverPort, + }) + if err == nil { + break + } + time.Sleep((1 << i) * 5 * time.Millisecond) + } + if err != nil { + t.Fatalf("error connecting to the OpenSSH server: %v (%v)\n\n%s", err, cmd.Wait(), output.Bytes()) + } + + record := &recordingConn{ + Conn: tcpConn, + clientToServer: true, + } + + return record +} + +func (test *clientTest) dataPath() string { + return filepath.Join("..", "testdata", "Client-"+test.name) +} + +func (test *clientTest) usernameDataPath() string { + return filepath.Join("..", "testdata", "Client-username") +} + +func (test *clientTest) loadData() (flows [][]byte, err error) { + in, err := os.Open(test.dataPath()) + if err != nil { + return nil, err + } + defer in.Close() + return parseTestData(in) +} + +func (test *clientTest) storeUsername() (err error) { + storeUsernameOnce.Do(func() { + err = os.WriteFile(test.usernameDataPath(), []byte(username()), 0666) + }) + return err +} + +func (test *clientTest) loadUsername() (string, error) { + data, err := os.ReadFile(test.usernameDataPath()) + return string(data), err +} + +func (test *clientTest) run(t *testing.T, write bool) { + var clientConn net.Conn + var recordingConn *recordingConn + + setDeterministicRandomSource(&test.config.Config) + + if write { + // We store the username used when we record the connection so we can + // reuse the same username when running tests. + if err := test.storeUsername(); err != nil { + t.Fatalf("failed to store username to %q: %v", test.usernameDataPath(), err) + } + recordingConn = test.connFromCommand(t, "default") + clientConn = recordingConn + } else { + username, err := test.loadUsername() + if err != nil { + t.Fatalf("failed to load username from %q: %v", test.usernameDataPath(), err) + } + test.config.User = username + timer := time.AfterFunc(10*time.Second, func() { + fmt.Println("This test may be stuck, try running using -timeout 10s") + }) + t.Cleanup(func() { + timer.Stop() + }) + flows, err := test.loadData() + if err != nil { + t.Fatalf("failed to load data from %s: %v", test.dataPath(), err) + } + clientConn = newReplayingConn(t, flows) + } + c, chans, reqs, err := ssh.NewClientConn(clientConn, "", test.config) + if err != nil { + if test.expectError == "" { + t.Fatal(err) + } else { + if !strings.Contains(err.Error(), test.expectError) { + t.Fatalf("%q not found in %v", test.expectError, err) + } + } + } else { + if test.expectError != "" { + t.Error("dial should have failed.") + } + client := ssh.NewClient(c, chans, reqs) + if test.successCallback != nil { + test.successCallback(t, client) + } + if err := client.Close(); err != nil { + t.Fatal(err) + } + } + + if write { + path := test.dataPath() + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + t.Fatalf("Failed to create output file: %v", err) + } + defer out.Close() + recordingConn.Close() + + recordingConn.WriteTo(out) + t.Logf("Wrote %s\n", path) + } +} + +func recordingsClientConfig() *ssh.ClientConfig { + config := clientConfig() + config.SetDefaults() + // Remove ML-KEM since it only works with Go 1.24. + if config.KeyExchanges[0] == ssh.KeyExchangeMLKEM768X25519 { + config.KeyExchanges = config.KeyExchanges[1:] + } + config.Auth = []ssh.AuthMethod{ + ssh.PublicKeys(testSigners["rsa"]), + } + return config +} + +func TestClientKeyExchanges(t *testing.T) { + config := ssh.ClientConfig{} + config.SetDefaults() + + var keyExchanges []string + for _, kex := range config.KeyExchanges { + // Exclude ecdh for now, to make them deterministic we should use see a + // stream of fixed bytes as the random source. + if !strings.HasPrefix(kex, "ecdh-") { + keyExchanges = append(keyExchanges, kex) + } + } + // Add diffie-hellman-group-exchange-sha256 and + // diffie-hellman-group16-sha512 as they are not enabled by default. + keyExchanges = append(keyExchanges, "diffie-hellman-group-exchange-sha256", "diffie-hellman-group16-sha512") + + for _, kex := range keyExchanges { + c := recordingsClientConfig() + c.KeyExchanges = []string{kex} + test := clientTest{ + name: "KEX-" + kex, + config: c, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) + } +} + +func TestClientCiphers(t *testing.T) { + config := ssh.ClientConfig{} + config.SetDefaults() + + for _, ciph := range config.Ciphers { + c := recordingsClientConfig() + c.Ciphers = []string{ciph} + test := clientTest{ + name: "Cipher-" + ciph, + config: c, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) + } +} + +func TestClientMACs(t *testing.T) { + config := ssh.ClientConfig{} + config.SetDefaults() + + for _, mac := range config.MACs { + c := recordingsClientConfig() + c.MACs = []string{mac} + test := clientTest{ + name: "MAC-" + mac, + config: c, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) + } +} + +func TestBannerCallback(t *testing.T) { + var receivedBanner string + config := recordingsClientConfig() + config.BannerCallback = func(message string) error { + receivedBanner = message + return nil + } + test := clientTest{ + name: "BannerCallback", + config: config, + successCallback: func(t *testing.T, client *ssh.Client) { + expected := "Server Banner" + if receivedBanner != expected { + t.Fatalf("got %v; want %v", receivedBanner, expected) + } + }, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) +} + +func TestRunCommandSuccess(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("skipping test, executing a command, session.Run(), is not supported on wasm") + } + test := clientTest{ + name: "RunCommandSuccess", + config: recordingsClientConfig(), + successCallback: func(t *testing.T, client *ssh.Client) { + session, err := client.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + err = session.Run("true") + if err != nil { + t.Fatalf("session failed: %v", err) + } + }, + } + + runTestAndUpdateIfNeeded(t, test.name, test.run) +} + +func TestHostKeyCheck(t *testing.T) { + config := recordingsClientConfig() + hostDB := hostKeyDB() + config.HostKeyCallback = hostDB.Check + + // change the keys. + hostDB.keys[ssh.KeyAlgoRSA][25]++ + hostDB.keys[ssh.InsecureKeyAlgoDSA][25]++ + hostDB.keys[ssh.KeyAlgoECDSA256][25]++ + + test := clientTest{ + name: "HostKeyCheck", + config: config, + expectError: "host key mismatch", + } + + runTestAndUpdateIfNeeded(t, test.name, test.run) +} + +func TestRunCommandStdin(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("skipping test, executing a command, session.Run(), is not supported on wasm") + } + test := clientTest{ + name: "RunCommandStdin", + config: recordingsClientConfig(), + successCallback: func(t *testing.T, client *ssh.Client) { + session, err := client.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + r, w := io.Pipe() + defer r.Close() + defer w.Close() + session.Stdin = r + + err = session.Run("true") + if err != nil { + t.Fatalf("session failed: %v", err) + } + }, + } + + runTestAndUpdateIfNeeded(t, test.name, test.run) +} + +func TestRunCommandStdinError(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("skipping test, executing a command, session.Run(), is not supported on wasm") + } + test := clientTest{ + name: "RunCommandStdinError", + config: recordingsClientConfig(), + successCallback: func(t *testing.T, client *ssh.Client) { + session, err := client.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + r, w := io.Pipe() + defer r.Close() + session.Stdin = r + pipeErr := errors.New("closing write end of pipe") + w.CloseWithError(pipeErr) + + err = session.Run("true") + if err != pipeErr { + t.Fatalf("expected %v, found %v", pipeErr, err) + } + }, + } + + runTestAndUpdateIfNeeded(t, test.name, test.run) +} + +func TestRunCommandFailed(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("skipping test, executing a command, session.Run(), is not supported on wasm") + } + test := clientTest{ + name: "RunCommandFailed", + config: recordingsClientConfig(), + successCallback: func(t *testing.T, client *ssh.Client) { + session, err := client.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + // Trigger a failure by attempting to execute a non-existent + // command. + err = session.Run(`non-existent command`) + if err == nil { + t.Fatalf("session succeeded: %v", err) + } + }, + } + + runTestAndUpdateIfNeeded(t, test.name, test.run) +} + +func TestWindowChange(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("skipping test, stdin/out are not supported on wasm") + } + test := clientTest{ + name: "WindowChange", + config: recordingsClientConfig(), + successCallback: func(t *testing.T, client *ssh.Client) { + session, err := client.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("unable to acquire stdout pipe: %s", err) + } + + stdin, err := session.StdinPipe() + if err != nil { + t.Fatalf("unable to acquire stdin pipe: %s", err) + } + + tm := ssh.TerminalModes{ssh.ECHO: 0} + if err = session.RequestPty("xterm", 80, 40, tm); err != nil { + t.Fatalf("req-pty failed: %s", err) + } + + if err := session.WindowChange(100, 100); err != nil { + t.Fatalf("window-change failed: %s", err) + } + + err = session.Shell() + if err != nil { + t.Fatalf("session failed: %s", err) + } + + stdin.Write([]byte("stty size && exit\n")) + + var buf bytes.Buffer + if _, err := io.Copy(&buf, stdout); err != nil { + t.Fatalf("reading failed: %s", err) + } + + if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") { + t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput) + } + }, + } + + runTestAndUpdateIfNeeded(t, test.name, test.run) +} diff --git a/ssh/test/recording_server_test.go b/ssh/test/recording_server_test.go new file mode 100644 index 0000000000..898a8478e5 --- /dev/null +++ b/ssh/test/recording_server_test.go @@ -0,0 +1,284 @@ +// Copyright 2025 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 test + +import ( + "bytes" + "errors" + "fmt" + "net" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + + "golang.org/x/crypto/internal/testenv" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/testdata" +) + +type serverTest struct { + // name is a freeform string identifying the test and the file in which + // the expected results will be stored. + name string + // config contains the server configuration to use for this test. + config *ssh.ServerConfig +} + +// connFromCommand starts opens a listening socket and starts the reference +// client to connect to it. It returns a recordingConn that wraps the resulting +// connection. +func (test *serverTest) connFromCommand(t *testing.T) (conn *recordingConn, err error) { + sshCLI, err := exec.LookPath("ssh") + if err != nil { + t.Skipf("skipping test: %v", err) + } + l, err := net.ListenTCP("tcp", &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: 0, + }) + if err != nil { + return nil, err + } + defer l.Close() + + port := l.Addr().(*net.TCPAddr).Port + dir, err := os.MkdirTemp("", "sshtest") + if err != nil { + t.Fatal(err) + } + + filename := "id_ed25519" + writeFile(filepath.Join(dir, filename), testdata.PEMBytes["ed25519"]) + writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys["ed25519"])) + var args []string + args = append(args, "-v", "-i", filepath.Join(dir, filename), "-o", "StrictHostKeyChecking=no") + args = append(args, "-oKexAlgorithms=+diffie-hellman-group14-sha1") + args = append(args, "-p", strconv.Itoa(port)) + args = append(args, "testuser@127.0.0.1") + args = append(args, "true") + cmd := testenv.Command(t, sshCLI, args...) + cmd.Stdin = nil + var output bytes.Buffer + cmd.Stdout = &output + cmd.Stderr = &output + if err := cmd.Start(); err != nil { + return nil, err + } + + t.Cleanup(func() { + if err := os.RemoveAll(dir); err != nil { + t.Error(err) + } + // Don't check for errors; if it fails it's most + // likely "os: process already finished", and we don't + // care about that. + cmd.Process.Kill() + cmd.Wait() + if t.Failed() { + t.Logf("OpenSSH output:\n\n%s", cmd.Stdout) + } + }) + + connChan := make(chan any, 1) + go func() { + tcpConn, err := l.Accept() + if err != nil { + connChan <- err + return + } + connChan <- tcpConn + }() + + var tcpConn net.Conn + select { + case connOrError := <-connChan: + if err, ok := connOrError.(error); ok { + return nil, err + } + tcpConn = connOrError.(net.Conn) + case <-time.After(2 * time.Second): + return nil, errors.New("timed out waiting for connection from child process") + } + + record := &recordingConn{ + Conn: tcpConn, + clientToServer: false, + } + + return record, nil +} + +func (test *serverTest) dataPath() string { + return filepath.Join("..", "testdata", "Server-"+test.name) +} + +func (test *serverTest) loadData() (flows [][]byte, err error) { + in, err := os.Open(test.dataPath()) + if err != nil { + return nil, err + } + defer in.Close() + return parseTestData(in) +} + +func (test *serverTest) run(t *testing.T, write bool) { + var serverConn net.Conn + var recordingConn *recordingConn + + setDeterministicRandomSource(&test.config.Config) + + if write { + var err error + recordingConn, err = test.connFromCommand(t) + if err != nil { + t.Fatalf("Failed to start subcommand: %v", err) + } + serverConn = recordingConn + } else { + timer := time.AfterFunc(10*time.Second, func() { + fmt.Println("This test may be stuck, try running using -timeout 10s") + }) + t.Cleanup(func() { + timer.Stop() + }) + flows, err := test.loadData() + if err != nil { + t.Fatalf("Failed to load data from %s", test.dataPath()) + } + serverConn = newReplayingConn(t, flows) + } + + server, chans, reqs, err := ssh.NewServerConn(serverConn, test.config) + if err != nil { + t.Fatalf("Failed to create server conn: %v", err) + } + defer server.Close() + + go ssh.DiscardRequests(reqs) + + done := make(chan bool) + + for newChannel := range chans { + if newChannel.ChannelType() != "session" { + newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") + continue + } + + channel, requests, err := newChannel.Accept() + if err != nil { + continue + } + + go func(in <-chan *ssh.Request) { + for req := range in { + switch req.Type { + case "exec": + if req.WantReply { + req.Reply(true, nil) + } + channel.SendRequest("exit-status", false, ssh.Marshal(&exitStatusMsg{Status: 0})) + channel.Close() + done <- true + default: + if req.WantReply { + req.Reply(false, nil) + } + } + } + }(requests) + } + + <-done + + if write { + path := test.dataPath() + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + t.Fatalf("Failed to create output file: %v", err) + } + defer out.Close() + recordingConn.Close() + + recordingConn.WriteTo(out) + t.Logf("Wrote %s\n", path) + } +} + +func recordingsServerConfig() *ssh.ServerConfig { + config := &ssh.ServerConfig{ + PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { + return nil, nil + }, + } + config.SetDefaults() + // Remove ML-KEM since it only works with Go 1.24. + config.SetDefaults() + if config.KeyExchanges[0] == ssh.KeyExchangeMLKEM768X25519 { + config.KeyExchanges = config.KeyExchanges[1:] + } + config.AddHostKey(testSigners["rsa"]) + return config +} + +func TestServerKeyExchanges(t *testing.T) { + config := ssh.ClientConfig{} + config.SetDefaults() + + var keyExchanges []string + for _, kex := range config.KeyExchanges { + // Exclude ecdh for now, to make them deterministic we should use see a + // stream of fixed bytes as the random source. + // Exclude ML-KEM because server side is not deterministic. + if !strings.HasPrefix(kex, "ecdh-") && !strings.HasPrefix(kex, "mlkem") { + keyExchanges = append(keyExchanges, kex) + } + } + // Add diffie-hellman-group16-sha512 as it is not enabled by default. + keyExchanges = append(keyExchanges, "diffie-hellman-group16-sha512") + + for _, kex := range keyExchanges { + c := recordingsServerConfig() + c.KeyExchanges = []string{kex} + test := serverTest{ + name: "KEX-" + kex, + config: c, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) + } +} + +func TestServerCiphers(t *testing.T) { + config := ssh.ClientConfig{} + config.SetDefaults() + + for _, ciph := range config.Ciphers { + c := recordingsServerConfig() + c.Ciphers = []string{ciph} + test := serverTest{ + name: "Cipher-" + ciph, + config: c, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) + } +} + +func TestServerMACs(t *testing.T) { + config := ssh.ClientConfig{} + config.SetDefaults() + + for _, mac := range config.MACs { + c := recordingsServerConfig() + c.MACs = []string{mac} + test := serverTest{ + name: "MAC-" + mac, + config: c, + } + runTestAndUpdateIfNeeded(t, test.name, test.run) + } +} diff --git a/ssh/test/recording_test.go b/ssh/test/recording_test.go new file mode 100644 index 0000000000..4356345ca2 --- /dev/null +++ b/ssh/test/recording_test.go @@ -0,0 +1,433 @@ +// Copyright 2025 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 test + +import ( + "bufio" + "bytes" + "encoding/hex" + "errors" + "flag" + "fmt" + "io" + "log" + "net" + "os" + "os/user" + "strconv" + "strings" + "sync" + "testing" + "text/template" + "time" + + "golang.org/x/crypto/sha3" + "golang.org/x/crypto/ssh" +) + +const ( + defaultSSHDConfig = ` +Protocol 2 +Banner {{.Dir}}/banner +HostKey {{.Dir}}/id_rsa +HostKey {{.Dir}}/id_dsa +HostKey {{.Dir}}/id_ecdsa +HostCertificate {{.Dir}}/id_rsa-sha2-512-cert.pub +Pidfile {{.Dir}}/sshd.pid +KeyRegenerationInterval 3600 +ServerKeyBits 768 +SyslogFacility AUTH +LogLevel DEBUG2 +LoginGraceTime 120 +PermitRootLogin no +StrictModes no +RSAAuthentication yes +PubkeyAuthentication yes +AuthorizedKeysFile {{.Dir}}/authorized_keys +TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub +IgnoreRhosts yes +RhostsRSAAuthentication no +HostbasedAuthentication no +PubkeyAcceptedKeyTypes=* +# In recent versions of OpenSSH, Diffie-Hellman key exchange algorithms +# are disabled by default. However, they are still included in our default +# Key Exchange (KEX) configuration. We explicitly enable them here to +# maintain compatibility for our test cases. +KexAlgorithms +diffie-hellman-group14-sha1,diffie-hellman-group14-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group-exchange-sha256 +` + multiAuthSshdConfigTail = ` +UsePAM yes +PasswordAuthentication yes +ChallengeResponseAuthentication yes +AuthenticationMethods {{.AuthMethods}} +` + maxAuthTriesSshdConfigTail = ` +PasswordAuthentication yes +MaxAuthTries 1 +` +) + +var configTmpl = map[string]*template.Template{ + "default": template.Must(template.New("").Parse(defaultSSHDConfig)), + "MultiAuth": template.Must(template.New("").Parse(defaultSSHDConfig + multiAuthSshdConfigTail)), + "MaxAuthTries": template.Must(template.New("").Parse(defaultSSHDConfig + maxAuthTriesSshdConfigTail))} + +type server struct { + t *testing.T + configfile string + + testUser string // test username for sshd + testPasswd string // test password for sshd + sshdTestPwSo string // dynamic library to inject a custom password into sshd + + lastDialConn net.Conn +} + +type storedHostKey struct { + // keys map from an algorithm string to binary key data. + keys map[string][]byte + + // checkCount counts the Check calls. Used for testing + // rekeying. + checkCount int +} + +func (k *storedHostKey) Add(key ssh.PublicKey) { + if k.keys == nil { + k.keys = map[string][]byte{} + } + k.keys[key.Type()] = key.Marshal() +} + +func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { + k.checkCount++ + algo := key.Type() + + if k.keys == nil || !bytes.Equal(key.Marshal(), k.keys[algo]) { + return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) + } + return nil +} + +func hostKeyDB() *storedHostKey { + keyChecker := &storedHostKey{} + keyChecker.Add(testPublicKeys["ecdsa"]) + keyChecker.Add(testPublicKeys["rsa"]) + keyChecker.Add(testPublicKeys["dsa"]) + return keyChecker +} + +func clientConfig() *ssh.ClientConfig { + config := &ssh.ClientConfig{ + User: username(), + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(testSigners["user"]), + }, + HostKeyCallback: hostKeyDB().Check, + HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker + ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, + ssh.KeyAlgoRSA, ssh.InsecureKeyAlgoDSA, + ssh.KeyAlgoED25519, + }, + } + return config +} + +// SSH reference tests run a connection against a reference implementation +// (OpenSSH) of SSH and record the bytes of the resulting connection. The Go +// code, during a test, is configured with deterministic randomness and so the +// reference test can be reproduced exactly in the future. +// +// In order to save everyone who wishes to run the tests from needing the +// reference implementation installed, the reference connections are saved in +// files in the testdata directory. Thus running the tests involves nothing +// external, but creating and updating them requires the reference +// implementation. +// +// Tests can be updated by running them with the -update flag. This will cause +// the test files for failing tests to be regenerated. Since the reference +// implementation will always generate fresh random numbers, large parts of the +// reference connection will always change. + +var ( + update = flag.Bool("update", false, "update golden files on failure") +) + +func runTestAndUpdateIfNeeded(t *testing.T, name string, run func(t *testing.T, update bool)) { + success := t.Run(name, func(t *testing.T) { + if !*update { + t.Parallel() + } + run(t, false) + }) + + if !success && *update { + t.Run(name+"#update", func(t *testing.T) { + run(t, true) + }) + } +} + +// recordingConn is a net.Conn that records the traffic that passes through it. +// WriteTo can be used to produce output that can be later be loaded with +// ParseTestData. +type recordingConn struct { + net.Conn + clientToServer bool + sync.Mutex + flows [][]byte + reading bool +} + +func (r *recordingConn) Read(b []byte) (n int, err error) { + if n, err = r.Conn.Read(b); n == 0 { + return + } + b = b[:n] + + r.Lock() + defer r.Unlock() + + if l := len(r.flows); l == 0 || !r.reading { + buf := make([]byte, len(b)) + copy(buf, b) + r.flows = append(r.flows, buf) + } else { + r.flows[l-1] = append(r.flows[l-1], b[:n]...) + } + r.reading = true + return +} + +func (r *recordingConn) Write(b []byte) (n int, err error) { + if n, err = r.Conn.Write(b); n == 0 { + return + } + b = b[:n] + + r.Lock() + defer r.Unlock() + + if l := len(r.flows); l == 0 || r.reading { + buf := make([]byte, len(b)) + copy(buf, b) + r.flows = append(r.flows, buf) + } else { + r.flows[l-1] = append(r.flows[l-1], b[:n]...) + } + r.reading = false + return +} + +// WriteTo writes Go source code to w that contains the recorded traffic. +func (r *recordingConn) WriteTo(w io.Writer) (int64, error) { + var written int64 + for i, flow := range r.flows { + source, dest := "client", "server" + if !r.clientToServer { + source, dest = dest, source + } + n, err := fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest) + written += int64(n) + if err != nil { + return written, err + } + dumper := hex.Dumper(w) + n, err = dumper.Write(flow) + written += int64(n) + if err != nil { + return written, err + } + err = dumper.Close() + if err != nil { + return written, err + } + r.clientToServer = !r.clientToServer + } + return written, nil +} + +func parseTestData(r io.Reader) (flows [][]byte, err error) { + var currentFlow []byte + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + // If the line starts with ">>> " then it marks the beginning + // of a new flow. + if strings.HasPrefix(line, ">>> ") { + if len(currentFlow) > 0 || len(flows) > 0 { + flows = append(flows, currentFlow) + currentFlow = nil + } + continue + } + + // Otherwise the line is a line of hex dump that looks like: + // 00000170 fc f5 06 bf (...) |.....X{&?......!| + // (Some bytes have been omitted from the middle section.) + _, after, ok := strings.Cut(line, " ") + if !ok { + return nil, errors.New("invalid test data") + } + line = after + + before, _, ok := strings.Cut(line, "|") + if !ok { + return nil, errors.New("invalid test data") + } + line = before + + hexBytes := strings.Fields(line) + for _, hexByte := range hexBytes { + val, err := strconv.ParseUint(hexByte, 16, 8) + if err != nil { + return nil, errors.New("invalid hex byte in test data: " + err.Error()) + } + currentFlow = append(currentFlow, byte(val)) + } + } + + if len(currentFlow) > 0 { + flows = append(flows, currentFlow) + } + + return flows, nil +} + +func newReplayingConn(t testing.TB, flows [][]byte) net.Conn { + r := &replayingConn{ + t: t, + flows: flows, + reading: false, + } + r.readCond = sync.NewCond(&r.Mutex) + return r +} + +// replayingConn is a net.Conn that replays flows recorded by recordingConn. +type replayingConn struct { + t testing.TB + sync.Mutex + flows [][]byte + reading bool + // SSH channels use a read loop goroutine, we use this condition to wait + // until we are ready to read/write. + readCond *sync.Cond +} + +var _ net.Conn = (*replayingConn)(nil) + +func (r *replayingConn) Read(b []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + + for !r.reading { + r.readCond.Wait() + } + + // Some tests run commands that return no output. + if len(r.flows) == 0 { + return 0, nil + } + + n = copy(b, r.flows[0]) + r.flows[0] = r.flows[0][n:] + if len(r.flows[0]) == 0 { + r.flows = r.flows[1:] + r.reading = false + r.readCond.Broadcast() + if len(r.flows) == 0 { + return n, io.EOF + } + } + return n, nil +} + +func (r *replayingConn) Write(b []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + + for r.reading { + r.readCond.Wait() + } + + if !bytes.HasPrefix(r.flows[0], b) { + r.t.Errorf("write mismatch: expected %x, got %x", r.flows[0], b) + r.reading = true + r.readCond.Broadcast() + return 0, fmt.Errorf("write mismatch") + } + r.flows[0] = r.flows[0][len(b):] + if len(r.flows[0]) == 0 { + r.flows = r.flows[1:] + r.reading = true + r.readCond.Broadcast() + } + return len(b), nil +} + +func (r *replayingConn) Close() error { + r.Lock() + defer r.Unlock() + + if len(r.flows) > 0 { + r.t.Errorf("closed with unfinished flows: %d", len(r.flows)) + return fmt.Errorf("unexpected close") + } + return nil +} + +func (r *replayingConn) LocalAddr() net.Addr { return nil } +func (r *replayingConn) RemoteAddr() net.Addr { return nil } +func (r *replayingConn) SetDeadline(_ time.Time) error { return nil } +func (r *replayingConn) SetReadDeadline(_ time.Time) error { return nil } +func (r *replayingConn) SetWriteDeadline(_ time.Time) error { return nil } + +func username() string { + var username string + if user, err := user.Current(); err == nil { + username = user.Username + } else { + // user.Current() currently requires cgo. If an error is + // returned attempt to get the username from the environment. + log.Printf("user.Current: %v; falling back on $USER", err) + username = os.Getenv("USER") + } + if username == "" { + panic("Unable to get username") + } + return username +} + +func writeFile(path string, contents []byte) { + f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) + if err != nil { + panic(err) + } + defer f.Close() + if _, err := f.Write(contents); err != nil { + panic(err) + } +} + +// setDeterministicRandomSource sets a deterministic random source for the +// provided ssh.Config. It is intended solely for use in test cases, as +// deterministic randomness is insecure and should never be used in production +// environments. A deterministic random source is required to enable consistent +// testing against recorded session files. +func setDeterministicRandomSource(config *ssh.Config) { + config.Rand = sha3.NewShake128() +} + +func TestMain(m *testing.M) { + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args) + flag.PrintDefaults() + } + + flag.Parse() + os.Exit(m.Run()) +} diff --git a/ssh/test/server_test.go b/ssh/test/server_test.go new file mode 100644 index 0000000000..5c04fba98c --- /dev/null +++ b/ssh/test/server_test.go @@ -0,0 +1,98 @@ +// Copyright 2023 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 test + +import ( + "net" + + "golang.org/x/crypto/ssh" +) + +type exitStatusMsg struct { + Status uint32 +} + +// goTestServer is a test Go SSH server that accepts public key and certificate +// authentication and replies with a 0 exit status to any exec request without +// running any commands. +type goTestServer struct { + listener net.Listener + config *ssh.ServerConfig + done <-chan struct{} +} + +func newTestServer(config *ssh.ServerConfig) (*goTestServer, error) { + server := &goTestServer{ + config: config, + } + listener, err := net.Listen("tcp", "127.0.0.1:") + if err != nil { + return nil, err + } + server.listener = listener + done := make(chan struct{}, 1) + server.done = done + go server.acceptConnections(done) + + return server, nil +} + +func (s *goTestServer) port() (string, error) { + _, port, err := net.SplitHostPort(s.listener.Addr().String()) + return port, err +} + +func (s *goTestServer) acceptConnections(done chan<- struct{}) { + defer close(done) + + for { + c, err := s.listener.Accept() + if err != nil { + return + } + _, chans, reqs, err := ssh.NewServerConn(c, s.config) + if err != nil { + return + } + go ssh.DiscardRequests(reqs) + defer c.Close() + + for newChannel := range chans { + if newChannel.ChannelType() != "session" { + newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") + continue + } + + channel, requests, err := newChannel.Accept() + if err != nil { + continue + } + + go func(in <-chan *ssh.Request) { + for req := range in { + ok := false + switch req.Type { + case "exec": + ok = true + go func() { + channel.SendRequest("exit-status", false, ssh.Marshal(&exitStatusMsg{Status: 0})) + channel.Close() + }() + } + if req.WantReply { + req.Reply(ok, nil) + } + } + }(requests) + } + } +} + +func (s *goTestServer) Close() error { + err := s.listener.Close() + // wait for the accept loop to exit + <-s.done + return err +} diff --git a/ssh/test/session_test.go b/ssh/test/session_test.go index e363869642..fda8d8c7bb 100644 --- a/ssh/test/session_test.go +++ b/ssh/test/session_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !windows,!solaris,!js +//go:build !windows && !js && !wasip1 package test @@ -10,9 +10,10 @@ package test import ( "bytes" - "errors" "fmt" "io" + "path/filepath" + "regexp" "runtime" "strings" "testing" @@ -20,117 +21,21 @@ import ( "golang.org/x/crypto/ssh" ) -func TestRunCommandSuccess(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - err = session.Run("true") - if err != nil { - t.Fatalf("session failed: %v", err) - } -} - -func TestHostKeyCheck(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - - conf := clientConfig() - hostDB := hostKeyDB() - conf.HostKeyCallback = hostDB.Check - - // change the keys. - hostDB.keys[ssh.KeyAlgoRSA][25]++ - hostDB.keys[ssh.KeyAlgoDSA][25]++ - hostDB.keys[ssh.KeyAlgoECDSA256][25]++ - - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - t.Fatalf("dial should have failed.") - } else if !strings.Contains(err.Error(), "host key mismatch") { - t.Fatalf("'host key mismatch' not found in %v", err) - } -} - -func TestRunCommandStdin(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - r, w := io.Pipe() - defer r.Close() - defer w.Close() - session.Stdin = r - - err = session.Run("true") - if err != nil { - t.Fatalf("session failed: %v", err) - } -} - -func TestRunCommandStdinError(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - r, w := io.Pipe() - defer r.Close() - session.Stdin = r - pipeErr := errors.New("closing write end of pipe") - w.CloseWithError(pipeErr) - - err = session.Run("true") - if err != pipeErr { - t.Fatalf("expected %v, found %v", pipeErr, err) - } -} - -func TestRunCommandFailed(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - err = session.Run(`bash -c "kill -9 $$"`) - if err == nil { - t.Fatalf("session succeeded: %v", err) +func skipIfIssue64959(t *testing.T, err error) { + if err != nil && runtime.GOOS == "darwin" && strings.Contains(err.Error(), "ssh: unexpected packet in response to channel open: ") { + t.Helper() + t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959") } } func TestRunCommandWeClosed(t *testing.T) { server := newServer(t) - defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("session failed: %v", err) } err = session.Shell() @@ -145,12 +50,12 @@ func TestRunCommandWeClosed(t *testing.T) { func TestFuncLargeRead(t *testing.T) { server := newServer(t) - defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("unable to create new session: %s", err) } @@ -177,7 +82,6 @@ func TestFuncLargeRead(t *testing.T) { func TestKeyChange(t *testing.T) { server := newServer(t) - defer server.Shutdown() conf := clientConfig() hostDB := hostKeyDB() conf.HostKeyCallback = hostDB.Check @@ -188,6 +92,7 @@ func TestKeyChange(t *testing.T) { for i := 0; i < 4; i++ { session, err := conn.NewSession() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("unable to create new session: %s", err) } @@ -224,12 +129,12 @@ func TestValidTerminalMode(t *testing.T) { t.Skipf("skipping on %s", runtime.GOOS) } server := newServer(t) - defer server.Shutdown() conn := server.Dial(clientConfig()) defer conn.Close() session, err := conn.NewSession() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("session failed: %v", err) } defer session.Close() @@ -254,74 +159,36 @@ func TestValidTerminalMode(t *testing.T) { t.Fatalf("session failed: %s", err) } - stdin.Write([]byte("stty -a && exit\n")) - - var buf bytes.Buffer - if _, err := io.Copy(&buf, stdout); err != nil { - t.Fatalf("reading failed: %s", err) - } - - if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { - t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput) - } -} - -func TestWindowChange(t *testing.T) { - if runtime.GOOS == "aix" { - // On AIX, sshd cannot acquire /dev/pts/* if launched as - // a non-root user. - t.Skipf("skipping on %s", runtime.GOOS) - } - server := newServer(t) - defer server.Shutdown() - conn := server.Dial(clientConfig()) - defer conn.Close() - - session, err := conn.NewSession() - if err != nil { - t.Fatalf("session failed: %v", err) - } - defer session.Close() - - stdout, err := session.StdoutPipe() - if err != nil { - t.Fatalf("unable to acquire stdout pipe: %s", err) - } - - stdin, err := session.StdinPipe() - if err != nil { - t.Fatalf("unable to acquire stdin pipe: %s", err) + if _, err := io.WriteString(stdin, "echo && echo SHELL $SHELL && stty -a && exit\n"); err != nil { + t.Fatal(err) } - tm := ssh.TerminalModes{ssh.ECHO: 0} - if err = session.RequestPty("xterm", 80, 40, tm); err != nil { - t.Fatalf("req-pty failed: %s", err) + buf := new(strings.Builder) + if _, err := io.Copy(buf, stdout); err != nil { + t.Fatalf("reading failed: %s", err) } - if err := session.WindowChange(100, 100); err != nil { - t.Fatalf("window-change failed: %s", err) + if testing.Verbose() { + t.Logf("echo && echo SHELL $SHELL && stty -a && exit:\n%s", buf) } - err = session.Shell() - if err != nil { - t.Fatalf("session failed: %s", err) + shellLine := regexp.MustCompile("(?m)^SHELL (.*)$").FindStringSubmatch(buf.String()) + if len(shellLine) != 2 { + t.Fatalf("missing output from echo SHELL $SHELL") } - - stdin.Write([]byte("stty size && exit\n")) - - var buf bytes.Buffer - if _, err := io.Copy(&buf, stdout); err != nil { - t.Fatalf("reading failed: %s", err) + switch shell := filepath.Base(strings.TrimSpace(shellLine[1])); shell { + case "sh", "bash": + default: + t.Skipf("skipping test on non-Bourne shell %q", shell) } - if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") { - t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput) + if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { + t.Fatal("terminal mode failure: expected -echo in stty output") } } func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { server := newServer(t) - defer server.Shutdown() conf := clientConfig() conf.Ciphers = []string{cipher} // Don't fail if sshd doesn't have the cipher. @@ -334,14 +201,10 @@ func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { numBytes := 4096 - // Exercise sending data to the server - if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { - t.Fatalf("SendRequest: %v", err) - } - // Exercise receiving data from the server session, err := conn.NewSession() if err != nil { + skipIfIssue64959(t, err) t.Fatalf("NewSession: %v", err) } @@ -353,11 +216,16 @@ func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { if len(out) != numBytes { t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) } + + // Exercise sending data to the server + if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { + t.Fatalf("SendRequest: %v", err) + } } var deprecatedCiphers = []string{ - "aes128-cbc", "3des-cbc", - "arcfour128", "arcfour256", + ssh.InsecureCipherAES128CBC, ssh.InsecureCipherTripleDESCBC, + ssh.InsecureCipherRC4128, ssh.InsecureCipherRC4256, } func TestCiphers(t *testing.T) { @@ -372,58 +240,9 @@ func TestCiphers(t *testing.T) { } } -func TestMACs(t *testing.T) { - var config ssh.Config - config.SetDefaults() - macOrder := config.MACs - - for _, mac := range macOrder { - t.Run(mac, func(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - conf.MACs = []string{mac} - // Don't fail if sshd doesn't have the MAC. - conf.MACs = append(conf.MACs, macOrder...) - if conn, err := server.TryDial(conf); err == nil { - conn.Close() - } else { - t.Fatalf("failed for MAC %q", mac) - } - }) - } -} - -func TestKeyExchanges(t *testing.T) { - var config ssh.Config - config.SetDefaults() - kexOrder := config.KeyExchanges - // Based on the discussion in #17230, the key exchange algorithms - // diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256 - // are not included in the default list of supported kex so we have to add them - // here manually. - kexOrder = append(kexOrder, "diffie-hellman-group-exchange-sha1", "diffie-hellman-group-exchange-sha256") - for _, kex := range kexOrder { - t.Run(kex, func(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - // Don't fail if sshd doesn't have the kex. - conf.KeyExchanges = append([]string{kex}, kexOrder...) - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - } else { - t.Errorf("failed for kex %q", kex) - } - }) - } -} - func TestClientAuthAlgorithms(t *testing.T) { for _, key := range []string{ "rsa", - "dsa", "ecdsa", "ed25519", } { @@ -441,8 +260,75 @@ func TestClientAuthAlgorithms(t *testing.T) { } else { t.Errorf("failed for key %q", key) } - - server.Shutdown() }) } } + +func TestClientAuthDisconnect(t *testing.T) { + // Use a static key that is not accepted by server. + // This key has been generated with following ssh-keygen command and + // used exclusively in this unit test: + // $ ssh-keygen -t RSA -b 2048 -f /tmp/static_key \ + // -C "Static RSA key for golang.org/x/crypto/ssh unit test" + + const privKeyData = `-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEAwV1Zg3MqX27nIQQNWd8V09P4q4F1fx7H2xNJdL3Yg3y91GFLJ92+ +0IiGV8n1VMGL/71PPhzyqBpUYSTpWjiU2JZSfA+iTg1GJBcOaEOA6vrXsTtXTHZ//mOT4d +mlvuP4+9NqfCBLGXN7ZJpT+amkD8AVW9YW9QN3ipY61ZWxPaAocVpDd8rVgJTk54KvaPa7 +t4ddOSQDQq61aubIDR1Z3P+XjkB4piWOsbck3HJL+veTALy12C09tAhwUnZUAXS+DjhxOL +xpDVclF/yXYhAvBvsjwyk/OC3+nK9F799hpQZsjxmbP7oN+tGwz06BUcAKi7u7QstENvvk +85SDZy1q1QAAA/A7ylbJO8pWyQAAAAdzc2gtcnNhAAABAQDBXVmDcypfbuchBA1Z3xXT0/ +irgXV/HsfbE0l0vdiDfL3UYUsn3b7QiIZXyfVUwYv/vU8+HPKoGlRhJOlaOJTYllJ8D6JO +DUYkFw5oQ4Dq+texO1dMdn/+Y5Ph2aW+4/j702p8IEsZc3tkmlP5qaQPwBVb1hb1A3eKlj +rVlbE9oChxWkN3ytWAlOTngq9o9ru3h105JANCrrVq5sgNHVnc/5eOQHimJY6xtyTcckv6 +95MAvLXYLT20CHBSdlQBdL4OOHE4vGkNVyUX/JdiEC8G+yPDKT84Lf6cr0Xv32GlBmyPGZ +s/ug360bDPToFRwAqLu7tCy0Q2++TzlINnLWrVAAAAAwEAAQAAAQAIvPDHMiyIxgCksGPF +uyv9F9U4XjVip8/abE9zkAMJWW5++wuT/bRlBOUPRrWIXZEM9ETbtsqswo3Wxah+7CjRIH +qR7SdFlYTP1jPk4yIKXF4OvggBUPySkMpAGJ9hwOMW8Ymcb4gn77JJ4aMoWIcXssje+XiC +8iO+4UWU3SV2i6K7flK1UDCI5JVCyBr3DVf3QhMOgvwJl9TgD7FzWy1hkjuZq/Pzdv+fA2 +OfrUFiSukLNolidNoI9+KWa1yxixE+B2oN4Xan3ZbqGbL6Wc1dB+K9h/bNcu+SKf7fXWRi +/vVG44A61xGDZzen1+eQlqFp7narkKXoaU71+45VXDThAAAAgBPWUdQykEEm0yOS6hPIW+ +hS8z1LXWGTEcag9fMwJXKE7cQFO3LEk+dXMbClHdhD/ydswOZYGSNepxwvmo/a5LiO2ulp +W+5tnsNhcK3skdaf71t+boUEXBNZ6u3WNTkU7tDN8h9tebI+xlNceDGSGjOlNoHQVMKZdA +W9TA4ZqXUPAAAAgQDWU0UZVOSCAOODPz4PYsbFKdCfXNP8O4+t9txyc9E3hsLAsVs+CpVX +Gr219MGLrublzAxojipyzuQb6Tp1l9nsu7VkcBrPL8I1tokz0AyTnmNF3A9KszBal7gGNS +a2qYuf6JO4cub1KzonxUJQHZPZq9YhCxOtDwTd+uyHZiPy9QAAAIEA5vayd+nfVJgCKTdf +z5MFsxBSUj/cAYg7JYPS/0bZ5bEkLosL22wl5Tm/ZftJa8apkyBPhguAWt6jEWLoDiK+kn +Fv0SaEq1HUdXgWmISVnWzv2pxdAtq/apmbxTg3iIJyrAwEDo13iImR3k6rNPx1m3i/jX56 +HLcvWM4Y6bFzbGEAAAA0U3RhdGljIFJTQSBrZXkgZm9yIGdvbGFuZy5vcmcveC9jcnlwdG +8vc3NoIHVuaXQgdGVzdAECAwQFBgc= +-----END OPENSSH PRIVATE KEY-----` + + signer, err := ssh.ParsePrivateKey([]byte(privKeyData)) + if err != nil { + t.Fatalf("failed to create signer from key: %v", err) + } + + // Start server with MaxAuthTries 1 and publickey and password auth + // enabled + server := newServerForConfig(t, "MaxAuthTries", map[string]string{}) + + // Connect to server, expect failure, that PublicKeysCallback is called + // and that PasswordCallback is not called. + publicKeysCallbackCalled := false + config := clientConfig() + config.Auth = []ssh.AuthMethod{ + ssh.PublicKeysCallback(func() ([]ssh.Signer, error) { + publicKeysCallbackCalled = true + return []ssh.Signer{signer}, nil + }), + ssh.PasswordCallback(func() (string, error) { + t.Errorf("unexpected call to PasswordCallback()") + return "notaverygoodpassword", nil + }), + } + client, err := server.TryDial(config) + if err == nil { + t.Errorf("expected TryDial() to fail") + _ = client.Close() + } + if !publicKeysCallbackCalled { + t.Errorf("expected PublicKeysCallback() to be called") + } +} diff --git a/ssh/test/sshcli_test.go b/ssh/test/sshcli_test.go new file mode 100644 index 0000000000..767dd6c8f4 --- /dev/null +++ b/ssh/test/sshcli_test.go @@ -0,0 +1,163 @@ +// Copyright 2023 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 test + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" + + "golang.org/x/crypto/internal/testenv" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/testdata" +) + +func sshClient(t *testing.T) string { + if testing.Short() { + t.Skip("Skipping test that executes OpenSSH in -short mode") + } + sshCLI := os.Getenv("SSH_CLI_PATH") + if sshCLI == "" { + sshCLI = "ssh" + } + var err error + sshCLI, err = exec.LookPath(sshCLI) + if err != nil { + t.Skipf("Can't find an ssh(1) client to test against: %v", err) + } + return sshCLI +} + +// setupSSHCLIKeys writes the provided key files to a temporary directory and +// returns the path to the private key. +func setupSSHCLIKeys(t *testing.T, keyFiles map[string][]byte, privKeyName string) string { + tmpDir := t.TempDir() + for fn, content := range keyFiles { + if err := os.WriteFile(filepath.Join(tmpDir, fn), content, 0600); err != nil { + t.Fatalf("WriteFile(%q): %v", fn, err) + } + } + return filepath.Join(tmpDir, privKeyName) +} + +func TestSSHCLIAuth(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skipf("always fails on Windows, see #64403") + } + sshCLI := sshClient(t) + keyFiles := map[string][]byte{ + "rsa": testdata.PEMBytes["rsa"], + "rsa.pub": ssh.MarshalAuthorizedKey(testPublicKeys["rsa"]), + "rsa-cert.pub": testdata.SSHCertificates["rsa-user-testcertificate"], + } + keyPrivPath := setupSSHCLIKeys(t, keyFiles, "rsa") + + certChecker := ssh.CertChecker{ + IsUserAuthority: func(k ssh.PublicKey) bool { + return bytes.Equal(k.Marshal(), testPublicKeys["ca"].Marshal()) + }, + UserKeyFallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { + if conn.User() == "testpubkey" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + + return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) + }, + } + + config := &ssh.ServerConfig{ + PublicKeyCallback: certChecker.Authenticate, + } + config.AddHostKey(testSigners["rsa"]) + + server, err := newTestServer(config) + if err != nil { + t.Fatalf("unable to start test server: %v", err) + } + defer server.Close() + + port, err := server.port() + if err != nil { + t.Fatalf("unable to get server port: %v", err) + } + + // test public key authentication. + cmd := testenv.Command(t, sshCLI, "-vvv", "-i", keyPrivPath, "-o", "StrictHostKeyChecking=no", + "-p", port, "testpubkey@127.0.0.1", "true") + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("public key authentication failed, error: %v, command output %q", err, string(out)) + } + // Test SSH user certificate authentication. + // The username must match one of the principals included in the certificate. + // The certificate "rsa-user-testcertificate" has "testcertificate" as principal. + cmd = testenv.Command(t, sshCLI, "-vvv", "-i", keyPrivPath, "-o", "StrictHostKeyChecking=no", + "-p", port, "testcertificate@127.0.0.1", "true") + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("user certificate authentication failed, error: %v, command output %q", err, string(out)) + } +} + +func TestSSHCLIKeyExchanges(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skipf("always fails on Windows, see #64403") + } + sshCLI := sshClient(t) + keyFiles := map[string][]byte{ + "rsa": testdata.PEMBytes["rsa"], + "rsa.pub": ssh.MarshalAuthorizedKey(testPublicKeys["rsa"]), + } + keyPrivPath := setupSSHCLIKeys(t, keyFiles, "rsa") + + keyExchanges := append(ssh.SupportedAlgorithms().KeyExchanges, ssh.InsecureAlgorithms().KeyExchanges...) + for _, kex := range keyExchanges { + t.Run(kex, func(t *testing.T) { + cmd := testenv.Command(t, sshCLI, "-Q", "kex") + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s failed to check if the KEX is supported, error: %v, command output %q", kex, err, string(out)) + } + if !bytes.Contains(out, []byte(kex)) { + t.Skipf("KEX %q is not supported in the installed ssh CLI", kex) + } + config := &ssh.ServerConfig{ + Config: ssh.Config{ + KeyExchanges: []string{kex}, + }, + PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { + if conn.User() == "testpubkey" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + + return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) + }, + } + config.AddHostKey(testSigners["rsa"]) + + server, err := newTestServer(config) + if err != nil { + t.Fatalf("unable to start test server: %v", err) + } + defer server.Close() + + port, err := server.port() + if err != nil { + t.Fatalf("unable to get server port: %v", err) + } + + cmd = testenv.Command(t, sshCLI, "-vvv", "-i", keyPrivPath, "-o", "StrictHostKeyChecking=no", + "-o", fmt.Sprintf("KexAlgorithms=%s", kex), "-p", port, "testpubkey@127.0.0.1", "true") + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s failed, error: %v, command output %q", kex, err, string(out)) + } + }) + } +} diff --git a/ssh/test/sshd_test_pw.c b/ssh/test/sshd_test_pw.c index 2794a563a4..1e48619994 100644 --- a/ssh/test/sshd_test_pw.c +++ b/ssh/test/sshd_test_pw.c @@ -20,7 +20,7 @@ // Run sshd: // LD_PRELOAD="sshd_test_pw.so" TEST_USER="..." TEST_PASSWD="..." sshd ... -// +build ignore +//go:build ignore #define _GNU_SOURCE #include diff --git a/ssh/test/test_unix_test.go b/ssh/test/test_unix_test.go index cf62d4244f..89743d204c 100644 --- a/ssh/test/test_unix_test.go +++ b/ssh/test/test_unix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9 +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 || solaris package test @@ -13,144 +13,23 @@ import ( "crypto/rand" "encoding/base64" "fmt" - "io/ioutil" - "log" "net" "os" "os/exec" "os/user" "path/filepath" "testing" - "text/template" + "golang.org/x/crypto/internal/testenv" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/testdata" ) -const ( - defaultSshdConfig = ` -Protocol 2 -Banner {{.Dir}}/banner -HostKey {{.Dir}}/id_rsa -HostKey {{.Dir}}/id_dsa -HostKey {{.Dir}}/id_ecdsa -HostCertificate {{.Dir}}/id_rsa-cert.pub -Pidfile {{.Dir}}/sshd.pid -#UsePrivilegeSeparation no -KeyRegenerationInterval 3600 -ServerKeyBits 768 -SyslogFacility AUTH -LogLevel DEBUG2 -LoginGraceTime 120 -PermitRootLogin no -StrictModes no -RSAAuthentication yes -PubkeyAuthentication yes -AuthorizedKeysFile {{.Dir}}/authorized_keys -TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub -IgnoreRhosts yes -RhostsRSAAuthentication no -HostbasedAuthentication no -PubkeyAcceptedKeyTypes=* -` - multiAuthSshdConfigTail = ` -UsePAM yes -PasswordAuthentication yes -ChallengeResponseAuthentication yes -AuthenticationMethods {{.AuthMethods}} -` -) - -var configTmpl = map[string]*template.Template{ - "default": template.Must(template.New("").Parse(defaultSshdConfig)), - "MultiAuth": template.Must(template.New("").Parse(defaultSshdConfig + multiAuthSshdConfigTail))} - -type server struct { - t *testing.T - cleanup func() // executed during Shutdown - configfile string - cmd *exec.Cmd - output bytes.Buffer // holds stderr from sshd process - - testUser string // test username for sshd - testPasswd string // test password for sshd - sshdTestPwSo string // dynamic library to inject a custom password into sshd - - // Client half of the network connection. - clientConn net.Conn -} - -func username() string { - var username string - if user, err := user.Current(); err == nil { - username = user.Username - } else { - // user.Current() currently requires cgo. If an error is - // returned attempt to get the username from the environment. - log.Printf("user.Current: %v; falling back on $USER", err) - username = os.Getenv("USER") - } - if username == "" { - panic("Unable to get username") - } - return username -} - -type storedHostKey struct { - // keys map from an algorithm string to binary key data. - keys map[string][]byte - - // checkCount counts the Check calls. Used for testing - // rekeying. - checkCount int -} - -func (k *storedHostKey) Add(key ssh.PublicKey) { - if k.keys == nil { - k.keys = map[string][]byte{} - } - k.keys[key.Type()] = key.Marshal() -} - -func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { - k.checkCount++ - algo := key.Type() - - if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { - return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) - } - return nil -} - -func hostKeyDB() *storedHostKey { - keyChecker := &storedHostKey{} - keyChecker.Add(testPublicKeys["ecdsa"]) - keyChecker.Add(testPublicKeys["rsa"]) - keyChecker.Add(testPublicKeys["dsa"]) - return keyChecker -} - -func clientConfig() *ssh.ClientConfig { - config := &ssh.ClientConfig{ - User: username(), - Auth: []ssh.AuthMethod{ - ssh.PublicKeys(testSigners["user"]), - }, - HostKeyCallback: hostKeyDB().Check, - HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker - ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, - ssh.KeyAlgoRSA, ssh.KeyAlgoDSA, - ssh.KeyAlgoED25519, - }, - } - return config -} - // unixConnection creates two halves of a connected net.UnixConn. It // is used for connecting the Go SSH client with sshd without opening // ports. func unixConnection() (*net.UnixConn, *net.UnixConn, error) { - dir, err := ioutil.TempDir("", "unixConnection") + dir, err := os.MkdirTemp("", "unixConnection") if err != nil { return nil, nil, err } @@ -182,7 +61,7 @@ func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { // addr is the user specified host:port. While we don't actually dial it, // we need to know this for host key matching -func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) { +func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (client *ssh.Client, err error) { sshd, err := exec.LookPath("sshd") if err != nil { s.t.Skipf("skipping test: %v", err) @@ -192,16 +71,29 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl if err != nil { s.t.Fatalf("unixConnection: %v", err) } + defer func() { + // Close c2 after we've started the sshd command so that it won't prevent c1 + // from returning EOF when the sshd command exits. + c2.Close() + + // Leave c1 open if we're returning a client that wraps it. + // (The client is responsible for closing it.) + // Otherwise, close it to free up the socket. + if client == nil { + c1.Close() + } + }() - s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e") f, err := c2.File() if err != nil { s.t.Fatalf("UnixConn.File: %v", err) } defer f.Close() - s.cmd.Stdin = f - s.cmd.Stdout = f - s.cmd.Stderr = &s.output + + cmd := testenv.Command(s.t, sshd, "-f", s.configfile, "-i", "-e") + cmd.Stdin = f + cmd.Stdout = f + cmd.Stderr = new(bytes.Buffer) if s.sshdTestPwSo != "" { if s.testUser == "" { @@ -210,18 +102,29 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl if s.testPasswd == "" { s.t.Fatal("password missing from sshd_test_pw.so config") } - s.cmd.Env = append(os.Environ(), + cmd.Env = append(os.Environ(), fmt.Sprintf("LD_PRELOAD=%s", s.sshdTestPwSo), fmt.Sprintf("TEST_USER=%s", s.testUser), fmt.Sprintf("TEST_PASSWD=%s", s.testPasswd)) } - if err := s.cmd.Start(); err != nil { - s.t.Fail() - s.Shutdown() + if err := cmd.Start(); err != nil { s.t.Fatalf("s.cmd.Start: %v", err) } - s.clientConn = c1 + s.lastDialConn = c1 + s.t.Cleanup(func() { + // Don't check for errors; if it fails it's most + // likely "os: process already finished", and we don't + // care about that. Use os.Interrupt, so child + // processes are killed too. + cmd.Process.Signal(os.Interrupt) + cmd.Wait() + if s.t.Failed() || testing.Verbose() { + // log any output from sshd process + s.t.Logf("sshd:\n%s", cmd.Stderr) + } + }) + conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config) if err != nil { return nil, err @@ -232,40 +135,11 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { conn, err := s.TryDial(config) if err != nil { - s.t.Fail() - s.Shutdown() s.t.Fatalf("ssh.Client: %v", err) } return conn } -func (s *server) Shutdown() { - if s.cmd != nil && s.cmd.Process != nil { - // Don't check for errors; if it fails it's most - // likely "os: process already finished", and we don't - // care about that. Use os.Interrupt, so child - // processes are killed too. - s.cmd.Process.Signal(os.Interrupt) - s.cmd.Wait() - } - if s.t.Failed() { - // log any output from sshd process - s.t.Logf("sshd: %s", s.output.String()) - } - s.cleanup() -} - -func writeFile(path string, contents []byte) { - f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) - if err != nil { - panic(err) - } - defer f.Close() - if _, err := f.Write(contents); err != nil { - panic(err) - } -} - // generate random password func randomPassword() (string, error) { b := make([]byte, 12) @@ -315,7 +189,7 @@ func newServerForConfig(t *testing.T, config string, configVars map[string]strin if uname == "root" { t.Skip("skipping test because current user is root") } - dir, err := ioutil.TempDir("", "sshtest") + dir, err := os.MkdirTemp("", "sshtest") if err != nil { t.Fatal(err) } @@ -351,20 +225,20 @@ func newServerForConfig(t *testing.T, config string, configVars map[string]strin authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k])) } writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes()) + t.Cleanup(func() { + if err := os.RemoveAll(dir); err != nil { + t.Error(err) + } + }) return &server{ t: t, configfile: f.Name(), - cleanup: func() { - if err := os.RemoveAll(dir); err != nil { - t.Error(err) - } - }, } } func newTempSocket(t *testing.T) (string, func()) { - dir, err := ioutil.TempDir("", "socket") + dir, err := os.MkdirTemp("", "socket") if err != nil { t.Fatal(err) } diff --git a/ssh/testdata/Client-BannerCallback b/ssh/testdata/Client-BannerCallback new file mode 100644 index 0000000000..f8e8b1d4bf --- /dev/null +++ b/ssh/testdata/Client-BannerCallback @@ -0,0 +1,298 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 c8 9f 47 8f 1d b3 6c e4 86 d8 |........G...l...| +00000010 29 d2 db 83 c7 ee 00 00 01 7a 73 6e 74 72 75 70 |)........zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 37 00 93 5e 60 8c 9f e2 e0 4b |..... 7..^`....K| +00000080 59 97 5c 6f d4 5a 3e 25 f8 fb 08 72 92 05 4d 6c |Y.\o.Z>%...r..Ml| +00000090 80 c4 27 0e ec 26 00 00 00 64 00 00 00 13 65 63 |..'..&...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 ec c1 21 3e be 3c |6...I...!...!>.<| +000000c0 7a 50 7b 47 eb c2 92 bf 0b 93 cf 59 b5 84 2c f5 |zP{G.......Y..,.| +000000d0 bf 9b 2d 01 cc 2e 42 15 b0 04 00 00 00 20 61 99 |..-...B...... a.| +000000e0 9e 54 45 c1 54 a4 da d6 0b 3a d1 09 24 0f a0 b1 |.TE.T....:..$...| +000000f0 66 b9 6f 06 a4 f4 09 7e 51 3f 5a e2 98 6c 00 00 |f.o....~Q?Z..l..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 57 9a 3e 61 |...........@W.>a| +00000120 04 0a 62 05 83 8d 82 84 8a e6 91 0b 2c 28 d5 ce |..b.........,(..| +00000130 b8 06 56 59 54 af 80 60 6c 9b 8c a5 1c 8a 5a 30 |..VYT..`l.....Z0| +00000140 e3 70 23 61 86 ed a3 6a b6 fc 8d b8 d0 c3 72 25 |.p#a...j......r%| +00000150 1c 4c 5c 84 a5 77 59 83 31 52 1b f4 09 8c 9f a7 |.L\..wY.1R......| +00000160 b5 b2 ca f2 2c 8d ca 8f 2f 49 b9 83 65 af 97 5d |....,.../I..e..]| +00000170 a3 a9 02 97 8f ee 42 30 9a 6c 8a 38 2c 23 33 1b |......B0.l.8,#3.| +00000180 16 08 cd 7e 5e 2a 9b b4 34 26 9e 3b cb ec 37 0b |...~^*..4&.;..7.| +00000190 39 8e 39 62 80 57 a2 95 d7 0d b6 ce 02 d8 66 b0 |9.9b.W........f.| +000001a0 15 c4 cf 77 01 80 7b 42 41 96 4d 92 d6 5d b3 03 |...w..{BA.M..]..| +000001b0 f3 83 22 c8 fe a7 7a c3 a4 aa 6a 75 23 de 4a 30 |.."...z...ju#.J0| +000001c0 76 e6 8d 2a c7 3a c8 1a 60 f3 db ce 8a 53 44 2f |v..*.:..`....SD/| +000001d0 ff 02 38 3e 23 28 cf 45 08 ae b8 a8 24 db 6f 1e |..8>#(.E....$.o.| +000001e0 77 7a 33 19 e8 d0 13 11 63 19 b6 71 8b 19 3b 5b |wz3.....c..q..;[| +000001f0 ad b5 3d cc 08 6f bd 89 cb fa c9 d7 e6 af e0 82 |..=..o..........| +00000200 25 8b 60 bb 08 64 d3 71 d0 71 05 f1 94 1e 9b 7b |%.`..d.q.q.....{| +00000210 07 35 64 fa 05 c3 23 4d 95 d0 4d 49 7d 93 61 72 |.5d...#M..MI}.ar| +00000220 11 14 07 94 fb 3e a4 0f 7c ce 24 e3 a5 24 3e ae |.....>..|.$..$>.| +00000230 e5 11 f5 29 f1 aa 2d 6c a8 8d 47 fb cb 0c 62 e2 |...)..-l..G...b.| +00000240 cc 80 89 bc a6 76 e6 60 5c bf 86 78 58 ea e3 b2 |.....v.`\..xX...| +00000250 b3 61 35 c4 80 23 f5 c6 ac 45 fd 5f 5b 41 8d 59 |.a5..#...E._[A.Y| +00000260 eb 4c b2 3c fa df 0a 78 c4 af 59 42 |.L.<...x..YB| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000010 00 00 00 20 ad 6d e9 f4 a6 ee b0 dc 51 d0 16 a8 |... .m......Q...| +00000020 48 f5 0b cf 15 42 51 3a 8a 0a 3d 4b cd 20 82 ce |H....BQ:..=K. ..| +00000030 3f ac d4 33 0d ff 29 ea f8 28 2c dc e2 c4 bc 46 |?..3..)..(,....F| +00000040 c2 5e 8a ce |.^..| +>>> Flow 8 (server to client) +00000000 00 00 00 20 25 d5 f5 9e c7 e4 76 15 a5 03 f4 30 |... %.....v....0| +00000010 02 2e 64 e7 b7 a8 33 12 d1 d1 e0 62 3d b5 23 12 |..d...3....b=.#.| +00000020 eb 61 31 21 5c 07 bb 54 bc 4f 29 5d 80 1e 7c 88 |.a1!\..T.O)]..|.| +00000030 b9 46 b0 56 |.F.V| +>>> Flow 9 (client to server) +00000000 00 00 00 30 dc 6c b3 a7 e2 60 9c a8 41 3c 12 4b |...0.l...`..A<.K| +00000010 f0 90 69 20 65 08 60 50 b0 52 22 ed 50 cf 5f 5c |..i e.`P.R".P._\| +00000020 d3 ed 35 13 88 32 2c 7c d5 5b 6c f3 09 1b 50 0e |..5..2,|.[l...P.| +00000030 9b bb ac 21 73 94 51 93 73 de 71 6c 0a fd 11 a4 |...!s.Q.s.ql....| +00000040 77 70 55 ef |wpU.| +>>> Flow 10 (server to client) +00000000 00 00 00 20 32 b6 e9 e4 79 15 00 f8 5a 72 08 38 |... 2...y...Zr.8| +00000010 55 af 59 21 6e 7f f4 6f f2 0e e8 d8 a5 61 bb a4 |U.Y!n..o.....a..| +00000020 ce 26 3b 94 a8 e7 d9 5d 69 d7 6d d7 70 5f b8 a9 |.&;....]i.m.p_..| +00000030 e9 ee 02 e8 00 00 00 40 21 fe 1d 4e 06 ce c3 51 |.......@!..N...Q| +00000040 34 9d ad 04 60 1b 5e b7 89 c9 8d f5 24 d7 ff 69 |4...`.^.....$..i| +00000050 a0 89 fe 95 58 66 7f af 63 1b b2 f5 b0 ad 26 b8 |....Xf..c.....&.| +00000060 b4 25 33 9d 47 02 69 98 a1 a2 5c 30 5b 1c da 9d |.%3.G.i...\0[...| +00000070 7d 75 8c f3 be 05 dd b2 0f 65 5c 1e 17 08 d7 00 |}u.......e\.....| +00000080 03 97 99 ca a4 ca a3 c2 |........| +>>> Flow 11 (client to server) +00000000 00 00 01 60 4d a5 d0 b6 1a b3 dc c9 f2 da 8e 8a |...`M...........| +00000010 03 a4 d3 61 0b 95 e5 7e db cc 31 49 21 c7 fa 95 |...a...~..1I!...| +00000020 43 d0 ee 93 d6 45 29 85 3c 9a 82 e4 6b 65 5d 7c |C....E).<...ke]|| +00000030 cc 52 e8 83 b2 5a 65 ad 2f 83 1f b0 e7 a4 aa c7 |.R...Ze./.......| +00000040 49 40 98 10 d8 af c2 c0 0f a2 54 d0 30 37 13 06 |I@........T.07..| +00000050 12 63 a6 3b 73 30 74 d3 47 56 51 ba 23 32 c8 6f |.c.;s0t.GVQ.#2.o| +00000060 e7 8a b1 27 fa f6 21 6c 26 2a f7 00 cb 14 d6 9a |...'..!l&*......| +00000070 c2 f7 45 51 c8 20 6c 96 24 b2 64 57 06 23 31 ed |..EQ. l.$.dW.#1.| +00000080 3a b2 10 7f 1d 8e 48 25 db 95 6c 0e 30 90 aa 69 |:.....H%..l.0..i| +00000090 92 ae a5 1b 36 40 43 62 95 b0 d8 f6 bf 5c c1 8e |....6@Cb.....\..| +000000a0 48 ab 38 f9 75 52 e1 8e b2 4b 75 6e f4 ac 03 24 |H.8.uR...Kun...$| +000000b0 73 f4 01 51 98 0c 6f ed 4f 19 29 88 d7 08 13 d2 |s..Q..o.O.).....| +000000c0 84 d9 54 63 b3 e3 8a 0d 42 6c f0 67 ac dc 4b 93 |..Tc....Bl.g..K.| +000000d0 79 f2 70 ff 53 1f 27 f3 70 7c bf 75 33 79 64 3c |y.p.S.'.p|.u3yd<| +000000e0 eb 30 1b dc c4 ff 11 f9 6f 74 f3 d1 1a c0 6b 4e |.0......ot....kN| +000000f0 f2 56 32 5f 0d 82 eb 49 10 a1 0a df 47 af 18 c6 |.V2_...I....G...| +00000100 21 c3 77 b4 39 7a 62 c3 aa f4 fb 19 95 bc 2d d2 |!.w.9zb.......-.| +00000110 36 ca 6b d6 bf 91 00 3d 73 e8 41 65 60 44 89 48 |6.k....=s.Ae`D.H| +00000120 57 89 9b 69 a4 c8 5e c2 df b8 bb e8 da e4 09 f9 |W..i..^.........| +00000130 29 17 39 c6 35 88 7f 26 9b c8 94 02 03 c4 03 e8 |).9.5..&........| +00000140 f6 df 68 52 e2 6e 84 91 10 7b 06 23 b0 4b f5 75 |..hR.n...{.#.K.u| +00000150 4f b6 b8 b4 f2 b3 72 8a bf 91 92 1f 73 0a de e4 |O.....r.....s...| +00000160 20 62 3d 30 50 c3 b9 7b cd 59 d1 83 fd e7 f0 cd | b=0P..{.Y......| +00000170 c6 a0 11 12 |....| +>>> Flow 12 (server to client) +00000000 00 00 01 40 57 32 56 54 ba 8e a5 73 bc 12 1e 11 |...@W2VT...s....| +00000010 02 03 72 e9 23 4f b2 70 a5 23 ea de f6 1e 25 e3 |..r.#O.p.#....%.| +00000020 6c d0 8d c5 db da 81 e5 04 71 7e 9b 75 99 1b 70 |l........q~.u..p| +00000030 ef 04 fc 64 ef 83 2b a9 4b 87 32 ed 28 98 17 ec |...d..+.K.2.(...| +00000040 c6 e9 bf 8f 85 8e 93 ac 91 a2 fe a0 78 bc e3 88 |............x...| +00000050 97 a4 3a 2e 3e 11 f5 04 0e 6f 38 6d 33 7f b7 10 |..:.>....o8m3...| +00000060 9f 1d 84 45 02 11 da 63 37 f7 86 c7 1b b3 36 ec |...E...c7.....6.| +00000070 ea b7 1a 2d 38 39 0a a1 0d 44 84 6b ad d7 22 28 |...-89...D.k.."(| +00000080 27 ab 24 b5 c3 85 77 31 b3 97 0c 12 35 7f 3e c7 |'.$...w1....5.>.| +00000090 d4 0e 3f 16 07 70 e8 fc b1 f7 29 94 28 2c ae 1b |..?..p....).(,..| +000000a0 b3 1a 25 8a 2e e7 5f 52 5b 17 dd e5 ec e9 db 93 |..%..._R[.......| +000000b0 12 29 3d ba bf ac 90 d4 37 42 36 53 ae 3e 8c db |.)=.....7B6S.>..| +000000c0 d7 7c 48 c5 43 a1 ee d3 b6 74 ac 01 27 c9 06 0c |.|H.C....t..'...| +000000d0 ae 31 68 a7 a9 ff 40 9e d1 f3 c9 ee ca 3b 98 13 |.1h...@......;..| +000000e0 aa 5d 00 67 a0 fb 68 32 64 07 ff 4c f3 e1 4c be |.].g..h2d..L..L.| +000000f0 38 3e 26 10 5c 9d 4b fc 7f 3f 22 0f ee 12 af f9 |8>&.\.K..?".....| +00000100 3d 51 83 b1 5c 65 63 f1 fa 92 0e 1d 76 b9 27 a4 |=Q..\ec.....v.'.| +00000110 a4 a3 ec ba e9 43 b1 77 e1 c7 db 9e 25 bc 93 4d |.....C.w....%..M| +00000120 0c 9c bd 64 a0 db f4 a1 2b 9a 24 99 a9 0d be 17 |...d....+.$.....| +00000130 cd 99 31 da 3f 83 66 c0 4e 6f a5 1a 1e ec 4d 07 |..1.?.f.No....M.| +00000140 a4 04 d7 23 03 f7 ec 2c 8a 12 96 85 c1 d0 cb 59 |...#...,.......Y| +00000150 e8 6b 4a 6d |.kJm| +>>> Flow 13 (client to server) +00000000 00 00 02 80 5e 7e 95 09 c2 ec 6e cd 14 10 2c 4f |....^~....n...,O| +00000010 d3 f5 0a 89 6c 4a 3a b0 26 e4 c4 bc 51 26 ec a2 |....lJ:.&...Q&..| +00000020 1a c9 35 8e b6 7a a7 88 1d fe 04 04 73 f1 e7 e1 |..5..z......s...| +00000030 86 4c 3d 85 61 02 cc 5d 24 bb 87 a2 3e b2 5d bd |.L=.a..]$...>.].| +00000040 19 5f ce 47 5a 6c 6c ab 45 84 2d 3e 51 82 90 e7 |._.GZll.E.->Q...| +00000050 76 41 b7 37 0a b8 57 d9 3c 43 3e 3b 3d ba 39 41 |vA.7..W.;=.9A| +00000060 01 84 1b 3f 80 e0 f4 9b 32 32 12 02 c5 f5 23 4e |...?....22....#N| +00000070 36 75 37 2b ce 24 5e f7 9b 5b 3c 6e f8 2c aa d5 |6u7+.$^..[S...| +000001d0 c0 31 f3 d0 19 4d 51 a5 05 da 8d d3 9b a7 58 29 |.1...MQ.......X)| +000001e0 1e 25 c1 2e f8 27 ad 05 3f 11 b6 1f 9c 6d a5 d0 |.%...'..?....m..| +000001f0 28 db ba 57 8a 12 9f c5 f3 73 93 48 05 ba d2 0a |(..W.....s.H....| +00000200 a8 6d a4 a8 96 02 de a8 77 fd 01 e4 fe 14 87 46 |.m......w......F| +00000210 d4 df f4 fc a7 e7 40 c2 3a 64 52 98 b8 5e 0f 00 |......@.:dR..^..| +00000220 06 bf 70 d9 5b 2d 14 22 3e 6a a8 e2 c5 9b 91 76 |..p.[-.">j.....v| +00000230 50 c9 92 b5 c0 31 32 a8 77 c9 be 02 00 68 08 c4 |P....12.w....h..| +00000240 1e 08 d1 fa d8 e8 32 97 5a 0a 56 a8 9b 78 94 20 |......2.Z.V..x. | +00000250 84 dd 56 18 2e eb 5d d2 e3 fd 28 05 b7 15 32 87 |..V...]...(...2.| +00000260 c4 78 71 f6 11 41 22 da 3b b5 4c 60 71 df 6c eb |.xq..A".;.L`q.l.| +00000270 c3 7c 4a 9c b3 e3 c9 12 2b a3 79 c9 e2 99 2a 4d |.|J.....+.y...*M| +00000280 6b 88 2b 42 48 79 c7 52 33 f5 09 2e 60 1f 96 b1 |k.+BHy.R3...`...| +00000290 b5 35 94 5a |.5.Z| +>>> Flow 14 (server to client) +00000000 00 00 00 10 60 4c c8 0d e2 72 d3 60 e0 94 a4 06 |....`L...r.`....| +00000010 79 85 52 74 0f 2d 35 96 99 61 f6 8d d4 01 6e e3 |y.Rt.-5..a....n.| +00000020 b2 54 8a 0f |.T..| diff --git a/ssh/testdata/Client-Cipher-aes128-ctr b/ssh/testdata/Client-Cipher-aes128-ctr new file mode 100644 index 0000000000..fdce462602 --- /dev/null +++ b/ssh/testdata/Client-Cipher-aes128-ctr @@ -0,0 +1,295 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 5c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 0a 61 65 73 31 32 38 2d 63 74 72 00 00 00 0a |..aes128-ctr....| +00000150 61 65 73 31 32 38 2d 63 74 72 00 00 00 6e 68 6d |aes128-ctr...nhm| +00000160 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +00000170 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000180 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +00000190 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001a0 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +000001b0 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +000001c0 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e |hmac-sha1-96...n| +000001d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 |hmac-sha2-256-et| +000001e0 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +000001f0 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 |ac-sha2-512-etm@| +00000200 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000210 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 |-sha2-256,hmac-s| +00000220 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 |ha2-512,hmac-sha| +00000230 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |1,hmac-sha1-96..| +00000240 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000250 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 3c 7e 44 d5 52 42 76 d2 6a fa |......<~D.RBv.j.| +00000010 8b b0 ea cc ef 95 00 00 01 7a 73 6e 74 72 75 70 |.........zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 13 cf b6 0f c2 c9 |...,..... ......| +00000010 08 d9 7b f6 60 d4 53 7f 4b b1 29 37 59 98 3c dd |..{.`.S.K.)7Y.<.| +00000020 ab b1 51 12 94 92 eb 56 4c 6f e8 a3 63 9c a8 a1 |..Q....VLo..c...| +>>> Flow 6 (server to client) +00000000 00 00 01 04 09 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 e9 56 86 74 34 11 d7 d3 48 a0 |..... .V.t4...H.| +00000080 a8 6d bd 3f 00 ae da 7d 63 fb 6f b2 2d 90 c8 53 |.m.?...}c.o.-..S| +00000090 3f 14 42 43 88 12 00 00 00 65 00 00 00 13 65 63 |?.BC.....e....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 4a 00 00 00 21 00 ed ac 80 ff 90 17 |6...J...!.......| +000000c0 05 2b 9b 55 14 f1 04 45 f5 8e 59 7b 0f a9 69 51 |.+.U...E..Y{..iQ| +000000d0 39 04 ef ab 75 03 27 8d b2 a6 00 00 00 21 00 fb |9...u.'......!..| +000000e0 5c 9b 84 8f 26 00 81 c4 7a 58 c8 c1 e7 3c 15 b7 |\...&...zX...<..| +000000f0 a3 06 27 f8 e2 a1 b5 02 5d 7f 73 29 8a e5 98 00 |..'.....].s)....| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 fc d3 1f 73 |...........@...s| +00000120 95 a6 4b 07 99 e0 76 21 16 09 1e 47 bb 69 67 42 |..K...v!...G.igB| +00000130 5c f2 e4 d2 24 8c a4 92 56 65 11 8a 8e 58 64 fd |\...$...Ve...Xd.| +00000140 20 69 4d fd a3 61 44 1d d6 b8 40 3e 9a 07 05 d5 | iM..aD...@>....| +00000150 be 5d 02 bf a0 6e 9c 1b 5d 3f b1 10 21 88 6b 78 |.]...n..]?..!.kx| +00000160 5b 36 a4 ba 01 a4 62 50 e7 e2 d1 d2 7a 47 a3 fc |[6....bP....zG..| +00000170 27 38 15 89 10 13 ee d4 bc 72 d2 16 95 d5 3a 52 |'8.......r....:R| +00000180 df 54 1e 9c 6e dd 01 2a 30 3e 5c 0a 5e 08 19 ef |.T..n..*0>\.^...| +00000190 d4 60 a6 f0 85 34 da 53 f6 c0 51 8b 5a 6b 3e 28 |.`...4.S..Q.Zk>(| +000001a0 4a 7b 41 72 89 73 c3 16 1e d4 62 fe 21 3a 0f 74 |J{Ar.s....b.!:.t| +000001b0 45 6d 61 01 3c b1 95 a0 37 6e b5 5d 38 a8 54 be |Ema.<...7n.]8.T.| +000001c0 f2 67 0d 99 cc 61 4d 11 4a 64 93 93 05 47 0f 08 |.g...aM.Jd...G..| +000001d0 75 fc 41 25 24 ce a6 b4 e7 71 c8 f4 eb 77 00 82 |u.A%$....q...w..| +000001e0 a9 8d 5d 7a f5 b9 d1 01 cb 3f d1 30 41 c4 35 56 |..]z.....?.0A.5V| +000001f0 d6 7c 13 e5 1a d2 ae 59 3a a1 35 bc 0f ca 67 73 |.|.....Y:.5...gs| +00000200 39 da 3f 33 d0 d4 ad 16 37 0d 23 52 45 c5 48 a1 |9.?3....7.#RE.H.| +00000210 0a 07 44 34 f2 a4 f1 59 91 2f ec 46 2b 47 fd 7a |..D4...Y./.F+G.z| +00000220 80 82 60 7b 22 e0 aa e2 be 9f ca 5f d0 da 58 23 |..`{"......_..X#| +00000230 b3 f9 30 e0 f6 48 a6 97 99 55 76 79 fd cc c3 fd |..0..H...Uvy....| +00000240 1b c3 91 51 f3 a2 17 c4 50 ad 34 c9 66 47 5d f2 |...Q....P.4.fG].| +00000250 0a 77 81 a2 74 35 3e e0 e1 ce 7b 10 22 9c 4a 10 |.w..t5>...{.".J.| +00000260 6b b8 5e 21 49 dc cb 02 85 7a 96 4f d6 39 b5 e5 |k.^!I....z.O.9..| +00000270 a1 40 7a 1d d6 b3 c5 3e 08 65 31 ad |.@z....>.e1.| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 e3 f9 ae 57 e2 35 b8 cc 87 3c |.........W.5...<| +00000010 00 00 00 20 33 e5 12 ab 62 1c 2c 69 88 93 54 76 |... 3...b.,i..Tv| +00000020 f7 f8 fd dc 60 17 93 77 87 cd 82 b1 07 a3 b1 ab |....`..w........| +00000030 3c 1a 85 46 bb 6d 43 54 d5 63 49 d9 1d 51 55 89 |<..F.mCT.cI..QU.| +00000040 e9 5c 5f 7c 62 b8 76 b4 0b c6 c4 e9 be d2 b2 9b |.\_|b.v.........| +00000050 d3 dc 15 b8 |....| +>>> Flow 8 (server to client) +00000000 00 00 00 20 93 ba c4 77 30 8a 7f d5 56 ed 0b b8 |... ...w0...V...| +00000010 85 c8 49 71 3a a1 8b 8b 94 d4 b1 e2 2b 0f 54 12 |..Iq:.......+.T.| +00000020 74 89 06 dc a5 92 37 aa 5e 3a 24 4d 82 df a6 40 |t.....7.^:$M...@| +00000030 74 48 79 db 42 bf 49 49 67 61 a3 e5 96 c2 f8 11 |tHy.B.IIga......| +00000040 a6 74 2c 1b |.t,.| +>>> Flow 9 (client to server) +00000000 00 00 00 30 78 7e e0 d6 9f ee 3f ac 47 ee a1 ab |...0x~....?.G...| +00000010 1f 7a d5 00 e0 b8 0a 00 69 61 db 12 f2 d4 b2 c5 |.z......ia......| +00000020 a0 09 12 08 c2 fa c1 2a 3b 21 18 03 4f be 96 0a |.......*;!..O...| +00000030 fc b4 36 8f c6 4d 8d 13 c7 ca 48 80 65 db 25 da |..6..M....H.e.%.| +00000040 4e 36 29 44 fb 19 b4 96 53 b9 2f 74 56 c9 8c 66 |N6)D....S./tV..f| +00000050 85 03 eb 98 |....| +>>> Flow 10 (server to client) +00000000 00 00 00 20 36 ba 73 95 01 22 06 8d e9 7c c1 41 |... 6.s.."...|.A| +00000010 92 85 b9 b8 f4 37 52 b0 b4 99 8f 47 f7 ef 38 10 |.....7R....G..8.| +00000020 a6 b0 35 c4 44 f1 72 89 0a 67 75 09 de 70 68 d5 |..5.D.r..gu..ph.| +00000030 4e 81 af 5b e4 5b 61 02 aa ed bb 31 fe 70 59 f5 |N..[.[a....1.pY.| +00000040 fc bf 7a 44 00 00 00 40 e3 5b ae 48 03 59 c7 d0 |..zD...@.[.H.Y..| +00000050 22 f6 34 db c7 f4 2a 09 7e 0d ad c0 e4 b6 52 c2 |".4...*.~.....R.| +00000060 7d de 8e 63 04 a0 06 d6 74 76 51 57 a6 16 7b 39 |}..c....tvQW..{9| +00000070 90 8c af 32 c3 c1 84 3f 65 39 15 d7 0e 8e b9 8e |...2...?e9......| +00000080 8f 13 97 9a ff f8 9b aa 5f 09 11 4c 46 e4 3d f6 |........_..LF.=.| +00000090 d1 e3 ac b7 d5 3e ae 68 6e ca 52 c6 f9 78 c4 ba |.....>.hn.R..x..| +000000a0 f7 37 0c 28 a5 7e 2d 45 |.7.(.~-E| +>>> Flow 11 (client to server) +00000000 00 00 01 60 90 e3 71 e0 56 c9 9e 55 b4 59 3c 28 |...`..q.V..U.Y<(| +00000010 9e 51 1c 69 16 61 e8 39 fd 0c 67 80 eb f4 c7 70 |.Q.i.a.9..g....p| +00000020 1a f9 6a b4 f3 b7 65 25 28 f5 a5 1a 56 b7 3c dc |..j...e%(...V.<.| +00000030 5b 6c 77 df 08 a2 31 e1 7f 77 17 24 fd 5a a3 e6 |[lw...1..w.$.Z..| +00000040 42 cf 4b da 75 e0 8b bf f3 e5 59 cb 11 95 d7 87 |B.K.u.....Y.....| +00000050 21 69 64 91 91 dc d8 b3 11 48 df 36 72 b1 05 43 |!id......H.6r..C| +00000060 d5 09 95 92 90 b9 d8 e4 0f 84 dd 3b c7 55 3b 93 |...........;.U;.| +00000070 d6 d0 3c 08 04 84 5a 25 55 76 ad 70 da 4d 17 6c |..<...Z%Uv.p.M.l| +00000080 5b 5e 56 0f 96 3b 4a 89 0f 23 7a a5 69 e3 b1 61 |[^V..;J..#z.i..a| +00000090 0d 19 a9 88 e9 79 bc 70 43 15 48 5e 7e 7f 76 75 |.....y.pC.H^~.vu| +000000a0 5f 8f d4 dc f7 90 af 67 e0 0a 62 56 0c 46 69 5c |_......g..bV.Fi\| +000000b0 92 bd 1d 3e bb 96 9e e9 a5 77 8a a4 70 ab df 5e |...>.....w..p..^| +000000c0 cb 09 7c 84 43 c4 d1 0e 86 0f ad e2 b7 fe d1 24 |..|.C..........$| +000000d0 e3 59 5c 22 00 07 77 a6 05 d0 53 90 47 ae c7 72 |.Y\"..w...S.G..r| +000000e0 f2 6a 56 98 f9 1e 6e 4c b1 a6 b8 3f 9f 04 c0 60 |.jV...nL...?...`| +000000f0 9a 79 14 75 4d 5f e4 c4 70 da f9 3e 88 71 94 04 |.y.uM_..p..>.q..| +00000100 5e 07 67 a9 d8 4c 4d e2 af 51 13 d1 e5 65 15 fe |^.g..LM..Q...e..| +00000110 b7 cd 7d 79 3c ba 3f 99 f3 4a 1f 2b f5 7f ff d6 |..}y<.?..J.+....| +00000120 77 48 34 96 33 1d 87 c6 41 f8 cf f8 b5 94 e8 47 |wH4.3...A......G| +00000130 d2 12 4d 21 9c 4a d8 ea 02 27 d5 dd 69 87 9a c6 |..M!.J...'..i...| +00000140 86 71 9f 97 14 d1 a3 03 35 d3 02 ed dd 5d 51 5d |.q......5....]Q]| +00000150 f5 12 47 b9 c5 39 eb fb 2d dc 56 99 da 6e e9 0a |..G..9..-.V..n..| +00000160 e6 50 94 7d f3 2e c0 64 e8 32 89 dc 43 3f ed f2 |.P.}...d.2..C?..| +00000170 99 21 c6 81 6b a6 05 90 9d 88 1e 28 d7 15 8e b8 |.!..k......(....| +00000180 6e e1 4a de |n.J.| +>>> Flow 12 (server to client) +00000000 00 00 01 40 c2 47 39 65 3f a2 7e 94 17 b3 10 86 |...@.G9e?.~.....| +00000010 f9 73 32 6e f3 ec ab e3 ac d0 8a fb 82 d3 b1 e5 |.s2n............| +00000020 45 f9 cb 72 41 f8 23 ad f8 ce b6 7d 94 f6 2b 56 |E..rA.#....}..+V| +00000030 4e 99 b0 0d d5 11 2f 55 c3 67 44 bf 0f 72 5c 5a |N...../U.gD..r\Z| +00000040 6f 41 16 b2 46 f2 f5 1d fe d7 3b cc 47 3f d7 97 |oA..F.....;.G?..| +00000050 4e 9b 2c 84 de 31 10 2a 98 91 5e 55 15 fb df 61 |N.,..1.*..^U...a| +00000060 6d 6d 0e 59 dd 9c f4 f3 bf bc 8a 6b 37 ce 78 c6 |mm.Y.......k7.x.| +00000070 cc 21 c9 56 42 11 04 65 01 6c 94 29 e3 0c 12 31 |.!.VB..e.l.)...1| +00000080 7e cc f7 3c e3 9d 74 d4 2a 5a 35 ba 85 33 86 e1 |~..<..t.*Z5..3..| +00000090 99 2f 79 1e 7e 42 ca c4 b4 fa e7 60 2f f4 6f 80 |./y.~B.....`/.o.| +000000a0 28 f1 9c f8 94 89 90 7f ad ce fd d4 be cd af 66 |(..............f| +000000b0 93 4e 53 29 2c 15 4d 5d d4 36 73 97 0e 9c 53 95 |.NS),.M].6s...S.| +000000c0 42 69 1a 80 34 ab 46 2b 97 7f 42 ca d9 33 94 e2 |Bi..4.F+..B..3..| +000000d0 35 b9 c8 ec 98 34 87 4f fe 14 ce cd 47 c4 77 22 |5....4.O....G.w"| +000000e0 74 8b f6 c6 4a dd 95 b2 57 b1 ba cd 3e bd a2 cb |t...J...W...>...| +000000f0 c7 0f e2 75 24 48 a8 75 83 35 45 8f 11 16 a8 6c |...u$H.u.5E....l| +00000100 05 3d d3 bb 2c 81 4c 67 ae 33 32 ae 28 d9 dd dd |.=..,.Lg.32.(...| +00000110 ea 73 b7 7c 88 7e ac 72 fa b9 e4 ed 37 2e 0c 0a |.s.|.~.r....7...| +00000120 8f 24 f7 80 15 af b3 61 4b 1e 83 73 34 7f bd d7 |.$.....aK..s4...| +00000130 8f 24 25 93 43 75 3c a7 e1 dc ff e1 f7 e7 9a b5 |.$%.Cu<.........| +00000140 18 1c bd 8d 81 12 a3 1a 16 1d fa e5 72 9c c7 9d |............r...| +00000150 f3 d2 1b 76 ca a6 76 50 c5 83 56 1b 20 e5 c9 99 |...v..vP..V. ...| +00000160 c0 68 fb 99 |.h..| +>>> Flow 13 (client to server) +00000000 00 00 02 80 93 38 6e 30 08 53 2e 06 7f 0b 15 9f |.....8n0.S......| +00000010 f0 12 11 34 be b5 e6 77 ef 32 d1 e5 ab b7 25 5a |...4...w.2....%Z| +00000020 2a 97 6b 83 f2 08 35 d0 ae 3b 45 ec 47 72 60 b0 |*.k...5..;E.Gr`.| +00000030 2c c1 2c 5e 66 23 a0 b0 b5 c4 77 04 97 fc 89 14 |,.,^f#....w.....| +00000040 e6 d2 60 a6 40 d0 78 22 da c9 6a a4 72 8b 63 ad |..`.@.x"..j.r.c.| +00000050 60 57 b4 27 15 8f 66 0b a0 0c c2 c0 31 a2 74 4b |`W.'..f.....1.tK| +00000060 89 4c 8f d1 cd 45 a2 3d bf f9 8d 72 95 4f fa c8 |.L...E.=...r.O..| +00000070 46 09 ec 4c cc b0 7b 69 dd 20 3e e7 b0 ac 2d a4 |F..L..{i. >...-.| +00000080 f0 34 88 02 24 e1 5b 53 c7 aa 06 96 fe 35 ab d0 |.4..$.[S.....5..| +00000090 47 95 be 42 2f 75 22 d4 14 1f c4 cb 40 89 6f a0 |G..B/u".....@.o.| +000000a0 ff 73 01 dc 40 9d c7 3d 8b 96 f1 f9 89 f6 b1 fe |.s..@..=........| +000000b0 00 35 53 9c f7 09 25 a6 90 90 bb c8 a7 a2 88 e0 |.5S...%.........| +000000c0 ee 78 97 a8 d2 26 b7 b4 8c c6 3d 10 16 29 4b 6c |.x...&....=..)Kl| +000000d0 ee 30 90 73 09 57 f2 e1 c3 90 5f bc a2 48 aa 7b |.0.s.W...._..H.{| +000000e0 34 a3 95 1c 33 29 04 e4 97 f9 5f 62 5b 70 a0 c7 |4...3)...._b[p..| +000000f0 35 0f 28 ea 66 f8 42 61 a5 09 c3 c3 f1 81 26 66 |5.(.f.Ba......&f| +00000100 c3 c7 b9 b8 8e eb fa 22 30 a7 61 39 35 04 ba dc |......."0.a95...| +00000110 ff ab 5c 4e f6 0a 1d dc da 1d 37 88 fb 13 83 9b |..\N......7.....| +00000120 64 7c 5a 80 dc 05 df 3c 5a 36 16 67 6f 3f eb d1 |d|Z......U.7.J].....e| +000001d0 94 66 7e 4e e2 94 b4 f0 5a 83 08 f6 e1 ce 62 e5 |.f~N....Z.....b.| +000001e0 24 d6 98 6e a7 10 23 03 57 e8 03 b1 b0 84 53 0b |$..n..#.W.....S.| +000001f0 74 85 df fd b2 e1 0d 52 af 51 e3 64 5b 9d ed 42 |t......R.Q.d[..B| +00000200 88 a6 bd f1 e5 61 05 a7 40 f6 0b c2 97 26 ad 3c |.....a..@....&.<| +00000210 60 4f 75 d9 fb 20 b1 4d 96 a0 e8 80 c1 fe 1c 2c |`Ou.. .M.......,| +00000220 d5 b2 17 d5 8a 63 50 16 ae 67 3c dc 56 28 68 6d |.....cP..g<.V(hm| +00000230 3d ec ca 11 58 f4 98 30 dc 92 f4 38 6b 7c ff 4d |=...X..0...8k|.M| +00000240 e4 f0 63 66 b4 e6 20 56 3a d0 b7 e8 10 d0 13 44 |..cf.. V:......D| +00000250 a7 ac 20 2a ca 8c 4f 73 12 36 8d 29 66 92 0c 5a |.. *..Os.6.)f..Z| +00000260 db 11 49 8b c2 2a e4 7c 2d 4c 26 5c d7 a5 37 2f |..I..*.|-L&\..7/| +00000270 4b 4e 95 90 1b de 4c 7d 78 6a 62 ac b0 a0 e8 93 |KN....L}xjb.....| +00000280 46 65 ce c9 39 19 36 14 d4 22 28 75 23 3b 33 97 |Fe..9.6.."(u#;3.| +00000290 95 46 f1 7a 87 ae d4 4b dd 2d 3b 7e 5b 3a e1 d2 |.F.z...K.-;~[:..| +000002a0 17 85 9c 7e |...~| +>>> Flow 14 (server to client) +00000000 00 00 00 10 f5 bc 41 31 d1 0d d3 47 ed 2b 87 a0 |......A1...G.+..| +00000010 53 67 74 1d 19 c6 af f6 59 6a 8c d2 0d 29 0a 63 |Sgt.....Yj...).c| +00000020 b1 0d cc db d3 b4 d3 1b d3 d0 73 a6 f8 ec 16 06 |..........s.....| +00000030 de e2 0e b8 |....| diff --git a/ssh/testdata/Client-Cipher-aes128-gcm@openssh.com b/ssh/testdata/Client-Cipher-aes128-gcm@openssh.com new file mode 100644 index 0000000000..53b9c0a97f --- /dev/null +++ b/ssh/testdata/Client-Cipher-aes128-gcm@openssh.com @@ -0,0 +1,287 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 7c 0d 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...|....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 16 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |..aes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 00 00 00 16 61 65 73 31 |nssh.com....aes1| +00000160 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-gcm@openssh.c| +00000170 6f 6d 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d |om...nhmac-sha2-| +00000180 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |256-etm@openssh.| +00000190 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 |com,hmac-sha2-51| +000001a0 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |2-etm@openssh.co| +000001b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +000001c0 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +000001d0 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 |ac-sha1,hmac-sha| +000001e0 31 2d 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 |1-96...nhmac-sha| +000001f0 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-256-etm@openss| +00000200 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d |h.com,hmac-sha2-| +00000210 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |512-etm@openssh.| +00000220 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +00000230 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +00000240 68 6d 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 |hmac-sha1,hmac-s| +00000250 68 61 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 |ha1-96....none..| +00000260 00 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 |..none..........| +00000270 00 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa |....;........n..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 5b f0 eb 4c e5 38 1d df 00 dc |......[..L.8....| +00000010 d7 5e f9 2f 04 3b 00 00 01 7a 73 6e 74 72 75 70 |.^./.;...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 7e 4a 3b cc bf 9a |...,..... ~J;...| +00000010 2e 84 5f cb bb 32 fa b6 67 2f 28 60 b3 d3 48 e8 |.._..2..g/(`..H.| +00000020 f9 c9 38 6f ae b4 a3 c4 5b 73 ae 57 e2 35 b8 cc |..8o....[s.W.5..| +>>> Flow 6 (server to client) +00000000 00 00 01 04 09 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 24 91 84 75 c5 47 0e f0 65 f7 |..... $..u.G..e.| +00000080 b4 24 f9 69 a6 ba b0 3c fa c7 6b 47 67 93 ed 68 |.$.i...<..kGg..h| +00000090 c7 24 9f 85 d1 20 00 00 00 65 00 00 00 13 65 63 |.$... ...e....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 4a 00 00 00 21 00 be d5 c3 20 93 2a |6...J...!.... .*| +000000c0 6f 26 6e ff 6e 3b fc 85 55 ff 33 8a a9 ce 0a 46 |o&n.n;..U.3....F| +000000d0 33 6f b8 b6 8c ee 3d dd 0c 81 00 00 00 21 00 c7 |3o....=......!..| +000000e0 f1 e0 5b 89 be 5f c2 55 77 8a 0b 08 e8 d0 f3 e6 |..[.._.Uw.......| +000000f0 ce d0 fe 20 4e 64 8e 8e 76 1d 2c 86 06 48 0a 00 |... Nd..v.,..H..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 7a e3 f5 9b |...........@z...| +00000120 b1 a1 ce 3c 76 3c 19 bd fd 43 ae a0 cd 49 a6 2e |....| +00000240 bb 65 12 af 72 f7 3d 26 cd 29 7e 12 ee 90 e4 f8 |.e..r.=&.)~.....| +00000250 f9 b5 93 11 1f 96 a9 82 5f d0 c3 d3 8a 5c ba cc |........_....\..| +00000260 6b 6f ae 87 92 4e ba 86 a8 dc 68 6f |ko...N....ho| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 87 3c 23 dc 62 b8 d2 60 16 9a |.......<#.b..`..| +00000010 00 00 00 20 79 7f 77 85 3c a1 cd 5b 68 fb 0d 92 |... y.w.<..[h...| +00000020 3c d9 58 4c a3 88 ff 1c 94 e5 50 cb 1d ab 83 ab |<.XL......P.....| +00000030 7e b2 ff 51 e4 3a d2 c6 65 c8 42 f5 de 8c 90 71 |~..Q.:..e.B....q| +00000040 1c 99 e1 09 |....| +>>> Flow 8 (server to client) +00000000 00 00 00 20 9e 31 c9 bd a5 a4 95 f8 67 2b 5e 5a |... .1......g+^Z| +00000010 63 53 db 9d a9 ae ef 08 43 f9 2b 0a 15 b7 38 71 |cS......C.+...8q| +00000020 7e d0 68 16 d6 03 c4 0c 66 b9 e8 0e 4b 0f e8 53 |~.h.....f...K..S| +00000030 e4 bc c2 60 |...`| +>>> Flow 9 (client to server) +00000000 00 00 00 30 9f 76 ec e4 9c a3 55 3e 8a 83 03 54 |...0.v....U>...T| +00000010 c9 d1 e4 20 91 6b d9 2c 28 28 a5 7f 82 92 3a 89 |... .k.,((....:.| +00000020 d0 cd 98 e7 a4 85 d7 31 a8 3e be a3 b3 c0 65 65 |.......1.>....ee| +00000030 e6 6c 74 e5 38 13 42 51 12 e2 d0 1b 53 39 f6 b3 |.lt.8.BQ....S9..| +00000040 e8 b2 73 3f |..s?| +>>> Flow 10 (server to client) +00000000 00 00 00 20 e4 45 97 15 a1 64 3b ff 65 37 c4 2e |... .E...d;.e7..| +00000010 03 d6 8e e7 91 ca 58 65 55 f5 b9 fa ef 3b 7d cc |......XeU....;}.| +00000020 ad 11 3b 54 c8 e3 2c f8 de 42 55 b2 97 b4 a7 ec |..;T..,..BU.....| +00000030 d8 a0 90 98 00 00 00 40 5c bc 96 d5 fe 09 4a e9 |.......@\.....J.| +00000040 d1 a5 f9 2e 9f 4c 0f 28 0c 66 79 aa 53 bb 78 d5 |.....L.(.fy.S.x.| +00000050 41 a5 8f 7d 53 09 98 fb be 3d 26 35 f3 8a 76 88 |A..}S....=&5..v.| +00000060 3f e1 66 b3 93 9e c9 00 b6 33 0e 12 ac 37 50 8f |?.f......3...7P.| +00000070 f7 b3 25 51 71 9f f7 e1 f9 b3 7b c8 4d 0f ca 92 |..%Qq.....{.M...| +00000080 21 32 5c f4 22 c1 63 90 |!2\.".c.| +>>> Flow 11 (client to server) +00000000 00 00 01 60 98 3f bc 85 ef 21 41 c0 61 b1 ad d1 |...`.?...!A.a...| +00000010 d9 73 3d 13 54 fe d7 c1 d3 d8 65 02 e4 3f 32 eb |.s=.T.....e..?2.| +00000020 78 2f fc fe 5f fc 48 ea 7f d9 53 51 59 a8 ad c0 |x/.._.H...SQY...| +00000030 a4 65 c8 e6 6b 11 44 e7 ab 9a 1a 84 4e 83 1c a9 |.e..k.D.....N...| +00000040 48 95 0a d1 f2 4c 64 c8 43 c4 0c 15 5b 5b af e0 |H....Ld.C...[[..| +00000050 3c 21 0d ff f2 a8 7c 91 a1 d9 cc 7a f1 ff 53 56 |>> Flow 12 (server to client) +00000000 00 00 01 40 ef 68 cf f5 46 8a f8 c9 2f 84 67 34 |...@.h..F.../.g4| +00000010 bf 28 5f 6c b4 f5 87 1c 93 4a 87 30 5c cf 3c f1 |.(_l.....J.0\.<.| +00000020 2b 86 d7 28 26 00 ae e5 8b 68 e7 66 ed 14 e7 95 |+..(&....h.f....| +00000030 c1 33 d1 34 e0 d2 d8 f7 eb 7d 94 0c e4 22 c9 69 |.3.4.....}...".i| +00000040 c8 68 b6 e3 01 fc f0 32 a8 2f 82 56 2d 04 fd 55 |.h.....2./.V-..U| +00000050 fd 7a 89 d9 b6 19 e0 32 34 27 82 c5 61 ff 20 95 |.z.....24'..a. .| +00000060 44 c6 fd fd 8c 62 3c 39 16 9e 62 6d 5d 30 3c b4 |D....b<9..bm]0<.| +00000070 43 47 72 6e b7 2a 61 5f 95 9b 4f 9b b3 0b 76 e3 |CGrn.*a_..O...v.| +00000080 c3 5f d0 61 8d a1 7d c7 6d 5b f3 54 57 8a 43 aa |._.a..}.m[.TW.C.| +00000090 03 19 06 06 1e cd d9 b1 52 1d 59 c8 38 60 da 12 |........R.Y.8`..| +000000a0 52 35 52 41 b0 45 73 b3 c3 f2 d8 e8 cc a5 c4 84 |R5RA.Es.........| +000000b0 88 cd 78 4b 92 ec 02 02 25 fd e9 ea 2f 1d 62 ec |..xK....%.../.b.| +000000c0 17 af 3e 2e bd d2 d5 d5 94 f8 30 ad 75 9d 36 31 |..>.......0.u.61| +000000d0 51 37 e7 d7 1d 06 fe 4b 06 f6 6a 90 0e 53 0b 2e |Q7.....K..j..S..| +000000e0 5b d2 7d d3 b3 28 f7 22 31 29 47 b3 f5 8a 40 d4 |[.}..(."1)G...@.| +000000f0 bd 90 fa cc 0e 43 66 fb 3b cb 12 9a e6 4c 84 84 |.....Cf.;....L..| +00000100 55 0d 84 cc 71 10 55 79 a4 51 1a b5 f4 61 d0 bf |U...q.Uy.Q...a..| +00000110 07 34 b0 a1 d8 96 81 fe 51 b1 63 fa a5 90 82 87 |.4......Q.c.....| +00000120 0d bc 15 63 d8 7f 8e 5f 4d c3 be 7d 54 36 3c f4 |...c..._M..}T6<.| +00000130 4c 88 5e 8d 41 6f f3 74 25 b3 3b f1 3d 4d 8c 14 |L.^.Ao.t%.;.=M..| +00000140 83 5e 5e b7 78 e5 8a 8f 73 28 30 7d 64 0f 5c bd |.^^.x...s(0}d.\.| +00000150 31 e4 9a c4 |1...| +>>> Flow 13 (client to server) +00000000 00 00 02 80 00 cb 00 7f f2 7f 90 a4 6b 52 c0 6c |............kR.l| +00000010 7b 1b 0a a0 0e 61 e9 93 be a0 96 da 8b 25 10 2d |{....a.......%.-| +00000020 1f 12 3b 87 cf 98 45 5c 59 91 c0 5c 37 a5 0c 5b |..;...E\Y..\7..[| +00000030 df 23 6b b6 b4 8a c4 f0 c7 b5 28 2f e3 21 b7 10 |.#k.......(/.!..| +00000040 fc 8d 32 04 1d e9 11 7d 68 1c 68 eb 8c a3 38 45 |..2....}h.h...8E| +00000050 a7 a2 01 37 97 ac b2 fd 90 29 15 0e c6 13 ce 66 |...7.....).....f| +00000060 85 ff a7 4e 48 4c ba d9 fc 15 ec e3 64 98 36 9d |...NHL......d.6.| +00000070 0b dd fe 21 8b 1f ba 81 39 ac 79 f0 b9 01 aa 09 |...!....9.y.....| +00000080 64 a0 8e da 7b d4 e1 13 28 57 fe 1c 05 ec ad ed |d...{...(W......| +00000090 38 de 3e 79 a0 74 d5 01 4e fe 4b e6 e8 53 d3 d6 |8.>y.t..N.K..S..| +000000a0 03 a6 79 46 77 c1 5f ee a7 c3 c5 9e 97 f6 57 1d |..yFw._.......W.| +000000b0 5e 35 3e 8a a7 fc 91 f3 f1 91 dd 6c ea ae d8 04 |^5>........l....| +000000c0 5a 03 69 b4 1e fb 40 be b9 39 56 08 7c 32 ca a2 |Z.i...@..9V.|2..| +000000d0 c5 e0 ec 0a 66 61 25 49 5c 78 ce 08 8c b6 39 3a |....fa%I\x....9:| +000000e0 5e 29 da f3 a1 9b 0b 0b 70 8f 54 fd 1e c7 36 26 |^)......p.T...6&| +000000f0 9d ae 82 79 0e fb 18 27 ce 45 6d 04 ce 0e a7 c2 |...y...'.Em.....| +00000100 81 27 e8 53 8e 03 a7 55 c4 ca c4 48 26 c5 8d 2b |.'.S...U...H&..+| +00000110 3b dc 66 ca 98 35 bb b7 ab 22 e3 93 64 6d e7 10 |;.f..5..."..dm..| +00000120 8a 9b fb e7 af 24 b1 ff 58 e4 01 90 18 d6 2c 38 |.....$..X.....,8| +00000130 4c aa b1 44 15 cd 9d 76 9f 8f a4 1d 11 36 96 41 |L..D...v.....6.A| +00000140 1b 33 a3 ee 1f 4a e5 23 8c bc 82 a5 10 6a 3c 27 |.3...J.#.....j<'| +00000150 68 7f 8f 8a b8 cc 22 1b 0f 1c b5 ea 51 05 5c 43 |h.....".....Q.\C| +00000160 2d 85 c3 4e 2d d9 6c b3 4c 2c 5d 45 c0 77 85 20 |-..N-.l.L,]E.w. | +00000170 df 40 38 0a e7 ab 33 f0 60 66 fa 2a 94 46 3b 73 |.@8...3.`f.*.F;s| +00000180 9a 80 2b 5a 8b ec eb 0a c6 93 e0 85 e2 78 99 9e |..+Z.........x..| +00000190 5d 03 3a ea 9c 43 e4 a2 05 5f 6d 3b bb e2 8a 70 |].:..C..._m;...p| +000001a0 f8 ce bc 36 f2 9f 58 b6 42 30 83 2c 45 3e 5b 6d |...6..X.B0.,E>[m| +000001b0 23 f1 8c 86 4a 42 cf c9 50 88 9c 4c 28 18 64 4b |#...JB..P..L(.dK| +000001c0 14 48 82 b3 35 42 82 c7 3b 4a bf cb 7e c1 4a e2 |.H..5B..;J..~.J.| +000001d0 e8 de a3 55 19 94 3e 38 80 2d a9 60 16 73 7e 85 |...U..>8.-.`.s~.| +000001e0 50 47 4f 0a 26 d8 e9 b8 14 ab 1a 8f 67 9a a1 a5 |PGO.&.......g...| +000001f0 0e fe 67 59 4f f6 2c 57 01 98 c5 65 b3 7c f0 57 |..gYO.,W...e.|.W| +00000200 42 c4 30 41 8b cc f0 c7 05 32 a3 e0 ef 97 bf 23 |B.0A.....2.....#| +00000210 f0 d8 fc 87 fc 13 9f 3d 33 6d 80 a2 e1 75 df 93 |.......=3m...u..| +00000220 34 1b 9a 7f 36 c6 80 f5 75 c5 4c 0b 43 75 5a 97 |4...6...u.L.CuZ.| +00000230 f6 c0 bf 67 86 8e 2e 8a 15 ef 30 cc a8 d6 43 3f |...g......0...C?| +00000240 aa 1a 7a 39 bf 9d 45 8d 60 97 02 2d 7d 2b c3 b7 |..z9..E.`..-}+..| +00000250 fb ea d0 9e 99 69 26 05 f7 bb 79 5d 9a fa 86 fb |.....i&...y]....| +00000260 96 fe 42 58 32 7a 7c d1 05 0b 1b 7a 12 35 ea be |..BX2z|....z.5..| +00000270 dc 56 19 8f 32 4c 92 17 53 d9 33 00 04 e8 6f ba |.V..2L..S.3...o.| +00000280 4f bb 52 83 ff ba e6 f9 87 3c aa 6f c1 58 93 23 |O.R......<.o.X.#| +00000290 b0 5e 26 42 |.^&B| +>>> Flow 14 (server to client) +00000000 00 00 00 10 79 b4 da e8 8c a4 14 53 a6 e7 37 65 |....y......S..7e| +00000010 37 76 0e 7d ef a8 d9 91 1d 99 2a 57 95 fc 2a 97 |7v.}......*W..*.| +00000020 37 12 13 73 |7..s| diff --git a/ssh/testdata/Client-Cipher-aes192-ctr b/ssh/testdata/Client-Cipher-aes192-ctr new file mode 100644 index 0000000000..ceb6a43f15 --- /dev/null +++ b/ssh/testdata/Client-Cipher-aes192-ctr @@ -0,0 +1,295 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 5c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 0a 61 65 73 31 39 32 2d 63 74 72 00 00 00 0a |..aes192-ctr....| +00000150 61 65 73 31 39 32 2d 63 74 72 00 00 00 6e 68 6d |aes192-ctr...nhm| +00000160 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +00000170 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000180 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +00000190 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001a0 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +000001b0 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +000001c0 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e |hmac-sha1-96...n| +000001d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 |hmac-sha2-256-et| +000001e0 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +000001f0 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 |ac-sha2-512-etm@| +00000200 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000210 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 |-sha2-256,hmac-s| +00000220 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 |ha2-512,hmac-sha| +00000230 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |1,hmac-sha1-96..| +00000240 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000250 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 e1 22 f6 a4 d0 5d ab 07 1b 53 |......."...]...S| +00000010 71 9b 45 3a a8 4e 00 00 01 7a 73 6e 74 72 75 70 |q.E:.N...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 13 cf b6 0f c2 c9 |...,..... ......| +00000010 08 d9 7b f6 60 d4 53 7f 4b b1 29 37 59 98 3c dd |..{.`.S.K.)7Y.<.| +00000020 ab b1 51 12 94 92 eb 56 4c 6f e8 a3 63 9c a8 a1 |..Q....VLo..c...| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 81 ce f7 63 d7 91 ec be e9 c0 |..... ...c......| +00000080 0d 73 92 94 15 ef e2 e9 6d 47 38 ea 62 67 78 12 |.s......mG8.bgx.| +00000090 07 2b 79 f3 27 77 00 00 00 64 00 00 00 13 65 63 |.+y.'w...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 9e c5 62 22 31 5f |6...I...!...b"1_| +000000c0 fd 0f bc 20 d6 20 0c 3f f3 68 26 38 6b 97 09 c2 |... . .?.h&8k...| +000000d0 07 4f 1b 4f 7f 3c 56 cf 79 4b 00 00 00 20 22 b5 |.O.O...| +00000190 23 05 c2 95 55 d3 57 12 7f 0e c4 a1 5a 75 46 9a |#...U.W.....ZuF.| +000001a0 7a ba a1 ea 81 f4 e9 68 0c 4e a2 63 bf 67 01 97 |z......h.N.c.g..| +000001b0 4d 95 98 64 4e ba 8a fd e0 c4 79 d7 9f 36 93 a8 |M..dN.....y..6..| +000001c0 55 47 71 96 2b 7e a1 ae 6f 09 b2 d0 39 bd bd 23 |UGq.+~..o...9..#| +000001d0 76 19 6f d9 40 6c 3d dd 1c 6e 12 5b a1 68 50 60 |v.o.@l=..n.[.hP`| +000001e0 8d bb 28 2b bd 6b 06 8d 95 98 3d 6c 4a 4a 87 e2 |..(+.k....=lJJ..| +000001f0 99 47 b4 1d 71 5e 4d 8b 99 f3 95 d9 21 e9 50 6a |.G..q^M.....!.Pj| +00000200 c5 46 09 2d 42 47 9f a4 5a fb 23 12 09 f4 87 95 |.F.-BG..Z.#.....| +00000210 1e 27 4d c6 9e 99 d8 69 3a e9 3c 70 47 f4 70 f2 |.'M....i:..z.:..]..!.| +00000240 b5 99 7d 96 aa 23 01 18 1e ee 55 89 7e 98 2b a4 |..}..#....U.~.+.| +00000250 06 08 9d 47 cf 7a f9 b4 2a f8 34 43 bf 8c 11 f6 |...G.z..*.4C....| +00000260 10 b7 c5 cc e8 a0 46 d0 d8 ec 9f ff 0b 14 79 a4 |......F.......y.| +00000270 fb cf 27 7d b8 0d 44 9d 52 ed 60 44 |..'}..D.R.`D| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 e3 f9 ae 57 e2 35 b8 cc 87 3c |.........W.5...<| +00000010 00 00 00 20 f4 13 e8 fa 65 88 0b 90 e2 19 fc 17 |... ....e.......| +00000020 98 47 93 de 21 47 e1 74 8c b8 81 6f 70 cf 17 07 |.G..!G.t...op...| +00000030 ab a5 08 eb 35 04 48 0b c8 ae 85 62 76 1e 24 7f |....5.H....bv.$.| +00000040 2a 9c ec 6a 19 af 9c d6 8f b0 a8 51 97 c6 69 bb |*..j.......Q..i.| +00000050 67 c3 4a c2 |g.J.| +>>> Flow 8 (server to client) +00000000 00 00 00 20 da 65 ba 85 a0 a2 83 b6 ac ec bc cb |... .e..........| +00000010 5b c7 e2 57 e7 b3 ff 29 a8 13 71 52 4b c8 52 dd |[..W...)..qRK.R.| +00000020 fb 5c b1 c9 bd ff 16 05 ea d3 b5 0e 4d 29 a6 0d |.\..........M)..| +00000030 12 f7 5d 5c 75 ca 2a 2a 35 ca 19 3d 51 98 6b 02 |..]\u.**5..=Q.k.| +00000040 4d 49 8c 55 |MI.U| +>>> Flow 9 (client to server) +00000000 00 00 00 30 9b 75 2d cc 5b a2 24 12 e8 b6 54 a5 |...0.u-.[.$...T.| +00000010 f2 32 2d e6 27 b9 97 5c eb 6d bc 05 4d 92 4d 04 |.2-.'..\.m..M.M.| +00000020 ef e9 cf 8e a7 7f c0 d8 46 43 0e 5c 72 c0 07 af |........FC.\r...| +00000030 e7 00 52 d4 6d 2a 32 14 95 9e 00 36 8e 51 60 12 |..R.m*2....6.Q`.| +00000040 7e 42 66 d6 72 55 08 b3 10 4e ee cb 91 3d 3d 9a |~Bf.rU...N...==.| +00000050 7b a4 03 9f |{...| +>>> Flow 10 (server to client) +00000000 00 00 00 20 ea eb e4 be 7a 89 14 50 31 3b 2d c3 |... ....z..P1;-.| +00000010 07 33 c0 dd 20 bd 0b 29 f3 31 a3 c0 8c 0b a6 fe |.3.. ..).1......| +00000020 19 55 ff 30 63 18 a0 88 98 b6 ec 1f 8e 17 f1 3e |.U.0c..........>| +00000030 b7 e9 db 17 c3 d3 c2 65 5d 8c b1 6b 46 a3 5c cc |.......e]..kF.\.| +00000040 ed e2 76 52 00 00 00 40 84 e9 87 0e b9 7a 45 1c |..vR...@.....zE.| +00000050 6e 0a 5e 34 d8 43 11 50 84 fc e8 8a eb a9 11 4f |n.^4.C.P.......O| +00000060 3a 38 e1 e1 8c 46 32 1b 2e d2 02 5c 41 f5 48 f5 |:8...F2....\A.H.| +00000070 28 cd 8e 09 55 4d 6a 75 62 15 39 48 df fb c1 58 |(...UMjub.9H...X| +00000080 07 57 7b 11 f4 71 76 bd 5f bf 3a 2d f0 7b bf a0 |.W{..qv._.:-.{..| +00000090 cd 2c e0 3f 6e 53 66 aa 4b 2a a5 63 e7 bb 86 37 |.,.?nSf.K*.c...7| +000000a0 56 dd 80 66 58 70 e6 cd |V..fXp..| +>>> Flow 11 (client to server) +00000000 00 00 01 60 fa a3 83 90 6b bc 23 18 34 ed 38 05 |...`....k.#.4.8.| +00000010 93 78 66 20 8b f1 36 92 cb c5 b2 1b 1a d6 d1 57 |.xf ..6........W| +00000020 1f 62 a9 58 5d 30 26 16 09 65 f7 f5 9d da 81 90 |.b.X]0&..e......| +00000030 b0 40 68 0c 30 11 9a 7c ae 41 67 9e 93 3d 53 c4 |.@h.0..|.Ag..=S.| +00000040 3d fc e8 c7 a2 e2 b5 69 b0 41 65 51 71 f8 d6 e9 |=......i.AeQq...| +00000050 cf c8 6f 61 1e 2c 51 d3 3b 52 ff 6f cc 6e 7c 6e |..oa.,Q.;R.o.n|n| +00000060 e8 0d 16 b2 c8 d3 d8 23 0f 75 fb 04 ce 4e 74 f2 |.......#.u...Nt.| +00000070 ea 9d 08 75 6f 73 e0 26 9a f2 88 67 a6 57 5c 6c |...uos.&...g.W\l| +00000080 33 10 f3 43 b0 a0 c3 89 48 6f cf ff db 2a 66 30 |3..C....Ho...*f0| +00000090 92 14 26 8c 60 7e f5 df 40 21 28 56 6c 57 be 57 |..&.`~..@!(VlW.W| +000000a0 a2 bf 0c 35 c4 0d 5f 8c 79 a6 9a ea 10 65 57 2f |...5.._.y....eW/| +000000b0 b1 f8 09 e9 63 a3 11 7d 04 f2 99 4b 8e 09 1c b5 |....c..}...K....| +000000c0 bb ff ee 80 8a 18 77 73 f7 4b 4c 03 8e 1c 67 45 |......ws.KL...gE| +000000d0 98 42 1b e6 a4 11 ef 65 df 91 8d eb 87 7c aa 96 |.B.....e.....|..| +000000e0 42 06 a0 e2 6c b9 81 68 84 5f 6b 7a 6f 54 50 1d |B...l..h._kzoTP.| +000000f0 a3 f7 8f c1 21 c9 8f 0d 9b a4 bd e7 b7 76 45 7f |....!........vE.| +00000100 60 bf 88 f4 24 ad a2 2b 85 bf 3b 6d 4e 72 b4 4e |`...$..+..;mNr.N| +00000110 f4 03 2c 6d 81 4a 78 43 f2 f2 09 78 10 0b 48 8d |..,m.JxC...x..H.| +00000120 1a 63 16 dc fd e9 cb c7 ce 40 f2 fd 27 cd 5a 59 |.c.......@..'.ZY| +00000130 9e 7f e1 b7 3a d5 a9 2a 7e 89 1c 4b 3f 9f f3 93 |....:..*~..K?...| +00000140 49 13 3f ce 87 1d 40 70 69 65 2a 1f 12 13 87 2b |I.?...@pie*....+| +00000150 dc 02 99 19 7a 2f 17 5e 6f 02 94 18 de 14 1d 7e |....z/.^o......~| +00000160 50 33 d4 38 d5 92 9d 08 62 3b 1e fd b8 cb 5a c6 |P3.8....b;....Z.| +00000170 bd 35 d4 de f4 6b dc ca e4 eb 0d a2 50 04 f4 02 |.5...k......P...| +00000180 c1 5e 42 97 |.^B.| +>>> Flow 12 (server to client) +00000000 00 00 01 40 66 c2 3c 75 cc 6e c1 dc 86 d8 36 bf |...@f.'..).| +00000070 e5 88 e1 64 0b c8 6e e0 3b 89 7f b0 e1 22 97 7c |...d..n.;....".|| +00000080 5a 08 fc 67 83 a7 4a 4e fa 6b a2 43 68 1d 16 82 |Z..g..JN.k.Ch...| +00000090 07 24 48 ca b0 fa 44 0c 3d 81 1b ea 63 3a a2 40 |.$H...D.=...c:.@| +000000a0 36 a3 36 a2 ef a4 b8 0e 0a 97 35 0b 43 9e 5e c5 |6.6.......5.C.^.| +000000b0 b5 52 17 d1 0e 63 84 90 e3 82 a9 1d 29 67 91 2c |.R...c......)g.,| +000000c0 23 75 13 a4 7a bb f4 02 18 ac 63 02 f4 ec c3 53 |#u..z.....c....S| +000000d0 a9 52 bd bc 8d a5 cf 69 4b c5 36 9e 02 f8 47 29 |.R.....iK.6...G)| +000000e0 ad be bd 06 41 c7 bd b9 e5 a0 8f 82 ee 57 06 4d |....A........W.M| +000000f0 86 1d 3b ea 63 13 f2 e4 65 8d 50 10 1c 4b f0 0a |..;.c...e.P..K..| +00000100 22 04 3d 45 c5 d9 7d 96 47 00 bb dd ef dd cb f6 |".=E..}.G.......| +00000110 cb 50 83 f6 ef 43 9a ec 52 15 24 05 1e f9 45 fb |.P...C..R.$...E.| +00000120 77 c2 4d 9d 63 88 7b 79 5d 4b 26 83 ac 0a 3b 1e |w.M.c.{y]K&...;.| +00000130 68 96 d4 c8 3e 05 c5 f6 1c 2a 7a 55 cd 2c 57 00 |h...>....*zU.,W.| +00000140 2f e6 ed 38 e2 e2 3f 04 26 f1 88 f5 ba a7 4d 55 |/..8..?.&.....MU| +00000150 66 b8 fe 14 38 e8 9d fa 61 cb 20 91 40 71 1d 32 |f...8...a. .@q.2| +00000160 5e ec 27 1b |^.'.| +>>> Flow 13 (client to server) +00000000 00 00 02 80 9e c7 90 7d 44 f4 3c 3f 6f 44 dc 81 |.......}D...N.7| +00000110 70 e2 07 7f 5c 31 71 22 3d d4 76 72 28 c1 20 f4 |p...\1q"=.vr(. .| +00000120 21 bc 34 ca 25 9d b5 95 9e 96 15 65 b3 23 91 2a |!.4.%......e.#.*| +00000130 ed a9 95 dd df 5d ae 16 e9 9a 35 ec a8 9f ec 46 |.....]....5....F| +00000140 cf 81 5f 6b 22 f7 43 d2 e1 29 7e 10 75 9e cb 19 |.._k".C..)~.u...| +00000150 3e 3a 17 28 7f 50 8d 2a 96 c4 ef 98 ab f8 57 a7 |>:.(.P.*......W.| +00000160 1e 9d 6a 22 19 0b c5 a3 d2 de 16 82 2c c4 11 de |..j"........,...| +00000170 16 e4 89 fc 63 3d af 52 d7 d4 24 67 f2 a7 12 4d |....c=.R..$g...M| +00000180 bb 97 55 dd 6c 10 dc f0 72 ee 7a 5d dd 81 06 62 |..U.l...r.z]...b| +00000190 de 5a c4 f2 c5 28 e7 c4 fb 9e 35 59 c0 5b 2c b3 |.Z...(....5Y.[,.| +000001a0 66 ec 11 df 1e ff 6a bf a8 82 41 2c f6 6d 98 cc |f.....j...A,.m..| +000001b0 d4 30 38 93 15 86 05 4e 93 32 aa fa ec 28 d2 0b |.08....N.2...(..| +000001c0 6b df 90 2b 97 56 60 0d 14 c0 d7 ec bf be 6d fb |k..+.V`.......m.| +000001d0 e9 18 62 27 a9 c4 e2 ff 98 87 d6 67 0a cc ae f1 |..b'.......g....| +000001e0 53 5e 51 df e3 49 f7 0c b9 b7 c8 d3 e2 77 11 15 |S^Q..I.......w..| +000001f0 84 4f 33 5a 7d 7c 8c ff f3 f4 56 ef 79 2d 46 c7 |.O3Z}|....V.y-F.| +00000200 7f 16 0e 88 57 8d 8a 0c a4 92 21 f8 d6 76 a7 9b |....W.....!..v..| +00000210 af bf 55 11 7f f4 ff 55 0e 2a 03 5c 99 01 55 da |..U....U.*.\..U.| +00000220 c6 8d 39 17 57 58 c0 c8 c7 8c 81 e6 ca a7 70 fe |..9.WX........p.| +00000230 57 ea c2 8a dc e7 fa a2 ee 7c 5c 07 53 df fb 99 |W........|\.S...| +00000240 aa 67 34 5f 6d 38 82 45 9d c8 ab c9 17 f2 80 70 |.g4_m8.E.......p| +00000250 41 cd bb 7f f0 ff 20 8b aa ac ba 1b 8c f4 90 b3 |A..... .........| +00000260 e4 98 7c 2a eb a2 16 16 c2 27 c1 54 9f 80 c2 c8 |..|*.....'.T....| +00000270 d0 91 e3 89 e6 90 8d a0 40 c9 5f eb a5 a5 89 b4 |........@._.....| +00000280 d9 c8 2e 5e 40 ab 35 a8 3f 3a bc bc af aa ba e6 |...^@.5.?:......| +00000290 94 97 2e 83 6e 1a b0 e0 b7 d4 3c 6c c4 3a bf ae |....n.....>> Flow 14 (server to client) +00000000 00 00 00 10 9a cb e8 50 5a fa b7 db f6 2a 92 99 |.......PZ....*..| +00000010 3e c5 a8 26 39 35 50 b0 4c b6 f1 75 7c ce d4 90 |>..&95P.L..u|...| +00000020 0c 9a 84 73 e3 be ac c2 79 7d ed 65 bd 31 f8 0a |...s....y}.e.1..| +00000030 25 d1 03 7e |%..~| diff --git a/ssh/testdata/Client-Cipher-aes256-ctr b/ssh/testdata/Client-Cipher-aes256-ctr new file mode 100644 index 0000000000..8565604839 --- /dev/null +++ b/ssh/testdata/Client-Cipher-aes256-ctr @@ -0,0 +1,295 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 5c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 0a 61 65 73 32 35 36 2d 63 74 72 00 00 00 0a |..aes256-ctr....| +00000150 61 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d |aes256-ctr...nhm| +00000160 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +00000170 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000180 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +00000190 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001a0 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +000001b0 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +000001c0 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e |hmac-sha1-96...n| +000001d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 |hmac-sha2-256-et| +000001e0 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +000001f0 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 |ac-sha2-512-etm@| +00000200 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000210 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 |-sha2-256,hmac-s| +00000220 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 |ha2-512,hmac-sha| +00000230 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |1,hmac-sha1-96..| +00000240 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000250 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 b9 f9 b6 c4 ed 7e 18 3f 94 37 |...........~.?.7| +00000010 5b 4a d6 e0 42 bc 00 00 01 7a 73 6e 74 72 75 70 |[J..B....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 13 cf b6 0f c2 c9 |...,..... ......| +00000010 08 d9 7b f6 60 d4 53 7f 4b b1 29 37 59 98 3c dd |..{.`.S.K.)7Y.<.| +00000020 ab b1 51 12 94 92 eb 56 4c 6f e8 a3 63 9c a8 a1 |..Q....VLo..c...| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 dc b4 2e a2 97 2c 11 80 39 31 |..... .....,..91| +00000080 ff f8 28 cb 42 d6 59 49 6b 25 4c ff a8 b2 88 3f |..(.B.YIk%L....?| +00000090 59 5c 08 1d 50 5f 00 00 00 64 00 00 00 13 65 63 |Y\..P_...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 fd 1e a5 2f 00 a1 |6...I...!..../..| +000000c0 3a da d5 57 e0 57 81 e4 72 06 53 63 20 41 e8 51 |:..W.W..r.Sc A.Q| +000000d0 b1 f8 70 0a c7 dd 45 c9 53 d1 00 00 00 20 2f 0e |..p...E.S.... /.| +000000e0 42 dd ff 31 fd 52 a0 5e d5 fd f1 3f 02 a6 9d 4b |B..1.R.^...?...K| +000000f0 72 60 05 64 a8 c9 5d dc 38 03 2b 45 11 ec 00 00 |r`.d..].8.+E....| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 29 e3 86 8d |...........@)...| +00000120 8a 4f dc fc 5e d4 a5 fd 8f 31 49 e5 fb e5 94 a3 |.O..^....1I.....| +00000130 3e 01 06 15 a7 61 49 1a ff b4 7d 3e ef c6 ef cc |>....aI...}>....| +00000140 a4 9d 2d e8 79 1f cd c5 61 b3 8c df 52 00 94 ba |..-.y...a...R...| +00000150 90 91 38 65 5e 4e fb f3 6c cb dc ca be 2a ad 68 |..8e^N..l....*.h| +00000160 3d 23 06 8a 7f c4 71 b8 55 6c af 83 57 91 40 fd |=#....q.Ul..W.@.| +00000170 bd e6 4e e3 fd 48 0d 11 50 b2 91 b9 ac 7d 39 7f |..N..H..P....}9.| +00000180 96 fe 88 c3 e8 e3 49 76 df 8e 33 13 63 84 35 75 |......Iv..3.c.5u| +00000190 13 5a ea 45 0f e0 28 82 c5 01 73 78 31 7b de 08 |.Z.E..(...sx1{..| +000001a0 b2 c9 e4 ab f9 40 df 8a 04 a5 58 b9 cb b6 5c 12 |.....@....X...\.| +000001b0 53 07 e3 53 83 24 43 76 5b 66 e1 fe b9 df 48 f0 |S..S.$Cv[f....H.| +000001c0 36 82 95 d7 21 5b 07 84 d5 f6 06 f6 19 79 a8 9d |6...![.......y..| +000001d0 3d d7 6c 06 6e 0b c8 05 aa 50 43 7b 97 ae 78 c8 |=.l.n....PC{..x.| +000001e0 24 d5 af 7f 6f 6b 75 9f 9b e3 b2 00 74 b3 28 8f |$...oku.....t.(.| +000001f0 3d 0e e3 27 c6 34 8d 06 1f 5d d7 9e 7f 72 ec 84 |=..'.4...]...r..| +00000200 f9 bb 1f 7e a7 84 be 9d 47 a8 26 39 1b df be bb |...~....G.&9....| +00000210 66 5e 93 88 81 97 aa dc 4c 25 18 0f 84 e7 e2 c2 |f^......L%......| +00000220 96 c4 55 1b 76 75 84 b2 06 9c 00 4f 11 2b 91 d0 |..U.vu.....O.+..| +00000230 cb 05 ba f5 9d d9 42 cd bc 83 e7 dc e1 2a be 90 |......B......*..| +00000240 9a 68 b1 45 e4 e2 ac 7e 1e 5a de 1a 90 38 ea c1 |.h.E...~.Z...8..| +00000250 f2 2a ff 52 d6 13 06 f9 58 9e d6 14 49 9b 11 b5 |.*.R....X...I...| +00000260 8a 39 a3 d9 2e e4 3d 31 d4 29 53 50 cd 91 19 db |.9....=1.)SP....| +00000270 b8 fd 5a 75 c7 55 11 72 0e c7 22 13 |..Zu.U.r..".| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 e3 f9 ae 57 e2 35 b8 cc 87 3c |.........W.5...<| +00000010 00 00 00 20 b7 cd e5 1e 32 4c af 0d 14 b0 15 9c |... ....2L......| +00000020 28 f1 f9 23 ab 40 ef 2a 61 e3 b5 14 e8 28 ff bf |(..#.@.*a....(..| +00000030 94 a0 19 88 b8 4b a1 e4 bf de f1 bf e8 45 99 18 |.....K.......E..| +00000040 ab 42 06 0f 9a 8e 49 9e e0 92 a5 89 b8 fa 0c c5 |.B....I.........| +00000050 b4 6a 5e 44 |.j^D| +>>> Flow 8 (server to client) +00000000 00 00 00 20 a7 59 4a e8 1f ed d6 91 0c fd 51 fe |... .YJ.......Q.| +00000010 f8 b1 81 7c 21 fe de 37 0d 29 6c c4 06 4c d5 48 |...|!..7.)l..L.H| +00000020 59 50 54 35 aa 62 1f 45 1c ba 71 37 24 d4 4c 09 |YPT5.b.E..q7$.L.| +00000030 15 14 35 6e 93 99 6c f7 2b 7b 0e 60 1c 3e 9d 46 |..5n..l.+{.`.>.F| +00000040 98 b6 bd b5 |....| +>>> Flow 9 (client to server) +00000000 00 00 00 30 db 4f da 1a 98 a1 d5 a0 35 44 5f ca |...0.O......5D_.| +00000010 61 62 cc b5 6b 67 d5 ac 57 67 10 1c 11 b9 8d 46 |ab..kg..Wg.....F| +00000020 1c ff 4c 9c 76 cd 32 93 46 47 bd 6c 50 b3 16 b8 |..L.v.2.FG.lP...| +00000030 91 82 0c e6 d0 a9 07 0a b3 a2 56 87 be 97 10 3c |..........V....<| +00000040 04 99 37 e4 a2 af 47 f0 21 a3 54 fb 0a 50 f8 3b |..7...G.!.T..P.;| +00000050 70 13 c4 79 |p..y| +>>> Flow 10 (server to client) +00000000 00 00 00 20 ef a1 05 ef bf d2 8b bc 40 f3 71 ca |... ........@.q.| +00000010 64 f7 bb 7b 49 56 e8 9e 4f d6 7f 25 4e 81 c3 b0 |d..{IV..O..%N...| +00000020 f9 af 58 40 5e 7e 77 d4 05 c7 c5 9f bd d5 18 fb |..X@^~w.........| +00000030 2c 29 c5 0d 9f 94 21 7c 9c f3 2a 3a 09 31 ad ac |,)....!|..*:.1..| +00000040 08 40 75 d9 00 00 00 40 0c bc d9 17 fc 1b a9 28 |.@u....@.......(| +00000050 1e 5b 51 30 f1 4c 33 31 74 93 21 21 3a b1 3a f8 |.[Q0.L31t.!!:.:.| +00000060 75 41 8d c4 4d 06 96 85 5c 73 d4 b0 26 0b e4 37 |uA..M...\s..&..7| +00000070 80 26 8f 7c 1a 59 61 bd 99 04 0d a9 5e e5 50 fc |.&.|.Ya.....^.P.| +00000080 bc f7 fd 8d 1e 69 9a 83 e8 62 bb 23 bf 1a 40 d2 |.....i...b.#..@.| +00000090 d5 e7 ed e1 c3 da 97 a3 69 ff de 3f 89 d4 a6 8b |........i..?....| +000000a0 63 09 2c 7c 7c ea bc 34 |c.,||..4| +>>> Flow 11 (client to server) +00000000 00 00 01 60 9a dc 8b 51 bb ac d1 45 74 61 ed 7a |...`...Q...Eta.z| +00000010 f2 cb 8a 43 39 a0 c1 74 93 3b d5 69 06 8e b7 ee |...C9..t.;.i....| +00000020 d2 0f 44 a5 b2 66 5d 1d 9e b3 37 9c d3 fc 55 61 |..D..f]...7...Ua| +00000030 1a 04 00 d3 37 e0 c1 cc 53 c4 eb 22 12 4c 02 f7 |....7...S..".L..| +00000040 98 d0 16 c0 3e af bb d9 2d ec 97 e0 39 d6 6b a5 |....>...-...9.k.| +00000050 9f af f9 20 97 01 30 af d5 cd 58 71 36 81 24 6a |... ..0...Xq6.$j| +00000060 24 95 88 20 fb dc 62 97 82 97 e1 a4 09 f6 8b 1b |$.. ..b.........| +00000070 b5 ab 28 b4 6f d1 0b 67 40 76 cc 07 44 98 d9 d5 |..(.o..g@v..D...| +00000080 ca d0 ef bf 8d 5f 47 27 3d 68 63 f1 05 12 da 04 |....._G'=hc.....| +00000090 66 9d 53 57 09 b0 6a 92 3c 0a bd da 2e 85 96 50 |f.SW..j.<......P| +000000a0 13 43 19 c3 8e fc 33 44 3b b4 6a dd 2e 9c f5 fb |.C....3D;.j.....| +000000b0 35 ac a1 96 85 81 bc 65 59 7b e0 8d 2a c5 bf 40 |5......eY{..*..@| +000000c0 0b c9 59 62 35 e9 0d bc 41 86 9e 5e ab 28 45 42 |..Yb5...A..^.(EB| +000000d0 7c c6 9f 40 0a 6c 30 06 f7 9c f3 2c 64 86 be cc ||..@.l0....,d...| +000000e0 7f 51 04 e9 f2 86 7d 4b 1b e8 b9 10 ad 7c e3 35 |.Q....}K.....|.5| +000000f0 34 a4 9c 80 fe a9 03 ce 85 de 6e 67 f3 9f ad 8a |4.........ng....| +00000100 d0 3b 61 db 6c 96 af 22 cb b2 e5 20 9a 8e 58 d8 |.;a.l.."... ..X.| +00000110 15 5d 11 47 20 f1 8c 7a d2 0f b0 be d9 14 49 89 |.].G ..z......I.| +00000120 8a 37 c4 12 ff 6f 92 78 01 ff 59 dc 50 a1 8c 10 |.7...o.x..Y.P...| +00000130 c7 f6 91 da 5e 0b dd b7 18 93 9f fe 0d 07 af ec |....^...........| +00000140 79 a1 2a 03 03 a8 e4 83 60 44 e5 21 d4 24 54 8f |y.*.....`D.!.$T.| +00000150 4f 18 71 68 9d 53 ad bc 72 18 82 bf 6c 8b ca d9 |O.qh.S..r...l...| +00000160 f2 3a b7 bd 3c 0d 46 0b bb 6a 38 83 ee fa 19 62 |.:..<.F..j8....b| +00000170 07 bf 09 38 fa d5 94 06 0f 8e 93 fa 82 c3 fc 6e |...8...........n| +00000180 39 aa df e4 |9...| +>>> Flow 12 (server to client) +00000000 00 00 01 40 be 1d 0f a6 fb 0e ab e1 7e e6 60 1d |...@........~.`.| +00000010 ab ed 8f dd f6 36 f3 d9 28 01 8d 51 5a 2d bd 30 |.....6..(..QZ-.0| +00000020 94 8b c3 8b d7 d0 8d 6c 85 6a 26 7f 1f 3e 44 48 |.......l.j&..>DH| +00000030 f8 8b d2 47 da 8d 18 26 3a 2f 7c 4f 2f 49 34 89 |...G...&:/|O/I4.| +00000040 c9 ec 9b 72 1c 3d 22 c1 b5 0f 7c 6a 1e e7 f1 a6 |...r.="...|j....| +00000050 59 9f aa af 06 1d 54 51 55 4f ab a3 a9 98 f0 e1 |Y.....TQUO......| +00000060 0a 72 fe 06 71 e6 b5 ce 81 71 5c d9 32 00 0e dc |.r..q....q\.2...| +00000070 a4 a8 e8 94 6e de 3f 7d 01 81 59 d3 31 92 e1 a0 |....n.?}..Y.1...| +00000080 a8 e2 43 24 cb a9 50 b7 19 ee 88 eb 1a b6 c5 68 |..C$..P........h| +00000090 38 b3 58 6f 5b fb 1b 94 8d 53 8d 03 8b 0c 6d 6f |8.Xo[....S....mo| +000000a0 7d 22 44 e5 ed ec 5a d4 b9 f5 b6 71 7f e6 69 4f |}"D...Z....q..iO| +000000b0 1a 5d 41 07 e0 68 d4 39 4a 71 1d 45 23 42 6b 9d |.]A..h.9Jq.E#Bk.| +000000c0 51 37 4c 08 cd 07 6e 6a 7f fc af 54 57 cc f9 f9 |Q7L...nj...TW...| +000000d0 a1 f8 b9 43 fe ef 10 7e 08 2a 84 a7 cc c6 fa 10 |...C...~.*......| +000000e0 36 4a 3c cf 5c 88 42 0b 9f c5 99 18 0f 4f 7f 4b |6J<.\.B......O.K| +000000f0 4b cf dc d7 45 6b f2 73 20 20 7a 05 4a 2e 91 9a |K...Ek.s z.J...| +00000100 9d 9b 11 b9 d1 8b 42 e8 b4 5e 37 47 af 6a bf d7 |......B..^7G.j..| +00000110 c0 fc b1 0b 9f bb 37 e1 dc bc 87 61 0b d4 a4 ff |......7....a....| +00000120 60 09 0c ed 58 de f3 d6 75 e5 50 37 cc ce da fc |`...X...u.P7....| +00000130 db d5 c3 fe 10 6b 82 f2 20 60 1e 2c a1 85 cb df |.....k.. `.,....| +00000140 13 5b b3 34 ae 0c 6c 47 63 d1 a5 4a f0 a4 6d cd |.[.4..lGc..J..m.| +00000150 27 49 b3 f4 64 d8 ad f1 d5 98 b5 ad eb be 00 1f |'I..d...........| +00000160 87 f4 db aa |....| +>>> Flow 13 (client to server) +00000000 00 00 02 80 a3 75 dd 61 db 5d ec c8 01 75 ed 65 |.....u.a.]...u.e| +00000010 40 8e d8 3b 85 28 d5 8e 14 c3 dc 3f e6 f5 78 35 |@..;.(.....?..x5| +00000020 50 41 cf 9d 0e d4 e2 de bf d5 31 12 3f ea da d6 |PA........1.?...| +00000030 bf 7d 0e 77 80 eb 0f 8c 6e 93 61 20 4b be 31 0b |.}.w....n.a K.1.| +00000040 45 83 08 93 cd c1 da 70 b5 6c f0 9a 34 f7 a4 86 |E......p.l..4...| +00000050 19 63 a8 39 82 9b 58 a8 15 88 6e 6d 11 0d e1 f9 |.c.9..X...nm....| +00000060 34 41 39 26 3c 1a d6 9c 94 fe 40 55 44 7d b7 87 |4A9&<.....@UD}..| +00000070 0c 72 5c 1e e5 fb 5c f5 9a f7 c7 fa 64 47 79 8e |.r\...\.....dGy.| +00000080 e2 b3 9c 67 19 27 85 c5 2c 1b 65 47 32 20 e8 14 |...g.'..,.eG2 ..| +00000090 82 d4 f4 3d bc 3c 12 f1 6c 96 05 80 53 d0 9f 77 |...=.<..l...S..w| +000000a0 a6 58 8e 01 a3 dc 65 4b 11 ff 1c 21 66 98 c4 9a |.X....eK...!f...| +000000b0 c3 44 d5 fe 5d bd fd 77 ad ab a0 96 73 81 87 34 |.D..]..w....s..4| +000000c0 47 6d 98 2f 3f 8d 10 ea d3 9f 25 62 b4 e7 7b e6 |Gm./?.....%b..{.| +000000d0 b9 1c 0d 3b 32 d5 85 a0 40 5f c7 c1 92 f9 9a 7f |...;2...@_......| +000000e0 11 93 f7 9e d8 60 5e 93 17 d8 07 aa 3c eb fa d3 |.....`^.....<...| +000000f0 85 8f e5 34 8b a1 23 3b 03 b4 8d 2d 71 1d 20 6d |...4..#;...-q. m| +00000100 d1 04 13 fb 9c dd 0d b5 4b 8c 85 47 55 5f 72 c7 |........K..GU_r.| +00000110 66 43 35 5a b5 d8 26 94 fa 83 0d 45 47 a3 47 9b |fC5Z..&....EG.G.| +00000120 72 5c 96 78 94 37 49 2a ca e7 59 9f 34 aa 2d df |r\.x.7I*..Y.4.-.| +00000130 f7 95 82 b7 b9 52 dc ea a4 72 a4 60 23 ab 4a 3a |.....R...r.`#.J:| +00000140 1a fc 56 ae e4 39 6e da f3 00 f6 18 7a 45 48 46 |..V..9n.....zEHF| +00000150 a2 ad 06 86 6b d2 e1 02 4c f8 e0 84 cc 09 07 cd |....k...L.......| +00000160 b5 6c 12 58 14 7b a1 b6 a1 72 eb 89 75 22 3f 2d |.l.X.{...r..u"?-| +00000170 11 a4 61 4b cb c0 2f 4a 67 52 f5 3a 58 5b 34 63 |..aK../JgR.:X[4c| +00000180 5d d0 01 d1 af 8d d3 26 2c 97 41 81 ee 22 5b 5a |]......&,.A.."[Z| +00000190 3e e0 f2 08 64 52 4d b7 4a cf 49 69 ac 1d 6c 55 |>...dRM.J.Ii..lU| +000001a0 2f 58 c3 e6 7c 72 91 80 94 51 83 40 56 ab cc 70 |/X..|r...Q.@V..p| +000001b0 bd 48 1c e2 1d ef 4f 00 b9 bd ce e4 f0 be 17 9e |.H....O.........| +000001c0 3f e0 ae 36 f4 f5 2a 59 5f e6 62 77 e3 3e 59 2c |?..6..*Y_.bw.>Y,| +000001d0 5a 8d b1 22 7d 37 ef a3 ae 9c 7a a4 ab 90 e9 81 |Z.."}7....z.....| +000001e0 2e 3f 29 2b 67 d6 7b 36 1c 12 62 16 03 62 3d 51 |.?)+g.{6..b..b=Q| +000001f0 bc 0a 71 25 d9 0a 98 51 4c a0 53 aa cf 61 20 56 |..q%...QL.S..a V| +00000200 a0 03 5a 70 cd 2b 2a 74 90 16 bb de 54 c0 5f 82 |..Zp.+*t....T._.| +00000210 f4 43 e7 d1 69 b9 69 a4 a8 14 92 6a 97 3b bf e5 |.C..i.i....j.;..| +00000220 5a f6 45 d2 2e cc 6e b2 a9 68 d5 7f 86 0d d8 e9 |Z.E...n..h......| +00000230 9d e3 bd 22 1a 5e cd 1a fd 64 b1 61 9a fe 41 16 |...".^...d.a..A.| +00000240 e0 7a 6b 30 a0 35 99 9d 1e 77 e0 03 44 f7 b3 6c |.zk0.5...w..D..l| +00000250 ee 22 a7 b8 4c 2c 26 4c 30 c7 a0 38 66 66 45 0d |."..L,&L0..8ffE.| +00000260 7f 63 aa 36 e5 07 96 0c 16 14 fb 95 62 f9 41 a7 |.c.6........b.A.| +00000270 aa 2b 6c 19 7d f6 da f2 21 e8 62 a1 cb ce f6 8c |.+l.}...!.b.....| +00000280 d6 75 43 c9 ea f8 7b 7b ed 37 10 b4 4b 3a b9 81 |.uC...{{.7..K:..| +00000290 0f 67 ba 13 e9 d5 7a 41 f4 f8 98 0b ea f6 6b 20 |.g....zA......k | +000002a0 2f f0 a1 0d |/...| +>>> Flow 14 (server to client) +00000000 00 00 00 10 3f 5d 35 f7 01 4c 70 e9 30 90 09 84 |....?]5..Lp.0...| +00000010 b0 ec 12 34 93 9d 81 4d f4 34 83 37 62 ef 31 a5 |...4...M.4.7b.1.| +00000020 d3 03 ce 5d dd 58 1d 5d 0f a5 7c 65 db c9 c2 24 |...].X.]..|e...$| +00000030 c8 35 8e 77 |.5.w| diff --git a/ssh/testdata/Client-Cipher-aes256-gcm@openssh.com b/ssh/testdata/Client-Cipher-aes256-gcm@openssh.com new file mode 100644 index 0000000000..87c8e809e7 --- /dev/null +++ b/ssh/testdata/Client-Cipher-aes256-gcm@openssh.com @@ -0,0 +1,287 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 7c 0d 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...|....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 16 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 |..aes256-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 00 00 00 16 61 65 73 32 |nssh.com....aes2| +00000160 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-gcm@openssh.c| +00000170 6f 6d 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d |om...nhmac-sha2-| +00000180 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |256-etm@openssh.| +00000190 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 |com,hmac-sha2-51| +000001a0 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |2-etm@openssh.co| +000001b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +000001c0 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +000001d0 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 |ac-sha1,hmac-sha| +000001e0 31 2d 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 |1-96...nhmac-sha| +000001f0 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-256-etm@openss| +00000200 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d |h.com,hmac-sha2-| +00000210 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |512-etm@openssh.| +00000220 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +00000230 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +00000240 68 6d 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 |hmac-sha1,hmac-s| +00000250 68 61 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 |ha1-96....none..| +00000260 00 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 |..none..........| +00000270 00 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa |....;........n..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 03 91 97 87 a7 dc fc 58 9c f9 |.............X..| +00000010 12 c3 72 62 44 c3 00 00 01 7a 73 6e 74 72 75 70 |..rbD....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 7e 4a 3b cc bf 9a |...,..... ~J;...| +00000010 2e 84 5f cb bb 32 fa b6 67 2f 28 60 b3 d3 48 e8 |.._..2..g/(`..H.| +00000020 f9 c9 38 6f ae b4 a3 c4 5b 73 ae 57 e2 35 b8 cc |..8o....[s.W.5..| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 6f 1c 0a 10 b7 60 53 0b e1 9e |..... o....`S...| +00000080 ef 53 02 0f 90 c5 91 92 17 e2 5f be 6a 69 7b f3 |.S........_.ji{.| +00000090 b9 d0 fa 44 a4 0f 00 00 00 64 00 00 00 13 65 63 |...D.....d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 2d 84 a6 de 6c 7f 15 |6...I... -...l..| +000000c0 62 4e 01 3f b2 e3 d5 d0 49 6c d4 49 ba 88 91 50 |bN.?....Il.I...P| +000000d0 65 12 77 52 fd 05 06 5a e4 00 00 00 21 00 f5 50 |e.wR...Z....!..P| +000000e0 28 ab 99 21 48 6a a1 dc 58 1e b4 d4 3c 3c c2 1a |(..!Hj..X...<<..| +000000f0 55 41 da 44 38 57 05 ce eb 03 1a 5b 6d 3b 00 00 |UA.D8W.....[m;..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 b6 4c c2 9f |...........@.L..| +00000120 41 92 5c 10 ee c9 55 48 4a f5 42 da ff 2b c6 34 |A.\...UHJ.B..+.4| +00000130 b7 8d 3f 48 a3 f1 61 57 dc 5b f9 f2 3a bc 19 14 |..?H..aW.[..:...| +00000140 31 72 fc 1e fb 12 c6 1f cf c6 ee 5c 3b b4 e8 d0 |1r.........\;...| +00000150 b5 1a f4 ef 1f a8 40 68 2d 99 10 17 97 83 b7 35 |......@h-......5| +00000160 6e e9 81 0e 54 ad d2 05 2a 50 c1 36 0c b9 af c9 |n...T...*P.6....| +00000170 cc 27 30 ac ea 70 65 7a e8 2b 0d 82 9a 60 b2 09 |.'0..pez.+...`..| +00000180 3b fb 55 8b e3 2a c3 27 bb ba d0 40 5b d3 4b 94 |;.U..*.'...@[.K.| +00000190 59 59 0b 23 ec 55 cd fb 70 9a eb f1 54 cb 83 8f |YY.#.U..p...T...| +000001a0 d0 52 fb 3c 59 0e 49 7e 8b 5d 9a 1a f9 0b 85 2a |.R.>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 87 3c 23 dc 62 b8 d2 60 16 9a |.......<#.b..`..| +00000010 00 00 00 20 7c 71 d9 dc 5d cc a9 fd ae 24 a4 97 |... |q..]....$..| +00000020 41 b8 a5 d4 9a 32 d5 b7 f9 b7 e3 a1 38 2d 68 0d |A....2......8-h.| +00000030 bf 8a 17 14 6e 0d d7 d8 9a 4e 46 06 ca a5 b9 8e |....n....NF.....| +00000040 33 3d 14 3f |3=.?| +>>> Flow 8 (server to client) +00000000 00 00 00 20 d5 70 c2 d4 80 cb d1 bb e2 1d ff 1d |... .p..........| +00000010 db b1 8a a0 71 4d 9c a2 63 b9 56 0e 77 27 f5 58 |....qM..c.V.w'.X| +00000020 2a bd 6d 3d b3 4c 03 61 9f 4f b5 4d 00 40 83 58 |*.m=.L.a.O.M.@.X| +00000030 5c bb 23 03 |\.#.| +>>> Flow 9 (client to server) +00000000 00 00 00 30 37 f6 af dc 45 36 44 d6 4d ac 66 4c |...07...E6D.M.fL| +00000010 75 05 bb 94 58 cf 92 a1 a6 65 ae 74 f2 cd 57 fc |u...X....e.t..W.| +00000020 89 e0 6d 5a 1d 9f 0b 6c 91 af 66 0b dc f8 ff b6 |..mZ...l..f.....| +00000030 af 02 ff 3e ed 57 ec d4 59 00 76 42 d0 59 a3 c5 |...>.W..Y.vB.Y..| +00000040 52 b1 2b 16 |R.+.| +>>> Flow 10 (server to client) +00000000 00 00 00 20 79 bc 0a 5d f3 59 0d d6 11 6e c4 8c |... y..].Y...n..| +00000010 f1 ca 15 d2 fc 1f da 1b 63 5b b6 b5 ce 29 14 e6 |........c[...)..| +00000020 e4 98 cb b1 7f 47 4e c3 21 65 19 ea de 65 1f 53 |.....GN.!e...e.S| +00000030 98 9a 5e 7f 00 00 00 40 ae 3d 2e cc 14 74 18 4c |..^....@.=...t.L| +00000040 9b 82 c3 af 1c 24 75 89 1f 8f a4 db dd 41 2e 16 |.....$u......A..| +00000050 b8 56 b7 1e 3c 62 3b 48 96 97 6c f3 51 36 4a ec |.V..>> Flow 11 (client to server) +00000000 00 00 01 60 87 65 80 4e 94 61 76 b8 1d 06 ff 7c |...`.e.N.av....|| +00000010 f2 89 9c ee 77 6a 38 f6 aa 17 d4 33 25 81 c2 91 |....wj8....3%...| +00000020 75 5b ae b8 15 c6 28 bc 98 9e 70 91 68 68 08 ae |u[....(...p.hh..| +00000030 6b 36 ea da 18 60 91 45 85 62 bf f6 23 a1 f0 4b |k6...`.E.b..#..K| +00000040 0b d2 02 e6 57 d1 5e 79 ef 6f 6a 72 b5 04 5b f5 |....W.^y.ojr..[.| +00000050 e1 d7 73 b2 f9 d9 21 65 fc 69 2d 02 1f c5 4c 78 |..s...!e.i-...Lx| +00000060 92 7b b6 da ff 88 19 f2 48 57 3e e5 e7 6b 79 74 |.{......HW>..kyt| +00000070 67 8d 65 f7 09 63 6f 04 0a e1 5e a1 c9 a0 83 2a |g.e..co...^....*| +00000080 69 fb 41 12 48 82 e9 71 5e 05 b2 23 44 87 c1 dc |i.A.H..q^..#D...| +00000090 7a d0 37 a6 bc 8d 45 39 37 c7 bf 91 14 8e e3 9b |z.7...E97.......| +000000a0 9c 47 4e e6 75 71 67 d9 cd 13 54 ca 08 5d 0f b6 |.GN.uqg...T..]..| +000000b0 79 2e fa 6f 13 a9 e5 d0 2e f7 05 a6 34 91 94 23 |y..o........4..#| +000000c0 fe b4 90 44 9b cf 53 ed b0 21 b5 5d c6 51 3a 93 |...D..S..!.].Q:.| +000000d0 9d 26 a5 47 f2 6c 01 98 c1 9b 15 ff cd 5a 7a a9 |.&.G.l.......Zz.| +000000e0 88 7c 32 3c e0 36 61 91 08 1e f3 d2 ca 8d d7 9d |.|2<.6a.........| +000000f0 28 9f bc c5 71 e0 ee 69 11 9d b9 a0 9b a4 e6 cc |(...q..i........| +00000100 57 29 48 ff bf ae 00 cc ef 25 bc 87 d4 d1 ec a8 |W)H......%......| +00000110 6e e4 5e 1b 4f a6 71 da 5f 0e b8 57 a5 72 bf 30 |n.^.O.q._..W.r.0| +00000120 0f 62 e2 da 76 01 92 67 a5 c5 5d d5 ec c3 e7 8f |.b..v..g..].....| +00000130 04 33 51 17 e3 46 4c 86 1c 03 26 0d e2 25 9b 80 |.3Q..FL...&..%..| +00000140 fe 99 63 a1 57 26 20 ed 20 0c 38 3a 3a e3 65 3a |..c.W& . .8::.e:| +00000150 98 e4 1b 76 05 f8 22 2e 8d f2 6e ec b3 ac ed 86 |...v.."...n.....| +00000160 b7 ab f9 b8 d5 5e c6 a5 08 fa 5e 14 48 24 02 52 |.....^....^.H$.R| +00000170 ca ab d6 9f |....| +>>> Flow 12 (server to client) +00000000 00 00 01 40 ab 28 ac fe d0 b6 a5 bb 27 a8 07 87 |...@.(......'...| +00000010 10 3f 81 13 69 32 61 02 d7 3a 1c d2 87 96 5c 84 |.?..i2a..:....\.| +00000020 87 5a b9 aa f4 f5 53 97 64 de 31 37 6f 96 ab 41 |.Z....S.d.17o..A| +00000030 71 f4 13 0c 2a 0c 97 c4 33 52 3c 45 84 de b2 d8 |q...*...3R>> Flow 13 (client to server) +00000000 00 00 02 80 8b 2f be b2 46 70 97 b1 d1 3c 8b de |...../..Fp...<..| +00000010 53 82 86 33 ed 61 0d 2f bf 22 cd 98 93 2f 68 94 |S..3.a./.".../h.| +00000020 ed c0 3c 25 fc 82 fb 33 fa 03 16 5d 32 1a 87 4d |..<%...3...]2..M| +00000030 52 d5 c0 7f 1d 0d 3d 88 29 32 54 8a 31 b5 a7 18 |R.....=.)2T.1...| +00000040 17 0a 47 a2 98 70 c3 43 bb f8 31 1e 0d 19 c2 f0 |..G..p.C..1.....| +00000050 d5 f9 ff 70 5d d8 db cf 63 1f 49 fb d6 fe 0a 41 |...p]...c.I....A| +00000060 fc 86 f6 e9 18 11 04 21 db 11 82 1c 0e 23 90 11 |.......!.....#..| +00000070 b3 f5 90 64 f2 65 f6 35 ac a5 e3 99 ee 12 1d a2 |...d.e.5........| +00000080 9a db a7 1b e8 99 65 eb 92 a0 3d e5 bd da 5e 56 |......e...=...^V| +00000090 97 29 5c bb 7f 22 1e 0c 96 9c cc 1f 0f 07 f8 18 |.)\.."..........| +000000a0 f0 db 47 a4 6c 85 c5 3c ab df 84 4e 04 06 24 1c |..G.l..<...N..$.| +000000b0 84 cf 7c 13 90 81 9b 7e c9 56 43 66 ff 63 05 33 |..|....~.VCf.c.3| +000000c0 5c 70 2e 74 9a 8e ba 43 e2 61 65 67 2e e3 8b d2 |\p.t...C.aeg....| +000000d0 e0 47 80 61 66 ff 33 87 7e 97 b3 e9 1e 8d 9a 96 |.G.af.3.~.......| +000000e0 c9 ca e2 61 3e 28 ec 1d d5 18 72 65 57 44 fb 17 |...a>(....reWD..| +000000f0 ca 70 d6 26 87 d4 a0 42 2e 3f f7 a2 3e 93 08 1d |.p.&...B.?..>...| +00000100 ad b4 3f 7f 93 08 d0 6d 76 0b 2b 8b 2d ae 09 04 |..?....mv.+.-...| +00000110 f7 4d 02 0d ad 66 44 08 91 16 70 b1 98 b9 5a 86 |.M...fD...p...Z.| +00000120 5e 69 7d f3 0d 3d 9a 0c 08 f6 7d 66 87 ea 9a 0b |^i}..=....}f....| +00000130 60 43 f6 67 07 1c 37 41 54 65 c0 06 c1 b5 91 0c |`C.g..7ATe......| +00000140 83 49 ba 53 2f 87 bb 83 27 29 c8 7f 27 09 ba f2 |.I.S/...')..'...| +00000150 ac 77 e3 a5 71 b8 13 73 74 90 63 a7 89 ec e2 b6 |.w..q..st.c.....| +00000160 2c bf 3e ac 78 45 ec 48 3a 97 2a 63 74 35 04 55 |,.>.xE.H:.*ct5.U| +00000170 a7 16 c1 dd 1a 1b 9c ea f7 18 73 5d 8e 94 7e c1 |..........s]..~.| +00000180 15 49 5c fd 2f 0e b0 40 e4 22 e1 38 0d c0 3d ee |.I\./..@.".8..=.| +00000190 c9 9d 74 34 a0 a0 f9 cf fd 94 ff 0f db c2 4c f1 |..t4..........L.| +000001a0 ea 2e c0 ce fb f8 b4 af 8b 8d 2f 9c 61 21 b7 8f |........../.a!..| +000001b0 fb 95 3e ac e8 81 a3 66 a7 83 8c 7c 0e 63 d7 fb |..>....f...|.c..| +000001c0 e5 49 af 6c 6d 23 51 26 d3 ac c8 55 12 f7 42 44 |.I.lm#Q&...U..BD| +000001d0 61 6a 1b 0c f7 9c 85 9b 87 66 f6 0e b6 2e 41 f2 |aj.......f....A.| +000001e0 c4 9c 98 35 8e 27 84 8b 48 44 19 8d bf 0f e2 0d |...5.'..HD......| +000001f0 93 f9 c8 34 8d 7f f5 54 28 d2 02 7d 00 02 c4 a2 |...4...T(..}....| +00000200 34 96 40 3d ab be 35 9e b9 be ad 83 8b 34 19 5f |4.@=..5......4._| +00000210 12 93 22 f2 c5 2b ec 2f e5 db bb 37 05 6c 7e cc |.."..+./...7.l~.| +00000220 d9 0b 1f 46 70 b6 cb 41 8a 79 19 0d eb fe 4d 53 |...Fp..A.y....MS| +00000230 7c 24 f4 9a d3 43 8f 3a 0c 31 8c 30 7d 4b 5a 8f ||$...C.:.1.0}KZ.| +00000240 81 33 18 65 fe 04 8b a6 67 85 ef c9 34 43 8a 78 |.3.e....g...4C.x| +00000250 0d 85 47 5d 17 72 6d d7 29 e6 14 cb f7 6e ee cf |..G].rm.)....n..| +00000260 4f 22 84 ed b7 40 1f 24 ce 11 17 0d bb bb ea fd |O"...@.$........| +00000270 26 68 7e 73 04 d6 41 c0 fe f0 66 b8 03 12 52 46 |&h~s..A...f...RF| +00000280 7b 1d e5 49 93 80 ec 32 6f 41 81 46 a4 e3 02 23 |{..I...2oA.F...#| +00000290 f8 35 25 2f |.5%/| +>>> Flow 14 (server to client) +00000000 00 00 00 10 8b 43 54 b5 76 8b ee 65 e2 20 47 aa |.....CT.v..e. G.| +00000010 9b 27 eb 3c a6 cb dc ca d0 f9 a2 ee d9 33 60 1e |.'.<.........3`.| +00000020 2d 77 5a 63 |-wZc| diff --git a/ssh/testdata/Client-Cipher-chacha20-poly1305@openssh.com b/ssh/testdata/Client-Cipher-chacha20-poly1305@openssh.com new file mode 100644 index 0000000000..9305f40ef7 --- /dev/null +++ b/ssh/testdata/Client-Cipher-chacha20-poly1305@openssh.com @@ -0,0 +1,282 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 8c 0f 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 1d 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 |..chacha20-poly1| +00000150 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |305@openssh.com.| +00000160 00 00 1d 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 |...chacha20-poly| +00000170 31 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |1305@openssh.com| +00000180 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +00000190 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000001a0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000001b0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000001c0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000001d0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000001e0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +000001f0 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d |96...nhmac-sha2-| +00000200 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |256-etm@openssh.| +00000210 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 |com,hmac-sha2-51| +00000220 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |2-etm@openssh.co| +00000230 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000250 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 |ac-sha1,hmac-sha| +00000260 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 |1-96....none....| +00000270 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 |none............| +00000280 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef |..;........n..f.| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 2f eb 28 ce 9c 5d d8 9e bb 3c |....../.(..]...<| +00000010 8b 7a f7 f2 71 bc 00 00 01 7a 73 6e 74 72 75 70 |.z..q....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 b4 a9 7d fd 9e 94 |...,..... ..}...| +00000010 7e 5f be f6 5c 5f 3f ca 56 d5 49 14 88 a0 84 49 |~_..\_?.V.I....I| +00000020 79 61 2d 25 d7 0b 0f d8 b9 53 e2 35 b8 cc 87 3c |ya-%.....S.5...<| +>>> Flow 6 (server to client) +00000000 00 00 01 04 09 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 c7 36 22 b7 17 99 92 92 37 dd |..... .6".....7.| +00000080 14 42 9c 37 a4 54 99 71 c7 ee 4f 3c 6a 13 8a 61 |.B.7.T.q..O.u.aZ;.|.......| +00000170 59 4f d1 52 e9 58 c2 db 7f 66 27 ef 1e 2d cb 11 |YO.R.X...f'..-..| +00000180 f0 37 28 2a 23 97 20 14 8a 1d 0a de 05 04 ec 63 |.7(*#. ........c| +00000190 7d f5 af 6c 42 96 9e 31 ad ca c4 38 ba db f0 a5 |}..lB..1...8....| +000001a0 9b 4a 31 ff e2 0d 5f eb f2 bd 17 9e ba 57 1c 24 |.J1..._......W.$| +000001b0 bc 76 f7 5a f1 1c 71 bf f4 56 08 25 0f 76 4c 7a |.v.Z..q..V.%.vLz| +000001c0 40 dc 82 88 2c 97 f0 45 99 72 52 49 35 8c 04 ff |@...,..E.rRI5...| +000001d0 9c f4 6b 06 7e af ce 51 68 1a 64 58 47 02 a3 8b |..k.~..Qh.dXG...| +000001e0 6a c4 51 5d 86 05 86 7b db f4 81 e4 40 63 06 c4 |j.Q]...{....@c..| +000001f0 fd ae 4c f4 8d 98 49 2f f8 86 59 d4 3a 5b 02 88 |..L...I/..Y.:[..| +00000200 73 19 76 bb 0f 5d 8a f0 ce f1 d3 d0 ef 20 0b 1b |s.v..]....... ..| +00000210 48 e1 d0 9f 4f 76 57 9b 24 b4 2c 02 07 b4 eb a9 |H...OvW.$.,.....| +00000220 06 93 ae c1 61 9b a1 28 e3 20 68 49 8d 58 7b 35 |....a..(. hI.X{5| +00000230 7e 16 5c ad 6d f0 2e 43 44 58 90 3f 9f e6 19 5f |~.\.m..CDX.?..._| +00000240 dc 89 9e 6e e9 ce cc 6c d6 c0 a0 b3 f8 93 1d 2a |...n...l.......*| +00000250 2f be a5 be bc e3 64 79 a6 85 9e 17 47 1c 04 39 |/.....dy....G..9| +00000260 20 33 c8 ba | 3..| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 23 dc 62 b8 d2 60 16 9a fa 2f |......#.b..`.../| +00000010 3a 3a 49 cd 8e 18 51 64 5f ad ec fd 18 0d 67 93 |::I...Qd_.....g.| +00000020 dc 69 96 a5 3a 55 3b 23 a6 90 c1 da ff ba 80 e5 |.i..:U;#........| +00000030 21 a1 87 7e c8 d1 6d e9 bd 1e 59 08 |!..~..m...Y.| +>>> Flow 8 (server to client) +00000000 f5 90 9d 63 c4 ef 0d f2 b8 74 64 a4 c4 e7 4a f3 |...c.....td...J.| +00000010 18 40 b7 65 ae f5 8e 1f 8d ef 69 01 c7 74 f7 b6 |.@.e......i..t..| +00000020 9a 38 cd 3c 0a ff 7f b6 b6 fd 25 b1 |.8.<......%.| +>>> Flow 9 (client to server) +00000000 a0 93 a8 e3 ec 1e 7a a9 73 9a b1 17 61 5d 64 dd |......z.s...a]d.| +00000010 59 8e 40 25 06 16 99 21 d2 86 7e aa c9 c7 9a df |Y.@%...!..~.....| +00000020 45 8b b2 95 58 b1 9f f2 04 c1 24 44 3b f4 e8 05 |E...X.....$D;...| +00000030 70 29 74 8a d1 f8 be 75 59 1e a3 30 1d 6b 6e 25 |p)t....uY..0.kn%| +00000040 93 d8 1b e8 |....| +>>> Flow 10 (server to client) +00000000 91 31 b3 9f 83 fd d6 0d 5a 4f 1e c4 ba 7f ea 5e |.1......ZO.....^| +00000010 58 cd a5 0a 32 18 7a f6 e2 dd 41 70 7c 03 a8 cb |X...2.z...Ap|...| +00000020 24 da 46 d8 ee bc ba 0c 15 b0 2e 67 82 b2 81 b4 |$.F........g....| +00000030 d2 a6 eb e2 ae 80 80 11 fd 23 9e e8 52 82 8c d3 |.........#..R...| +00000040 15 9c 00 64 3a 2b 20 fe 79 18 63 35 b5 01 a3 18 |...d:+ .y.c5....| +00000050 ad 90 fb 88 9a ef f5 fc 7c 5c b8 f4 88 1f 4f 7e |........|\....O~| +00000060 a1 9e 60 1f ab 40 f9 3b 7d 7d 31 7f c4 6f 8e e6 |..`..@.;}}1..o..| +00000070 a1 2e 66 6f a1 e7 45 86 82 de 78 87 09 e4 94 bf |..fo..E...x.....| +>>> Flow 11 (client to server) +00000000 c4 02 e3 fc 38 5e ea 90 76 a4 8f 6c c2 17 e1 57 |....8^..v..l...W| +00000010 ea d0 6d a9 78 b4 01 65 9d 45 4e 5c cf 52 51 e4 |..m.x..e.EN\.RQ.| +00000020 df 29 ff 66 bd 07 d8 7f cc 6a 88 02 22 92 94 68 |.).f.....j.."..h| +00000030 7d 54 45 36 bc b8 41 17 83 10 28 af 38 19 a6 d4 |}TE6..A...(.8...| +00000040 19 01 dc 8c 0a 01 c3 87 41 a3 61 dd 96 2b bc 40 |........A.a..+.@| +00000050 65 32 59 22 9b 98 fe cb 96 71 f2 a1 c3 f1 d5 e2 |e2Y".....q......| +00000060 d5 b7 92 3e 5c 1c 9c 6a 25 05 d6 d3 0d f2 29 db |...>\..j%.....).| +00000070 4c 36 ea 22 bc 21 13 4e b4 e5 90 e6 be 24 c0 d3 |L6.".!.N.....$..| +00000080 93 d8 1a b8 d4 bc 51 a7 79 b7 ba b5 e4 01 6b aa |......Q.y.....k.| +00000090 3e 42 70 c0 10 24 c4 77 ad 11 db 50 d8 a8 0b 53 |>Bp..$.w...P...S| +000000a0 ab ef a6 e4 9b 81 86 f3 75 fd 00 b5 65 ad d6 1d |........u...e...| +000000b0 08 a1 d1 fc 7b 50 61 0e 56 51 d2 58 13 4e c2 1e |....{Pa.VQ.X.N..| +000000c0 7b c0 1e c6 61 c7 36 ad 00 71 fb cc 9e 89 80 df |{...a.6..q......| +000000d0 83 69 22 99 cd f0 ce 6c d4 e9 d8 4d 23 f8 c6 3f |.i"....l...M#..?| +000000e0 42 1a 4f b1 00 ea cb b7 4d 41 d5 b5 ec f8 11 80 |B.O.....MA......| +000000f0 a6 c5 e0 07 bc b5 b8 8d 8e 67 45 ef 6b 67 4f 37 |.........gE.kgO7| +00000100 d5 56 b5 5c 13 84 91 31 83 73 37 4e 04 f0 50 84 |.V.\...1.s7N..P.| +00000110 3c 42 a8 e6 30 05 10 11 7c f4 3d db 3c 50 59 09 |.RR.#...| +00000150 d2 e4 61 c1 12 fa 8a 6e 01 c9 4d a4 66 20 ba da |..a....n..M.f ..| +00000160 36 20 4a 35 56 91 28 42 33 33 b5 71 f2 ef 8c 63 |6 J5V.(B33.q...c| +00000170 24 c9 74 c2 |$.t.| +>>> Flow 12 (server to client) +00000000 96 bc 95 18 58 09 46 79 9d 57 59 05 e2 72 e0 de |....X.Fy.WY..r..| +00000010 f6 38 4c 44 09 55 ba ff 0d d1 2c 8a 96 47 b6 df |.8LD.U....,..G..| +00000020 13 25 b4 85 89 cb 18 df ac b9 6c 5c 5c 43 77 a2 |.%........l\\Cw.| +00000030 1b f5 74 6e 5a 2f 72 77 67 03 43 b4 e1 0e 5e 46 |..tnZ/rwg.C...^F| +00000040 94 05 6a 74 04 62 b1 0f c7 76 99 be 13 8b 3f 23 |..jt.b...v....?#| +00000050 38 12 b4 e2 6d 27 6f c3 e5 12 87 8d 6a 54 50 00 |8...m'o.....jTP.| +00000060 7e 31 12 b4 97 8c 30 10 33 15 21 73 51 1d 7c cb |~1....0.3.!sQ.|.| +00000070 57 1f 17 a9 86 5b 70 3d 30 e1 a1 55 10 3a 0c 37 |W....[p=0..U.:.7| +00000080 7f 61 ab ff 2a ec e8 44 1e 02 be e9 c4 73 b2 61 |.a..*..D.....s.a| +00000090 8c f0 87 c1 bf 35 8f 2b 51 60 04 07 07 28 d6 60 |.....5.+Q`...(.`| +000000a0 7f 89 15 62 cf 2b aa 98 89 d9 3e 2b 05 db 4f b3 |...b.+....>+..O.| +000000b0 24 b0 95 15 97 8d 4d c0 ba ab a9 24 d8 ee 7a 3a |$.....M....$..z:| +000000c0 bd e8 c2 d7 9e 61 97 b3 68 87 fa e5 d3 1e 23 a2 |.....a..h.....#.| +000000d0 e2 5c 65 71 56 d5 10 1d 79 a1 ab 96 61 2e 78 90 |.\eqV...y...a.x.| +000000e0 2e b2 96 de 5e b1 f2 ba 1e 1f b6 f3 77 9e 4c 3b |....^.......w.L;| +000000f0 9e 85 b0 b2 2a 99 cf da 4c c9 46 1b 0f 5e a8 28 |....*...L.F..^.(| +00000100 d8 3a c4 19 a6 ff 3c 0b 88 6f 30 cd 8d 21 c8 34 |.:....<..o0..!.4| +00000110 35 95 67 a9 b3 02 f9 17 2c c2 ed 4b c4 97 08 47 |5.g.....,..K...G| +00000120 c0 9d 1a ff 17 1c c0 61 82 b2 f0 82 34 51 58 1a |.......a....4QX.| +00000130 7c a9 9d 51 04 0f d3 4d 89 b3 a1 0e 96 78 07 39 ||..Q...M.....x.9| +00000140 c7 12 9d 8d 8a 0b 1d b7 e3 f8 a9 4b |...........K| +>>> Flow 13 (client to server) +00000000 1e 8d 8b 82 d0 80 8d ec 30 b3 03 e9 57 2c 3c e3 |........0...W,<.| +00000010 d1 22 02 9b 49 71 bc 2c db da fa a3 72 72 84 f0 |."..Iq.,....rr..| +00000020 01 ba 67 ef b1 5e b2 c1 59 84 9f ba 24 06 3b d9 |..g..^..Y...$.;.| +00000030 bb 11 47 5e 90 1f 92 b1 d9 26 5a 07 6d d7 94 40 |..G^.....&Z.m..@| +00000040 d3 3b 51 36 54 9a 57 af 84 7a 40 82 2e e4 95 80 |.;Q6T.W..z@.....| +00000050 0b 5f 16 92 3c d7 c9 77 94 1f 82 43 f0 2f 0c ed |._..<..w...C./..| +00000060 08 43 b7 1b 61 dc b1 d5 50 04 a6 fa ae 7c 58 9b |.C..a...P....|X.| +00000070 9f fa 00 97 0d 1d 4e 4a 85 9c f5 32 ab b9 af d2 |......NJ...2....| +00000080 f1 1c dd 9e b1 4d 51 31 46 25 90 05 5f 8b b4 22 |.....MQ1F%.._.."| +00000090 45 9d 87 af c6 a9 ab 25 26 b5 b3 26 99 97 cd 10 |E......%&..&....| +000000a0 06 ee 07 dc 51 0d c2 46 54 2c 20 95 43 d8 01 f3 |....Q..FT, .C...| +000000b0 55 2e 7a 79 21 44 0e b8 d1 5a 09 7c fb 1d d6 39 |U.zy!D...Z.|...9| +000000c0 09 90 03 6d 2d ce a5 5f f0 eb 46 79 40 e5 7f ca |...m-.._..Fy@...| +000000d0 f9 de cf 88 c4 64 8a c6 f7 24 96 87 f2 ae e1 17 |.....d...$......| +000000e0 ef 1b b4 4b 99 46 d9 da e8 f9 c0 c3 c6 4e e9 09 |...K.F.......N..| +000000f0 c2 c3 49 22 45 82 42 ed 63 5e 09 c6 d6 a8 c3 fd |..I"E.B.c^......| +00000100 c8 ac 06 37 99 9b fe d3 a1 2d f9 14 7d 2a c0 f3 |...7.....-..}*..| +00000110 da e1 5c 64 61 bd 0b 72 27 b2 3b a4 da d1 9f 1b |..\da..r'.;.....| +00000120 86 e6 9e 50 d3 39 76 fc 06 54 d4 6c 7c 17 30 cc |...P.9v..T.l|.0.| +00000130 0b ac bc 75 83 07 b6 2f 40 6e 55 6a 6a 0d a0 79 |...u.../@nUjj..y| +00000140 6b 27 6b bb 34 66 7b 4d 26 18 50 96 0e d4 8c ca |k'k.4f{M&.P.....| +00000150 a5 53 68 68 9e 73 ae 5d 93 70 ed c3 94 6e 61 11 |.Shh.s.].p...na.| +00000160 ea d3 6e 73 8c 06 d9 09 7c 08 a9 a0 05 52 98 ab |..ns....|....R..| +00000170 09 70 4e 72 f8 29 90 c8 77 83 9f dd 4e 22 98 f0 |.pNr.)..w...N"..| +00000180 c8 22 60 80 50 86 13 7e 93 0b 06 53 75 af 9d 75 |."`.P..~...Su..u| +00000190 27 e6 7f a0 7f 66 3a fd 33 b3 45 2e cc e9 b5 22 |'....f:.3.E...."| +000001a0 76 c4 e6 24 3f e1 db 53 b9 f1 69 20 76 40 f0 bf |v..$?..S..i v@..| +000001b0 b9 5e 1a 8e 1b 44 43 4b 44 2c ac 02 f4 f5 5f 8b |.^...DCKD,...._.| +000001c0 da 0f b6 2d de 09 75 7a 79 3a 4a 5a d7 9a 95 2c |...-..uzy:JZ...,| +000001d0 b3 f8 d9 8c 45 74 fb a0 a8 d6 2b 1f b2 35 bf dc |....Et....+..5..| +000001e0 5d 9d c2 e8 30 5b 8b 96 8f 2c 07 be 78 3c b6 9f |]...0[...,..x<..| +000001f0 be 07 4c 7e 50 c8 41 cc df 75 04 f3 29 be 38 ec |..L~P.A..u..).8.| +00000200 2a 99 df 2a 6b 21 a7 e5 88 70 ed 7d 2c 25 a1 28 |*..*k!...p.},%.(| +00000210 82 79 f4 01 09 78 60 fa 57 77 e8 7c 91 a5 32 cc |.y...x`.Ww.|..2.| +00000220 22 b2 25 5f f0 cf f6 84 c3 49 72 56 91 e5 9d 08 |".%_.....IrV....| +00000230 2f 3e 7d 8c ce f6 7a 3b 31 33 4f ce 06 57 a0 2d |/>}...z;13O..W.-| +00000240 cb c8 6e 3a 96 df f0 20 99 c9 77 39 82 7d 47 ca |..n:... ..w9.}G.| +00000250 d9 05 5c af 61 53 71 ea e2 6f 4b 31 b2 0f 6a e3 |..\.aSq..oK1..j.| +00000260 75 0b 44 30 c9 32 9e 30 20 c1 13 49 fe dc fd 63 |u.D0.2.0 ..I...c| +00000270 cb 03 48 6f aa cd 61 b2 e5 b8 1e c2 df 56 bf b0 |..Ho..a......V..| +00000280 c8 eb 46 33 54 8e 06 7e fd d1 2a 42 |..F3T..~..*B| +>>> Flow 14 (server to client) +00000000 1a a1 84 7d 94 88 a6 79 88 4f 79 2a 60 72 b4 2b |...}...y.Oy*`r.+| +00000010 20 b1 1e 55 6a 1f 1c a2 ba 49 8b 9e | ..Uj....I..| diff --git a/ssh/testdata/Client-HostKeyCheck b/ssh/testdata/Client-HostKeyCheck new file mode 100644 index 0000000000..bc5ed20b4b --- /dev/null +++ b/ssh/testdata/Client-HostKeyCheck @@ -0,0 +1,176 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 f3 f0 95 b8 f3 48 8a d7 53 02 |...........H..S.| +00000010 0f 06 e2 fa ec 09 00 00 01 7a 73 6e 74 72 75 70 |.........zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 5c ba 6d 1c b4 b7 84 24 3b 46 |..... \.m....$;F| +00000080 0c 91 27 c1 65 2e b0 59 06 8e 7f bb d0 f6 16 66 |..'.e..Y.......f| +00000090 29 e8 5f 52 cb 42 00 00 00 64 00 00 00 13 65 63 |)._R.B...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 c3 27 7c 33 6a d5 |6...I...!..'|3j.| +000000c0 c4 a3 ee b8 4a 13 27 24 11 69 64 ce 2d 0c 1a 79 |....J.'$.id.-..y| +000000d0 8d 34 23 4e 96 79 7b 14 5f 8c 00 00 00 20 49 2b |.4#N.y{._.... I+| +000000e0 48 81 ee 1a c2 8b 85 42 95 7b be 27 b2 96 d5 3e |H......B.{.'...>| +000000f0 ca e9 16 47 eb 66 4e 2b 88 37 42 61 c0 76 00 00 |...G.fN+.7Ba.v..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 8a 7d de de |...........@.}..| +00000120 4a 81 5e 93 af c1 ae 6a 42 49 ae dd 1a 89 d5 2e |J.^....jBI......| +00000130 e3 84 6a 60 cf 52 51 61 24 f6 1d 5a 2e 03 f4 4b |..j`.RQa$..Z...K| +00000140 9e 98 83 49 34 ff e6 5b 01 ea 58 a6 af b5 f6 64 |...I4..[..X....d| +00000150 ab 29 c4 51 e2 32 1f f9 c4 78 d7 b4 5e 06 c6 45 |.).Q.2...x..^..E| +00000160 59 3e 31 7b d7 30 fa dc 40 43 26 2b 24 c6 7b 31 |Y>1{.0..@C&+$.{1| +00000170 4b a7 ee a9 cd d1 61 29 8c 87 d6 81 28 70 27 7e |K.....a)....(p'~| +00000180 5c 07 a1 28 e3 06 9b f9 1a e7 01 07 23 0f 6d 3e |\..(........#.m>| +00000190 22 e8 c4 9d 96 f7 7c 84 4b 13 13 d2 e0 22 1d c0 |".....|.K...."..| +000001a0 60 7d 3e 17 28 c3 60 83 db 19 8b 80 a8 5f 2b ed |`}>.(.`......_+.| +000001b0 72 3d c2 0d d9 e9 6b 20 88 9c 27 e1 dc b7 bd af |r=....k ..'.....| +000001c0 fa 44 6c ef 2d c5 72 ed d8 9c 68 c8 be 1a 75 81 |.Dl.-.r...h...u.| +000001d0 be 81 a4 27 f5 cc c5 0b c8 4a 91 17 9d fa 58 c0 |...'.....J....X.| +000001e0 7a 7f fc 4a 72 d6 1a 9d 89 8a 2e 1a ca dc a3 9d |z..Jr...........| +000001f0 10 bb ad c6 eb fc 73 03 6f e8 0a cd b0 75 6e dc |......s.o....un.| +00000200 0c 5a c9 f5 7a d8 dd 40 94 9f b5 09 17 ad 4b f2 |.Z..z..@......K.| +00000210 3f 49 37 bb d1 6a fd 6a 1a eb fd ff f0 ad 1f 6c |?I7..j.j.......l| +00000220 ea d8 b8 86 4b 86 74 e2 e1 9c 8a 5c ed 54 bf d8 |....K.t....\.T..| +00000230 70 16 df 35 be 41 6d 39 da 2c c0 a6 fd 47 4a 4b |p..5.Am9.,...GJK| +00000240 37 87 b7 7f ed 83 af 76 39 e3 71 67 aa 41 e6 83 |7......v9.qg.A..| +00000250 fa b1 c1 ba 0f f9 8c 3e 2c 65 25 c5 c7 1f 9e f7 |.......>,e%.....| +00000260 b3 61 4f 86 6c c4 7a 30 f2 ea cc b1 |.aO.l.z0....| diff --git a/ssh/testdata/Client-KEX-curve25519-sha256 b/ssh/testdata/Client-KEX-curve25519-sha256 new file mode 100644 index 0000000000..c0b35d246c --- /dev/null +++ b/ssh/testdata/Client-KEX-curve25519-sha256 @@ -0,0 +1,288 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 31 30 2e 30 0d 0a |10.0..| +>>> Flow 3 (client to server) +00000000 00 00 02 ac 04 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 56 63 75 72 76 65 32 |EPv..>...Vcurve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 78 74 2d 69 6e 66 |bssh.org,ext-inf| +00000050 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 74 2d 63 |o-c,kex-strict-c| +00000060 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-v00@openssh.com| +00000070 00 00 00 57 65 63 64 73 61 2d 73 68 61 32 2d 6e |...Wecdsa-sha2-n| +00000080 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +00000090 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +000000a0 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +000000b0 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 73 73 2c |ssh-rsa,ssh-dss,| +000000c0 73 73 68 2d 65 64 32 35 35 31 39 00 00 00 6c 61 |ssh-ed25519...la| +000000d0 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 |es128-gcm@openss| +000000e0 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d |h.com,aes256-gcm| +000000f0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 |@openssh.com,cha| +00000100 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f |cha20-poly1305@o| +00000110 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 |penssh.com,aes12| +00000120 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 |8-ctr,aes192-ctr| +00000130 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 |,aes256-ctr...la| +00000140 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 |es128-gcm@openss| +00000150 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d |h.com,aes256-gcm| +00000160 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 |@openssh.com,cha| +00000170 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f |cha20-poly1305@o| +00000180 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 |penssh.com,aes12| +00000190 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 |8-ctr,aes192-ctr| +000001a0 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 |,aes256-ctr...nh| +000001b0 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +000001c0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +000001d0 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +000001e0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +000001f0 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000200 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000210 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000220 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 |nhmac-sha2-256-e| +00000230 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +00000240 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d |mac-sha2-512-etm| +00000250 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +00000260 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d |c-sha2-256,hmac-| +00000270 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 |sha2-512,hmac-sh| +00000280 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 |a1,hmac-sha1-96.| +00000290 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 |...none....none.| +000002a0 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 |.............;..| +>>> Flow 4 (server to client) +00000000 00 00 04 7c 08 14 d7 da a8 cd 40 76 e6 8a 12 b5 |...|......@v....| +00000010 5f ff a4 a5 57 4b 00 00 01 5c 6d 6c 6b 65 6d 37 |_...WK...\mlkem7| +00000020 36 38 78 32 35 35 31 39 2d 73 68 61 32 35 36 2c |68x25519-sha256,| +00000030 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 2d |sntrup761x25519-| +00000040 73 68 61 35 31 32 2c 73 6e 74 72 75 70 37 36 31 |sha512,sntrup761| +00000050 78 32 35 35 31 39 2d 73 68 61 35 31 32 40 6f 70 |x25519-sha512@op| +00000060 65 6e 73 73 68 2e 63 6f 6d 2c 63 75 72 76 65 32 |enssh.com,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 64 69 |-group14-sha1,di| +000000f0 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f |ffie-hellman-gro| +00000100 75 70 31 34 2d 73 68 61 32 35 36 2c 64 69 66 66 |up14-sha256,diff| +00000110 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 |ie-hellman-group| +00000120 31 36 2d 73 68 61 35 31 32 2c 64 69 66 66 69 65 |16-sha512,diffie| +00000130 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 2d 65 |-hellman-group-e| +00000140 78 63 68 61 6e 67 65 2d 73 68 61 32 35 36 2c 65 |xchange-sha256,e| +00000150 78 74 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 |xt-info-s,kex-st| +00000160 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 |rict-s-v00@opens| +00000170 73 68 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 |sh.com...-rsa-sh| +00000180 61 32 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d |a2-512,rsa-sha2-| +00000190 32 35 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |256,ecdsa-sha2-n| +000001a0 69 73 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 |istp256...lchach| +000001b0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 |aes256-gcm@opens| +000001f0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000200 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000210 32 35 36 2d 63 74 72 00 00 00 6c 63 68 61 63 68 |256-ctr...lchach| +00000220 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000230 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000240 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000250 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 |aes256-gcm@opens| +00000260 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000270 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000280 32 35 36 2d 63 74 72 00 00 00 d5 75 6d 61 63 2d |256-ctr....umac-| +00000290 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +000002a0 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +000002b0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +000002c0 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +00000310 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +00000320 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +00000330 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000340 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000350 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000360 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000370 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000380 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000390 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +000003a0 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000003e0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000003f0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +00000400 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +00000410 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +00000420 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +00000430 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000440 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000450 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000460 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 13 87 32 34 3e 68 |...,..... ..24>h| +00000010 e6 9b 9a cb 23 22 06 11 e8 24 71 e5 d7 96 79 83 |....#"...$q...y.| +00000020 48 59 1a 95 f2 b0 86 1c 76 54 58 e8 a3 63 9c a8 |HY......vTX..c..| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 85 12 a8 ca dd 22 7d 74 89 87 |..... ....."}t..| +00000080 df 36 23 6e fb 59 c0 75 4b 38 1e 49 d6 fa 5e 8c |.6#n.Y.uK8.I..^.| +00000090 cd 6c eb fd 26 34 00 00 00 64 00 00 00 13 65 63 |.l..&4...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 f4 8e 10 b5 77 04 |6...I...!.....w.| +000000c0 3e 1b 59 06 4f ef 48 08 2b 15 07 4a 69 0f 30 a2 |>.Y.O.H.+..Ji.0.| +000000d0 a4 37 7b 5e f9 de 15 0a ca 1a 00 00 00 20 6a 97 |.7{^......... j.| +000000e0 a3 23 e3 7c 92 67 28 0d 02 9e 36 e0 ae b1 f3 37 |.#.|.g(...6....7| +000000f0 19 34 12 cd bf db 84 31 8e 97 72 a5 e1 3f 00 00 |.4.....1..r..?..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 03 fb e9 4c |...........@...L| +00000120 15 76 5c bf 4b d7 6a 8b 2a 83 6f df bd 5e f6 45 |.v\.K.j.*.o..^.E| +00000130 b2 2b bc bf 38 9f f0 30 13 e1 03 67 d3 4f e6 6f |.+..8..0...g.O.o| +00000140 88 97 39 8e a6 2d df 6f a7 d2 90 df c2 9a 87 93 |..9..-.o........| +00000150 ad 91 12 2e 92 c1 c4 bb 93 b7 7d 6e fd 7c c2 10 |..........}n.|..| +00000160 fe fa b6 22 7e a5 a7 64 c4 25 ce cc bb 5d a5 f0 |..."~..d.%...]..| +00000170 ad 41 c7 8c a1 59 c3 a9 23 f0 69 38 4a 64 2a a1 |.A...Y..#.i8Jd*.| +00000180 62 8d bc 69 1c c1 01 ce ac a9 30 58 a1 d0 68 92 |b..i......0X..h.| +00000190 35 e8 7b 3a bf 1b 68 82 f6 90 8e dd 01 e6 92 4b |5.{:..h........K| +000001a0 bc ce 50 a8 96 2a 7d a5 4d 61 13 98 67 83 11 70 |..P..*}.Ma..g..p| +000001b0 ef f2 af 94 a6 0c 34 78 05 a8 39 d3 44 f6 c4 13 |......4x..9.D...| +000001c0 76 59 77 38 72 83 c4 92 a7 4c 7f 5e 25 08 9b a0 |vYw8r....L.^%...| +000001d0 6f eb 02 4d 4d c6 0a 07 09 2d c6 80 d3 05 8b c2 |o..MM....-......| +000001e0 e7 de 37 16 5a db 1c 02 2e 35 fb 3a 93 ce 79 4e |..7.Z....5.:..yN| +000001f0 0c 25 05 c9 b7 be b7 47 31 8c 18 d8 37 ba 66 34 |.%.....G1...7.f4| +00000200 bb 03 15 0d 0d cc da ad 2d 2c 36 0f 88 3f 5a 70 |........-,6..?Zp| +00000210 21 5f f1 cc 8a 21 e7 5a af c7 7c a0 e3 51 04 4a |!_...!.Z..|..Q.J| +00000220 d3 cb bb a4 60 2f d1 28 7b 6f 52 10 e8 76 fa c2 |....`/.({oR..v..| +00000230 86 9b 08 3f b2 72 e5 f0 0a 7c e0 19 ce 6f d2 74 |...?.r...|...o.t| +00000240 3e 12 8f 7d 1e 21 73 25 57 b8 c9 96 ad 35 f3 b6 |>..}.!s%W....5..| +00000250 5f b0 ae 82 90 4b 05 10 de 11 46 ea ad d7 3b 08 |_....K....F...;.| +00000260 a6 0d b5 24 f6 e3 ae 3b 67 3c a0 44 |...$...;g<.D| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 a1 e3 f9 ae 57 e2 35 b8 cc 87 |..........W.5...| +00000010 00 00 00 20 ba d9 4a 00 05 48 df ec d8 c5 bf f8 |... ..J..H......| +00000020 7d ed c8 ac a8 5f 1c 46 a0 21 c3 26 7e c6 51 2d |}...._.F.!.&~.Q-| +00000030 b8 e8 12 50 38 3a 08 8c a8 0e 98 e7 8c 27 4f 4d |...P8:.......'OM| +00000040 76 42 94 1f |vB..| +>>> Flow 8 (server to client) +00000000 00 00 00 20 53 c2 11 dc 60 cb f1 e0 55 eb f8 50 |... S...`...U..P| +00000010 38 11 aa 98 fc 4c 2a d1 36 0f 57 c2 c9 55 cb 04 |8....L*.6.W..U..| +00000020 dc 2f 79 36 28 5d fa 67 08 01 0a 1b fc a5 57 cd |./y6(].g......W.| +00000030 7f 67 ea 81 |.g..| +>>> Flow 9 (client to server) +00000000 00 00 00 30 c5 dd dd 05 d4 df 9e 48 d6 58 76 a1 |...0.......H.Xv.| +00000010 8a 7e 04 c6 51 26 44 1a cb 85 8b 9a 51 44 bd 57 |.~..Q&D.....QD.W| +00000020 bc 4f 2e a0 0a b9 e0 ee 00 b6 57 d3 2f 52 71 8e |.O........W./Rq.| +00000030 b6 4e f6 f7 34 7c 9f fe c7 c7 ec ca 08 6f d9 b0 |.N..4|.......o..| +00000040 e3 85 81 49 |...I| +>>> Flow 10 (server to client) +00000000 00 00 00 20 4e d8 10 08 39 ab 47 f6 49 42 4e bd |... N...9.G.IBN.| +00000010 2f 69 f7 bc 48 26 1b 5f ee ee 08 25 2e b8 8d 1f |/i..H&._...%....| +00000020 a0 e0 fa 11 28 26 9c af f0 6b 7e e0 f0 00 8f 92 |....(&...k~.....| +00000030 08 96 73 64 00 00 00 40 60 bb 40 d2 c4 8f 5e 09 |..sd...@`.@...^.| +00000040 e6 d9 13 04 fc 4e 21 81 51 dc ad 06 48 51 fc 35 |.....N!.Q...HQ.5| +00000050 b2 cd bb ba df 66 c4 20 b1 c0 b0 7e 7b c0 a7 41 |.....f. ...~{..A| +00000060 6f 16 7a fe 01 fe 3a be 45 4a b9 94 d1 46 a1 82 |o.z...:.EJ...F..| +00000070 09 24 97 57 17 83 9e e6 1b 4e 04 83 a0 73 55 08 |.$.W.....N...sU.| +00000080 2f e6 de 6b 43 77 84 31 |/..kCw.1| +>>> Flow 11 (client to server) +00000000 00 00 01 60 f2 7d b2 4f d9 db ec 78 6b a2 c2 77 |...`.}.O...xk..w| +00000010 6a a1 f8 d0 3c 5c e0 3b d3 99 33 ac 54 4b f7 e2 |j...<\.;..3.TK..| +00000020 3d 1f 6e 51 6f 4c c2 7e d5 3a 79 1e 9f 51 70 75 |=.nQoL.~.:y..Qpu| +00000030 67 35 8c f8 5d 62 35 9a ff fe b2 46 6f 72 47 0b |g5..]b5....ForG.| +00000040 5b 78 30 5b ce 54 5c ab 46 a4 a5 12 8b ef 32 2e |[x0[.T\.F.....2.| +00000050 1e a9 4a 25 07 9e a3 87 42 f9 69 ae c6 9d 83 68 |..J%....B.i....h| +00000060 e8 dd 19 a3 ef 4e 97 c9 ef 19 be a7 08 77 28 7d |.....N.......w(}| +00000070 ee aa b4 a4 3a e5 c1 4e 78 ee b2 b7 50 6d f2 eb |....:..Nx...Pm..| +00000080 2b df 38 22 a3 c9 be f7 ea 36 2f 7d f7 25 fd f4 |+.8".....6/}.%..| +00000090 9f 54 ec cf d5 82 5c 4b e5 e0 3f 74 da 9d d0 32 |.T....\K..?t...2| +000000a0 06 f6 a1 13 15 f4 11 24 e9 74 4c 9b 5e e2 c8 5b |.......$.tL.^..[| +000000b0 32 6b 89 87 d4 d4 ee e3 0c 81 16 d4 54 b7 97 ef |2k..........T...| +000000c0 c6 a4 d7 16 2d 87 be 2c 19 b8 48 9d d6 82 3c 82 |....-..,..H...<.| +000000d0 88 de bc 18 5b 64 ab aa d7 ac 8b 64 6a ad a8 4d |....[d.....dj..M| +000000e0 5a 20 a3 6e ee 7b 7f bf dc 6d 69 6a b0 8b ee 26 |Z .n.{...mij...&| +000000f0 0b 34 f0 22 a6 81 0f d3 b5 15 e8 86 1b 71 1a 60 |.4.".........q.`| +00000100 16 dc 2f 6b ca 63 6c 52 b3 33 42 46 c0 ea 63 50 |../k.clR.3BF..cP| +00000110 bb 23 29 69 79 0c 23 3f fb da 29 dd 94 44 f1 7e |.#)iy.#?..)..D.~| +00000120 58 1c 12 0f df a7 80 3c 69 8a 44 f7 4d 2e 7b db |X......>> Flow 12 (server to client) +00000000 00 00 01 40 ed 8c ad 60 63 f2 de d8 77 4e ea e5 |...@...`c...wN..| +00000010 7f 0e e7 65 d5 07 51 66 b5 f6 60 1f ba f0 00 59 |...e..Qf..`....Y| +00000020 ed b3 87 97 9f 52 71 a1 60 9b 3b ef 16 5c 69 2b |.....Rq.`.;..\i+| +00000030 73 1b 35 01 61 52 d6 36 50 5b 61 04 da e3 eb 2f |s.5.aR.6P[a..../| +00000040 b1 5f e4 b2 20 fa f9 52 76 ff 90 66 fe 69 98 26 |._.. ..Rv..f.i.&| +00000050 c2 72 9f 93 aa e3 bb 9a b4 28 62 e3 ea 7f 94 c6 |.r.......(b.....| +00000060 92 e3 2a 81 99 6c 08 f1 df 99 dc d1 a0 cd d0 e6 |..*..l..........| +00000070 31 21 7b d4 c0 e7 85 66 2c 3f 0e 9e 8f 8b 49 11 |1!{....f,?....I.| +00000080 64 6b 61 c4 39 15 d2 c0 83 76 f5 cf f5 5d 0c dc |dka.9....v...]..| +00000090 03 37 22 a7 fa f5 3c 8b b2 a4 2f 1b c3 57 7f 9a |.7"...<.../..W..| +000000a0 4b eb 80 dc e2 17 fd 8f 55 90 b9 03 2d 7f 1e e8 |K.......U...-...| +000000b0 5a 2b 08 57 76 a1 c7 7b 46 97 68 6e af b4 42 8a |Z+.Wv..{F.hn..B.| +000000c0 ea 13 b1 d7 7a 88 c1 f1 9d 45 ec 41 aa ed ef a0 |....z....E.A....| +000000d0 40 3b b8 74 e4 80 88 a9 6a bf d4 a8 9c 27 3d 21 |@;.t....j....'=!| +000000e0 65 8f 28 8a e5 4e 33 a7 fd 9b 78 08 07 ee d0 cf |e.(..N3...x.....| +000000f0 51 f9 b7 5c e3 6c cb 07 5a 74 55 f6 0f ef 42 2b |Q..\.l..ZtU...B+| +00000100 da 28 ac 34 e7 70 64 9b 4d 35 dd a0 d6 94 4f 48 |.(.4.pd.M5....OH| +00000110 d0 91 d5 6b 36 64 9e ce 88 c7 07 9b b7 c4 2e e3 |...k6d..........| +00000120 3b a9 0e 2e b2 63 f6 f6 0c 38 48 71 a0 a4 de 1b |;....c...8Hq....| +00000130 42 61 82 1e d8 1f d0 6b 83 71 ff e8 d5 c6 bc 7b |Ba.....k.q.....{| +00000140 ee 53 5b 87 b5 38 cf 07 5d 73 6e 59 cb d5 d7 d6 |.S[..8..]snY....| +00000150 bc 76 4e e8 |.vN.| +>>> Flow 13 (client to server) +00000000 00 00 02 80 62 66 4c ce e6 ed b9 56 ed 11 4a 46 |....bfL....V..JF| +00000010 93 45 c7 16 71 c0 e2 c4 fc bf 06 58 fb 20 3d ca |.E..q......X. =.| +00000020 2f 85 8f 6f da 51 9a 0d 90 3e 0b e0 af d5 00 5d |/..o.Q...>.....]| +00000030 f2 17 db fb 3c e9 4a 93 df a7 f2 a9 e1 d0 65 33 |....<.J.......e3| +00000040 18 f2 45 09 28 4e eb d2 58 22 b7 9e a9 df b4 48 |..E.(N..X".....H| +00000050 8e 60 e0 b3 b6 78 e9 e5 1c 37 26 1a a1 82 4b e8 |.`...x...7&...K.| +00000060 c3 9d 06 69 f5 13 59 18 2a 78 f6 2c 36 f0 96 0a |...i..Y.*x.,6...| +00000070 99 c5 f0 90 de 38 c4 58 b7 0d 42 0f e1 5d 11 2f |.....8.X..B..]./| +00000080 1f 56 da d6 d9 94 86 68 df bb 4b df ce ea 31 86 |.V.....h..K...1.| +00000090 32 cc 7f 50 75 ac 03 f3 48 c1 7b 58 7f db f8 3b |2..Pu...H.{X...;| +000000a0 5e 02 79 9d 59 38 9d 7f 7c ee 24 8b a1 22 92 a0 |^.y.Y8..|.$.."..| +000000b0 a1 52 2a 09 3a a1 b8 fb 3e be 40 63 7d af cf 21 |.R*.:...>.@c}..!| +000000c0 c8 a0 b6 86 94 af d8 bc 21 3b 83 77 55 c4 0a d0 |........!;.wU...| +000000d0 8e ea 4b 19 04 e7 88 2d 6f ff 9f 79 32 8a 7a 7d |..K....-o..y2.z}| +000000e0 20 09 9b 52 05 d7 a2 95 53 0d 7b 57 b0 92 be 0e | ..R....S.{W....| +000000f0 52 c2 0e c2 71 a4 d2 67 f5 80 e9 89 7b 6c d1 ea |R...q..g....{l..| +00000100 7c 83 f1 af 13 3e b6 69 62 e7 10 ed 75 c8 f8 cf ||....>.ib...u...| +00000110 60 07 d8 9a 46 e6 4f b4 22 f2 f7 ca ba ed 36 f9 |`...F.O.".....6.| +00000120 f3 ac a9 e0 f3 e5 37 b0 b0 7d 23 ed b9 7f 1f b3 |......7..}#.....| +00000130 57 38 7c c3 34 b0 78 a5 e8 29 a9 cb 35 17 68 4d |W8|.4.x..)..5.hM| +00000140 dd 8f 35 9c f1 b5 e6 e6 29 00 3b 1c ac 5d d0 cd |..5.....).;..]..| +00000150 1f a0 a8 a1 25 b0 97 53 ed 9a 72 a8 f0 61 0b 66 |....%..S..r..a.f| +00000160 2c 67 c9 e1 dd 86 6a 14 54 00 7b 90 7e 3c d2 5c |,g....j.T.{.~<.\| +00000170 d8 d3 a2 a0 cd c9 b2 82 8f 48 a0 22 49 63 54 6d |.........H."IcTm| +00000180 9f 04 f9 47 27 db 4f 3d 41 82 4a 1a be 4a b7 2f |...G'.O=A.J..J./| +00000190 81 c5 ad 12 cc 1e 45 f8 bb 42 93 ea 4b 24 97 44 |......E..B..K$.D| +000001a0 6b c4 4c 4d f4 61 08 0c a3 37 20 48 d3 be 47 71 |k.LM.a...7 H..Gq| +000001b0 1b b2 8a a1 eb 9f b9 17 61 07 64 15 29 6e fc 93 |........a.d.)n..| +000001c0 7d 21 fd 7d f2 09 6b 9c 5f 05 79 2b dc e0 c6 d4 |}!.}..k._.y+....| +000001d0 03 d4 9e 23 f2 3e 4b 23 11 5e 58 ec a8 5e 96 63 |...#.>K#.^X..^.c| +000001e0 6d 51 22 d5 3e e3 de ee 1a c5 d5 85 c3 c5 c4 05 |mQ".>...........| +000001f0 38 4c bd 54 b4 1e 6a 64 5a 9a 3e 48 82 ec e7 fe |8L.T..jdZ.>H....| +00000200 6a 67 a5 30 c0 fc fd c6 7e d4 d0 68 a7 30 40 e0 |jg.0....~..h.0@.| +00000210 87 c1 5d 75 0b a0 4f 90 f7 46 51 18 8b 02 36 c5 |..]u..O..FQ...6.| +00000220 fb b5 54 bd 32 75 dc 63 84 6f 61 a5 36 fe a6 23 |..T.2u.c.oa.6..#| +00000230 f8 a5 b9 cc af 00 e4 83 c0 11 50 ad 81 2b e2 bd |..........P..+..| +00000240 20 08 85 11 40 5e 66 25 d8 ac 06 a3 a2 10 dc 52 | ...@^f%.......R| +00000250 7a d5 13 61 82 b5 48 83 02 32 7b 20 96 78 40 14 |z..a..H..2{ .x@.| +00000260 38 10 9f 88 25 d3 60 3c 7e e4 11 da a9 6e 1e 58 |8...%.`<~....n.X| +00000270 13 de d8 d4 74 78 b2 5f 8c ce 9c ce 33 5c 1a 6e |....tx._....3\.n| +00000280 76 56 49 a4 54 0c ab 20 b9 c6 20 d4 fa b8 6f 41 |vVI.T.. .. ...oA| +00000290 81 1a 7e f4 |..~.| +>>> Flow 14 (server to client) +00000000 00 00 00 10 6e 70 e8 37 1b 64 e5 98 df 83 52 b2 |....np.7.d....R.| +00000010 40 ca 82 24 96 8c 21 c4 df d2 ec a8 d8 c7 b1 48 |@..$..!........H| +00000020 c2 48 90 90 |.H..| diff --git a/ssh/testdata/Client-KEX-curve25519-sha256@libssh.org b/ssh/testdata/Client-KEX-curve25519-sha256@libssh.org new file mode 100644 index 0000000000..c35f741796 --- /dev/null +++ b/ssh/testdata/Client-KEX-curve25519-sha256@libssh.org @@ -0,0 +1,289 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 9c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 44 63 75 72 76 65 32 |EPv..>...Dcurve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 62 73 |5519-sha256@libs| +00000030 73 68 2e 6f 72 67 2c 65 78 74 2d 69 6e 66 6f 2d |sh.org,ext-info-| +00000040 63 2c 6b 65 78 2d 73 74 72 69 63 74 2d 63 2d 76 |c,kex-strict-c-v| +00000050 30 30 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 |00@openssh.com..| +00000060 00 57 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |.Wecdsa-sha2-nis| +00000070 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 61 32 |tp256,ecdsa-sha2| +00000080 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 61 2d |-nistp384,ecdsa-| +00000090 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c 73 73 |sha2-nistp521,ss| +000000a0 68 2d 72 73 61 2c 73 73 68 2d 64 73 73 2c 73 73 |h-rsa,ssh-dss,ss| +000000b0 68 2d 65 64 32 35 35 31 39 00 00 00 6c 61 65 73 |h-ed25519...laes| +000000c0 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |128-gcm@openssh.| +000000d0 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f |com,aes256-gcm@o| +000000e0 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 |penssh.com,chach| +000000f0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000100 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000110 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000120 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 73 |es256-ctr...laes| +00000130 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |128-gcm@openssh.| +00000140 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f |com,aes256-gcm@o| +00000150 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 |penssh.com,chach| +00000160 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000170 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000180 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000190 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 |es256-ctr...nhma| +000001a0 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +000001b0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +000001c0 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +000001d0 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +000001e0 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +000001f0 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +00000200 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 |mac-sha1-96...nh| +00000210 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +00000220 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +00000230 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +00000240 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000250 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000260 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000270 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000280 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000290 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 b0 cd 36 b8 9a 47 6c e0 8f a2 |........6..Gl...| +00000010 06 ec 96 16 17 7c 00 00 01 7a 73 6e 74 72 75 70 |.....|...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 ee a0 9c c6 be 90 |...,..... ......| +00000010 37 5d 28 ba ea a8 41 a5 72 c8 5e 4d 2d 23 c4 f9 |7](...A.r.^M-#..| +00000020 26 88 44 60 fc 30 d9 da 91 6a a3 63 9c a8 a1 e3 |&.D`.0...j.c....| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 18 93 88 e4 65 66 c6 6a 6e 8e |..... ....ef.jn.| +00000080 26 98 82 64 63 d0 3f 29 9a 7c 42 ca 2d f3 16 24 |&..dc.?).|B.-..$| +00000090 1c 7f 22 9d 9c 6f 00 00 00 64 00 00 00 13 65 63 |.."..o...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 46 20 40 87 9c 83 06 |6...I... F @....| +000000c0 c7 08 5e 36 4d f7 b4 2a 48 7e 01 8e af 7c 90 41 |..^6M..*H~...|.A| +000000d0 ed 43 26 fb 56 3e 47 67 ad 00 00 00 21 00 bf a9 |.C&.V>Gg....!...| +000000e0 45 23 c7 27 0b 7a df 14 a0 15 af 82 e5 43 09 5a |E#.'.z.......C.Z| +000000f0 2a 23 30 c3 d7 66 36 d8 cd 83 d7 e6 15 4f 00 00 |*#0..f6......O..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 e8 49 e6 95 |...........@.I..| +00000120 02 27 90 c3 8d 11 8f f4 3b 85 09 dc 8e 93 f6 5e |.'......;......^| +00000130 3d 03 64 18 71 86 40 0d fb ef 22 a8 36 01 8a 07 |=.d.q.@...".6...| +00000140 96 1a 13 e1 66 70 aa e3 22 62 de c4 61 bf 64 4e |....fp.."b..a.dN| +00000150 33 24 6c e5 c4 f0 b2 20 21 31 20 3b 3d 54 0f bc |3$l.... !1 ;=T..| +00000160 4c 24 27 c7 83 94 b1 f7 89 0c ea fb 8e a8 e7 6e |L$'............n| +00000170 84 d2 da c5 77 f0 d4 64 c2 09 d5 20 1c f6 94 46 |....w..d... ...F| +00000180 85 20 79 35 e3 3e 2a 3d 86 d3 8a 99 a2 95 dc ca |. y5.>*=........| +00000190 ef e0 53 06 de e8 4a 36 3b 41 a4 21 49 5f 50 e9 |..S...J6;A.!I_P.| +000001a0 84 9d 0b a6 92 80 0a 9a 89 d9 db f8 24 a6 5f 2d |............$._-| +000001b0 e1 7b f5 31 a4 c9 a7 7f 07 f0 60 68 09 25 5b 97 |.{.1......`h.%[.| +000001c0 fe b0 ce d2 74 fb e3 92 27 a8 4f 8a ff cc a4 cc |....t...'.O.....| +000001d0 78 85 52 44 a2 46 f2 36 cb 13 6b 1b 8a 77 c0 7c |x.RD.F.6..k..w.|| +000001e0 16 6e 0f 33 d9 d0 aa 9d 25 b1 5f ba 7b 8d da bd |.n.3....%._.{...| +000001f0 fe 0f 4f f6 20 e7 1d bc 7f 19 b6 bc 7f d0 ae f3 |..O. ...........| +00000200 70 da 69 fa e2 9e 15 9e c2 e6 23 0f c2 1a 30 9a |p.i.......#...0.| +00000210 00 64 d3 ba 91 c5 ec 43 dc a1 82 87 5d 63 67 6c |.d.....C....]cgl| +00000220 02 99 04 ca cd a8 ef 35 61 54 60 59 92 4c 85 7e |.......5aT`Y.L.~| +00000230 3a a7 2c c0 25 e2 a4 a4 f5 cf 96 5f 04 2a c1 ad |:.,.%......_.*..| +00000240 1d 3e d8 0c 50 f6 1b e7 0b b1 e2 4c b6 cf 1f f0 |.>..P......L....| +00000250 fa e5 4b 42 b9 e6 44 35 f2 be bc 2a b9 62 a8 43 |..KB..D5...*.b.C| +00000260 1c 09 68 c3 85 48 b3 9a b7 75 95 79 |..h..H...u.y| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 f9 ae 57 e2 35 b8 cc 87 3c 23 |........W.5...<#| +00000010 00 00 00 20 1c 89 71 b1 5d 73 b7 6f d6 14 e8 79 |... ..q.]s.o...y| +00000020 50 e9 90 fa 11 7b a6 25 a1 95 84 ff c8 44 1c b1 |P....{.%.....D..| +00000030 43 88 2d c5 0c 40 61 5a a9 28 4c c9 77 00 82 87 |C.-..@aZ.(L.w...| +00000040 4e 86 bd 67 |N..g| +>>> Flow 8 (server to client) +00000000 00 00 00 20 b2 8d 5d a8 d5 32 77 c5 a4 6a 51 0f |... ..]..2w..jQ.| +00000010 42 55 ec b4 16 5a 94 ad bd 2a dd 01 c3 37 58 0d |BU...Z...*...7X.| +00000020 f0 0e 3d 28 8b f6 2f 3a 64 4c 5d bc 84 5d bc 7f |..=(../:dL]..]..| +00000030 59 24 98 0f |Y$..| +>>> Flow 9 (client to server) +00000000 00 00 00 30 9b ac 39 ff 48 bf fe d0 dd 87 5f 14 |...0..9.H....._.| +00000010 08 03 9b 20 89 fa 84 fb dd 4a 35 b2 74 2b 99 a9 |... .....J5.t+..| +00000020 aa a9 ea 89 91 09 93 fe f0 15 71 55 2e 37 b6 29 |..........qU.7.)| +00000030 68 0f 0f 67 59 1b 3e dd 69 d3 d3 52 c6 78 1e f0 |h..gY.>.i..R.x..| +00000040 3e b2 bc cc |>...| +>>> Flow 10 (server to client) +00000000 00 00 00 20 68 e7 bd c2 ed f5 29 52 3d a4 1b 2b |... h.....)R=..+| +00000010 f0 aa 11 47 7a 0b 39 77 2c aa 7a d4 28 15 60 85 |...Gz.9w,.z.(.`.| +00000020 c6 15 d3 9c 30 d3 36 e6 0b b1 d3 10 c1 66 e6 dc |....0.6......f..| +00000030 eb 75 91 6b 00 00 00 40 78 c3 94 19 9f 78 9c dd |.u.k...@x....x..| +00000040 dd 7d a5 ec 56 dd de 7a e4 ac 78 47 d3 10 b6 d9 |.}..V..z..xG....| +00000050 7f 5c 8d 32 16 32 d0 63 06 e4 8a 64 8a 82 0e 02 |.\.2.2.c...d....| +00000060 71 7e 01 2f 90 29 89 cb e9 6b 2e 8d 92 0d 60 89 |q~./.)...k....`.| +00000070 5a 45 04 45 c1 d4 04 50 8b 99 44 2c 02 de a5 7b |ZE.E...P..D,...{| +00000080 31 0c dd 93 0d 58 1d 6e |1....X.n| +>>> Flow 11 (client to server) +00000000 00 00 01 60 05 5a 2a 52 6e 58 06 70 de 77 4a 66 |...`.Z*RnX.p.wJf| +00000010 6a 2f 3e 38 4b 7c 86 00 b1 0a 29 04 5c 0b 33 7e |j/>8K|....).\.3~| +00000020 fb 6e 20 8c b3 e0 5e d7 83 53 4c 46 c5 66 11 31 |.n ...^..SLF.f.1| +00000030 bb 79 ee c4 69 9c 5e 8e c2 95 29 2b 71 ce e5 92 |.y..i.^...)+q...| +00000040 b6 a7 de 9f 4d 1b 7c ee e0 70 41 cc c9 b5 09 ac |....M.|..pA.....| +00000050 93 59 eb d6 f4 5d 36 77 06 18 6c 48 70 1f 66 1d |.Y...]6w..lHp.f.| +00000060 0f 5d cc ac 05 ae cc 4f 20 0c 69 38 b5 84 21 48 |.].....O .i8..!H| +00000070 91 4c f3 cf ee a3 d7 8d 9f f0 04 e8 e3 d2 dc 5d |.L.............]| +00000080 4f 19 7d 8e 6c 41 68 ea 48 45 82 29 8d 7d 07 47 |O.}.lAh.HE.).}.G| +00000090 31 7c b2 4f ea c5 25 2a f4 69 7a ce b0 72 56 8c |1|.O..%*.iz..rV.| +000000a0 43 78 7d ca 2c 68 b1 8a 40 17 44 9b c9 d6 9d 36 |Cx}.,h..@.D....6| +000000b0 28 1a 3f b8 88 4b 1e 9d 45 bf 20 52 d3 0a 42 93 |(.?..K..E. R..B.| +000000c0 1c 46 52 ed 5c df 99 90 45 ed ab 7e 6d e1 4b 7c |.FR.\...E..~m.K|| +000000d0 2a 79 c5 32 f6 72 86 38 7f f5 ae 6c 8b 87 ca de |*y.2.r.8...l....| +000000e0 57 90 82 e7 a6 0e 31 36 b3 60 03 61 df 53 36 6e |W.....16.`.a.S6n| +000000f0 31 16 2f 77 7c 44 d2 87 24 3e 3f d4 81 fd d5 88 |1./w|D..$>?.....| +00000100 a2 e2 fe 8f 8b 4b e8 24 56 2d 8d 50 fc d9 7c 39 |.....K.$V-.P..|9| +00000110 5e 99 a7 6d df 3e 3d 9e 32 01 63 37 f3 64 f7 64 |^..m.>=.2.c7.d.d| +00000120 a0 c7 66 8f 7a 50 da c3 5f 19 07 14 09 e2 0a 10 |..f.zP.._.......| +00000130 f9 83 7e 6e 60 b4 50 3d c4 34 5e 37 e3 b5 be f5 |..~n`.P=.4^7....| +00000140 13 c1 54 5d 66 47 9b 77 35 18 6f 9d c4 97 82 f5 |..T]fG.w5.o.....| +00000150 c6 b0 32 28 76 89 43 d1 4e 2d 14 ac 75 d9 41 51 |..2(v.C.N-..u.AQ| +00000160 19 7a b2 18 fb f0 d7 3b 9e f0 c0 80 c6 20 b8 cf |.z.....;..... ..| +00000170 30 16 3f d9 |0.?.| +>>> Flow 12 (server to client) +00000000 00 00 01 40 82 4b b0 d9 9c 0a 97 38 ff 35 cb 0c |...@.K.....8.5..| +00000010 1b c5 a9 d9 63 1c a5 12 3a 22 8f 93 c2 e3 30 f7 |....c...:"....0.| +00000020 d0 dd b5 89 3d 2d f4 d6 b3 d6 ee 65 24 2d 19 ea |....=-.....e$-..| +00000030 04 0d 31 ff a4 d0 7c d3 09 5f 0b 36 c0 26 5f 56 |..1...|.._.6.&_V| +00000040 0f 0d af 9a 00 1a d9 8a e7 b8 fc d1 0f 0f 99 2d |...............-| +00000050 ee 1e a5 52 8e dc 21 80 a0 29 e2 98 99 3d df b5 |...R..!..)...=..| +00000060 f9 4a f7 9f 07 4a 6f 06 ce 70 77 e2 f5 7d 53 52 |.J...Jo..pw..}SR| +00000070 9a 15 82 81 5f 9a dc 69 ca c8 84 91 52 9d 7d f6 |...._..i....R.}.| +00000080 1a 4b be 90 d7 60 f9 f9 b6 6c 8a 16 96 c3 8c f9 |.K...`...l......| +00000090 3e bb 2c 3d f9 aa 40 bd a6 a8 f0 47 0a 15 e5 bd |>.,=..@....G....| +000000a0 7a 42 01 b5 28 d2 46 7b 39 83 b9 49 2c ce ea 00 |zB..(.F{9..I,...| +000000b0 50 a1 0a 1c 92 1c 9b a5 58 c6 0f 7e 5e 4b af 88 |P.......X..~^K..| +000000c0 c5 06 f9 f8 5d a5 99 a3 a4 92 74 84 c9 ca 34 cd |....].....t...4.| +000000d0 86 20 32 e0 dd 2a 69 f7 eb 71 37 3f b2 63 7d 9f |. 2..*i..q7?.c}.| +000000e0 6b 7d c7 4a fd 57 67 a1 a0 22 f6 a3 cf 46 c7 ed |k}.J.Wg.."...F..| +000000f0 38 cf 41 d3 f1 f0 8b 9f dd 6a 73 f3 0a e8 e5 f2 |8.A......js.....| +00000100 84 f0 d6 b5 d2 ba 3e af 11 db d8 df ba aa 85 e6 |......>.........| +00000110 44 86 1c 85 9e 6b 57 d7 6c 80 4c ef 44 fb f1 14 |D....kW.l.L.D...| +00000120 8b 99 4a 61 8a 37 8d 5b 54 53 6a cd 5c 6f 9f 0c |..Ja.7.[TSj.\o..| +00000130 86 dc db 97 e4 2c ff 64 cf f8 69 9e 82 0d 28 3e |.....,.d..i...(>| +00000140 a9 91 e4 39 68 9d 4a 76 cf 99 7c ac 40 90 a6 0d |...9h.Jv..|.@...| +00000150 8e e0 62 05 |..b.| +>>> Flow 13 (client to server) +00000000 00 00 02 80 87 c1 35 bf fa 7e d1 55 cd 2e e9 80 |......5..~.U....| +00000010 ee a5 09 06 87 ea e0 49 a4 c3 be 1d fb a4 ef 74 |.......I.......t| +00000020 35 1f 18 7b 46 fc 07 82 50 89 b6 63 67 6a c8 72 |5..{F...P..cgj.r| +00000030 1c 86 32 33 8b 94 72 ce 41 15 82 02 f2 31 5e 03 |..23..r.A....1^.| +00000040 72 28 77 e4 5d 55 df 53 c5 07 d0 62 db 3b 70 f4 |r(w.]U.S...b.;p.| +00000050 10 76 36 4f ea 0c 6f eb 63 c5 d8 7f ce e9 34 d2 |.v6O..o.c.....4.| +00000060 a1 b1 ee 97 bd d6 d2 2f 35 a8 35 86 2e 7f a4 0c |......./5.5.....| +00000070 da 32 59 8f c1 69 b2 f2 9d b7 50 8f 91 4d 0f d8 |.2Y..i....P..M..| +00000080 90 19 6d 63 72 bd 8b 26 08 65 66 64 d3 85 60 fc |..mcr..&.efd..`.| +00000090 d8 df 74 44 e9 6f b7 63 84 d3 34 21 58 22 ff 36 |..tD.o.c..4!X".6| +000000a0 f5 f9 2b db 4f b6 13 2c 02 b5 52 5b be 20 db 1e |..+.O..,..R[. ..| +000000b0 6d 3c 00 cb 85 f0 88 32 98 e5 4d f6 e4 8d a5 5b |m<.....2..M....[| +000000c0 93 ea 44 3e 53 87 0d 68 f8 b5 7e e2 7f 66 f5 4b |..D>S..h..~..f.K| +000000d0 72 17 fd 3d 7b c9 1d 4a ef 57 1e 98 2a 70 b9 60 |r..={..J.W..*p.`| +000000e0 ef 13 ea 39 c4 50 96 5f c6 b4 2c 3e bc 8e df e2 |...9.P._..,>....| +000000f0 7d 90 79 ab c8 98 b8 30 e0 c7 46 31 20 a4 f5 b3 |}.y....0..F1 ...| +00000100 07 bc 6f d4 58 5b 4f 89 df fe 2b d8 d2 6b b8 2e |..o.X[O...+..k..| +00000110 48 8e aa 0e f1 34 5e 5f fb e3 28 10 a6 d9 63 c9 |H....4^_..(...c.| +00000120 79 9c 67 d8 e7 3b 2b 1d 66 d1 84 28 46 a2 84 9f |y.g..;+.f..(F...| +00000130 ed 94 4d 15 5d 26 ec 61 0c cb 5f d9 26 4c df 9d |..M.]&.a.._.&L..| +00000140 cc 18 80 de 2e 4b 33 76 35 87 c6 c3 8f 98 1c 0b |.....K3v5.......| +00000150 77 55 79 7a fa 70 44 09 bb 62 11 51 64 62 69 d1 |wUyz.pD..b.Qdbi.| +00000160 06 a4 c6 54 d4 7c bb 1f 1a b3 4e 42 2c 2e d8 29 |...T.|....NB,..)| +00000170 dd ff 50 1c ec 30 f9 b2 bc da 0d 93 37 87 c5 9f |..P..0......7...| +00000180 4b 3a d0 8d 12 77 09 1d 29 b3 34 8f cc ce 43 f6 |K:...w..).4...C.| +00000190 1f 0f e4 cc 54 60 25 aa ca c7 99 60 00 93 72 46 |....T`%....`..rF| +000001a0 21 9c 68 a1 eb ff cb 44 7a b7 57 b3 9b 9c 14 a8 |!.h....Dz.W.....| +000001b0 a4 19 13 99 58 cf 18 49 64 95 03 eb 1a dc d6 32 |....X..Id......2| +000001c0 f7 d9 23 fe 08 d6 0b da ec d7 06 54 13 78 e3 c3 |..#........T.x..| +000001d0 4e f4 d5 ff 9a 84 c9 62 ba 40 eb 10 0f 41 f9 0e |N......b.@...A..| +000001e0 4f d9 15 ad fe f4 09 f0 ee c7 b6 39 5a ef d0 24 |O..........9Z..$| +000001f0 16 d3 95 39 cb 2f 50 30 8c b9 c1 d9 95 98 1f 74 |...9./P0.......t| +00000200 a1 db 6d 2d fc 33 61 c2 d9 d1 91 41 f3 ae 69 1b |..m-.3a....A..i.| +00000210 e3 e6 9f 90 84 04 d0 1e 0c a0 7c 94 78 f0 69 5f |..........|.x.i_| +00000220 43 a4 66 3d 1c 5e a6 eb c6 a5 3b 0e 61 82 65 66 |C.f=.^....;.a.ef| +00000230 26 fa 90 43 3b 0f 11 07 ab b1 3c cc 9a 40 80 79 |&..C;.....<..@.y| +00000240 c4 d1 da 40 71 70 11 d1 93 31 4a 44 91 f0 39 87 |...@qp...1JD..9.| +00000250 0a ed 53 e0 e4 00 9e 93 6d e7 a8 14 f1 69 84 49 |..S.....m....i.I| +00000260 d8 97 6c f0 db ab a0 13 1a e8 9b bf 43 a2 3e 84 |..l.........C.>.| +00000270 d2 45 16 d6 8d c9 85 f5 39 05 4b 3f db f3 87 47 |.E......9.K?...G| +00000280 56 36 fe 46 7b 36 4f 38 be 3a 13 bb 82 5f 59 5d |V6.F{6O8.:..._Y]| +00000290 a9 ec b3 02 |....| +>>> Flow 14 (server to client) +00000000 00 00 00 10 4a 36 13 a2 c0 c1 a9 77 7c dc 8e 24 |....J6.....w|..$| +00000010 4c 39 78 70 1c a1 07 99 21 50 ee 27 b9 7e 41 e0 |L9xp....!P.'.~A.| +00000020 99 80 7d 96 |..}.| diff --git a/ssh/testdata/Client-KEX-diffie-hellman-group-exchange-sha256 b/ssh/testdata/Client-KEX-diffie-hellman-group-exchange-sha256 new file mode 100644 index 0000000000..4996c68fc0 --- /dev/null +++ b/ssh/testdata/Client-KEX-diffie-hellman-group-exchange-sha256 @@ -0,0 +1,340 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 ac 0e 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 4c 64 69 66 66 69 65 |EPv..>...Ldiffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 2d 65 |-hellman-group-e| +00000030 78 63 68 61 6e 67 65 2d 73 68 61 32 35 36 2c 65 |xchange-sha256,e| +00000040 78 74 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 |xt-info-c,kex-st| +00000050 72 69 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 |rict-c-v00@opens| +00000060 73 68 2e 63 6f 6d 00 00 00 57 65 63 64 73 61 2d |sh.com...Wecdsa-| +00000070 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 |sha2-nistp256,ec| +00000080 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 |dsa-sha2-nistp38| +00000090 34 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |4,ecdsa-sha2-nis| +000000a0 74 70 35 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 |tp521,ssh-rsa,ss| +000000b0 68 2d 64 73 73 2c 73 73 68 2d 65 64 32 35 35 31 |h-dss,ssh-ed2551| +000000c0 39 00 00 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 |9...laes128-gcm@| +000000d0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 |openssh.com,aes2| +000000e0 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-gcm@openssh.c| +000000f0 6f 6d 2c 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 |om,chacha20-poly| +00000100 31 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |1305@openssh.com| +00000110 2c 61 65 73 31 32 38 2d 63 74 72 2c 61 65 73 31 |,aes128-ctr,aes1| +00000120 39 32 2d 63 74 72 2c 61 65 73 32 35 36 2d 63 74 |92-ctr,aes256-ct| +00000130 72 00 00 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 |r...laes128-gcm@| +00000140 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 |openssh.com,aes2| +00000150 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-gcm@openssh.c| +00000160 6f 6d 2c 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 |om,chacha20-poly| +00000170 31 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |1305@openssh.com| +00000180 2c 61 65 73 31 32 38 2d 63 74 72 2c 61 65 73 31 |,aes128-ctr,aes1| +00000190 39 32 2d 63 74 72 2c 61 65 73 32 35 36 2d 63 74 |92-ctr,aes256-ct| +000001a0 72 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 |r...nhmac-sha2-2| +000001b0 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +000001c0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +000001d0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000001e0 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 |,hmac-sha2-256,h| +000001f0 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 |mac-sha2-512,hma| +00000200 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 |c-sha1,hmac-sha1| +00000210 2d 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 |-96...nhmac-sha2| +00000220 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-256-etm@openssh| +00000230 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 |.com,hmac-sha2-5| +00000240 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |12-etm@openssh.c| +00000250 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +00000260 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 |,hmac-sha2-512,h| +00000270 6d 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 |mac-sha1,hmac-sh| +00000280 61 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 |a1-96....none...| +00000290 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 00 |.none...........| +000002a0 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 |...;........n..f| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 ce fa 42 f0 01 84 db 18 f9 c1 |........B.......| +00000010 aa 81 b5 e1 09 eb 00 00 01 7a 73 6e 74 72 75 70 |.........zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 1c 0e 22 00 00 08 00 00 00 08 00 00 00 |....."..........| +00000010 20 00 ef 26 3c b1 ee a9 88 00 4b 93 10 3c fb 0a | ..&<.....K..<..| +>>> Flow 6 (server to client) +00000000 00 00 01 14 08 1f 00 00 01 01 00 f7 b6 db 13 59 |...............Y| +00000010 f9 0c 03 25 32 08 9b f3 ba e4 a2 ed 12 09 ee 18 |...%2...........| +00000020 1e 51 7d 24 23 8a 7e df 32 48 9c 1e 6f 3d ba 19 |.Q}$#.~.2H..o=..| +00000030 c0 14 89 ff 3b 6a 27 64 e9 32 b1 08 21 84 62 11 |....;j'd.2..!.b.| +00000040 1d 8c 83 4e b6 42 72 6f 08 fd be eb c0 8d c2 5a |...N.Bro.......Z| +00000050 2a bd 10 d7 2d e4 05 3e f4 b4 8a d3 85 a0 eb 97 |*...-..>........| +00000060 f1 ef 96 f0 1b aa 45 aa 91 4b ad 80 96 b9 79 19 |......E..K....y.| +00000070 f7 24 c1 07 5f cf ba 43 11 90 06 c6 1a 5f 4e 99 |.$.._..C....._N.| +00000080 1b 79 1e 10 56 73 0c f1 9e 92 15 b4 82 f6 04 71 |.y..Vs.........q| +00000090 04 26 9c 11 22 aa 14 a7 6b 55 37 62 1c 0a 62 0c |.&.."...kU7b..b.| +000000a0 e4 bd 63 a7 0b 89 8e 00 2d 19 bd 28 97 a1 d0 36 |..c.....-..(...6| +000000b0 b6 28 3e f9 cb 8a df 92 80 6c ae a8 ae fc de 63 |.(>......l.....c| +000000c0 f9 45 c5 f0 98 e1 18 24 be 34 93 22 5f 98 48 e0 |.E.....$.4."_.H.| +000000d0 8f 4a ab 4e 4c 36 21 d8 af 20 9c 02 05 86 83 33 |.J.NL6!.. .....3| +000000e0 2c e1 16 3d 15 8c 48 4e cf 99 09 5c 88 9b 90 01 |,..=..HN...\....| +000000f0 27 de 43 67 d2 a8 43 3e 5d 23 da b5 f5 ae bd a9 |'.Cg..C>]#......| +00000100 7c 42 5f 8b 16 97 59 f2 66 cc cb 00 00 00 01 02 ||B_...Y.f.......| +00000110 00 00 00 00 00 00 00 00 |........| +>>> Flow 7 (client to server) +00000000 00 00 01 0c 06 20 00 00 01 00 3d 5f 1a c6 e8 7d |..... ....=_...}| +00000010 30 eb 84 57 b6 e4 82 2e 1c 5d 84 fe 30 aa 8a 8d |0..W.....]..0...| +00000020 74 ff 44 9a 08 fb 46 6d a4 69 32 ad cc 61 d2 95 |t.D...Fm.i2..a..| +00000030 fd 16 ba f7 a0 ff d8 e0 57 81 e5 a7 e3 36 4b 0f |........W....6K.| +00000040 f5 17 05 19 38 7e 08 de e0 2c 1d 03 11 7c 94 49 |....8~...,...|.I| +00000050 ea a8 d0 fa 52 7e bc ac c5 88 08 53 2a 4a 31 e8 |....R~.....S*J1.| +00000060 d9 ce 61 d6 3b 82 fd 28 40 73 7c 7a 1b c6 7d 31 |..a.;..(@s|z..}1| +00000070 8b 9c ba 15 9d fb a1 67 12 8b 51 df 00 69 df b6 |.......g..Q..i..| +00000080 a7 d6 bd c8 0b a6 7e d2 87 c6 ae a4 ff 63 20 be |......~......c .| +00000090 34 ca 0b 09 35 46 d3 14 25 23 ac 4a cd d2 7a 10 |4...5F..%#.J..z.| +000000a0 79 b5 d3 8a 11 9f 66 bd 54 2b 00 5e d5 06 ee dd |y.....f.T+.^....| +000000b0 fb 85 36 36 78 95 f1 aa 05 cb 28 3e f2 7f 62 f6 |..66x.....(>..b.| +000000c0 8b aa af c6 13 c7 28 c3 3f e2 2d 33 6f ff 51 6d |......(.?.-3o.Qm| +000000d0 ef e3 d9 e3 42 97 f3 68 7e 4e da fc 93 ec c4 0c |....B..h~N......| +000000e0 9c 0a 8d 41 3c d9 3c 0d 1f 6b 0f e5 75 4d 9c 1b |...A<.<..k..uM..| +000000f0 1d 4f 2b b3 cf a5 9b af d6 e0 2e 2d 05 93 9a 44 |.O+........-...D| +00000100 38 28 7c 08 27 30 b7 68 92 4d 26 ed c0 96 31 b1 |8(|.'0.h.M&...1.| +>>> Flow 8 (server to client) +00000000 00 00 01 e4 09 21 00 00 00 68 00 00 00 13 65 63 |.....!...h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 01 00 22 9c d1 15 5b 09 0e 26 5e 9e |......"...[..&^.| +00000080 07 7f c4 0f 06 80 aa 69 3f ad 26 1a e4 23 15 5e |.......i?.&..#.^| +00000090 0f f7 f3 25 dd 90 9e ee c8 ef dd bf 40 a6 f2 36 |...%........@..6| +000000a0 aa 5d 11 e0 79 8d 56 76 2e 38 26 f2 48 02 6f 67 |.]..y.Vv.8&.H.og| +000000b0 03 9e c5 e1 a2 00 40 28 92 74 9f f4 15 0b a7 eb |......@(.t......| +000000c0 bd 5b 61 8d f5 99 04 e3 bc 61 88 aa ff 32 cd b8 |.[a......a...2..| +000000d0 4c 47 62 7f 9f f4 d0 5b f2 cc 1b 2a b8 59 b4 bf |LGb....[...*.Y..| +000000e0 20 85 31 be 8c ec 9f b7 1b 7d a0 db 54 2a 6e 28 | .1......}..T*n(| +000000f0 46 bd 8a 8b d0 ab 7c a5 75 57 d9 c8 82 7e 3a 5b |F.....|.uW...~:[| +00000100 f2 37 bb 31 3e 31 7c 76 be 35 36 da a8 27 e0 8c |.7.1>1|v.56..'..| +00000110 f5 6f f3 59 7f 03 d0 43 cc 6a f9 35 cb 94 48 87 |.o.Y...C.j.5..H.| +00000120 bf 13 6b 55 76 cd 25 05 3a 6e 24 83 0a fb 8b 84 |..kUv.%.:n$.....| +00000130 a2 9f 11 4f 47 19 47 ce 8e 50 ed 0a 58 90 a8 4a |...OG.G..P..X..J| +00000140 a4 60 13 0c b5 08 ab cb c3 37 c4 dc ff e3 fa cb |.`.......7......| +00000150 58 ad ab 12 3e 78 63 e4 fc ba 87 9a 5c a7 9d 1d |X...>xc.....\...| +00000160 ba 55 31 6c be 30 cc e5 d1 78 dc 68 68 0b 06 3a |.U1l.0...x.hh..:| +00000170 6b d2 6f 00 89 7a 00 00 00 65 00 00 00 13 65 63 |k.o..z...e....ec| +00000180 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000190 36 00 00 00 4a 00 00 00 21 00 fa 2f 87 96 42 8a |6...J...!../..B.| +000001a0 6b ad 4f 7f 6a 18 23 7c 29 38 09 95 51 10 80 ad |k.O.j.#|)8..Q...| +000001b0 64 82 73 dc 51 c0 60 f8 72 95 00 00 00 21 00 a1 |d.s.Q.`.r....!..| +000001c0 88 1f 71 aa e2 1f 97 c5 ce 9a 5a 1c 09 3c 87 bc |..q.......Z..<..| +000001d0 e7 53 69 85 ed b6 59 f7 18 4c 76 02 75 1f 74 00 |.Si...Y..Lv.u.t.| +000001e0 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +000001f0 00 00 00 00 00 00 00 00 00 00 01 40 69 ce 95 02 |...........@i...| +00000200 42 fd f6 5a 31 a7 d8 0d cf d7 37 c2 be 4c ce 2a |B..Z1.....7..L.*| +00000210 87 4f 17 54 53 9e 51 c7 10 36 ed e7 c7 1f ea c9 |.O.TS.Q..6......| +00000220 13 5d 40 6e 97 cc 94 6b 5c 1c 47 8a 50 ed 11 1e |.]@n...k\.G.P...| +00000230 c8 08 7b a9 59 0e 8a 9d f3 1b 9b fb 55 42 f2 3f |..{.Y.......UB.?| +00000240 ba a9 60 7d 4f f4 d9 3e 31 2c 4f 00 6d 08 b5 b5 |..`}O..>1,O.m...| +00000250 26 7a 77 e6 b8 be a7 c2 a1 4a 03 e8 d5 f8 3e e6 |&zw......J....>.| +00000260 bc 35 8b cc de 91 6c 4b 04 13 56 d3 21 86 15 be |.5....lK..V.!...| +00000270 35 9e 3d 75 0b fb a2 60 55 0e fe 2a 97 59 08 ba |5.=u...`U..*.Y..| +00000280 d1 eb 1a 28 5b e8 c4 ab 57 6c 98 a0 07 44 12 da |...([...Wl...D..| +00000290 1c b5 a5 ff ff 40 fb 65 6f c1 36 39 9c fe 85 53 |.....@.eo.69...S| +000002a0 1d 0d cf e9 71 c3 54 a6 22 f9 4b b5 2d d0 16 05 |....q.T.".K.-...| +000002b0 01 bb e7 76 e6 37 27 53 12 9d 81 03 d5 51 68 5a |...v.7'S.....QhZ| +000002c0 1a 74 d2 86 9e a8 07 33 36 85 b0 83 fc 29 ec 55 |.t.....36....).U| +000002d0 9f 5a f3 65 dd 20 9e 78 16 77 47 1a 5f 91 dc 70 |.Z.e. .x.wG._..p| +000002e0 b5 5d cc 9f 39 29 e0 2a dd 11 8c 18 50 ba 4c 16 |.]..9).*....P.L.| +000002f0 cc 30 01 c4 3e 9c ff 04 53 51 26 e4 ca 00 2c 4d |.0..>...SQ&...,M| +00000300 9a d9 b2 28 38 c4 3f 23 cf 36 f2 cd cf 64 44 85 |...(8.?#.6...dD.| +00000310 12 1a 83 c5 fe e4 7c df e3 25 25 c0 72 35 1e e3 |......|..%%.r5..| +00000320 2b cc 4c 92 3f 72 50 cd d1 71 2b 25 66 7a 99 f3 |+.L.?rP..q+%fz..| +00000330 6f 89 40 14 fb de 87 46 98 a0 30 5e 1b 9b b7 07 |o.@....F..0^....| +00000340 d2 92 8b 85 71 e6 eb c3 59 4d 5a 31 |....q...YMZ1| +>>> Flow 9 (client to server) +00000000 00 00 00 0c 0a 15 09 58 f4 64 d8 89 f3 1b a0 10 |.......X.d......| +00000010 00 00 00 20 ec 44 9d 56 6e c0 a0 79 03 70 c7 71 |... .D.Vn..y.p.q| +00000020 19 8e 28 6e 94 8d c6 7c 91 8a 7b d3 32 b7 4c ca |..(n...|..{.2.L.| +00000030 01 a9 e8 69 be f2 bf 23 38 d1 8e 86 69 44 0c dd |...i...#8...iD..| +00000040 2a 29 b4 7c |*).|| +>>> Flow 10 (server to client) +00000000 00 00 00 20 27 f3 90 62 3a f5 4e fe cd 68 f5 8d |... '..b:.N..h..| +00000010 a1 b4 81 cd c7 38 12 c3 d9 62 39 d5 c8 25 c1 ec |.....8...b9..%..| +00000020 43 af cc 06 73 bb 11 c2 64 b1 ff 3f e9 2b b0 f8 |C...s...d..?.+..| +00000030 13 98 5c 6c |..\l| +>>> Flow 11 (client to server) +00000000 00 00 00 30 e2 28 97 cb ad 4d 45 8d 34 e7 cc f3 |...0.(...ME.4...| +00000010 bd 2c 74 ff ca 83 c4 f8 0a 72 1b 70 d1 a8 3c 13 |.,t......r.p..<.| +00000020 c7 43 41 ea 60 1e a4 3b 3e 95 91 38 c9 42 e0 1e |.CA.`..;>..8.B..| +00000030 ac 9b 8b 32 9e cd b6 e1 bc 94 76 88 2a b5 ba 15 |...2......v.*...| +00000040 b5 42 4e b7 |.BN.| +>>> Flow 12 (server to client) +00000000 00 00 00 20 14 d4 d1 f3 e6 23 83 6b 2f f6 4e 6e |... .....#.k/.Nn| +00000010 c3 b0 e0 bb 58 6d 45 f7 6d 4f 00 af d4 c2 48 87 |....XmE.mO....H.| +00000020 15 6b 5c 80 5e 98 88 13 32 8c 72 e1 70 8d 1b 15 |.k\.^...2.r.p...| +00000030 a7 5f 65 b8 00 00 00 40 77 9e 84 59 54 09 0a 5d |._e....@w..YT..]| +00000040 a2 be 9b cd 04 f4 76 2f b0 89 e2 93 0f 65 da 6f |......v/.....e.o| +00000050 3d c9 4a 52 e5 f4 7f 65 2e 7f 06 92 f9 ed ea 56 |=.JR...e.......V| +00000060 46 1e 06 80 a6 ef a0 ff 8a b1 ae 67 69 bd f2 a0 |F..........gi...| +00000070 34 b1 28 7e 69 46 17 3e d4 4a d5 87 67 fd 52 42 |4.(~iF.>.J..g.RB| +00000080 f6 1c f0 cd 58 1e 1f d8 |....X...| +>>> Flow 13 (client to server) +00000000 00 00 01 60 35 c8 4f 9e ab 8a 8a fb 0c c3 1a 28 |...`5.O........(| +00000010 64 a7 7c b3 d0 31 be e2 1a fd 0d 87 66 67 00 39 |d.|..1......fg.9| +00000020 24 89 c2 3d b6 ca d8 3e 8d bf e4 7d 60 c2 99 19 |$..=...>...}`...| +00000030 a0 2a d5 bd 17 6e e9 12 98 c3 a0 16 93 a2 de 1e |.*...n..........| +00000040 ad 81 76 24 15 b8 67 89 61 d9 79 df d1 32 1a 14 |..v$..g.a.y..2..| +00000050 9d 63 9b dc d3 e6 f8 60 46 41 bf 22 25 2b 21 6e |.c.....`FA."%+!n| +00000060 8f a1 9e 10 14 66 de c6 ab 21 0f 52 0a 12 87 ff |.....f...!.R....| +00000070 34 9d 37 96 44 e7 2d 86 3d 6b c3 db 98 01 da 06 |4.7.D.-.=k......| +00000080 8b 22 33 09 db bf 38 ad bf 8a 26 34 a1 0d cf ef |."3...8...&4....| +00000090 e6 1e 30 ba 0a f2 d5 de a0 52 7c e9 53 11 c6 ee |..0......R|.S...| +000000a0 21 24 ae 2d 10 9f 43 ac f1 75 04 1d 5d 56 22 6b |!$.-..C..u..]V"k| +000000b0 89 af bb 73 26 9d cb ef 8e 2f 38 f3 f5 63 71 c5 |...s&..../8..cq.| +000000c0 f7 68 7b 9c b8 fc af e5 c9 80 22 50 16 dd 81 88 |.h{......."P....| +000000d0 b7 1a 83 fc 67 67 f0 27 5e c4 f5 5b 82 fa f0 74 |....gg.'^..[...t| +000000e0 ab 92 3a fb 9b 8f ac 11 e6 77 e5 f8 2c 9f 52 2b |..:......w..,.R+| +000000f0 7e 52 09 96 2f b3 c9 09 4e 44 6b b5 8d 4e 4f 82 |~R../...NDk..NO.| +00000100 ac 5e d1 0d 45 79 90 e4 79 cc bd 8b 9a 0d ba ec |.^..Ey..y.......| +00000110 c3 1b 07 ba 64 80 6c 16 41 84 ee 64 0e 54 13 b9 |....d.l.A..d.T..| +00000120 b3 f5 20 7f f3 f3 ad de 8d 07 9c e0 f1 d5 a5 62 |.. ............b| +00000130 02 ca 24 61 7a 28 1b b7 d0 b8 8f 78 3f f3 cd d0 |..$az(.....x?...| +00000140 a1 c5 7b 9d 84 7c b2 29 99 07 b3 00 0b 74 d5 28 |..{..|.).....t.(| +00000150 8c 80 2d 4c f2 b1 51 bf d9 32 9d f4 bd 63 f5 85 |..-L..Q..2...c..| +00000160 68 17 a1 df b1 99 8d f4 04 ed 47 fb e9 f7 4c a0 |h.........G...L.| +00000170 05 ff 02 08 |....| +>>> Flow 14 (server to client) +00000000 00 00 01 40 e5 e3 bc 08 24 8c 7a d6 bc 39 3b e5 |...@....$.z..9;.| +00000010 4c 55 a0 c2 2a b1 c9 47 9e fe ae 7d 6e 17 51 18 |LU..*..G...}n.Q.| +00000020 eb d6 dc bb 83 e2 3b a8 2e 00 27 de 45 65 33 0f |......;...'.Ee3.| +00000030 6a 0c 6e 7b 47 6d 29 eb db d6 db f6 2a 40 9f 0a |j.n{Gm).....*@..| +00000040 1c ad ed e2 81 1f 4c 10 f2 e2 04 0f 20 78 56 37 |......L..... xV7| +00000050 b0 e9 f9 86 96 24 43 82 7f 3b 59 d4 bc e3 0e 27 |.....$C..;Y....'| +00000060 55 34 b8 b7 13 79 d3 1e 68 8a 8e 1a 8a 63 52 d7 |U4...y..h....cR.| +00000070 f3 22 63 f6 c6 d3 44 57 4e 95 d2 67 96 e7 19 9c |."c...DWN..g....| +00000080 62 23 58 37 72 38 e0 c3 6e 64 aa 84 ff 01 ec 9c |b#X7r8..nd......| +00000090 f6 94 43 e2 25 9c 4f ee 1d be fb 5c fb f2 bd c4 |..C.%.O....\....| +000000a0 ec 40 8f d2 91 b8 43 43 6d 49 d5 6d da 5e 09 63 |.@....CCmI.m.^.c| +000000b0 81 4e ef 0d 2b 9b 22 7f 55 e2 c0 17 cd 33 a1 17 |.N..+.".U....3..| +000000c0 f8 dc c1 6f dd c0 7c b5 2e 2b 1d d8 d7 8c e9 9d |...o..|..+......| +000000d0 ae 43 95 4f 28 c4 a4 45 af a2 5d e5 17 da eb 0e |.C.O(..E..].....| +000000e0 6e 73 75 5b 88 ec 52 dd 81 45 c6 4c 04 dc e1 6d |nsu[..R..E.L...m| +000000f0 45 bb de b9 41 c7 98 f8 20 4a 4e 93 08 9d b5 7e |E...A... JN....~| +00000100 66 e0 19 4e b2 94 aa 52 b9 a7 e3 c4 97 54 81 a4 |f..N...R.....T..| +00000110 ca 34 5d a3 ce 8b 96 ea 18 44 d8 b5 b8 2d e9 c0 |.4]......D...-..| +00000120 1a f6 82 fe 04 29 af 8b eb ff 89 cb 01 b0 0c 0c |.....)..........| +00000130 ae 07 62 fc 3e 9a 21 fa d5 59 6d 20 9f 37 28 b1 |..b.>.!..Ym .7(.| +00000140 55 e8 ab 6c d8 25 9b 88 4f 52 51 55 0e 69 72 4d |U..l.%..ORQU.irM| +00000150 9d d6 f8 ed |....| +>>> Flow 15 (client to server) +00000000 00 00 02 80 9d 12 cb 6f c8 d4 5a 31 87 f9 be b5 |.......o..Z1....| +00000010 a3 7b 3c 32 36 a8 5f b3 fa 7a 2c 03 dc 56 e5 52 |.{<26._..z,..V.R| +00000020 c4 dc 9c bd 5b 7a 81 ba bd 5a 98 32 72 a2 0e 5a |....[z...Z.2r..Z| +00000030 28 4e 40 28 ce e5 51 d5 06 2c 6e 39 43 cf 64 17 |(N@(..Q..,n9C.d.| +00000040 25 3f d0 99 d6 96 84 ac b1 c6 c7 06 2f e9 5a 95 |%?........../.Z.| +00000050 79 f4 07 b9 ba 20 a6 c2 77 87 5d 94 06 26 9c 1e |y.... ..w.]..&..| +00000060 eb 01 4e 3a 6a 44 0e 22 b1 c9 7a 8a a9 65 b1 28 |..N:jD."..z..e.(| +00000070 03 6f 16 78 15 48 23 b4 bd 9f 7e 13 76 40 99 26 |.o.x.H#...~.v@.&| +00000080 32 fc 04 40 4f 7c c9 88 d0 5d 53 ca 5b 51 b9 55 |2..@O|...]S.[Q.U| +00000090 3f 5f 3a dc fc d4 ca 67 67 39 b9 85 c0 52 7a 1b |?_:....gg9...Rz.| +000000a0 16 19 17 8d e5 e2 41 f4 8f 2c a7 1a a0 f3 b1 bc |......A..,......| +000000b0 40 78 ce 60 a2 7c 71 64 9b 3d 02 f1 5d 10 73 2a |@x.`.|qd.=..].s*| +000000c0 2f 89 7f 92 b1 f9 43 c6 b1 61 8a 0d c6 3b e7 e5 |/.....C..a...;..| +000000d0 63 ba a0 c6 1f 1d ac a1 bd ec 24 b2 d9 23 92 46 |c.........$..#.F| +000000e0 91 d9 97 cf 50 00 57 99 46 41 a7 92 a5 5c 42 ab |....P.W.FA...\B.| +000000f0 73 87 c5 50 1a aa 71 3c 37 88 09 c3 bd 05 bf 2b |s..P..q<7......+| +00000100 d2 36 81 64 2d 8f 19 f7 e2 0b 1f 09 de 05 a9 4e |.6.d-..........N| +00000110 f6 e8 85 11 e7 9f ff 83 5d d7 8f 16 cc ff a5 03 |........].......| +00000120 59 d7 f2 3a 01 05 4d 02 e8 6d d3 db a4 37 27 e2 |Y..:..M..m...7'.| +00000130 f6 ac c6 fa 61 99 5c e9 7e 3b e0 8f 60 a9 ee f7 |....a.\.~;..`...| +00000140 a9 dd 91 f3 83 21 04 9e 17 37 e2 25 87 0e 65 14 |.....!...7.%..e.| +00000150 29 c1 e2 f4 68 42 98 b6 b9 d0 99 a2 19 09 0d 83 |)...hB..........| +00000160 6b 5e b6 94 08 be a1 55 e5 c9 60 3b 9c 96 49 86 |k^.....U..`;..I.| +00000170 df f3 87 e1 34 33 3a 28 48 39 5b 3b e8 95 29 96 |....43:(H9[;..).| +00000180 fe 1b 0d 67 ff ca 94 4e c3 e3 87 23 85 ff aa ff |...g...N...#....| +00000190 24 39 3d 3a 32 4a 0d 91 f7 96 f9 f2 5b 36 9c a9 |$9=:2J......[6..| +000001a0 6d 15 3e cb 79 84 a9 c8 ac e6 cf a6 ac d3 24 14 |m.>.y.........$.| +000001b0 e2 7a 00 38 13 c7 c4 62 2e 69 c6 45 d2 1f 8c bf |.z.8...b.i.E....| +000001c0 f9 64 6d f8 ca 71 e3 2d 59 23 ec 8e c9 56 cd c5 |.dm..q.-Y#...V..| +000001d0 b6 9c e0 fa 58 61 5d bc 11 15 8b 3a e6 bc 3a 7b |....Xa]....:..:{| +000001e0 be 8e ae e5 a6 dc 6a f7 2b 1c 37 2e 75 6b 77 5b |......j.+.7.ukw[| +000001f0 45 d4 94 e2 67 d6 63 b1 d3 b8 d2 f9 d4 cf 87 5a |E...g.c........Z| +00000200 3b 2b b7 7c b7 c7 58 86 ed de 00 91 39 88 92 ca |;+.|..X.....9...| +00000210 84 03 0c 40 72 18 86 b7 48 77 2f 36 24 be b4 e7 |...@r...Hw/6$...| +00000220 ba c3 94 bb 95 af f5 b2 0c ce 12 d2 21 16 87 fa |............!...| +00000230 d7 e1 81 d1 85 6f a2 e6 06 46 86 1a bb c0 74 c4 |.....o...F....t.| +00000240 f9 0a 98 6c 5f c4 25 5c a8 f8 44 50 36 9e 3b 87 |...l_.%\..DP6.;.| +00000250 82 a4 ff d1 6b fa 95 e8 37 2f ce 52 5b a6 6c a7 |....k...7/.R[.l.| +00000260 b1 7a 74 1e 4a 3f 77 b2 1c 4c 99 0f 7f 90 55 cf |.zt.J?w..L....U.| +00000270 9c de 62 b4 31 47 3b 31 9a 17 12 6f 16 61 10 72 |..b.1G;1...o.a.r| +00000280 0b 17 b0 3d 76 87 46 b3 1f b0 6d 2f 2c 3b 1f 49 |...=v.F...m/,;.I| +00000290 ff 7c a8 3b |.|.;| +>>> Flow 16 (server to client) +00000000 00 00 00 10 80 00 79 db a8 ad 00 6f ae 0c 3f 21 |......y....o..?!| +00000010 55 c3 33 5b 0f 09 8a 8e 7f 90 49 69 df 9e 03 44 |U.3[......Ii...D| +00000020 a3 b9 41 49 |..AI| diff --git a/ssh/testdata/Client-KEX-diffie-hellman-group14-sha1 b/ssh/testdata/Client-KEX-diffie-hellman-group14-sha1 new file mode 100644 index 0000000000..f9d936a23f --- /dev/null +++ b/ssh/testdata/Client-KEX-diffie-hellman-group14-sha1 @@ -0,0 +1,317 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 9c 07 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 43 64 69 66 66 69 65 |EPv..>...Cdiffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 34 |-hellman-group14| +00000030 2d 73 68 61 31 2c 65 78 74 2d 69 6e 66 6f 2d 63 |-sha1,ext-info-c| +00000040 2c 6b 65 78 2d 73 74 72 69 63 74 2d 63 2d 76 30 |,kex-strict-c-v0| +00000050 30 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 |0@openssh.com...| +00000060 57 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 |Wecdsa-sha2-nist| +00000070 70 32 35 36 2c 65 63 64 73 61 2d 73 68 61 32 2d |p256,ecdsa-sha2-| +00000080 6e 69 73 74 70 33 38 34 2c 65 63 64 73 61 2d 73 |nistp384,ecdsa-s| +00000090 68 61 32 2d 6e 69 73 74 70 35 32 31 2c 73 73 68 |ha2-nistp521,ssh| +000000a0 2d 72 73 61 2c 73 73 68 2d 64 73 73 2c 73 73 68 |-rsa,ssh-dss,ssh| +000000b0 2d 65 64 32 35 35 31 39 00 00 00 6c 61 65 73 31 |-ed25519...laes1| +000000c0 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-gcm@openssh.c| +000000d0 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 |om,aes256-gcm@op| +000000e0 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 61 |enssh.com,chacha| +000000f0 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e |20-poly1305@open| +00000100 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 |ssh.com,aes128-c| +00000110 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 |tr,aes192-ctr,ae| +00000120 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 73 31 |s256-ctr...laes1| +00000130 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-gcm@openssh.c| +00000140 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 |om,aes256-gcm@op| +00000150 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 61 |enssh.com,chacha| +00000160 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e |20-poly1305@open| +00000170 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 |ssh.com,aes128-c| +00000180 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 |tr,aes192-ctr,ae| +00000190 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 63 |s256-ctr...nhmac| +000001a0 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +000001b0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001c0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000001d0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000001e0 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 2d |2-256,hmac-sha2-| +000001f0 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 6d |512,hmac-sha1,hm| +00000200 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 6d |ac-sha1-96...nhm| +00000210 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +00000220 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000230 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +00000240 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +00000250 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +00000260 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +00000270 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 04 |hmac-sha1-96....| +00000280 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 00 |none....none....| +00000290 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef bc |..........;.....| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 ff f5 d7 3a af 23 41 81 6a 18 |.........:.#A.j.| +00000010 ad 28 8a 69 66 8e 00 00 01 7a 73 6e 74 72 75 70 |.(.if....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 01 0c 05 1e 00 00 01 01 00 8d 90 76 04 3b |.............v.;| +00000010 04 11 b1 36 c8 be 80 a0 85 a0 f1 65 b6 ab a4 9c |...6.......e....| +00000020 3d f5 f0 27 4e 02 8f ef 22 50 f1 0c 1a 5c 06 e6 |=..'N..."P...\..| +00000030 d0 a9 0c bb eb 58 07 90 b8 a5 cf 44 89 1f 3f 2e |.....X.....D..?.| +00000040 95 84 03 33 22 a2 7a a4 61 90 d8 e9 cc 24 0b a1 |...3".z.a....$..| +00000050 c1 ba e2 0f 1b cd aa 1a 93 70 40 58 50 f7 d4 1a |.........p@XP...| +00000060 3b 24 d4 3c bc 73 d5 d5 60 72 63 36 cb 5c e9 44 |;$.<.s..`rc6.\.D| +00000070 67 16 6e 57 58 7f cd 46 bd 64 c7 8d 0f 45 02 80 |g.nWX..F.d...E..| +00000080 9c 74 0c ef 8b 9e b3 ce b5 f2 f2 be 1a 7f f8 34 |.t.............4| +00000090 f0 86 77 cf c1 20 03 87 13 6f 49 f4 ee 8f ed 63 |..w.. ...oI....c| +000000a0 ef e5 31 7c 5b 7a 8b 24 e6 a9 b1 43 39 3b 67 57 |..1|[z.$...C9;gW| +000000b0 8c 65 76 e2 22 24 9d 29 51 f4 64 fb ab 0d 9c 94 |.ev."$.)Q.d.....| +000000c0 fa 69 0e 33 3e 1d b7 23 66 ec ae 8a 04 78 57 64 |.i.3>..#f....xWd| +000000d0 41 9b 2e a2 03 a6 97 91 e8 35 b8 a6 b9 d5 0e 87 |A........5......| +000000e0 83 c0 da 73 b1 4e 1c a0 78 59 8a 82 17 1c ef 95 |...s.N..xY......| +000000f0 99 3f 11 86 d4 40 31 cc 29 b6 a4 b6 1f 43 45 a3 |.?...@1.)....CE.| +00000100 9d 9c af 0d 29 ee 4e e3 63 53 39 59 3e a3 ae eb |....).N.cS9Y>...| +>>> Flow 6 (server to client) +00000000 00 00 01 e4 08 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 01 01 00 bb e8 9c 28 7b fd 80 e3 c8 |..........({....| +00000080 e3 28 f9 6f 18 2c ec d3 b6 c5 97 3d 40 c5 68 29 |.(.o.,.....=@.h)| +00000090 21 b0 05 76 78 c4 7e 4b cf f4 a7 7a 9c 07 ea 3a |!..vx.~K...z...:| +000000a0 c0 f7 c8 1e 91 fa 90 1d d7 3b 39 63 25 57 d4 3c |.........;9c%W.<| +000000b0 01 60 a9 93 6a c8 6d ce 29 4d 44 b4 54 c9 bf ed |.`..j.m.)MD.T...| +000000c0 03 d8 d3 4f f2 0a 4a f3 b2 45 9c bf 10 b9 be 07 |...O..J..E......| +000000d0 1c 17 c4 fd 63 e8 df ed d9 e1 e4 fa e3 03 91 d5 |....c...........| +000000e0 a8 67 1b f5 d2 81 07 0d e0 34 20 32 ba fd 70 ab |.g.......4 2..p.| +000000f0 2b 04 2a a5 d1 58 30 b1 5e 76 89 72 1c 41 32 f4 |+.*..X0.^v.r.A2.| +00000100 7d 15 d8 e0 9d 98 65 f9 3c 5e 91 da e5 2e 73 43 |}.....e.<^....sC| +00000110 73 a5 81 2e 81 b1 c2 9b 8c bd 51 ba 7f 69 b4 67 |s.........Q..i.g| +00000120 78 eb 01 78 68 69 0f dd 82 1a a8 20 cc e3 29 77 |x..xhi..... ..)w| +00000130 89 28 97 0b 3f c4 07 bd 83 d3 19 a8 8a eb a8 aa |.(..?...........| +00000140 dc 8a b7 ad 1d 88 3b c8 81 5f 71 40 6f 52 b5 0a |......;.._q@oR..| +00000150 ed 04 39 9f 4d df f9 55 44 a1 e6 51 51 a9 9a 05 |..9.M..UD..QQ...| +00000160 c5 17 e3 b7 f8 70 bc 5d 00 a3 ee d0 c0 2f 57 29 |.....p.]...../W)| +00000170 95 1a 0d 70 36 07 1a 00 00 00 65 00 00 00 13 65 |...p6.....e....e| +00000180 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 |cdsa-sha2-nistp2| +00000190 35 36 00 00 00 4a 00 00 00 21 00 eb d8 60 e1 40 |56...J...!...`.@| +000001a0 ae af 29 c5 d4 6d ed 45 13 51 ae d1 69 a5 bf 65 |..)..m.E.Q..i..e| +000001b0 8d 24 84 7b 92 1c 90 d4 cb c4 78 00 00 00 21 00 |.$.{......x...!.| +000001c0 c6 1e 47 79 49 4d e5 33 5b 9e b2 c9 cf 52 fa f8 |..GyIM.3[....R..| +000001d0 93 d9 43 b4 43 5e bc d7 27 f9 3f bc f6 f7 a7 cd |..C.C^..'.?.....| +000001e0 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +000001f0 00 00 00 00 00 00 00 00 00 00 01 40 e0 46 21 57 |...........@.F!W| +00000200 04 64 96 ed d2 fa a6 f5 b0 bf 0a a2 c8 01 b5 9f |.d..............| +00000210 38 b4 cf c9 c0 2b 99 58 8f 18 c0 3c b3 d2 ca ad |8....+.X...<....| +00000220 bc 06 75 37 57 9e 94 ff 37 37 cd a4 56 5c b9 ba |..u7W...77..V\..| +00000230 4e 3c 25 6b b5 2f 5e 0f ab af 10 ed 87 27 09 e8 |N<%k./^......'..| +00000240 de 05 27 aa 44 ed 90 ff 0e dd 68 ec 03 25 90 13 |..'.D.....h..%..| +00000250 d6 50 8d 02 44 ad b6 2a f5 17 ca 65 c8 50 0f 51 |.P..D..*...e.P.Q| +00000260 44 41 5e ab aa ca 05 42 70 1e 88 39 60 e3 2b 76 |DA^....Bp..9`.+v| +00000270 57 55 65 48 34 57 fc 2e a5 3b ef a9 83 ab 4a 29 |WUeH4W...;....J)| +00000280 66 10 ca 2a a5 a2 9e d5 4c 59 00 18 91 b4 f6 61 |f..*....LY.....a| +00000290 ea c3 02 72 00 1b d5 42 db bf 51 52 d4 d1 14 64 |...r...B..QR...d| +000002a0 fe 80 f3 98 18 de 69 2d 52 cb 17 5f 01 5a 60 84 |......i-R.._.Z`.| +000002b0 c3 ab 7c 75 ea 76 40 c1 16 af 18 cd 98 b1 68 9f |..|u.v@.......h.| +000002c0 9f 65 d3 7e a1 fe a2 d0 35 fd f8 32 ea b1 0b ee |.e.~....5..2....| +000002d0 4d 8b d1 28 62 8b 7f c4 c1 96 f3 d5 dd aa 71 20 |M..(b.........q | +000002e0 17 1f 48 9d cc 13 5e a2 c6 a1 06 c0 8a ab 86 45 |..H...^........E| +000002f0 25 b2 87 dc 4e 86 b9 5f de f0 60 cd b9 8c 60 18 |%...N.._..`...`.| +00000300 26 87 78 44 8d e0 56 c2 f9 56 5a 0c 52 68 a7 b9 |&.xD..V..VZ.Rh..| +00000310 48 8a 62 55 b6 d4 4f f5 dd df 20 90 34 d7 24 b5 |H.bU..O... .4.$.| +00000320 a2 f4 77 ac c8 79 cf f4 ad 73 8a c8 48 0a f7 a8 |..w..y...s..H...| +00000330 53 7f 8f f3 25 1d a5 18 e4 c5 8e 18 b3 93 21 ac |S...%.........!.| +00000340 db 53 83 1a 61 b0 65 f7 bc 64 c7 91 |.S..a.e..d..| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 61 3a 7f 1b 1d e3 3f d7 50 81 |......a:....?.P.| +00000010 00 00 00 20 04 f6 df f4 31 88 9c 11 03 01 aa d5 |... ....1.......| +00000020 9b e4 26 59 10 5e 56 43 8e a7 a3 9f 63 e5 12 15 |..&Y.^VC....c...| +00000030 54 21 47 c7 9b 25 63 8b 94 c1 13 cc 29 24 c2 5c |T!G..%c.....)$.\| +00000040 c0 c1 aa 0c |....| +>>> Flow 8 (server to client) +00000000 00 00 00 20 4c 85 e2 fe 02 7f 88 69 0d 6f 4d 47 |... L......i.oMG| +00000010 66 10 ee 86 ea 1a 8a d3 55 15 c8 a9 35 c1 e8 2b |f.......U...5..+| +00000020 3b 65 1b 74 95 16 93 1b cc c4 80 fa 04 e5 c5 21 |;e.t...........!| +00000030 af 2e 33 24 |..3$| +>>> Flow 9 (client to server) +00000000 00 00 00 30 ca f0 de 0e 0d 83 1a 71 2e c9 8d f8 |...0.......q....| +00000010 bf 89 c0 6f 46 cd 5f 4a ea fc b1 a9 3c 4e 6b 4f |...oF._J....>> Flow 10 (server to client) +00000000 00 00 00 20 fa 4c 56 f5 13 7b 2f 88 ca 73 f0 12 |... .LV..{/..s..| +00000010 c4 bc be c1 72 b2 ab 60 93 2c 54 26 ce 43 f7 bf |....r..`.,T&.C..| +00000020 0e 83 6f dd 83 f8 51 0d 58 54 69 38 df f9 30 29 |..o...Q.XTi8..0)| +00000030 89 50 a0 61 00 00 00 40 31 e7 db 21 76 3b 12 fa |.P.a...@1..!v;..| +00000040 14 cd a3 d4 ac 6c 1c aa 2b df 09 97 0c 85 9e df |.....l..+.......| +00000050 64 1f 89 de 4a fb 55 a6 26 f4 65 b2 12 79 f7 1e |d...J.U.&.e..y..| +00000060 63 47 8b 63 07 4e cb cd 46 d8 1b 32 bf e3 f3 76 |cG.c.N..F..2...v| +00000070 20 1f 92 03 53 ad 9f 84 32 32 4f 6a 68 53 03 7e | ...S...22OjhS.~| +00000080 b6 16 1e 94 05 b4 20 0f |...... .| +>>> Flow 11 (client to server) +00000000 00 00 01 60 37 91 33 16 95 11 7a 78 6b 59 c7 22 |...`7.3...zxkY."| +00000010 cc 19 90 5b 3d 88 ff 6e af cf 69 0f f7 75 2d 3b |...[=..n..i..u-;| +00000020 53 6e 86 c3 93 58 b6 a3 b5 de 93 d4 ae 10 d9 5a |Sn...X.........Z| +00000030 d5 f1 f9 90 ea d9 38 97 46 ea 52 8c 91 b8 0b ce |......8.F.R.....| +00000040 82 52 3f 0a 7e fb 0b d4 0d c7 72 c7 b2 c5 0f 91 |.R?.~.....r.....| +00000050 71 de a4 f5 be 5c 5b 2e 48 e6 51 37 6c 0d 6c ab |q....\[.H.Q7l.l.| +00000060 47 84 c6 75 23 8d 90 64 dc f2 c1 14 4b 0e 9f 3b |G..u#..d....K..;| +00000070 3f ec d8 b3 73 34 a1 4a b4 aa 0e 6d 8b a8 2b 65 |?...s4.J...m..+e| +00000080 c2 a5 40 ef ea ef 89 cc 40 22 b8 d1 39 e4 c1 ff |..@.....@"..9...| +00000090 73 45 62 81 c9 20 27 9d 66 47 92 05 1c 8c 3b 1c |sEb.. '.fG....;.| +000000a0 b5 09 03 5b 90 c3 ad 5f 03 62 30 86 48 95 2a ac |...[..._.b0.H.*.| +000000b0 ac f5 b8 ec f2 e0 51 8e a9 40 ac 61 4b 69 50 c9 |......Q..@.aKiP.| +000000c0 e4 fa 2a 69 b8 3f 3a 84 e7 2b 49 60 6a d0 5e f7 |..*i.?:..+I`j.^.| +000000d0 af 6b 16 68 c0 1b fc d6 9e e4 23 95 12 4d c5 24 |.k.h......#..M.$| +000000e0 d2 01 75 27 aa 85 9b 6b 00 13 66 62 c3 82 12 6c |..u'...k..fb...l| +000000f0 5a 19 f9 ac 7e 3a 42 a9 f8 c4 27 5d f7 39 3b 11 |Z...~:B...'].9;.| +00000100 8a 4a 15 19 1d f6 cd 87 ed 9e c9 46 cc a3 0d 0a |.J.........F....| +00000110 92 50 c7 96 87 9c 5f 14 57 00 7b 5f 21 1f 15 14 |.P...._.W.{_!...| +00000120 82 4d 30 63 83 35 14 6b 2f af ee 24 13 6b 53 b3 |.M0c.5.k/..$.kS.| +00000130 5a db 12 08 cc a5 e1 da 81 47 3b 90 ee 79 64 37 |Z........G;..yd7| +00000140 a8 6a 12 93 3b c1 96 48 5d 66 69 7e 4d 7c 56 a7 |.j..;..H]fi~M|V.| +00000150 d2 1b 46 73 58 f7 89 22 fa 62 29 be 2c 7f 09 d6 |..FsX..".b).,...| +00000160 0f 5f 5d e4 18 1d 81 3b 0d 88 9c 75 d0 67 6c fe |._]....;...u.gl.| +00000170 65 d6 8c 17 |e...| +>>> Flow 12 (server to client) +00000000 00 00 01 40 cc dc 9b d2 f9 94 0d 33 75 fd b3 c3 |...@.......3u...| +00000010 cf 4c f0 c8 51 37 61 82 2a bc 63 a8 3d 7e dd da |.L..Q7a.*.c.=~..| +00000020 bc 27 da 3c e6 03 3e b8 37 7f 7b 89 d8 68 a8 a8 |.'.<..>.7.{..h..| +00000030 48 66 12 20 ff f5 17 fe 1b 97 c5 36 b8 4e c0 43 |Hf. .......6.N.C| +00000040 05 6d 9a ad 47 fc 28 6c f7 a5 ca a2 ef 86 02 e6 |.m..G.(l........| +00000050 0b 0b c1 b8 23 78 e1 c3 ee 79 42 f0 7b b5 4c 99 |....#x...yB.{.L.| +00000060 2d ab 91 a6 49 62 be 29 00 85 14 96 e8 68 d7 f0 |-...Ib.).....h..| +00000070 a5 d3 68 ab 1e 85 12 35 51 9a 9e 0a 91 80 d4 80 |..h....5Q.......| +00000080 b5 3c 64 a2 40 46 89 fb a3 f9 ff 4c 45 d8 f6 d5 |.>> Flow 13 (client to server) +00000000 00 00 02 80 ba 84 19 c9 a1 0b 8f a9 01 70 83 6c |.............p.l| +00000010 d6 57 d4 ab df bf 7b 26 80 19 ce 05 f3 10 d4 0d |.W....{&........| +00000020 90 bb f9 2e a8 2d 21 3e 1f 27 8f 0b 0c 7e b3 d5 |.....-!>.'...~..| +00000030 71 52 d8 91 89 a9 66 ca 22 f3 21 cf 94 d2 f4 6a |qR....f.".!....j| +00000040 1e b3 42 0f 36 84 5b ea 0f 68 c3 88 84 b5 87 63 |..B.6.[..h.....c| +00000050 21 7e 7b 5e 70 58 f8 1c ad f9 e1 d5 f0 46 a1 44 |!~{^pX.......F.D| +00000060 ee dd 15 f5 3d 81 15 7b e6 3b 9c dc df 81 30 ce |....=..{.;....0.| +00000070 94 26 01 78 05 aa 08 c9 60 d8 65 ab 36 63 27 b6 |.&.x....`.e.6c'.| +00000080 ae 3f dc 44 97 22 a8 6a 3e 79 39 82 31 26 c6 a1 |.?.D.".j>y9.1&..| +00000090 5b 15 1c 7d b2 d1 5b 84 99 3e 06 fe 33 61 88 fc |[..}..[..>..3a..| +000000a0 45 8b 43 f8 fe 73 37 66 71 0e 55 83 5a 61 4a 2f |E.C..s7fq.U.ZaJ/| +000000b0 e5 21 5a ca 24 f3 8c 57 ba e1 51 54 21 bf 0f b9 |.!Z.$..W..QT!...| +000000c0 cb 55 4c 73 c7 e8 a8 91 a9 48 25 1b ff ca 42 d2 |.ULs.....H%...B.| +000000d0 80 ca 0a 5b 80 7e d3 38 0c 9e c2 05 9d aa af e5 |...[.~.8........| +000000e0 13 56 14 84 f6 e8 b5 fe 7a 57 05 2c 90 29 5a 03 |.V......zW.,.)Z.| +000000f0 c6 55 9a 8a c1 0a a2 74 9f c6 ff 17 86 de 34 f1 |.U.....t......4.| +00000100 80 0a 09 5a 23 c1 d0 cc b2 e5 ad 1a ce e8 50 26 |...Z#.........P&| +00000110 67 2b 7e 88 c1 1b 4c 52 34 06 e3 dd b4 6e 17 53 |g+~...LR4....n.S| +00000120 f5 2e 6a 55 b3 cb b8 98 71 d6 54 e8 88 fe 47 55 |..jU....q.T...GU| +00000130 20 db 9d fa 1c 23 73 88 22 0b 4a 16 7a 9b 73 4b | ....#s.".J.z.sK| +00000140 d0 31 e9 60 8b 87 c6 e9 e5 f0 52 93 40 02 b4 bb |.1.`......R.@...| +00000150 e1 8d 28 a3 8b e6 73 8d 8c 3d 5f 9a 4f 7f a6 b4 |..(...s..=_.O...| +00000160 9f 55 58 57 dc 44 a2 9b 1a 67 43 37 45 e8 00 5c |.UXW.D...gC7E..\| +00000170 9a 06 a0 89 0c f2 72 67 9b 60 44 dd 15 62 aa 28 |......rg.`D..b.(| +00000180 e5 99 0d dd f6 7b 2e 6a e1 b8 fc c2 85 01 6a 9d |.....{.j......j.| +00000190 62 20 4f 28 24 1c 62 27 a2 0e 6e 5f 55 62 b2 5d |b O($.b'..n_Ub.]| +000001a0 c7 d2 12 f5 5f 2a a8 98 17 0d 2b 70 0d c0 50 2f |...._*....+p..P/| +000001b0 de e9 ca b5 10 20 17 d6 12 e6 ad bc 26 f9 b1 1a |..... ......&...| +000001c0 ed 7d 1b 41 a6 07 b7 43 2b fa 70 f5 cb 53 60 51 |.}.A...C+.p..S`Q| +000001d0 b6 79 05 20 ee 4b 5e 14 13 1c 37 29 77 94 c5 e1 |.y. .K^...7)w...| +000001e0 ac 3d 1c 90 7f ec bf d9 4f b7 07 b4 a9 86 67 8c |.=......O.....g.| +000001f0 c0 bf 80 61 9c be 2d 75 68 31 20 13 fd 1d ab 3b |...a..-uh1 ....;| +00000200 02 62 6d df 75 ce 30 18 35 be 00 e3 86 a9 00 ed |.bm.u.0.5.......| +00000210 c6 4a ca a1 26 51 f8 b2 bf b2 3c 01 53 4f 37 03 |.J..&Q....<.SO7.| +00000220 31 b0 52 36 bd bf 9f 04 4d 1d 21 10 c5 c1 5c 00 |1.R6....M.!...\.| +00000230 9c 7b 66 a8 97 10 64 d7 20 87 91 ec 92 62 01 99 |.{f...d. ....b..| +00000240 85 d2 4c 3b 54 d5 6d af cc a2 d6 a2 2d 9c e3 ea |..L;T.m.....-...| +00000250 9e fe c7 e4 d9 c1 31 02 ed 10 56 90 8e 19 c1 53 |......1...V....S| +00000260 70 b3 4a 44 95 cc b1 2d 1b a4 99 96 fd 16 db cd |p.JD...-........| +00000270 39 b9 62 60 00 c4 86 79 a4 3f fc a0 70 a2 c8 23 |9.b`...y.?..p..#| +00000280 59 0c f3 da 23 18 e1 78 25 f8 a2 dd 68 4b a2 fc |Y...#..x%...hK..| +00000290 27 eb 07 5b |'..[| +>>> Flow 14 (server to client) +00000000 00 00 00 10 b2 de ad b1 55 01 bf 1c 1f c3 73 60 |........U.....s`| +00000010 3b ec 6d 32 9b 16 32 6d 52 99 0e 29 39 c1 ce 51 |;.m2..2mR..)9..Q| +00000020 d3 02 db 78 |...x| diff --git a/ssh/testdata/Client-KEX-diffie-hellman-group14-sha256 b/ssh/testdata/Client-KEX-diffie-hellman-group14-sha256 new file mode 100644 index 0000000000..29730e1cfd --- /dev/null +++ b/ssh/testdata/Client-KEX-diffie-hellman-group14-sha256 @@ -0,0 +1,317 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 9c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 45 64 69 66 66 69 65 |EPv..>...Ediffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 34 |-hellman-group14| +00000030 2d 73 68 61 32 35 36 2c 65 78 74 2d 69 6e 66 6f |-sha256,ext-info| +00000040 2d 63 2c 6b 65 78 2d 73 74 72 69 63 74 2d 63 2d |-c,kex-strict-c-| +00000050 76 30 30 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |v00@openssh.com.| +00000060 00 00 57 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 |..Wecdsa-sha2-ni| +00000070 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 61 |stp256,ecdsa-sha| +00000080 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 61 |2-nistp384,ecdsa| +00000090 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c 73 |-sha2-nistp521,s| +000000a0 73 68 2d 72 73 61 2c 73 73 68 2d 64 73 73 2c 73 |sh-rsa,ssh-dss,s| +000000b0 73 68 2d 65 64 32 35 35 31 39 00 00 00 6c 61 65 |sh-ed25519...lae| +000000c0 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 |s128-gcm@openssh| +000000d0 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 |.com,aes256-gcm@| +000000e0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 |openssh.com,chac| +000000f0 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 |ha20-poly1305@op| +00000100 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 |enssh.com,aes128| +00000110 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c |-ctr,aes192-ctr,| +00000120 61 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 |aes256-ctr...lae| +00000130 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 |s128-gcm@openssh| +00000140 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 |.com,aes256-gcm@| +00000150 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 |openssh.com,chac| +00000160 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 |ha20-poly1305@op| +00000170 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 |enssh.com,aes128| +00000180 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c |-ctr,aes192-ctr,| +00000190 61 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d |aes256-ctr...nhm| +000001a0 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +000001b0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +000001c0 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +000001d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001e0 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +000001f0 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +00000200 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e |hmac-sha1-96...n| +00000210 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 |hmac-sha2-256-et| +00000220 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000230 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 |ac-sha2-512-etm@| +00000240 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000250 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 |-sha2-256,hmac-s| +00000260 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 |ha2-512,hmac-sha| +00000270 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |1,hmac-sha1-96..| +00000280 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000290 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 3b 38 33 fe f9 9b 4e 24 fc bf |......;83...N$..| +00000010 1e 5a 51 9c 33 20 00 00 01 7a 73 6e 74 72 75 70 |.ZQ.3 ...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 01 0c 05 1e 00 00 01 01 00 c0 df 6a 69 44 |.............jiD| +00000010 14 06 d3 98 91 ee 99 a4 d9 79 ef be 14 c2 ba 61 |.........y.....a| +00000020 05 12 b5 a3 14 03 76 7a f5 c5 65 c9 e1 a7 97 df |......vz..e.....| +00000030 65 00 8f 76 49 12 81 cc 7b dd 6c 4a b1 a3 92 92 |e..vI...{.lJ....| +00000040 ad 6c 00 10 b8 38 82 91 ce 9d ba 20 f9 88 4f 65 |.l...8..... ..Oe| +00000050 51 bf 19 5b 8e 08 de 30 57 99 65 81 76 b4 4a cd |Q..[...0W.e.v.J.| +00000060 d1 fb 8c be b0 b1 e9 17 c5 40 a3 85 da d8 6c 5c |.........@....l\| +00000070 33 e7 ba 7a 58 49 26 d7 d8 99 3c 41 46 94 dc ff |3..zXI&.....Bt.| +00000090 74 a6 1c 82 78 3e 1f 3e 43 2f 09 a6 16 a4 5b 0e |t...x>.>C/....[.| +000000a0 32 2d 9b 59 92 41 fc be 1e b9 7c 11 96 40 32 5a |2-.Y.A....|..@2Z| +000000b0 97 b2 2b 8f ff 49 b5 a4 88 55 9b dc 36 73 96 b2 |..+..I...U..6s..| +000000c0 07 36 87 8a ba 3f 18 87 24 69 f8 2c e5 f7 c9 1b |.6...?..$i.,....| +000000d0 fe 1a d7 06 1a 34 61 2b 71 3f 1f 51 67 1b b2 6f |.....4a+q?.Qg..o| +000000e0 31 ea 2d d0 0f d5 62 ee 6b 2d 2e 36 62 96 87 05 |1.-...b.k-.6b...| +000000f0 1a e8 e7 d3 e6 52 2b 41 6a 07 28 d0 ed a5 b2 41 |.....R+Aj.(....A| +00000100 bc 1d fd 60 f4 3e cb ab d8 7b 23 f7 0c 59 3e a3 |...`.>...{#..Y>.| +>>> Flow 6 (server to client) +00000000 00 00 01 e4 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 01 00 4d be 3f 6b a5 f8 18 67 76 77 |......M.?k...gvw| +00000080 cd 70 a8 ed d1 bf 49 2d 43 d0 0e 15 b6 9a f6 8b |.p....I-C.......| +00000090 80 ec 8f 33 40 df 38 7b 2c a8 b0 27 fa b4 0e 55 |...3@.8{,..'...U| +000000a0 0f df d1 38 3a 62 60 d0 a7 4f 5e 0e 35 1a 7e 00 |...8:b`..O^.5.~.| +000000b0 9c 07 f4 15 39 f8 17 45 1d 3f ad f7 3d 88 e8 c0 |....9..E.?..=...| +000000c0 2f c4 0c 94 f1 02 51 54 f0 3b a6 80 97 4e cc 7c |/.....QT.;...N.|| +000000d0 b9 e1 37 a6 83 1f 5c 3e cd 28 cd f6 b1 ca 70 e4 |..7...\>.(....p.| +000000e0 b2 26 66 ae f3 c9 a1 b6 70 ce 0b e6 9a 43 31 cb |.&f.....p....C1.| +000000f0 00 d2 2c b0 6b 23 3d 84 ea 0f 3e 7c 06 79 06 86 |..,.k#=...>|.y..| +00000100 b7 21 ae bc 53 0a 4d a0 79 93 96 06 b0 fa 0e ed |.!..S.M.y.......| +00000110 3d 76 03 22 03 b7 30 3d 49 6a 28 d1 f7 de d3 8f |=v."..0=Ij(.....| +00000120 ad dd 72 3e fc be 33 40 ba d2 2f 39 48 0e 4b 26 |..r>..3@../9H.K&| +00000130 1d 49 cf 64 9e 87 f6 e5 2f ee 3b bc e7 ce 64 0d |.I.d..../.;...d.| +00000140 0a da e9 2e cc 74 94 05 a4 7b 6a 2c 73 b0 a7 85 |.....t...{j,s...| +00000150 3d ed b3 cb c1 c1 ec 29 70 8c 99 ef 6b 3c 4f 41 |=......)p...k| +00000320 a2 50 26 36 c2 de 21 8a 27 23 87 19 d5 f6 ca 13 |.P&6..!.'#......| +00000330 f6 5b 04 3a 9f 26 fe ca e3 4a de fe e9 dd 24 a1 |.[.:.&...J....$.| +00000340 e6 ab 71 92 54 b2 42 ac 93 f9 07 57 |..q.T.B....W| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 ae eb 61 3a 7f 1b 1d e3 3f d7 |........a:....?.| +00000010 00 00 00 20 9a c9 b5 4d 42 44 d3 9e b3 da b2 a8 |... ...MBD......| +00000020 4d 74 61 3c 88 92 61 72 ac 39 46 11 d3 81 11 00 |Mta<..ar.9F.....| +00000030 47 f3 62 f1 a7 9a 0e a3 84 9b 0e d4 cd 05 dd ba |G.b.............| +00000040 74 cb ce c2 |t...| +>>> Flow 8 (server to client) +00000000 00 00 00 20 66 32 98 0b 1c 0e 4c 74 19 72 8c 85 |... f2....Lt.r..| +00000010 45 21 7d 86 2d 52 c4 83 68 93 96 0f f2 e5 3b 3d |E!}.-R..h.....;=| +00000020 d5 37 f7 94 b0 f2 9d 15 bd 41 df 95 ce 5e c7 e0 |.7.......A...^..| +00000030 99 80 c3 f6 |....| +>>> Flow 9 (client to server) +00000000 00 00 00 30 8e 4c 28 17 78 72 67 e6 17 5e 57 96 |...0.L(.xrg..^W.| +00000010 34 da 95 4b 17 d8 13 19 6c 5a 59 8a ac dd 9d ba |4..K....lZY.....| +00000020 13 52 86 a4 d9 28 b3 6c b2 8f 86 e5 52 71 9f 77 |.R...(.l....Rq.w| +00000030 94 c6 72 1d b0 f2 d3 23 f5 37 b1 6d 9b b9 bb be |..r....#.7.m....| +00000040 82 f0 5c 4d |..\M| +>>> Flow 10 (server to client) +00000000 00 00 00 20 13 bd 6c af 45 15 f6 ae 02 8a bf 95 |... ..l.E.......| +00000010 46 67 fb ee fa 4e 46 54 a1 b3 da 5b f7 b5 07 38 |Fg...NFT...[...8| +00000020 30 af 7f 6a bd 35 3f 24 c6 84 7a c3 64 95 63 62 |0..j.5?$..z.d.cb| +00000030 f6 78 be e9 00 00 00 40 53 9c 7b f6 e6 7b 85 0f |.x.....@S.{..{..| +00000040 3b 3e 47 5c 3d 6b 20 47 1d 6f 88 93 b9 01 e5 fa |;>G\=k G.o......| +00000050 57 85 c1 99 f1 84 a4 c2 d9 4a fb 00 4e 5b db 3a |W........J..N[.:| +00000060 ea 10 bd 8a 75 c6 54 a9 b7 33 7f 52 9a b0 ae b9 |....u.T..3.R....| +00000070 f0 7d 43 c9 65 e6 05 14 a8 4d 62 c0 20 92 5f 55 |.}C.e....Mb. ._U| +00000080 cb d5 c6 20 46 dd f7 bd |... F...| +>>> Flow 11 (client to server) +00000000 00 00 01 60 5d c5 de 89 30 9f ae 98 0c 85 11 7a |...`]...0......z| +00000010 99 b7 96 f7 d3 18 13 1d f7 28 b0 c6 4c 55 9a 64 |.........(..LU.d| +00000020 90 85 3d 80 da 61 df fc 44 d1 0d 92 cc fe 29 d5 |..=..a..D.....).| +00000030 c8 23 9e f8 73 59 0b e6 5d f1 2c 79 39 ca 54 51 |.#..sY..].,y9.TQ| +00000040 66 f8 51 00 3d 5b d6 7f 6e e5 ef eb b6 05 38 ac |f.Q.=[..n.....8.| +00000050 8e e8 d9 b2 53 96 58 97 6a 6a d0 50 f2 67 b0 b7 |....S.X.jj.P.g..| +00000060 9b 44 98 11 d3 ca f3 55 14 f9 5c 6c a5 3b d5 50 |.D.....U..\l.;.P| +00000070 95 2b ef 6a 13 50 27 74 b7 0e ae 03 92 da b8 a7 |.+.j.P't........| +00000080 e3 a7 d1 14 5a 8d e6 0a d6 cd f2 29 e6 79 05 3a |....Z......).y.:| +00000090 28 8f 6d a8 95 b9 2f d2 db d6 4f c1 ca 47 d9 1f |(.m.../...O..G..| +000000a0 0e ed 2b e3 0d df e3 7e 65 5f 1e ab 2e 65 a8 da |..+....~e_...e..| +000000b0 df 43 59 99 5e 6d 71 3c dc 6a 7a 80 62 2f 96 f9 |.CY.^mq<.jz.b/..| +000000c0 08 8b 62 c4 f9 77 74 93 1d 18 ad e1 d5 f9 8e 08 |..b..wt.........| +000000d0 bc 6b 4e 4b 09 de 6b 39 e0 ab c0 f6 f3 06 fa ef |.kNK..k9........| +000000e0 94 c9 80 cc 8a 8b f3 16 eb 00 9d 20 62 bb 6d 50 |........... b.mP| +000000f0 27 e0 df 13 9c 64 45 ae aa 8c 50 8d 87 66 7c d7 |'....dE...P..f|.| +00000100 37 bf e2 45 7e 0b bc 4e ab 7f a4 9d b8 ba 66 f2 |7..E~..N......f.| +00000110 4a f8 24 0c c1 83 fc cb d2 03 24 f8 d1 18 71 7b |J.$.......$...q{| +00000120 21 67 c8 e5 6d 48 92 99 25 70 4c 4a 99 e2 aa 2b |!g..mH..%pLJ...+| +00000130 6c 66 32 f8 81 d7 2a 62 46 ad e3 ae 03 7c f4 29 |lf2...*bF....|.)| +00000140 af a6 30 33 31 9e 91 9d ae 80 80 97 f7 cc 32 68 |..031.........2h| +00000150 f6 59 e6 82 9b f3 a5 9a c1 f8 8c 4f ef c8 1b 67 |.Y.........O...g| +00000160 11 0f 7c 46 5c 5b 14 49 7b a6 60 2d b7 8c 48 e7 |..|F\[.I{.`-..H.| +00000170 3c 2f f9 0d |>> Flow 12 (server to client) +00000000 00 00 01 40 0d 6b 28 2d 9c 27 de f3 ea 99 00 2e |...@.k(-.'......| +00000010 51 fc a7 29 ae cc 31 01 e9 d4 fe 3e 44 61 f6 57 |Q..)..1....>Da.W| +00000020 0e 07 4a bc ce 98 a2 34 e0 52 99 e7 17 d3 0b 51 |..J....4.R.....Q| +00000030 fc 58 17 c1 1e 38 33 4f c6 cb a9 33 f1 c5 5d 07 |.X...83O...3..].| +00000040 93 98 7f 3f c9 59 65 b1 a0 9d 54 81 fa be cb 5d |...?.Ye...T....]| +00000050 be e5 38 dd 1a a8 70 48 e1 f3 1e 29 7d 50 fa 1a |..8...pH...)}P..| +00000060 95 28 89 d8 76 03 58 29 cd 9e 74 38 4a b9 ec 04 |.(..v.X)..t8J...| +00000070 36 06 ba dd fb 78 d9 3a 94 18 52 ba e5 64 f5 b8 |6....x.:..R..d..| +00000080 3e 9d 86 b4 0a c0 91 36 a3 87 b4 7b 24 18 65 7a |>......6...{$.ez| +00000090 0c ad 41 fb 71 77 75 ce 84 77 5b 44 11 0d dc 55 |..A.qwu..w[D...U| +000000a0 0d 10 35 3e e6 20 67 42 3a e4 21 ec be b2 61 1e |..5>. gB:.!...a.| +000000b0 24 33 20 79 22 18 6a 06 49 57 c3 13 44 96 72 76 |$3 y".j.IW..D.rv| +000000c0 e6 00 fd 1a c6 cb c4 1d 98 2f cb 96 56 90 cc 13 |........./..V...| +000000d0 43 85 7a 0e 30 a8 71 59 2f 8f a9 db 91 9c cb 59 |C.z.0.qY/......Y| +000000e0 b3 16 1b 3b f6 9a 9c 8b 48 a4 ad 60 80 32 74 cd |...;....H..`.2t.| +000000f0 c5 ff 0f a5 1e 48 17 65 c5 97 73 b0 eb 73 46 6c |.....H.e..s..sFl| +00000100 56 ae 0e 6f 66 49 46 9f 39 6f 53 28 49 35 61 24 |V..ofIF.9oS(I5a$| +00000110 d6 4d 00 60 b3 fa 91 c5 6b 2f 1f 29 5f 16 e2 ae |.M.`....k/.)_...| +00000120 07 2b a5 b4 19 c5 b9 b0 3b ed 9e 60 56 22 da 8f |.+......;..`V"..| +00000130 df 22 dc e8 e6 c1 2e 09 a5 d3 9f 2a fe ab 94 6e |.".........*...n| +00000140 02 a3 a4 0a fa 1c 0a d9 fb b4 62 f4 74 58 95 d5 |..........b.tX..| +00000150 33 ee 31 51 |3.1Q| +>>> Flow 13 (client to server) +00000000 00 00 02 80 93 12 97 51 29 07 f8 48 52 c4 01 fb |.......Q)..HR...| +00000010 61 96 41 26 54 05 47 3d 2c c6 8b 8a 5f da 0b 47 |a.A&T.G=,..._..G| +00000020 0e ba 66 c3 69 cd 6e 8b 6b b7 81 6a 8f 4f 95 be |..f.i.n.k..j.O..| +00000030 5c 9f c7 78 54 e8 14 52 a0 cb 43 3a b0 97 75 1a |\..xT..R..C:..u.| +00000040 08 51 eb c0 47 b9 e5 19 aa 3f ef fc cb 5d 6f d4 |.Q..G....?...]o.| +00000050 54 2e 40 bd 02 3d 46 37 6b 11 04 f0 07 af cf b6 |T.@..=F7k.......| +00000060 ba 21 d0 bd ce 4f fd 8d 1d f0 5e ce c1 d2 65 7e |.!...O....^...e~| +00000070 3b 77 5c cb e9 cb 39 38 26 75 3f b8 24 53 58 96 |;w\...98&u?.$SX.| +00000080 3e 8e 2a 14 9b 48 9f 70 7f e6 85 33 9a 17 03 ae |>.*..H.p...3....| +00000090 10 81 d0 2d 37 fd 53 2a 3d 75 74 68 63 43 97 a0 |...-7.S*=uthcC..| +000000a0 e6 bb 5e 62 e1 86 aa 74 9c 26 25 b2 8f 2f 39 b4 |..^b...t.&%../9.| +000000b0 3a 76 bb 79 76 71 26 45 30 1b 96 1e a9 a3 32 90 |:v.yvq&E0.....2.| +000000c0 97 31 a3 93 90 d1 71 74 13 77 84 f2 a6 78 7a 3c |.1....qt.w...xz<| +000000d0 4e c6 10 41 43 9e 66 c5 27 5a 38 41 ff b4 ce 3d |N..AC.f.'Z8A...=| +000000e0 f8 0d 89 0e f1 3d bc 86 9a 1f aa b3 44 59 69 5e |.....=......DYi^| +000000f0 cb c4 66 6b 01 84 20 ab 07 64 ac e4 aa 9d 61 1a |..fk.. ..d....a.| +00000100 f9 3c ec 7e 7f 1a 16 7b c5 ca 8b f5 d0 74 5b 80 |.<.~...{.....t[.| +00000110 bc 94 f4 1c be 85 a4 1a ac 3b ed 7b e4 a1 6b 3f |.........;.{..k?| +00000120 80 50 75 41 c3 b5 d6 6d f2 35 26 b6 cf c6 5e 87 |.PuA...m.5&...^.| +00000130 b3 ae a6 6b 97 2b fa c9 dc ca b4 89 8e 0b 3a 09 |...k.+........:.| +00000140 7a 24 a7 2f f7 cf d6 69 b2 89 c1 de e2 97 5e 7b |z$./...i......^{| +00000150 53 30 bf b7 03 5e 0c ef 0c 9b fb c9 bb 4c 12 a0 |S0...^.......L..| +00000160 ad 6b 8f a0 10 f0 73 05 ea b8 8a 3f a0 58 eb 93 |.k....s....?.X..| +00000170 7b b4 4d 8e bd 36 ae 93 0c 2b 67 c6 a0 27 af f0 |{.M..6...+g..'..| +00000180 4e d5 be 66 ff 25 f1 58 87 1f 20 65 f0 41 98 e9 |N..f.%.X.. e.A..| +00000190 46 1e 1b 50 0d 25 70 dd 77 b0 ab 41 e0 54 32 e4 |F..P.%p.w..A.T2.| +000001a0 8e ed 30 d3 1c 99 3c 7d 68 10 6b 28 ed 1e a2 2d |..0...<}h.k(...-| +000001b0 76 34 54 d6 a1 ce 8e e0 ad b7 0f 9c 8e 0f 87 90 |v4T.............| +000001c0 fa d2 7b fc bc e3 fd 30 52 36 b9 87 f8 1e 4d 57 |..{....0R6....MW| +000001d0 c6 f8 74 0d bb d1 f5 a7 95 02 cb 4b 8e 33 6a 7c |..t........K.3j|| +000001e0 6c 26 ce d2 cb 28 18 46 08 fe d6 bf 4c 3b 83 34 |l&...(.F....L;.4| +000001f0 98 7f 6d b7 0f f1 27 5b 54 dc 87 97 ee 3a 83 99 |..m...'[T....:..| +00000200 a4 bb 49 bd 7c a3 36 e7 3c f4 c0 8f bf 97 ed 59 |..I.|.6.<......Y| +00000210 be d2 24 1a 1b bf e7 25 4d 17 d6 b9 89 c5 46 e8 |..$....%M.....F.| +00000220 d2 69 5c 8b fa b4 dc b8 f8 3d da b9 b4 4d 54 11 |.i\......=...MT.| +00000230 b6 f2 bf 82 71 e9 87 f5 57 f2 d8 77 ca 9f 1e 4e |....q...W..w...N| +00000240 4f 85 39 70 d4 b8 4f 1b dd 05 63 0f a5 17 1e 4a |O.9p..O...c....J| +00000250 ce 82 41 0f 46 39 4d fe c8 0f 9a 5e 8b 9f cc e0 |..A.F9M....^....| +00000260 65 1f dd 79 79 d4 bb 66 4a 40 cc de cd f8 24 89 |e..yy..fJ@....$.| +00000270 36 f6 54 54 c0 07 ea ea 0d fb 28 f9 dd f5 1e 24 |6.TT......(....$| +00000280 67 21 f9 c9 9f 41 6d 3b c8 2d 48 e3 77 ff 5f ea |g!...Am;.-H.w._.| +00000290 b1 9c 79 73 |..ys| +>>> Flow 14 (server to client) +00000000 00 00 00 10 07 08 d7 f3 96 64 73 c5 a1 1d d5 56 |.........ds....V| +00000010 6a 4b 7a 2d 9d 07 c8 4a ba b0 35 f4 d8 2b fc 2a |jKz-...J..5..+.*| +00000020 49 ff cb a4 |I...| diff --git a/ssh/testdata/Client-KEX-diffie-hellman-group16-sha512 b/ssh/testdata/Client-KEX-diffie-hellman-group16-sha512 new file mode 100644 index 0000000000..400e12c23d --- /dev/null +++ b/ssh/testdata/Client-KEX-diffie-hellman-group16-sha512 @@ -0,0 +1,349 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 9c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 45 64 69 66 66 69 65 |EPv..>...Ediffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 |-hellman-group16| +00000030 2d 73 68 61 35 31 32 2c 65 78 74 2d 69 6e 66 6f |-sha512,ext-info| +00000040 2d 63 2c 6b 65 78 2d 73 74 72 69 63 74 2d 63 2d |-c,kex-strict-c-| +00000050 76 30 30 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |v00@openssh.com.| +00000060 00 00 57 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 |..Wecdsa-sha2-ni| +00000070 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 61 |stp256,ecdsa-sha| +00000080 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 61 |2-nistp384,ecdsa| +00000090 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c 73 |-sha2-nistp521,s| +000000a0 73 68 2d 72 73 61 2c 73 73 68 2d 64 73 73 2c 73 |sh-rsa,ssh-dss,s| +000000b0 73 68 2d 65 64 32 35 35 31 39 00 00 00 6c 61 65 |sh-ed25519...lae| +000000c0 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 |s128-gcm@openssh| +000000d0 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 |.com,aes256-gcm@| +000000e0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 |openssh.com,chac| +000000f0 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 |ha20-poly1305@op| +00000100 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 |enssh.com,aes128| +00000110 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c |-ctr,aes192-ctr,| +00000120 61 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 |aes256-ctr...lae| +00000130 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 |s128-gcm@openssh| +00000140 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 |.com,aes256-gcm@| +00000150 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 |openssh.com,chac| +00000160 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 |ha20-poly1305@op| +00000170 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 |enssh.com,aes128| +00000180 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c |-ctr,aes192-ctr,| +00000190 61 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d |aes256-ctr...nhm| +000001a0 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +000001b0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +000001c0 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +000001d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001e0 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +000001f0 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +00000200 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e |hmac-sha1-96...n| +00000210 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 |hmac-sha2-256-et| +00000220 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000230 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 |ac-sha2-512-etm@| +00000240 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000250 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 |-sha2-256,hmac-s| +00000260 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 |ha2-512,hmac-sha| +00000270 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |1,hmac-sha1-96..| +00000280 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000290 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 d2 4a b6 5d 8b 7e d1 03 c4 f4 |.......J.].~....| +00000010 7a 17 56 11 92 67 00 00 01 7a 73 6e 74 72 75 70 |z.V..g...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 02 0c 05 1e 00 00 02 01 00 8c 9c 9f c9 11 |................| +00000010 7f c3 d4 4e a0 8b 88 6d e1 d6 7b 17 05 e4 93 8f |...N...m..{.....| +00000020 2e 13 f1 b6 0b 30 1b cb f6 da d5 86 41 95 b2 8b |.....0......A...| +00000030 13 3b 7f fa 8b d3 bc 2e d7 e8 cb 4a 58 1b f3 e9 |.;.........JX...| +00000040 f5 b6 4d 3f e8 10 98 0c 38 27 cf 76 04 94 50 4a |..M?....8'.v..PJ| +00000050 59 c8 d0 1d 85 b1 b0 c0 30 73 33 d6 d9 95 b6 c3 |Y.......0s3.....| +00000060 26 dd 66 4e 58 af df b4 26 97 0f 70 87 e2 cf 47 |&.fNX...&..p...G| +00000070 eb 98 f5 15 6e 4b 66 b3 0e 3a e8 ac b5 11 91 77 |....nKf..:.....w| +00000080 b1 1a 0e d1 dc 3c a8 28 8a 28 81 62 f7 2c 3d 20 |.....<.(.(.b.,= | +00000090 c3 2d f1 c1 0c 58 a8 bd 85 88 f3 5b d5 5a 7b 03 |.-...X.....[.Z{.| +000000a0 92 f8 91 1f ab d9 ea e0 4c bd b6 5f e5 49 b1 ba |........L.._.I..| +000000b0 38 b5 da 9d d2 a0 9e a4 ca b4 0b d3 03 0f 0e 7d |8..............}| +000000c0 98 e0 22 c6 10 f5 da bf 5d 87 27 2d 26 2e 4f ab |..".....].'-&.O.| +000000d0 8e 2c ae e4 f0 93 1a 6e a9 e3 cc a0 07 39 1c 4d |.,.....n.....9.M| +000000e0 16 23 94 a0 ed b4 68 65 eb 82 0d 7d fc 2b 3a ec |.#....he...}.+:.| +000000f0 e7 40 9c 58 15 aa 46 25 20 1b 90 f0 b2 db ac fd |.@.X..F% .......| +00000100 be 48 94 9e c4 59 e9 83 26 21 aa 82 96 a0 71 45 |.H...Y..&!....qE| +00000110 2a f3 4b bd cf 67 ce d1 cc 1a 17 5f 2d ff dd 75 |*.K..g....._-..u| +00000120 c8 55 f5 82 93 43 95 09 03 db 6c 57 26 0b 1e 45 |.U...C....lW&..E| +00000130 df 1a 51 b1 c0 89 ad 40 af a3 ed b6 7b 13 0c 34 |..Q....@....{..4| +00000140 91 22 3b 25 8a cd 93 40 a7 6f 07 23 40 da 51 15 |.";%...@.o.#@.Q.| +00000150 b6 48 cd 0c 1e 67 c6 c5 e9 8c a8 27 fb da 8d c8 |.H...g.....'....| +00000160 de 4c 39 b7 51 ee b8 2b 6a dd b1 4b 97 a7 8f 0e |.L9.Q..+j..K....| +00000170 37 b8 f8 cc ee 29 72 b7 03 ea 02 4b c2 c7 c3 59 |7....)r....K...Y| +00000180 7f be 04 3b 44 3a d8 5c 23 fe 08 5d 06 40 5c 77 |...;D:.\#..].@\w| +00000190 8b 08 63 30 9a d8 68 9c 45 a8 aa 38 b0 e9 6c 8c |..c0..h.E..8..l.| +000001a0 fb a3 e1 0e 79 bc 59 53 2e 0d 28 08 5c 6d 34 cc |....y.YS..(.\m4.| +000001b0 89 b5 7b 6d 38 4e 2b 6b 48 53 fb 5d 5c 9f 3a ac |..{m8N+kHS.]\.:.| +000001c0 ab 6c 10 3f e4 e5 4a 1d 8c a1 ee e1 96 1d db 53 |.l.?..J........S| +000001d0 42 ee b5 be 68 dd b6 e5 b5 2a 3f 0f c6 63 f2 a3 |B...h....*?..c..| +000001e0 b0 60 b6 29 a1 94 d3 f2 b9 33 0c 85 4a e6 41 11 |.`.).....3..J.A.| +000001f0 ef d1 56 31 91 71 db 3d 1f 7b e3 16 99 e0 20 96 |..V1.q.=.{.... .| +00000200 bf e7 be e2 ac b2 34 d0 45 e8 6a 30 2e e0 97 f0 |......4.E.j0....| +>>> Flow 6 (server to client) +00000000 00 00 02 e4 09 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 02 01 00 f9 1e 24 e5 e3 f9 f2 37 c0 |.........$....7.| +00000080 75 e3 a9 45 07 66 4d d6 d1 23 4f 14 67 ff 77 93 |u..E.fM..#O.g.w.| +00000090 30 81 85 51 1f b5 31 d5 f3 73 1b 64 54 2d f2 45 |0..Q..1..s.dT-.E| +000000a0 be 82 6c 9b 43 01 5b 10 9c 78 19 61 92 ba c6 0d |..l.C.[..x.a....| +000000b0 3e d9 0b 8b ba 43 1b a0 93 1d 6f 06 b3 35 4a d1 |>....C....o..5J.| +000000c0 e3 13 6f 65 e1 2f 43 a5 0b 1e 48 03 01 c0 83 4f |..oe./C...H....O| +000000d0 d7 99 28 b9 3f c7 95 d5 eb d6 9b 73 3c e7 43 b6 |..(.?......s<.C.| +000000e0 9e fb 61 02 e6 45 83 b6 d7 4f 30 55 6d df ec 4e |..a..E...O0Um..N| +000000f0 d2 5e cd 2a 7b 8c 3c d7 27 a7 e0 b7 33 5b c5 27 |.^.*{.<.'...3[.'| +00000100 a6 13 fc 3f 58 cd 5c 26 82 bd 32 b8 00 ad cd f9 |...?X.\&..2.....| +00000110 46 88 28 64 f1 a5 6d 4c c0 22 d6 35 d6 10 ca df |F.(d..mL.".5....| +00000120 e9 10 b4 9d d4 04 22 05 9e b0 3e 39 ab 8e 10 4a |......"...>9...J| +00000130 a1 52 1c 63 4e fd 5a cf 11 ba 46 77 c2 72 46 57 |.R.cN.Z...Fw.rFW| +00000140 49 54 9f 56 7e cb c5 0a bd e8 98 b1 d5 d9 07 78 |IT.V~..........x| +00000150 84 fa 25 b8 37 72 32 13 68 b1 50 18 d1 0a 3d 96 |..%.7r2.h.P...=.| +00000160 52 11 2c 6d f0 60 a8 2e 16 33 1d 66 cf 58 03 1e |R.,m.`...3.f.X..| +00000170 e8 e5 57 af 23 a6 78 2e 06 a4 ee 7f 73 52 04 73 |..W.#.x.....sR.s| +00000180 67 9a 67 a5 ef 15 ba d6 61 d1 95 65 c0 22 59 8f |g.g.....a..e."Y.| +00000190 f2 ef cc ba 62 4f 75 14 a2 3d 1d 34 0d 06 c8 cb |....bOu..=.4....| +000001a0 dd ca a4 72 d4 b6 4f b4 36 ef c0 46 61 b3 3c 1f |...r..O.6..Fa.<.| +000001b0 04 a6 12 c5 41 88 9d b7 39 23 ca 92 ae 73 7f 36 |....A...9#...s.6| +000001c0 46 ab 3b cd d4 89 12 27 a1 36 1a 35 b3 28 98 3f |F.;....'.6.5.(.?| +000001d0 24 2a 21 5f 7c de 1c c8 68 65 7a 01 13 5b ce 85 |$*!_|...hez..[..| +000001e0 f9 c8 9f f8 0e 34 98 c7 64 63 8e 1f c0 72 5a 33 |.....4..dc...rZ3| +000001f0 43 17 9a 16 b1 78 2d 40 56 4b df 18 66 cf 18 a6 |C....x-@VK..f...| +00000200 05 80 e1 8a b6 1c 67 7e e5 aa 2c 6e 61 92 85 cd |......g~..,na...| +00000210 17 87 09 6a 5d e0 c9 22 ce be de 1c 0c 3d 98 9c |...j]..".....=..| +00000220 1c 55 6f 95 94 0a 75 d1 0a ec 7e 80 db 6d 68 2f |.Uo...u...~..mh/| +00000230 73 7d a5 ee b6 10 79 ed 09 04 33 fe 23 26 9b 4c |s}....y...3.#&.L| +00000240 ab e9 f0 8a 2f bb 7c 73 54 ac 4d e5 a2 1b 2c 22 |..../.|sT.M...,"| +00000250 ac c3 5e 43 28 0c 12 cc c7 9d 81 87 a7 4b 38 09 |..^C(........K8.| +00000260 e5 28 dc 0b 3c aa 4d 13 e3 e6 05 91 71 cd 9c 64 |.(..<.M.....q..d| +00000270 b8 aa d3 99 52 99 7c 00 00 00 64 00 00 00 13 65 |....R.|...d....e| +00000280 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 |cdsa-sha2-nistp2| +00000290 35 36 00 00 00 49 00 00 00 20 77 df ca 22 f4 a3 |56...I... w.."..| +000002a0 86 33 24 22 39 c5 e5 80 22 bf a2 10 ea fc 4a b7 |.3$"9...".....J.| +000002b0 6c 68 06 9b af ac c1 f1 22 11 00 00 00 21 00 d1 |lh......"....!..| +000002c0 e5 47 13 00 d4 23 ad 6c ee 24 c8 85 9c c4 d9 10 |.G...#.l.$......| +000002d0 0b 02 cf b3 b5 af 6d f7 26 f8 38 53 1f 16 18 00 |......m.&.8S....| +000002e0 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +000002f0 00 00 00 00 00 00 00 00 00 00 01 40 e8 ac 64 a0 |...........@..d.| +00000300 6f a8 9a 04 12 e7 4e 5f 10 d2 ca 05 24 f1 b6 ce |o.....N_....$...| +00000310 e4 41 a0 03 48 d4 aa da 23 85 47 b7 81 64 2a 7a |.A..H...#.G..d*z| +00000320 e1 ac 16 2a 7a d9 9d 4f d1 ad 81 37 be 44 8f 9e |...*z..O...7.D..| +00000330 2c 47 58 44 b2 1a 1d 7d 9f 97 e3 96 1e 22 27 fd |,GXD...}....."'.| +00000340 b2 88 8d 5b 28 7e 2d 76 79 21 2e 7a db ea 30 8e |...[(~-vy!.z..0.| +00000350 85 4b 35 bf bc f1 23 7d fe 1d 30 5d ee aa 98 8e |.K5...#}..0]....| +00000360 76 e3 a9 59 f5 ef 5e 68 38 c9 47 84 ae 95 8d 95 |v..Y..^h8.G.....| +00000370 5e eb 29 23 06 d6 dd 87 65 20 98 58 9e 6b 91 8c |^.)#....e .X.k..| +00000380 d6 13 32 8f 74 1f d6 f0 1f 8c fa b0 b2 bb dd 97 |..2.t...........| +00000390 76 37 53 c7 9e 30 af ef 11 f2 5b 66 44 b7 b4 78 |v7S..0....[fD..x| +000003a0 a1 bc ab ce 66 7f b8 09 fd 6f 21 83 96 39 f9 db |....f....o!..9..| +000003b0 45 fa 78 ed 4a ed ec 2d 4f cb 7d a9 22 2c 34 21 |E.x.J..-O.}.",4!| +000003c0 2d ce a0 03 6c 1a 16 f1 03 9d ea 56 72 de 76 0a |-...l......Vr.v.| +000003d0 b6 4d 5d 09 27 79 64 84 31 07 79 15 bd a9 39 b9 |.M].'yd.1.y...9.| +000003e0 91 ba ae 5c af 81 39 9d 2d e0 09 29 f4 b4 4a 83 |...\..9.-..)..J.| +000003f0 25 67 1a 9e d6 46 a5 c1 72 bd 38 d7 eb 98 93 47 |%g...F..r.8....G| +00000400 85 66 5e 27 18 79 c1 4c 1e 28 ec 38 db da 5d 1e |.f^'.y.L.(.8..].| +00000410 f3 a8 28 ec 04 d1 46 0e 70 02 3a dd 38 dc 84 c4 |..(...F.p.:.8...| +00000420 9a 4d 00 d4 5a 5e 43 18 85 51 28 47 40 b5 29 a2 |.M..Z^C..Q(G@.).| +00000430 16 fd 53 6b 1c a4 01 08 5d f5 a2 4c 3d 44 8a 28 |..Sk....]..L=D.(| +00000440 c9 37 5a 62 90 15 36 39 a6 8f ac ff |.7Zb..69....| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 51 26 6b e6 9d c7 16 fd ee f9 |......Q&k.......| +00000010 00 00 00 20 8d b3 7d d6 80 ca f1 af 43 14 33 54 |... ..}.....C.3T| +00000020 6d d1 9f 11 f2 0d 24 9f 35 5f 1f 8e a0 5f b7 cb |m.....$.5_..._..| +00000030 35 a5 7a 73 67 68 07 4f b5 4e f3 da 07 c8 b2 24 |5.zsgh.O.N.....$| +00000040 e0 06 47 c6 |..G.| +>>> Flow 8 (server to client) +00000000 00 00 00 20 14 7e 81 5a 85 57 4a 02 7a e1 0e 85 |... .~.Z.WJ.z...| +00000010 0f 80 d3 38 19 f8 4b df 99 d9 a2 27 b8 bc dc b8 |...8..K....'....| +00000020 ec 8e 4c 27 a2 ae 8d 05 01 40 dd 19 7f 0d 79 5a |..L'.....@....yZ| +00000030 30 08 72 20 |0.r | +>>> Flow 9 (client to server) +00000000 00 00 00 30 ac 45 c9 1a d5 3e fe 78 92 94 9c 43 |...0.E...>.x...C| +00000010 95 e1 bb 3c 72 fc bc 49 f7 53 84 82 cc 1b aa 8f |...>> Flow 10 (server to client) +00000000 00 00 00 20 6a 8d fc 08 05 ea d4 ab 1d 78 9b f5 |... j........x..| +00000010 94 d2 78 7e bd 44 0d ec 51 20 d0 24 29 b0 91 9b |..x~.D..Q .$)...| +00000020 04 cd ba 5b e7 4e 40 a5 0f 3b ae 21 aa aa e1 bf |...[.N@..;.!....| +00000030 78 82 a7 c5 00 00 00 40 32 ec f5 d5 3d d3 0d 48 |x......@2...=..H| +00000040 13 6e ea be dc d5 65 fa 9d 86 67 9f 4f 9f 22 ad |.n....e...g.O.".| +00000050 94 0f cb d4 a1 20 e1 da d0 87 fb b7 78 8c f4 76 |..... ......x..v| +00000060 e0 5d bb 90 37 ed cc 51 fb b2 b1 60 4d 9e 38 06 |.]..7..Q...`M.8.| +00000070 72 21 4a 31 2d 5b 8f 7f 1d 7d 7d 6e 0a c2 0c f8 |r!J1-[...}}n....| +00000080 cb 97 e7 66 b2 74 18 75 |...f.t.u| +>>> Flow 11 (client to server) +00000000 00 00 01 60 21 51 bd 4f 01 fe 7e 6f c3 ee 8f e0 |...`!Q.O..~o....| +00000010 75 9b e1 07 e9 ed 0c 3f c3 18 3d 24 cb 67 c6 1e |u......?..=$.g..| +00000020 28 3f 9c 0e b3 48 e8 a1 2c 69 66 b7 20 ef 18 c3 |(?...H..,if. ...| +00000030 c4 f0 d6 5b 9b e1 f7 ed 7c c7 f6 39 3c 64 1d 73 |...[....|..9| +>>> Flow 12 (server to client) +00000000 00 00 01 40 27 8c ce 9f f2 8d 05 26 fb 68 14 c3 |...@'......&.h..| +00000010 eb 27 a0 81 77 ea 69 da 06 87 19 37 92 6e fa 5d |.'..w.i....7.n.]| +00000020 e9 25 67 d3 88 d6 ae e8 73 7f 06 51 53 30 d1 e2 |.%g.....s..QS0..| +00000030 05 32 ed 62 f4 cd 5e 23 7d a8 0d e7 15 43 61 4f |.2.b..^#}....CaO| +00000040 de ff a0 b4 39 3e 7c 82 65 98 5a c1 fb 25 63 6d |....9>|.e.Z..%cm| +00000050 45 65 56 15 46 2e 92 83 ca 61 b3 4e 9e e1 d2 33 |EeV.F....a.N...3| +00000060 93 a0 01 ec 8f 34 6e c3 e3 dc 5f 98 13 2b 26 a0 |.....4n..._..+&.| +00000070 e2 8f 85 4e f2 ee 67 e2 db bd ce 3d 3e b4 29 37 |...N..g....=>.)7| +00000080 24 3b 82 d6 5a d6 a4 3e 68 bf 7d 99 4a 79 73 29 |$;..Z..>h.}.Jys)| +00000090 05 df 3a 6b 91 c5 0c 36 6e 48 1d 94 33 aa 97 90 |..:k...6nH..3...| +000000a0 78 a0 2e 9e 3c 34 23 fb ec 16 97 72 2c 2a db 74 |x...<4#....r,*.t| +000000b0 70 72 17 48 5e 3c 50 23 53 1e a8 4a 67 c0 94 46 |pr.H^.?h..| +000000d0 70 2c 74 14 b7 db 43 51 f2 f3 af 8e 1e ca eb 74 |p,t...CQ.......t| +000000e0 d3 10 f5 08 bf 40 3a f3 4e 0c 69 b0 5a 88 d0 a0 |.....@:.N.i.Z...| +000000f0 c8 a7 61 16 7a 16 6f 11 2b b1 fa 89 fe 10 f6 d7 |..a.z.o.+.......| +00000100 c6 77 11 d2 f5 bc f1 9f aa 56 22 2b 08 42 14 2b |.w.......V"+.B.+| +00000110 f9 80 68 19 82 4c c2 42 e2 3f a8 30 04 18 e0 06 |..h..L.B.?.0....| +00000120 75 ca 0c 5f 0b d3 3a 9a 85 48 76 76 e6 ad 56 cb |u.._..:..Hvv..V.| +00000130 f3 d1 83 02 62 24 e2 a4 e6 0e aa 68 02 bd 38 e2 |....b$.....h..8.| +00000140 64 db 1e 86 f9 7a b1 54 21 c2 94 e9 b1 65 b7 ed |d....z.T!....e..| +00000150 36 01 ed 22 |6.."| +>>> Flow 13 (client to server) +00000000 00 00 02 80 88 c9 77 4f 84 f5 77 3e 81 77 5d 36 |......wO..w>.w]6| +00000010 43 24 da 9b 3a 2c a8 4d 71 ec 35 89 90 2a 9e d0 |C$..:,.Mq.5..*..| +00000020 85 8f 37 e0 df ab 08 42 2f 45 d3 a9 84 99 ca 37 |..7....B/E.....7| +00000030 81 0e 91 b5 ac bd 85 11 97 d9 2e 5c 9f 48 a2 3b |...........\.H.;| +00000040 14 c8 75 82 a9 df 8d 2c 68 4a 23 89 bc ae 9a 46 |..u....,hJ#....F| +00000050 1a 2a 88 aa 65 56 d4 af b3 98 b4 20 cc 80 a2 5e |.*..eV..... ...^| +00000060 83 3c 2f 2c cc 9b db 2c 41 78 ba 70 26 62 6a b5 |.w.| +000000d0 79 d7 25 66 93 fe 43 4a a8 bd 17 3d be 9f 3a 67 |y.%f..CJ...=..:g| +000000e0 67 c6 be e5 e8 2a 81 b5 19 de ca 7f d1 10 d6 20 |g....*......... | +000000f0 15 76 0b db 3b 66 8e 94 35 e5 d4 f3 9a 0e ab 67 |.v..;f..5......g| +00000100 6b d7 1d d8 d4 7b 86 d4 14 22 01 2e fb 85 24 1f |k....{..."....$.| +00000110 56 59 04 81 35 fe a9 7a a1 dc 08 87 a3 6e 88 81 |VY..5..z.....n..| +00000120 5a d3 75 55 90 8c fb f7 a0 be cf cf bd 0c f5 b1 |Z.uU............| +00000130 e9 17 82 d0 4d 19 82 25 e9 ad 36 5a 74 48 06 a7 |....M..%..6ZtH..| +00000140 99 16 3e ae 15 89 2d 90 27 f4 f4 08 e1 e1 25 6c |..>...-.'.....%l| +00000150 00 7e 83 1a f0 61 56 87 70 46 a2 ab 67 85 05 db |.~...aV.pF..g...| +00000160 70 ac 0e 17 cb 8c 67 2e f7 4f 18 7a 98 ab d2 10 |p.....g..O.z....| +00000170 39 bc e5 cc 77 e3 e3 92 bc 91 a4 70 31 9b 1e fa |9...w......p1...| +00000180 63 be dd e1 ae 51 88 83 92 3b 07 f7 c6 58 6f 43 |c....Q...;...XoC| +00000190 6b c6 e8 22 73 92 eb 98 fe 0a 2c c1 cf 68 e7 8f |k.."s.....,..h..| +000001a0 d0 c8 8d 0a c4 53 81 84 f5 38 87 08 eb f5 da 17 |.....S...8......| +000001b0 74 2d 33 3e 0f 00 ae cc af f6 84 5a 31 68 44 0c |t-3>.......Z1hD.| +000001c0 f7 da db 5c 2e 95 79 e3 20 9c 59 be 3a 07 d5 c1 |...\..y. .Y.:...| +000001d0 70 af 87 c6 05 e0 2d 0d cd a2 70 77 4b db e6 d0 |p.....-...pwK...| +000001e0 4a 18 3c 40 95 b5 09 5e 25 43 e4 db 25 44 a3 44 |J.<@...^%C..%D.D| +000001f0 2a 47 46 e2 57 9a ad 54 70 f5 8e 63 1c 10 ff 24 |*GF.W..Tp..c...$| +00000200 fc 37 30 72 42 5d 41 8f 72 0a 26 77 13 5e 6b 6e |.70rB]A.r.&w.^kn| +00000210 bd d7 54 d5 33 a4 1c 79 57 c4 a7 9a ec 93 fc 87 |..T.3..yW.......| +00000220 1e 62 b8 ae fd a0 2e 16 f6 63 6c dc 9e 2a 13 6c |.b.......cl..*.l| +00000230 ae 62 69 c0 69 b3 91 1c 54 7a ab 17 7d ef f5 af |.bi.i...Tz..}...| +00000240 b2 5b 4f c9 bf 08 c4 ee 6d 0a ec 96 93 54 51 4a |.[O.....m....TQJ| +00000250 e3 51 d7 52 5e eb 62 69 db 99 8b 77 2f e4 3b f7 |.Q.R^.bi...w/.;.| +00000260 c3 ee 42 90 24 b0 69 94 ef 74 38 4a 0f 36 e7 95 |..B.$.i..t8J.6..| +00000270 31 c7 74 e8 34 b5 d4 fc 87 3f 04 e7 7f 0b 28 c2 |1.t.4....?....(.| +00000280 22 2c 81 ec 1b 7e 94 4b ba 03 91 ad d8 6e 4c a5 |",...~.K.....nL.| +00000290 62 9e a2 78 |b..x| +>>> Flow 14 (server to client) +00000000 00 00 00 10 62 11 dc d1 aa fd 23 46 24 10 70 c9 |....b.....#F$.p.| +00000010 b2 d7 41 06 0f d9 21 5f e4 31 3f aa 4c ab 3f 03 |..A...!_.1?.L.?.| +00000020 8d 76 dc 61 |.v.a| diff --git a/ssh/testdata/Client-KEX-mlkem768x25519-sha256 b/ssh/testdata/Client-KEX-mlkem768x25519-sha256 new file mode 100644 index 0000000000..61036dc4e9 --- /dev/null +++ b/ssh/testdata/Client-KEX-mlkem768x25519-sha256 @@ -0,0 +1,431 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 9c 0d 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 3d 6d 6c 6b 65 6d 37 |EPv..>...=mlkem7| +00000020 36 38 78 32 35 35 31 39 2d 73 68 61 32 35 36 2c |68x25519-sha256,| +00000030 65 78 74 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 |ext-info-c,kex-s| +00000040 74 72 69 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e |trict-c-v00@open| +00000050 73 73 68 2e 63 6f 6d 00 00 00 57 65 63 64 73 61 |ssh.com...Wecdsa| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 |-sha2-nistp256,e| +00000070 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 33 |cdsa-sha2-nistp3| +00000080 38 34 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 |84,ecdsa-sha2-ni| +00000090 73 74 70 35 32 31 2c 73 73 68 2d 72 73 61 2c 73 |stp521,ssh-rsa,s| +000000a0 73 68 2d 64 73 73 2c 73 73 68 2d 65 64 32 35 35 |sh-dss,ssh-ed255| +000000b0 31 39 00 00 00 6c 61 65 73 31 32 38 2d 67 63 6d |19...laes128-gcm| +000000c0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000000d0 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |256-gcm@openssh.| +000000e0 63 6f 6d 2c 63 68 61 63 68 61 32 30 2d 70 6f 6c |com,chacha20-pol| +000000f0 79 31 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f |y1305@openssh.co| +00000100 6d 2c 61 65 73 31 32 38 2d 63 74 72 2c 61 65 73 |m,aes128-ctr,aes| +00000110 31 39 32 2d 63 74 72 2c 61 65 73 32 35 36 2d 63 |192-ctr,aes256-c| +00000120 74 72 00 00 00 6c 61 65 73 31 32 38 2d 67 63 6d |tr...laes128-gcm| +00000130 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000140 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |256-gcm@openssh.| +00000150 63 6f 6d 2c 63 68 61 63 68 61 32 30 2d 70 6f 6c |com,chacha20-pol| +00000160 79 31 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f |y1305@openssh.co| +00000170 6d 2c 61 65 73 31 32 38 2d 63 74 72 2c 61 65 73 |m,aes128-ctr,aes| +00000180 31 39 32 2d 63 74 72 2c 61 65 73 32 35 36 2d 63 |192-ctr,aes256-c| +00000190 74 72 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d |tr...nhmac-sha2-| +000001a0 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |256-etm@openssh.| +000001b0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 |com,hmac-sha2-51| +000001c0 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |2-etm@openssh.co| +000001d0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +000001e0 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +000001f0 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 |ac-sha1,hmac-sha| +00000200 31 2d 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 |1-96...nhmac-sha| +00000210 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-256-etm@openss| +00000220 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d |h.com,hmac-sha2-| +00000230 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e |512-etm@openssh.| +00000240 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +00000250 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +00000260 68 6d 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 |hmac-sha1,hmac-s| +00000270 68 61 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 |ha1-96....none..| +00000280 00 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 |..none..........| +00000290 00 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa |....;........n..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 13 87 be 98 05 82 0f cd db cd |................| +00000010 35 d2 89 cd 67 3f 00 00 01 7a 73 6e 74 72 75 70 |5...g?...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 04 cc 06 1e 00 00 04 c0 28 78 86 0d a4 88 |..........(x....| +00000010 c0 a9 3d 09 28 09 86 c8 9f cb 26 34 d4 cb 73 68 |..=.(.....&4..sh| +00000020 11 01 d7 d3 2e 46 7b 3c c6 39 c6 2c a6 7c ad d5 |.....F{<.9.,.|..| +00000030 64 81 c5 1b 56 fc 75 2d 71 42 d6 d3 72 2d 12 7f |d...V.u-qB..r-..| +00000040 25 71 be 48 da 71 6a 82 17 f6 c4 97 e2 bc 91 50 |%q.H.qj........P| +00000050 78 73 b9 5b 4f 73 06 51 bc 24 02 07 ca 6a c2 f7 |xs.[Os.Q.$...j..| +00000060 4a 8b 02 bf df 62 99 0c 1a c2 f0 63 62 94 90 9b |J....b.....cb...| +00000070 3e 63 72 30 61 4c 43 40 27 e6 d2 74 f7 d3 8a 74 |>cr0aLC@'..t...t| +00000080 41 40 ef 67 50 84 06 03 1b 4c 4c a2 64 17 c2 4b |A@.gP....LL.d..K| +00000090 21 53 f4 69 67 50 8d 7c 3a a8 a3 29 27 d8 57 59 |!S.igP.|:..)'.WY| +000000a0 d9 83 c8 15 82 2d 35 b0 51 d7 65 82 3b d4 78 06 |.....-5.Q.e.;.x.| +000000b0 71 70 95 1b ab e3 74 4a 87 2c 51 b3 b8 ae ea 7c |qp....tJ.,Q....|| +000000c0 c9 1a e4 79 2c e3 a2 6b 91 4c b4 14 cf 49 69 90 |...y,..k.L...Ii.| +000000d0 97 60 33 5d e7 28 ca 3a 68 97 9c a5 05 93 43 5e |.`3].(.:h.....C^| +000000e0 0c 05 15 c9 44 2e 25 c4 17 72 04 d3 e6 5c 97 10 |....D.%..r...\..| +000000f0 5a 28 b1 c9 e1 c8 ce 6b b7 4d 28 45 37 f8 35 c8 |Z(.....k.M(E7.5.| +00000100 04 3c cb 66 d1 0a 0f 16 bd 21 7c 42 f5 08 08 7a |.<.f.....!|B...z| +00000110 17 90 1f d8 5e eb 00 a5 8f 21 3e 96 30 65 8c 76 |....^....!>.0e.v| +00000120 40 a2 90 84 06 e9 63 2c 24 74 1c 93 4d 93 11 51 |@.....c,$t..M..Q| +00000130 ff 30 20 41 73 7f 96 94 92 e5 e5 3c 50 31 64 1f |.0 As.......Q;X.H.Yrd..| +00000250 8d a2 7f af 5b 2b 86 69 09 69 12 8b 8e c6 2d e7 |....[+.i.i....-.| +00000260 09 24 48 22 6c 14 96 c7 70 e7 20 c6 26 5c 69 ba |.$H"l...p. .&\i.| +00000270 cb 63 93 6c f6 12 c4 c6 24 42 00 f2 1a bb db 1c |.c.l....$B......| +00000280 3e b7 b2 80 b0 60 25 80 cc 8f 56 63 be 82 40 3c |>....`%...Vc..@<| +00000290 00 c4 b1 90 05 49 91 72 b2 a1 68 59 17 62 2d 68 |.....I.r..hY.b-h| +000002a0 3e 09 6c bc 1e 46 6c c8 5a 57 96 35 1b 82 38 2d |>.l..Fl.ZW.5..8-| +000002b0 42 8a 5c 5d c4 b0 0a 20 51 8a ca 6e 90 89 02 28 |B.\]... Q..n...(| +000002c0 68 34 b7 c6 2e 68 5c 3a e1 48 34 bd ba ab 96 11 |h4...h\:.H4.....| +000002d0 98 f0 58 09 d4 a2 7f ee 59 36 a5 20 57 37 80 a1 |..X.....Y6. W7..| +000002e0 02 4c 96 0e b2 9b 80 c4 7f 1e a6 8e 66 b6 8d 86 |.L..........f...| +000002f0 e9 3d 65 55 48 62 e1 60 62 97 84 03 85 54 b1 e6 |.=eUHb.`b....T..| +00000300 08 75 ea cb 7d 93 5c 3f 48 ba ec c1 52 36 42 ce |.u..}.\?H...R6B.| +00000310 50 74 68 0e b8 43 c9 90 a7 7a e7 28 fc 30 52 74 |Pth..C...z.(.0Rt| +00000320 48 9c 5a 61 5a 9e 62 64 e9 27 27 60 01 04 77 51 |H.ZaZ.bd.''`..wQ| +00000330 11 b9 93 ab c4 e3 85 b8 1a 1b 67 6c 15 6f ba 85 |..........gl.o..| +00000340 39 44 15 26 92 90 bb e0 8a 85 58 3a 44 40 40 83 |9D.&......X:D@@.| +00000350 68 79 65 b7 b0 30 32 c3 cf 3c 52 e1 e0 86 e5 41 |hye..02..>> Flow 6 (server to client) +00000000 00 00 05 44 09 1f 00 00 00 68 00 00 00 13 65 63 |...D.....h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 04 60 4f 59 50 a8 8c d3 ab 46 64 b7 |.....`OYP....Fd.| +00000080 23 0e b0 d0 67 f1 41 e4 41 8d 6a cf 00 b6 87 7c |#...g.A.A.j....|| +00000090 f2 e2 c9 5d 3a f7 ee 69 25 f3 b5 e5 44 ea e6 98 |...]:..i%...D...| +000000a0 39 57 09 1b ee 5b 43 27 6d d8 13 3d 2d 54 10 20 |9W...[C'm..=-T. | +000000b0 d2 27 d9 43 08 4f 9a 57 46 27 31 8f 76 5e ba 40 |.'.C.O.WF'1.v^.@| +000000c0 de f2 83 45 d3 c4 6c 75 cf 6b 0d 8e 79 66 6c a6 |...E..lu.k..yfl.| +000000d0 78 55 e4 f8 75 33 f1 d2 12 59 83 9c bb 97 42 16 |xU..u3...Y....B.| +000000e0 58 61 83 7b 25 30 c9 05 b1 75 f5 7b 84 03 e2 fc |Xa.{%0...u.{....| +000000f0 61 6c 69 8d 16 65 14 9b 4b a0 9c 52 9e 6c 9e 09 |ali..e..K..R.l..| +00000100 2f b7 ac a9 30 2f 10 00 52 f2 e0 a8 71 5a 7a 0b |/...0/..R...qZz.| +00000110 6d e2 1b 42 81 e4 99 43 a2 64 e1 4d 4a 9e dc 2f |m..B...C.d.MJ../| +00000120 f3 1f ab bd b2 f8 21 fd df 74 f7 f4 9d 9a 4c d6 |......!..t....L.| +00000130 5e b7 d3 b3 77 0e ba d2 c5 87 2b 29 ee 1b 6d b2 |^...w.....+)..m.| +00000140 e2 e0 f8 ee 63 39 57 4f db ea ed ea d9 fb de 3a |....c9WO.......:| +00000150 6c 16 67 46 ff 66 c7 fb c6 1c 2b 11 71 d1 73 75 |l.gF.f....+.q.su| +00000160 1d 96 27 0f a3 88 d9 42 af 7d eb 8b ed 3b cb f5 |..'....B.}...;..| +00000170 ad 57 e6 cd ae ee de 4f 2b a6 28 f6 0b ae 4f 82 |.W.....O+.(...O.| +00000180 e3 37 5a e1 c9 1c cd 63 d3 a2 b1 60 29 39 07 0e |.7Z....c...`)9..| +00000190 b6 6e c1 d3 d2 3e 2d cd 33 64 18 bf c0 3b ca cf |.n...>-.3d...;..| +000001a0 22 5f f5 d8 f3 eb 01 d9 93 e8 19 29 78 8a 06 61 |"_.........)x..a| +000001b0 33 02 e5 8d b9 fc b3 e9 f8 e1 fd 65 d0 ac df 78 |3..........e...x| +000001c0 83 e1 9e 4f d8 24 b4 1e a2 04 35 d0 8e 98 8d 28 |...O.$....5....(| +000001d0 62 d9 4a f5 07 c7 25 44 1e ab c3 7c 17 f9 5f fd |b.J...%D...|.._.| +000001e0 4c 12 a0 c7 4d f3 05 ed 79 aa de e9 99 82 30 a2 |L...M...y.....0.| +000001f0 57 f1 a4 da 7d 37 0d 26 39 15 25 41 93 be 9b a6 |W...}7.&9.%A....| +00000200 a5 4c 01 7b 82 18 27 c9 96 cb d8 f5 ce 42 04 9c |.L.{..'......B..| +00000210 83 4f ea 4b 64 00 12 ec 11 86 d7 92 35 e6 c8 e9 |.O.Kd.......5...| +00000220 2c ee f0 ef ed 60 6a dc 80 ec 75 00 1c fb f9 7b |,....`j...u....{| +00000230 3e 32 20 aa 6b 3c 62 69 d0 84 17 c5 77 bc 49 83 |>2 .kI| +00000420 aa 11 c2 53 41 37 c4 48 ad ba 7f 59 59 49 ab 59 |...SA7.H...YYI.Y| +00000430 7c f0 04 32 fa 07 64 23 86 ab d9 5c e0 ef 91 a3 ||..2..d#...\....| +00000440 b0 8c 86 20 dd 3c 4b 26 98 dc 28 3c c6 7c 11 cf |... ..A.N..| +00000580 f3 72 0e 62 ac 2d d2 b1 0b 77 7f 6a 1b da ba af |.r.b.-...w.j....| +00000590 eb d0 0c a6 0d fa 7c ec 3a cf 25 80 82 6a af 3c |......|.:.%..j.<| +000005a0 d8 f4 dc 0b 5a dd af 30 2c 6c f3 a3 50 48 15 0c |....Z..0,l..PH..| +000005b0 50 6f 0e 66 ca a4 af f8 48 58 28 ae 73 af 29 e1 |Po.f....HX(.s.).| +000005c0 50 60 91 41 29 d6 44 28 3b 87 5b 3f 75 5f 2d 3e |P`.A).D(;.[?u_->| +000005d0 b5 ad 02 cd 99 92 32 ae ec d1 2f 38 88 d9 ad 7c |......2.../8...|| +000005e0 1d d5 a0 36 b2 82 b4 f0 88 cd 61 7e 3b 3a c8 42 |...6......a~;:.B| +000005f0 58 34 8e 2c 10 29 2a ac cf 7a 2c 21 76 43 ff 8a |X4.,.)*..z,!vC..| +00000600 8c f6 d6 4b 47 9f ee 57 19 7d cb 63 c4 f9 bb 16 |...KG..W.}.c....| +00000610 a9 47 02 e2 93 94 40 0e 37 f9 82 7f 9d 61 d4 9a |.G....@.7....a..| +00000620 29 fb e5 d5 da 8f 32 1b 89 c2 15 58 84 58 0d 17 |).....2....X.X..| +00000630 e6 6d e1 39 7b 71 d7 4d a5 d7 c7 17 2e 2f e3 07 |.m.9{q.M...../..| +00000640 c9 4f 34 ec 6d 0a 05 81 f8 da bf 2f fb de 90 1d |.O4.m....../....| +00000650 4e 4c 97 6d a6 52 8f 4a 37 63 2e 48 5e 63 7f f5 |NL.m.R.J7c.H^c..| +00000660 68 5b 43 b1 99 a1 51 2d b4 66 a8 d8 47 0e 42 27 |h[C...Q-.f..G.B'| +00000670 d4 70 fa 10 1e f2 6d 13 68 86 0c a0 00 07 0a 76 |.p....m.h......v| +00000680 f3 b9 d8 1e 28 dc d9 76 4a 9d cd b7 99 26 25 62 |....(..vJ....&%b| +00000690 9f 17 43 31 be 91 68 a1 97 03 42 8a db 6b 4f 9a |..C1..h...B..kO.| +000006a0 ed 7e e6 3e 62 11 8e 28 47 e8 49 fe |.~.>b..(G.I.| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 cf ad 76 5f 56 23 47 4d 36 8c |........v_V#GM6.| +00000010 00 00 00 20 47 e3 ba 49 21 aa d2 2e 87 78 d6 95 |... G..I!....x..| +00000020 a7 09 49 c5 fd 45 c1 eb 65 52 ec aa ea 71 c0 a6 |..I..E..eR...q..| +00000030 0e 53 b7 05 e9 96 a7 fd cd cd 84 aa 6f 9c ba d4 |.S..........o...| +00000040 02 8a 20 01 |.. .| +>>> Flow 8 (server to client) +00000000 00 00 00 20 bc a6 26 a0 e1 ce 32 4f a3 26 19 11 |... ..&...2O.&..| +00000010 d4 d5 12 e5 3e 85 08 78 52 81 92 88 6b 83 32 b9 |....>..xR...k.2.| +00000020 3f 76 04 7b 44 c8 da dd 06 4e fc 31 3b 20 4f 15 |?v.{D....N.1; O.| +00000030 01 f0 a4 ed |....| +>>> Flow 9 (client to server) +00000000 00 00 00 30 a9 34 0c fe c5 8b 78 21 68 b5 2f 8b |...0.4....x!h./.| +00000010 7b 69 9c 4e a2 6a dd d0 50 36 d6 01 f9 f4 79 df |{i.N.j..P6....y.| +00000020 e7 25 97 57 09 ca 3b 85 ef fb 6b 90 51 03 ae a4 |.%.W..;...k.Q...| +00000030 f1 65 d0 84 ba 1f 3e c0 02 7f ad d7 38 dc 71 9b |.e....>.....8.q.| +00000040 28 8c 47 db |(.G.| +>>> Flow 10 (server to client) +00000000 00 00 00 20 bb 18 ce a6 b6 00 6d db e7 00 02 3f |... ......m....?| +00000010 5a f5 42 a4 a9 88 15 5f 25 c0 1d fa 0c 35 1b 26 |Z.B...._%....5.&| +00000020 df b0 f5 9c 9b 8b 2f 6f 87 d4 2e 5e e9 a1 07 c8 |....../o...^....| +00000030 83 2e 4a 09 00 00 00 40 30 11 f9 77 34 a1 18 79 |..J....@0..w4..y| +00000040 91 ef 8b 32 f1 e1 8f 41 3c 3a 81 e4 9f 84 c3 c6 |...2...A<:......| +00000050 91 bd a4 74 04 2a dd 1f fb c7 23 30 c9 8a 92 67 |...t.*....#0...g| +00000060 95 40 de 26 08 f6 74 79 52 ad 01 a3 dd d1 97 0f |.@.&..tyR.......| +00000070 9e 84 31 6b 04 f4 ca ff 0a 7b 4f d2 f1 5d a6 dd |..1k.....{O..]..| +00000080 18 f9 39 79 eb 7c 94 19 |..9y.|..| +>>> Flow 11 (client to server) +00000000 00 00 01 60 46 a4 b1 d7 37 fa 1a ed 9c d8 2d 45 |...`F...7.....-E| +00000010 14 db 96 23 10 55 6b f4 b6 bc 41 a3 ae 5e 63 3a |...#.Uk...A..^c:| +00000020 82 a1 bf 7a bb 30 4f 84 4e 5c c6 d2 9e d6 76 3e |...z.0O.N\....v>| +00000030 96 15 82 92 6d 45 1f 08 26 19 9a a0 4d de ac 12 |....mE..&...M...| +00000040 2f 0e f2 7e 38 94 da 1a 82 e4 31 f6 d5 70 1c c5 |/..~8.....1..p..| +00000050 7f 0f f5 af ac b0 a0 86 94 27 ee 9f 68 03 0c a8 |.........'..h...| +00000060 84 f6 fe 0d 20 69 70 66 de 58 12 d1 e5 1f e1 cf |.... ipf.X......| +00000070 ad 8d a2 f6 76 38 be 27 59 23 76 ee eb 9a 48 85 |....v8.'Y#v...H.| +00000080 2d 5a 35 69 08 dc 18 24 41 65 48 5e 69 a7 3c 67 |-Z5i...$AeH^i.>> Flow 12 (server to client) +00000000 00 00 01 40 d8 f3 ab e8 5a 68 2b 87 69 2f 89 82 |...@....Zh+.i/..| +00000010 79 d4 49 5f cb 3d d5 e9 c9 62 8f 0c 03 ef e3 33 |y.I_.=...b.....3| +00000020 6a 40 a0 5c 80 7e 36 b9 0c 21 28 ec 61 9f fa ac |j@.\.~6..!(.a...| +00000030 7b 6f 2a 1b e2 79 05 40 d5 be 16 3a 34 16 c7 aa |{o*..y.@...:4...| +00000040 e2 ff 96 6f fe c0 ca e9 c4 56 5c 0e 28 15 51 9d |...o.....V\.(.Q.| +00000050 e7 7b 34 d8 e4 87 cc 92 f7 38 10 87 79 9d 96 de |.{4......8..y...| +00000060 0c 26 81 d3 e2 14 12 ce 09 3c 8a a7 c2 86 7e 9a |.&.......<....~.| +00000070 64 35 71 8e 37 43 0c 82 ba bf 99 09 76 d0 1e 3e |d5q.7C......v..>| +00000080 7b 07 c3 3f e3 3a 87 b2 e6 56 de c7 30 c5 a6 1e |{..?.:...V..0...| +00000090 1f 15 9f 38 67 94 12 6c de a9 ae e6 42 fa 00 31 |...8g..l....B..1| +000000a0 2a 7f c3 39 fb a3 d0 60 26 ac d9 3f 10 5f c6 28 |*..9...`&..?._.(| +000000b0 49 eb ca 1f 51 b9 9d 6a f8 ab 51 80 71 99 77 28 |I...Q..j..Q.q.w(| +000000c0 40 21 64 6e 57 9a ea d1 56 ea 7a 34 dd 07 4b d4 |@!dnW...V.z4..K.| +000000d0 e0 ba 3c 1a 91 61 92 45 01 00 2c 97 87 3c 67 66 |..<..a.E..,..>> Flow 13 (client to server) +00000000 00 00 02 80 73 df 7a c3 c6 df 0c 86 29 85 09 e5 |....s.z.....)...| +00000010 49 43 1c f6 90 e3 e3 10 33 95 3b ab 9c 66 c5 db |IC......3.;..f..| +00000020 cb ed 75 99 c8 1e a8 e2 6c 23 81 c3 62 14 2c 46 |..u.....l#..b.,F| +00000030 43 84 76 e4 2f 9b f3 05 2e 75 0a 6a a6 09 50 8c |C.v./....u.j..P.| +00000040 54 53 61 05 ec 41 7e 66 e4 74 36 1d 59 78 79 43 |TSa..A~f.t6.YxyC| +00000050 ea 35 21 fc 14 3d d1 83 ed 48 95 60 5c f3 82 4f |.5!..=...H.`\..O| +00000060 03 a9 6d 37 2e f7 e5 e6 ea 65 db e8 36 05 4a fa |..m7.....e..6.J.| +00000070 44 c4 04 a0 41 a7 7f 3f 98 f1 91 6f d5 3c 00 57 |D...A..?...o.<.W| +00000080 0f 4a 65 e6 5e 9a 9d fd db c9 93 48 52 50 ad f9 |.Je.^......HRP..| +00000090 73 77 71 f9 f7 89 df 51 e9 1c ed 59 aa 33 57 93 |swq....Q...Y.3W.| +000000a0 6c d0 3f 71 6f 9d 88 34 cd f9 39 8c a3 eb 22 ea |l.?qo..4..9...".| +000000b0 d0 9d 04 f4 83 80 3c 27 5b 77 22 6c 69 15 10 c5 |......<'[w"li...| +000000c0 e0 6b 3c 70 52 7d 06 b6 6d 86 6c c5 df 24 1a f1 |.k.......gl| +000000e0 ac 4c b6 ce ab a7 a6 87 81 de 42 67 40 dc 1d bc |.L........Bg@...| +000000f0 c7 0c 57 c7 f1 8b b5 6e 2c d8 b1 9a 35 79 e4 c3 |..W....n,...5y..| +00000100 7f 3e 1f 83 c2 b3 db 7e 89 b7 9b 7f 7a 0b 1e 41 |.>.....~....z..A| +00000110 fd 13 65 bb 25 cd 95 2f c8 e3 6e 77 00 b0 dd 45 |..e.%../..nw...E| +00000120 34 17 4c 98 23 9e b0 e4 b6 2d 5f 98 e3 2a 36 73 |4.L.#....-_..*6s| +00000130 bd 37 da 23 7b d2 4b d8 c4 71 61 35 21 35 3a b2 |.7.#{.K..qa5!5:.| +00000140 c1 d5 64 72 90 ee 68 20 f8 49 e5 a0 b2 95 63 fe |..dr..h .I....c.| +00000150 df ab 21 eb 55 e4 df 57 22 cc 6e 6a e0 bd 20 90 |..!.U..W".nj.. .| +00000160 72 06 b8 da 3a ec 71 0a 53 4d 92 3d 57 db 0e 6c |r...:.q.SM.=W..l| +00000170 13 71 31 8f b5 73 56 5f 1c a7 d8 c3 88 04 e4 d2 |.q1..sV_........| +00000180 1e f1 3f 64 7e 5e 48 a1 dd 11 ea 9e 7f dc 8f 9a |..?d~^H.........| +00000190 ab dd 77 96 c3 d8 8f d5 22 82 74 29 90 fa 80 85 |..w.....".t)....| +000001a0 a7 4f df c0 e2 77 a9 d7 3c ff ae 15 1f ed c1 56 |.O...w..<......V| +000001b0 bf a0 e6 11 f6 89 6a 5c 7e 91 56 e3 10 e7 67 1c |......j\~.V...g.| +000001c0 b0 84 8e 77 8f 3b 94 10 99 2d c3 8b 5b bb 97 89 |...w.;...-..[...| +000001d0 83 f9 e3 78 92 84 45 f6 3f 10 57 e1 21 cb 23 97 |...x..E.?.W.!.#.| +000001e0 c2 97 e9 05 d6 70 6d 91 a3 75 5e 81 03 ba 4e 74 |.....pm..u^...Nt| +000001f0 2a 51 9e bd dc 67 f0 2b 73 4d b8 51 46 e6 82 e8 |*Q...g.+sM.QF...| +00000200 15 e9 d4 31 9d fd 46 18 2d ab 89 9a e7 2c 94 01 |...1..F.-....,..| +00000210 f4 61 53 d3 18 15 3f 1b 31 c7 40 44 df 89 6d df |.aS...?.1.@D..m.| +00000220 e7 df a3 dd 69 a7 61 d4 d4 c9 2c 84 07 80 1d e9 |....i.a...,.....| +00000230 8c e5 de a4 60 25 39 35 95 c9 af a1 37 ef 28 8f |....`%95....7.(.| +00000240 2a 1a c1 59 e3 7a ac 77 77 82 43 0e 9a 15 f4 40 |*..Y.z.ww.C....@| +00000250 1d 2c 26 2e 59 4a 9d 1b c0 4e 18 f3 a5 cb 32 8d |.,&.YJ...N....2.| +00000260 a3 7d da d6 77 fc 1a 45 17 f0 05 80 dc 4b 23 71 |.}..w..E.....K#q| +00000270 45 0d 0c c5 52 0c c5 0e 0b 26 0d 9a 83 2a 55 22 |E...R....&...*U"| +00000280 7e c7 da ca b6 37 1e 14 8b 5a 66 da 3d 6f 0d c7 |~....7...Zf.=o..| +00000290 f4 2b d9 87 |.+..| +>>> Flow 14 (server to client) +00000000 00 00 00 10 0f f7 b8 2d e5 e0 1a 69 67 73 61 5a |.......-...igsaZ| +00000010 7a fe 3d 4f d7 3a d6 50 cc 3f 21 32 2a d1 64 82 |z.=O.:.P.?!2*.d.| +00000020 b8 fb d6 31 |...1| diff --git a/ssh/testdata/Client-MAC-hmac-sha1 b/ssh/testdata/Client-MAC-hmac-sha1 new file mode 100644 index 0000000000..5bf2a2d18c --- /dev/null +++ b/ssh/testdata/Client-MAC-hmac-sha1 @@ -0,0 +1,285 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 5c 0b 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 09 68 6d 61 63 2d 73 68 61 31 00 00 00 09 68 |..hmac-sha1....h| +00000230 6d 61 63 2d 73 68 61 31 00 00 00 04 6e 6f 6e 65 |mac-sha1....none| +00000240 00 00 00 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 |....none........| +00000250 00 00 00 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e |......;........n| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 e9 cb 41 9a 90 81 ba 92 0e 19 |........A.......| +00000010 be 4a 95 d9 4c 20 00 00 01 7a 73 6e 74 72 75 70 |.J..L ...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 90 43 9e 5f db 35 |...,..... .C._.5| +00000010 6a 06 dc ee c2 cb 5b 73 c3 9a ad 63 f4 e8 c5 c6 |j.....[s...c....| +00000020 60 0e 6b 6d 49 93 ea 68 c0 26 e3 f9 ae 57 e2 35 |`.kmI..h.&...W.5| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 fd 1d b1 2f 12 02 cc da 86 7b |..... .../.....{| +00000080 19 49 89 38 e4 41 77 d6 1d f3 59 8e 06 ca 66 d4 |.I.8.Aw...Y...f.| +00000090 45 d4 20 a6 ca 5d 00 00 00 64 00 00 00 13 65 63 |E. ..]...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 8c 55 68 1e 48 68 |6...I...!..Uh.Hh| +000000c0 44 4f c9 c4 ef ce 2c 51 2b 5d 41 d5 79 6f cd c7 |DO....,Q+]A.yo..| +000000d0 78 52 b1 fe d3 4b 78 74 37 85 00 00 00 20 37 68 |xR...Kxt7.... 7h| +000000e0 52 2a b5 58 67 48 1c 2e 9f ba ec 7f d7 e4 08 84 |R*.XgH..........| +000000f0 c6 51 0e 13 33 26 10 5c 1f 5d 08 ea 67 50 00 00 |.Q..3&.\.]..gP..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 ba d2 50 93 |...........@..P.| +00000120 7b 59 49 97 a9 87 f0 35 ae 63 5f 78 17 05 a5 02 |{YI....5.c_x....| +00000130 ac 12 05 c6 09 09 56 ec 88 5f ac a7 61 77 62 d5 |......V.._..awb.| +00000140 87 b8 5e 41 3e 0b 02 48 46 60 50 4f 52 1c fb 55 |..^A>..HF`POR..U| +00000150 3c a3 1e 14 21 30 b2 b7 81 7d 32 37 c3 27 bb 57 |<...!0...}27.'.W| +00000160 0d cd 72 34 b9 6d c9 90 f6 0e ed 0a f3 19 f0 90 |..r4.m..........| +00000170 70 12 68 d3 c3 69 24 94 e7 87 d2 58 26 16 8e 8c |p.h..i$....X&...| +00000180 bd bf 1d 39 8a d9 f5 66 59 b4 f1 ac 96 ef 38 f7 |...9...fY.....8.| +00000190 56 c9 f0 40 76 98 a3 19 4b 9c d5 5f a9 c7 53 59 |V..@v...K.._..SY| +000001a0 81 58 9f 70 72 b2 31 56 c1 1e ab 89 0b a1 c6 b7 |.X.pr.1V........| +000001b0 23 7d c2 fc a8 00 7d 0b 85 9c e6 0c 18 f7 65 9f |#}....}.......e.| +000001c0 59 f5 b9 23 50 80 ca 79 ee e5 a1 12 6f 79 d6 4d |Y..#P..y....oy.M| +000001d0 32 91 da 53 60 85 f8 ed 68 cb 7a 27 9a ce c6 cc |2..S`...h.z'....| +000001e0 77 9e 0f 0e f9 13 80 74 fc f4 4b 28 5a 9b 6a 15 |w......t..K(Z.j.| +000001f0 ac a0 5e 04 60 67 e1 87 3e 50 d6 52 fc 4d 9e 3c |..^.`g..>P.R.M.<| +00000200 77 2f 31 60 c8 12 f1 59 74 30 01 9e 9c d6 c6 e4 |w/1`...Yt0......| +00000210 62 f8 eb de ff c8 d6 98 10 1f 54 69 2d 1d ae ce |b.........Ti-...| +00000220 f9 94 e6 ec cc 3c 3b c0 68 96 a7 28 8f 8f 39 0a |.....<;.h..(..9.| +00000230 1e 46 4f f1 5d 05 6b 99 d9 e2 0e f3 58 16 78 7b |.FO.].k.....X.x{| +00000240 9d 5f 62 06 c9 1b 35 de 1d 4d c2 fd e0 b5 d7 c4 |._b...5..M......| +00000250 a2 73 b7 fc 5d b9 73 33 f8 49 41 3f 87 1d 0d 48 |.s..].s3.IA?...H| +00000260 4a d2 32 d5 2a c3 36 87 0e 1e 00 30 |J.2.*.6....0| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 b8 cc 87 3c 23 dc 62 b8 d2 60 |.........<#.b..`| +00000010 00 00 00 20 23 ea f8 14 49 04 74 f5 66 c2 8e 5c |... #...I.t.f..\| +00000020 ef bc 31 df db a5 b4 90 d7 76 dc 8a 2a 45 30 2e |..1......v..*E0.| +00000030 c7 9f d3 7f 3b 9d c6 eb 95 56 60 f4 99 4a e1 07 |....;....V`..J..| +00000040 ad 0e 64 9a |..d.| +>>> Flow 8 (server to client) +00000000 00 00 00 20 9a 2a d0 a9 2a 53 17 f3 8e 87 2c 42 |... .*..*S....,B| +00000010 2d 71 70 57 e9 16 81 63 27 46 7c a2 16 97 a7 d7 |-qpW...c'F|.....| +00000020 2c cd ba a0 86 f5 4b 20 a6 f0 d2 89 68 64 ef 14 |,.....K ....hd..| +00000030 2b a9 26 f2 |+.&.| +>>> Flow 9 (client to server) +00000000 00 00 00 30 6e 5b 35 1d 7b 3d d3 15 b0 55 94 25 |...0n[5.{=...U.%| +00000010 f9 25 29 cc cb 9d d1 24 ab 9f b9 f6 84 11 01 e3 |.%)....$........| +00000020 73 cf d2 30 88 75 7a 66 57 d9 fb 12 7c 88 6c f1 |s..0.uzfW...|.l.| +00000030 0c 74 16 04 21 35 6e 45 56 6a f5 cb 53 92 4b ef |.t..!5nEVj..S.K.| +00000040 c9 98 05 ec |....| +>>> Flow 10 (server to client) +00000000 00 00 00 20 6d 1e b1 6a c6 34 ac 7d e5 c9 0c ad |... m..j.4.}....| +00000010 6d 76 c8 64 e0 97 08 3a 86 0c 0e e5 3c 80 f9 fd |mv.d...:....<...| +00000020 61 bb eb 51 6d 0d 8d 0c c3 3f 65 a6 53 a8 48 6f |a..Qm....?e.S.Ho| +00000030 31 29 e7 d6 00 00 00 40 1d ea 5e 15 62 ae b2 af |1).....@..^.b...| +00000040 54 01 a1 cd c3 e7 5d 40 e2 94 e6 d9 27 93 b6 ac |T.....]@....'...| +00000050 fc a7 37 43 c6 d6 b5 91 07 7e 20 0f 35 40 46 69 |..7C.....~ .5@Fi| +00000060 7b d2 f6 9b dc 95 ba bc fe 85 ae 93 f4 f1 61 78 |{.............ax| +00000070 c3 9d a1 ac 5a ab fc 49 4b 36 48 90 e5 e1 a9 29 |....Z..IK6H....)| +00000080 78 5b 1e 41 5c 5d f6 20 |x[.A\]. | +>>> Flow 11 (client to server) +00000000 00 00 01 60 ac 56 a1 af 43 27 43 fc ed 11 9a 4f |...`.V..C'C....O| +00000010 04 45 a6 90 cc f4 0a 53 12 7e c7 91 de 9c 00 1f |.E.....S.~......| +00000020 42 33 db 71 50 c3 66 ca f4 04 3e 7e 31 62 48 2f |B3.qP.f...>~1bH/| +00000030 ea cf 63 1e 6d b5 0e aa 1e 12 81 df d6 17 e5 3b |..c.m..........;| +00000040 fe b1 6b 8d ee 49 90 0d cf 7c 07 1a 17 06 0d 3b |..k..I...|.....;| +00000050 fc f5 71 ef 09 5e 3a 34 e4 fe 5c b5 42 16 6d 92 |..q..^:4..\.B.m.| +00000060 05 bc 9a 04 70 1c 3b 14 70 d9 25 6d 6d 72 1c c0 |....p.;.p.%mmr..| +00000070 54 be 28 49 17 ed 4c dc 78 4b f5 6b ba 76 6a 6c |T.(I..L.xK.k.vjl| +00000080 14 16 36 dd 26 f7 07 d1 0d f6 a0 49 2a 33 67 94 |..6.&......I*3g.| +00000090 b6 96 1a a3 d1 58 89 a5 46 2d 16 7e 19 66 b7 9c |.....X..F-.~.f..| +000000a0 d2 e3 19 f0 54 d6 04 54 dc 6a 37 b3 e8 08 a9 41 |....T..T.j7....A| +000000b0 27 69 ce 23 f4 aa f8 98 3e 02 d4 b3 e8 3b 69 0b |'i.#....>....;i.| +000000c0 0a 1a 4e 2e 78 2a 85 a6 6d a0 d9 70 45 13 d6 75 |..N.x*..m..pE..u| +000000d0 b6 f6 a5 7b 6a 9a 96 33 e7 c9 17 9d 8d 57 88 1c |...{j..3.....W..| +000000e0 7f 00 4c af 87 ca 27 ec 96 70 db b9 2f cf ec 75 |..L...'..p../..u| +000000f0 72 41 e2 f8 00 03 89 95 bc 69 c3 25 a5 20 88 74 |rA.......i.%. .t| +00000100 b6 e4 55 32 15 b4 50 2c 58 c9 ad 78 45 d9 3a 20 |..U2..P,X..xE.: | +00000110 85 c3 e3 ea 49 98 1d 0f 41 95 15 30 7c 75 6e 70 |....I...A..0|unp| +00000120 c6 b0 c1 55 61 97 22 4d d7 8d 26 33 8b 0e eb 69 |...Ua."M..&3...i| +00000130 fd 02 33 d5 17 74 63 3c b7 41 79 dd 91 54 0b bc |..3..tc<.Ay..T..| +00000140 9a ab ba 65 54 ce 49 69 29 e8 88 2a 92 b9 4f 58 |...eT.Ii)..*..OX| +00000150 fb 13 d5 ee d4 bc 41 ac df 90 f2 61 55 0c 99 4e |......A....aU..N| +00000160 43 f2 a3 1e 35 a0 54 16 a6 c9 18 c3 2e 30 9d 79 |C...5.T......0.y| +00000170 7c 0b ec b0 ||...| +>>> Flow 12 (server to client) +00000000 00 00 01 40 34 79 ba dd 20 7e 67 11 41 80 29 06 |...@4y.. ~g.A.).| +00000010 d4 7c 14 87 79 a0 1f cb d6 bb 90 ee 9e 91 b8 77 |.|..y..........w| +00000020 57 23 fe 4c 66 74 db f0 60 b9 cb 3b 87 ba 0e 3b |W#.Lft..`..;...;| +00000030 27 1d e7 67 2e be 2d db a4 c9 15 d8 d1 1c 91 f3 |'..g..-.........| +00000040 02 b7 8c 1d 52 04 75 1e 6c 58 a6 b0 28 a8 1e db |....R.u.lX..(...| +00000050 9a e1 d4 82 29 dd ab 24 24 c2 3f 50 ed 9d d8 8a |....)..$$.?P....| +00000060 75 b0 a0 66 eb 00 b7 fb 54 99 ff 53 83 e4 8c e9 |u..f....T..S....| +00000070 23 09 17 37 0c ed 22 f9 cf f4 ce 31 3d 88 30 54 |#..7.."....1=.0T| +00000080 dd 56 40 53 51 a7 f2 4e 69 65 2c 32 a1 ed 75 18 |.V@SQ..Nie,2..u.| +00000090 e3 fc 13 ca 79 9d d4 07 3d fa eb aa 1c af 78 7b |....y...=.....x{| +000000a0 60 4f ca 0b 58 32 cd b0 67 c9 90 e8 99 56 47 98 |`O..X2..g....VG.| +000000b0 47 bf 9e a1 02 e4 83 b4 48 cf 01 65 a9 b7 43 aa |G.......H..e..C.| +000000c0 8d 63 68 19 cb 24 c9 0c 3c bd e1 3a 51 db c5 1e |.ch..$..<..:Q...| +000000d0 a2 bf 80 1d a8 33 71 d7 7e e8 13 0b 00 d7 76 2d |.....3q.~.....v-| +000000e0 01 ba d7 2c 05 b8 9e a4 a7 82 3f 49 83 c9 31 b6 |...,......?I..1.| +000000f0 d1 2f 0d a2 f1 cc c6 18 de cf 62 03 93 30 12 15 |./........b..0..| +00000100 0b 3c ab 6a 98 45 0b 97 51 17 7e d1 d2 a1 eb d7 |.<.j.E..Q.~.....| +00000110 9c 96 13 ba 4c db 48 e3 4e ee 4a 9b 27 b2 c2 87 |....L.H.N.J.'...| +00000120 c0 95 21 09 d4 85 e2 40 b9 1c 70 02 15 02 bb 96 |..!....@..p.....| +00000130 48 a9 d6 56 33 e0 9e c2 82 bb ea fe 3d 04 7d c4 |H..V3.......=.}.| +00000140 a2 5f 9d 49 c2 36 6f 33 77 1f 30 e7 4d 88 59 bb |._.I.6o3w.0.M.Y.| +00000150 ca 3b f3 9c |.;..| +>>> Flow 13 (client to server) +00000000 00 00 02 80 cd d3 42 80 d7 90 70 d5 7d 57 31 29 |......B...p.}W1)| +00000010 a0 f5 02 d2 dd 48 eb f3 d3 29 ba b2 30 62 a5 00 |.....H...)..0b..| +00000020 aa 04 03 0b e5 8e 87 49 a3 e6 48 63 3c c5 c6 50 |.......I..Hc<..P| +00000030 b0 87 60 68 c8 da cf 06 c3 39 60 e6 51 a5 67 1f |..`h.....9`.Q.g.| +00000040 71 8a c2 f3 a6 63 26 6a f9 1b 22 28 92 d6 58 ac |q....c&j.."(..X.| +00000050 e7 6f c7 11 01 3f e4 26 2c b9 47 26 a1 60 c4 5e |.o...?.&,.G&.`.^| +00000060 76 4e 66 5d 55 a2 4a cf 45 84 7c b4 ae 27 3e 71 |vNf]U.J.E.|..'>q| +00000070 dd 5a ca 60 15 08 f1 51 5a 70 96 21 b7 fc 06 23 |.Z.`...QZp.!...#| +00000080 32 1f f4 4a 58 66 d3 2e 55 24 fc 5d 59 ad 65 dd |2..JXf..U$.]Y.e.| +00000090 d5 47 4e 47 40 04 43 be 5c d5 87 92 22 c8 21 a7 |.GNG@.C.\...".!.| +000000a0 d8 1a ca 88 51 80 88 d5 2a 1c 93 fc 3b 70 6e b9 |....Q...*...;pn.| +000000b0 a0 ca 65 ff 5c ad 9d 49 65 66 77 e2 32 2d 18 82 |..e.\..Iefw.2-..| +000000c0 16 a6 83 00 9d 9e db 8f 1b 77 0b 0e 37 50 a8 de |.........w..7P..| +000000d0 ee e0 33 48 a3 01 bb 82 13 58 b6 8b f1 bc 05 10 |..3H.....X......| +000000e0 7e 6d c1 4b c6 8f 2b cd aa 49 58 c8 4a 02 3e 8c |~m.K..+..IX.J.>.| +000000f0 20 51 41 64 f0 ff 1a 46 fd 3f b3 f7 19 9f aa 50 | QAd...F.?.....P| +00000100 48 bd 64 6f ef e1 14 55 55 10 ae d7 da fe 4e 9e |H.do...UU.....N.| +00000110 0b f1 19 da 9e ae c2 f6 b6 ff 23 17 e6 3a 3c 40 |..........#..:<@| +00000120 8a 99 bc 51 62 3e 67 80 03 d7 38 7e f3 70 ef 2d |...Qb>g...8~.p.-| +00000130 30 c9 ff bc fd 19 fe b7 46 08 cc c0 63 31 24 00 |0.......F...c1$.| +00000140 e9 d5 a4 f2 5f 4d ae f4 f1 d7 ac f7 49 bb 01 b2 |...._M......I...| +00000150 21 77 17 7e 19 a0 15 d9 cc 72 36 13 e0 b2 51 7f |!w.~.....r6...Q.| +00000160 51 2f 64 c9 f1 45 ed fb 7e 8e 13 49 8b ba 8f 72 |Q/d..E..~..I...r| +00000170 94 0a d6 30 6c 40 01 75 2d e1 2b 63 8d cc 73 ce |...0l@.u-.+c..s.| +00000180 da 36 16 cf 5f 28 ef 5f ef 06 ed 08 11 2e 80 11 |.6.._(._........| +00000190 19 42 e0 ea 4e ce 3c e5 78 ea c0 fa 11 17 d1 6f |.B..N.<.x......o| +000001a0 ca 62 aa 49 b1 8a 86 a4 c8 4f 03 e6 b6 92 7f 0e |.b.I.....O......| +000001b0 e5 6d 21 60 44 7a d6 c7 13 9b 56 99 bd 8a d1 93 |.m!`Dz....V.....| +000001c0 64 13 ad 0e 89 27 46 ef a4 b9 59 18 79 a9 82 ac |d....'F...Y.y...| +000001d0 cb d4 50 0d fd af a3 a8 c3 49 26 09 3c 22 e8 fb |..P......I&.<"..| +000001e0 ca 54 94 6a 78 fd 58 c4 08 99 0d b7 c0 ef 76 c1 |.T.jx.X.......v.| +000001f0 14 41 aa 63 e5 f9 35 cc 62 93 1b fb fa be 08 98 |.A.c..5.b.......| +00000200 44 2b 98 d0 dd e1 74 47 b7 d1 2d 51 60 cd ec 91 |D+....tG..-Q`...| +00000210 94 fa 53 0f dd 50 c0 67 10 e1 96 70 01 f0 b7 0b |..S..P.g...p....| +00000220 a6 83 d8 aa a4 ca e1 26 b7 37 a7 4e 22 43 43 80 |.......&.7.N"CC.| +00000230 75 f7 ab 50 0e 91 18 68 a7 bb 84 b6 84 01 05 1a |u..P...h........| +00000240 f7 69 29 68 61 8e 18 66 2f 44 73 6a aa 22 e8 cf |.i)ha..f/Dsj."..| +00000250 cc 22 48 d9 ea 74 76 e1 3a 87 ca 2e bd d9 9f 81 |."H..tv.:.......| +00000260 94 85 b0 c7 0b 1b ab 62 f0 62 18 b1 e8 6e af e5 |.......b.b...n..| +00000270 2f ec 4a 0a cc 18 10 6f 98 a6 91 de 5c 27 eb 3f |/.J....o....\'.?| +00000280 c5 d1 12 8c 4c 61 14 c4 87 44 44 53 09 a5 bf e7 |....La...DDS....| +00000290 5d 85 31 ff |].1.| +>>> Flow 14 (server to client) +00000000 00 00 00 10 b7 a2 15 df 62 f7 15 b4 d9 01 8f d5 |........b.......| +00000010 bc ef ae 73 43 7e 07 ca 16 9a 23 5e 03 8c 2e 60 |...sC~....#^...`| +00000020 d5 4f c2 8a |.O..| diff --git a/ssh/testdata/Client-MAC-hmac-sha1-96 b/ssh/testdata/Client-MAC-hmac-sha1-96 new file mode 100644 index 0000000000..e1c8765d41 --- /dev/null +++ b/ssh/testdata/Client-MAC-hmac-sha1-96 @@ -0,0 +1,285 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 5c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 0c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |..hmac-sha1-96..| +00000230 00 0c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |..hmac-sha1-96..| +00000240 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000250 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 b7 1e 80 3a dc 44 00 ea 1a 26 |.........:.D...&| +00000010 29 27 0e ab 98 ce 00 00 01 7a 73 6e 74 72 75 70 |)'.......zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 13 cf b6 0f c2 c9 |...,..... ......| +00000010 08 d9 7b f6 60 d4 53 7f 4b b1 29 37 59 98 3c dd |..{.`.S.K.)7Y.<.| +00000020 ab b1 51 12 94 92 eb 56 4c 6f e8 a3 63 9c a8 a1 |..Q....VLo..c...| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 42 6c f8 55 48 c4 d4 0b 3e 3c |..... Bl.UH...><| +00000080 12 07 f1 fb 36 f7 93 b6 a4 90 0f 61 fe 05 e1 df |....6......a....| +00000090 76 07 79 15 a8 67 00 00 00 64 00 00 00 13 65 63 |v.y..g...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 21 00 cc fe 10 cb a4 a5 |6...I...!.......| +000000c0 f2 94 6b 44 1b 58 f7 19 07 0d ff 6f 01 8f cf 93 |..kD.X.....o....| +000000d0 cb 10 9b 7f 37 91 28 73 f5 24 00 00 00 20 6f aa |....7.(s.$... o.| +000000e0 57 5a 24 07 c4 a6 52 ff a0 b1 b0 97 5b fe c3 e5 |WZ$...R.....[...| +000000f0 a8 48 95 ab 52 53 0e 17 4c 5a b3 5a 6e 25 00 00 |.H..RS..LZ.Zn%..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 62 fa 6f 58 |...........@b.oX| +00000120 cb d7 e3 9b 26 43 95 cb 22 91 ef 32 74 52 00 98 |....&C.."..2tR..| +00000130 bc ac a5 60 e6 6c bf 5e 78 26 e2 ca 60 5f 19 c6 |...`.l.^x&..`_..| +00000140 80 f1 bb b2 f0 27 b2 7a 5a 06 62 3d e3 49 59 47 |.....'.zZ.b=.IYG| +00000150 38 2e a3 3b bb dc bc e4 f3 e4 4d 6c 4b 8d ce a2 |8..;......MlK...| +00000160 bd a0 f4 c4 c1 11 93 1f a2 82 52 c0 f7 43 63 d2 |..........R..Cc.| +00000170 b9 c6 a6 16 c1 7c 6a 4d 94 85 3f fd fb f0 04 d9 |.....|jM..?.....| +00000180 60 64 29 9c 87 d8 7d b7 39 60 6b 4d 71 be ca f8 |`d)...}.9`kMq...| +00000190 03 4c c7 2f 03 a5 c1 35 2b e8 40 9c fc 4b f9 04 |.L./...5+.@..K..| +000001a0 38 88 be e1 86 7f 84 c6 b7 41 64 bc 63 60 75 6f |8........Ad.c`uo| +000001b0 53 05 78 b1 cd 2b fd 36 80 2a cc aa 14 2e ce c2 |S.x..+.6.*......| +000001c0 a6 93 21 d7 da f0 59 1d d7 07 6a a8 64 47 12 c8 |..!...Y...j.dG..| +000001d0 4c a4 fb 48 66 5c c3 60 0f 3c b8 00 69 41 cb 6a |L..Hf\.`.<..iA.j| +000001e0 17 e7 4f 44 80 ea 01 53 e4 c6 12 0e 60 8d 3a 9d |..OD...S....`.:.| +000001f0 1b ee 6d 6e 96 f2 a4 72 b1 c4 ef e7 cb c8 dd 95 |..mn...r........| +00000200 7b 73 3b 1f 83 7e 6e 01 2b 22 09 a2 e6 e0 70 c0 |{s;..~n.+"....p.| +00000210 11 34 b3 25 31 8e 68 be 5a c8 b9 5e f5 ea bf 18 |.4.%1.h.Z..^....| +00000220 6d 34 6d 63 00 56 63 ff 40 cd be db 92 17 06 8e |m4mc.Vc.@.......| +00000230 83 67 53 88 a4 8e 23 09 2d 77 93 b7 8f 50 b0 62 |.gS...#.-w...P.b| +00000240 08 01 5c 95 1c 7b e6 1b 22 e5 9d 87 88 ca a7 3b |..\..{.."......;| +00000250 79 c1 42 4b 78 fb b7 3c 7c 0d 16 2b 97 a2 48 49 |y.BKx..<|..+..HI| +00000260 01 f2 62 0d 97 30 30 97 60 6c b1 0b |..b..00.`l..| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 e3 f9 ae 57 e2 35 b8 cc 87 3c |.........W.5...<| +00000010 00 00 00 20 42 19 a8 33 98 e6 4c 26 c0 59 6b 23 |... B..3..L&.Yk#| +00000020 26 d4 32 01 de 8d 77 48 c8 0a 32 7d 56 9f 0a f5 |&.2...wH..2}V...| +00000030 44 f3 17 93 e8 7f cf 49 aa 71 2c 28 b6 36 47 3c |D......I.q,(.6G<| +00000040 88 5b 2d 05 |.[-.| +>>> Flow 8 (server to client) +00000000 00 00 00 20 4a 2b 22 75 04 04 2f cc 8d 24 da e3 |... J+"u../..$..| +00000010 96 86 dd 73 07 f6 31 a1 d3 02 a5 9f f9 08 4c fc |...s..1.......L.| +00000020 41 71 dd b8 57 e2 b2 30 bf 1c 2b a6 19 a8 79 51 |Aq..W..0..+...yQ| +00000030 a0 32 e0 78 |.2.x| +>>> Flow 9 (client to server) +00000000 00 00 00 30 54 3c 30 a6 b0 fe e5 9d 17 be 31 8f |...0T<0.......1.| +00000010 ec a5 88 15 af 3d f0 70 14 04 ef 0d 4b 4e 80 76 |.....=.p....KN.v| +00000020 91 e4 d4 55 8d 20 1a 01 9e 3b e6 c6 23 91 ec 49 |...U. ...;..#..I| +00000030 98 64 fd 58 de bc 05 dd 93 83 73 ad 54 df 74 65 |.d.X......s.T.te| +00000040 22 a7 11 1c |"...| +>>> Flow 10 (server to client) +00000000 00 00 00 20 fd f6 bf 30 3f 33 06 a1 d5 44 56 13 |... ...0?3...DV.| +00000010 d1 3a 68 9e 68 f4 42 6d 73 bf 33 04 09 ef 19 f6 |.:h.h.Bms.3.....| +00000020 21 93 b1 03 69 f1 ec 0a 2d 9d ad 28 59 fc 89 e8 |!...i...-..(Y...| +00000030 22 f7 85 38 00 00 00 40 49 2e 82 1f e4 ce 62 49 |"..8...@I.....bI| +00000040 72 31 0f 94 24 17 80 e3 11 41 a8 ae 98 06 71 71 |r1..$....A....qq| +00000050 0a d7 0b 85 c9 da 40 ec 13 e7 d0 45 f9 88 03 5c |......@....E...\| +00000060 9f 4d 05 6d 5b 7c 10 f0 43 5b fc 39 2b b6 79 e7 |.M.m[|..C[.9+.y.| +00000070 a6 3a 6c 42 a0 02 46 b7 1c df 40 df ba 49 7f 72 |.:lB..F...@..I.r| +00000080 06 f6 ef d4 64 8c f1 73 |....d..s| +>>> Flow 11 (client to server) +00000000 00 00 01 60 a6 b5 99 e8 82 3b 22 ec 93 9f 03 e4 |...`.....;".....| +00000010 9c 66 13 e8 8b 43 1f 79 8e 3f 16 e5 1d ab e8 88 |.f...C.y.?......| +00000020 c1 4b 39 31 a7 42 b7 e8 e1 fc 69 8f e7 db b5 79 |.K91.B....i....y| +00000030 74 bc bc 1b 78 3d 5c 90 dc 10 46 22 e4 d2 5a 3f |t...x=\...F"..Z?| +00000040 0b 33 ff 54 d2 f3 95 19 12 38 82 88 26 b1 e1 54 |.3.T.....8..&..T| +00000050 4a 1b 9d 55 a8 e5 d7 ce 26 ab c7 e5 7d d5 1f 61 |J..U....&...}..a| +00000060 91 11 ac b1 5d c3 f8 af 28 5d d2 dd 58 99 b9 8b |....]...(]..X...| +00000070 5d 88 18 ae 87 ac af ae 7b 57 e2 c2 3c 31 49 35 |].......{W..<1I5| +00000080 7b 61 38 53 9c 6b 3e 46 9e 33 23 e9 52 d4 11 20 |{a8S.k>F.3#.R.. | +00000090 38 22 85 d4 df 3e df e2 9c f9 a7 2b de 0c 60 bf |8"...>.....+..`.| +000000a0 e1 93 2f cb f3 03 a3 f1 61 5b 53 41 b4 7e 04 50 |../.....a[SA.~.P| +000000b0 f0 7c 0d 40 46 ec 6e 6c 5f a1 0f 6c 4e b1 9e d8 |.|.@F.nl_..lN...| +000000c0 63 bb 00 6c 12 97 62 52 45 b4 fa b2 76 fc 05 f3 |c..l..bRE...v...| +000000d0 74 82 a5 65 8e d3 4c a7 91 ce ea 91 1b 04 29 45 |t..e..L.......)E| +000000e0 56 0a ff e6 14 2f e8 db 2e e8 4e 3a bc 8a 51 e4 |V..../....N:..Q.| +000000f0 af ed cc 97 ca 0a 00 7b b4 db 97 d3 56 52 f6 a5 |.......{....VR..| +00000100 1b bb bb 00 77 04 46 f0 67 2a 95 45 46 da cd d8 |....w.F.g*.EF...| +00000110 ad 42 b7 76 6f 39 ed 92 aa c8 d0 7b 93 87 22 25 |.B.vo9.....{.."%| +00000120 26 c7 5c 40 9d 40 4d 70 4b 7b 86 c6 01 86 91 c3 |&.\@.@MpK{......| +00000130 4c 37 56 8a d6 76 22 fe 9b 54 6f 19 b6 be 1e 86 |L7V..v"..To.....| +00000140 c4 ca f4 3b 02 ed 70 c6 fe 02 0e b9 51 1f 38 f1 |...;..p.....Q.8.| +00000150 ae 57 cb 8c 5e b8 f5 fe 6f 2e 4a a6 52 25 b0 76 |.W..^...o.J.R%.v| +00000160 5e b4 08 f6 57 57 8f 1e 60 64 2c 56 b7 2c c6 23 |^...WW..`d,V.,.#| +00000170 e5 9e 59 3b |..Y;| +>>> Flow 12 (server to client) +00000000 00 00 01 40 06 8e ad 98 82 18 f3 9a aa d0 28 ae |...@..........(.| +00000010 dd e4 bc 61 8b 7f e3 61 b6 19 bf bf 88 0f f4 98 |...a...a........| +00000020 1b 66 61 3c 52 35 62 9e 74 e0 b9 5c 29 a0 f2 25 |.fa.| +000000e0 e0 5d 09 8a 2a 1e d3 0e 84 4c de 4a 15 d2 82 b8 |.]..*....L.J....| +000000f0 bb d8 c7 35 50 37 6c fa 22 bc da d4 f7 50 e9 4a |...5P7l."....P.J| +00000100 11 64 13 21 31 e1 33 63 08 fb be 9f cd d6 27 9e |.d.!1.3c......'.| +00000110 4c d1 d5 c4 fd dd 64 91 92 52 d7 e2 9d 9c 2f 09 |L.....d..R..../.| +00000120 1b 13 a3 d6 18 64 fb 72 92 1a 25 71 0b 78 d2 bf |.....d.r..%q.x..| +00000130 7e 30 02 e0 a4 c1 09 33 c3 a5 c8 b0 4d 7a 08 9e |~0.....3....Mz..| +00000140 5d b0 51 60 1c 69 a0 32 96 7b 9a a8 56 e7 9e 88 |].Q`.i.2.{..V...| +00000150 e9 3f 3c e7 |.?<.| +>>> Flow 13 (client to server) +00000000 00 00 02 80 2a 18 8b 9f 23 18 b2 42 29 bb bb 2a |....*...#..B)..*| +00000010 4c 10 14 90 bc f9 dc a8 2c c4 28 91 8d 2d d6 5f |L.......,.(..-._| +00000020 cc ce e4 88 ef b7 22 d7 4f 2c b2 fe e2 ea 71 b1 |......".O,....q.| +00000030 08 c0 6b 6a 70 47 05 4c 3f 60 35 17 17 e0 f7 23 |..kjpG.L?`5....#| +00000040 ce 84 70 06 56 09 f9 50 49 ce c6 51 a6 91 84 13 |..p.V..PI..Q....| +00000050 0c b1 f6 00 de f7 de c2 d5 b8 dd cf 93 73 d8 e4 |.............s..| +00000060 7e c9 9e f8 ec bc ac d7 64 cd b1 28 c8 02 fa 8a |~.......d..(....| +00000070 1d 5b 19 2e 81 09 32 29 4e 7f 7a b0 02 4b a1 00 |.[....2)N.z..K..| +00000080 1f 1f f7 94 34 22 e2 d5 cd 42 6c 9d b0 17 d8 60 |....4"...Bl....`| +00000090 a3 23 b8 5a ad d9 ec 6c 39 5f c5 79 84 bd 6c 54 |.#.Z...l9_.y..lT| +000000a0 5e b5 cd 3e 6a 39 25 56 7a cb 9a 4f db 1d 61 db |^..>j9%Vz..O..a.| +000000b0 ca 28 3b d4 43 60 f0 d2 cf 4e 06 36 a5 33 13 1e |.(;.C`...N.6.3..| +000000c0 70 30 b6 b2 89 18 95 99 4c 92 be 0a 0a 55 e0 78 |p0......L....U.x| +000000d0 e9 07 cf f5 5d 7d 12 80 d1 6c 8b ca 8d 2d 3c 8a |....]}...l...-<.| +000000e0 6e c2 76 2d 9c b3 2d 3a 71 34 66 7a 25 61 22 b6 |n.v-..-:q4fz%a".| +000000f0 04 69 76 d9 58 ad 78 3e 51 ce 79 b4 26 85 d2 15 |.iv.X.x>Q.y.&...| +00000100 8c a5 35 af b9 b9 88 a1 6c 35 75 29 46 06 3f dc |..5.....l5u)F.?.| +00000110 c5 1e 6b 70 fb 6e c4 fe 5a 26 f7 47 bb 74 59 1b |..kp.n..Z&.G.tY.| +00000120 e7 e7 f8 8b da 70 73 88 cb 0f 96 af 70 f0 9a 36 |.....ps.....p..6| +00000130 a2 75 5d 75 ef f6 91 8e 7d 9e 7f c5 48 00 0a 76 |.u]u....}...H..v| +00000140 32 75 1d 91 72 0b cf c2 8e 4a 7e 94 ba fc 36 cb |2u..r....J~...6.| +00000150 f7 4b 7a 87 12 7a 48 22 33 c8 89 61 db 44 1b 70 |.Kz..zH"3..a.D.p| +00000160 fc b1 f9 a3 44 b3 3f 19 d5 a3 be 6d f4 1d a0 79 |....D.?....m...y| +00000170 31 69 3d 8e 08 87 27 3b 0a 69 bd 6c b4 0c 70 34 |1i=...';.i.l..p4| +00000180 da fb ab bf 26 bd 3a d0 35 81 9f a3 7e ac 3c e0 |....&.:.5...~.<.| +00000190 f5 08 ff 71 6b 9a 56 a4 08 ab 87 38 20 83 1e 5c |...qk.V....8 ..\| +000001a0 ca d2 6c 60 9a e6 f6 e9 2a 70 ac b1 e7 aa 14 f6 |..l`....*p......| +000001b0 b4 9c e3 67 76 19 27 69 fa cc a3 97 0b b1 be bc |...gv.'i........| +000001c0 69 cd cc 50 66 f9 80 28 1c c6 a3 67 2a 31 51 05 |i..Pf..(...g*1Q.| +000001d0 d8 05 ff f8 7d 9f 31 f1 ce eb 9c d3 38 a2 13 53 |....}.1.....8..S| +000001e0 d5 fb 16 a0 2b a5 01 e3 c1 36 e3 0a 20 5b af 71 |....+....6.. [.q| +000001f0 01 69 51 5e bb 80 82 33 fe 2d 35 3f 6c 09 39 b9 |.iQ^...3.-5?l.9.| +00000200 7b 25 bd 07 67 a9 71 af e9 26 aa bf 17 3b a8 9d |{%..g.q..&...;..| +00000210 40 eb 81 ba c8 be 38 7c 68 b9 d9 a2 8d 18 36 ad |@.....8|h.....6.| +00000220 f0 02 93 bd 3a 33 18 8d 04 d9 e1 50 72 ee 66 0a |....:3.....Pr.f.| +00000230 21 dd 13 5b 11 18 61 4d b4 da ed 3f 41 da ca da |!..[..aM...?A...| +00000240 69 31 57 45 12 6c 0a 79 43 7a f3 3d 96 8f 88 da |i1WE.l.yCz.=....| +00000250 2c cf f6 69 fd f0 d1 84 3c f8 88 5b 06 78 35 52 |,..i....<..[.x5R| +00000260 81 50 b8 9a a8 ab 07 e8 45 d3 54 aa 3e 9c 51 8b |.P......E.T.>.Q.| +00000270 fb 19 e2 f5 ef 5e e4 a4 68 f0 49 8e c8 66 49 22 |.....^..h.I..fI"| +00000280 de 89 77 8e fe 42 25 41 e4 80 54 e7 8e ff 16 83 |..w..B%A..T.....| +00000290 0c 03 07 96 |....| +>>> Flow 14 (server to client) +00000000 00 00 00 10 1d 0a 2a 86 14 dc f2 11 85 9a eb c7 |......*.........| +00000010 90 43 5c 26 1c e2 16 27 f1 e5 cb a0 8b fa ea 80 |.C\&...'........| +00000020 9b 24 fe 02 |.$..| diff --git a/ssh/testdata/Client-MAC-hmac-sha2-256 b/ssh/testdata/Client-MAC-hmac-sha2-256 new file mode 100644 index 0000000000..3b17a35167 --- /dev/null +++ b/ssh/testdata/Client-MAC-hmac-sha2-256 @@ -0,0 +1,286 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 6c 13 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...l....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 0d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 00 |..hmac-sha2-256.| +00000230 00 00 0d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |...hmac-sha2-256| +00000240 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 |....none....none| +00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 |..............;.| +00000260 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c b1 ee |.......n..f.&<..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 ec 4f c3 11 74 78 f3 fe 64 e2 |.......O..tx..d.| +00000010 30 55 85 c0 e4 2f 00 00 01 7a 73 6e 74 72 75 70 |0U.../...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 58 e9 46 d2 c0 7e |...,..... X.F..~| +00000010 a3 4f 8e f3 28 59 e0 fe 90 59 d0 b5 89 16 f2 d5 |.O..(Y...Y......| +00000020 ed 34 95 12 7a d4 e5 93 20 10 87 3c 23 dc 62 b8 |.4..z... ..<#.b.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 09 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 6a d6 9d cc 7a 3e d3 88 9f 1c |..... j...z>....| +00000080 fe f4 0d 10 f8 e0 7d 73 a1 9c 9f f6 43 29 9b 95 |......}s....C)..| +00000090 bc 57 8c 0d 91 7c 00 00 00 65 00 00 00 13 65 63 |.W...|...e....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 4a 00 00 00 21 00 d3 98 c9 c3 b8 e3 |6...J...!.......| +000000c0 38 fe ad 54 67 79 56 10 4c 96 7a 0e 65 ac f1 69 |8..TgyV.L.z.e..i| +000000d0 09 51 fd 22 f1 bc 9f 1f 26 40 00 00 00 21 00 b1 |.Q."....&@...!..| +000000e0 a8 cd 33 89 12 ae 65 1b 67 4d 3d 64 62 7a 9e 49 |..3...e.gM=dbz.I| +000000f0 5a 3d e1 67 e9 10 68 72 da a1 06 ba 25 46 36 00 |Z=.g..hr....%F6.| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 d9 e7 56 64 |...........@..Vd| +00000120 cd 13 0b 4d 0e 3f cf d3 cb 04 33 d7 8a ae 73 7a |...M.?....3...sz| +00000130 10 ae 5a 26 8d 37 19 3f 5b cf 4a cc de eb 05 11 |..Z&.7.?[.J.....| +00000140 e5 2f cd 78 c1 4b 61 2c 47 86 bd cd 12 bc a4 0f |./.x.Ka,G.......| +00000150 a6 f4 88 d2 14 77 c0 a7 63 54 ee 37 69 8b 63 ad |.....w..cT.7i.c.| +00000160 fe 6e 00 92 f6 b3 27 3f a6 98 fb 59 5c 54 a4 85 |.n....'?...Y\T..| +00000170 40 79 0e 8c 66 45 0a b1 8a be f3 a8 8a 99 40 04 |@y..fE........@.| +00000180 c9 32 57 28 98 23 b8 c5 76 c7 20 18 0c 9e d5 6f |.2W(.#..v. ....o| +00000190 20 3c 0e d6 ca 8a 6c 9c 94 bb 7d 1b cd 50 fc aa | <....l...}..P..| +000001a0 f5 da af d3 1e 69 3a 0a 23 db f9 dd ea 03 92 bf |.....i:.#.......| +000001b0 d6 3c 03 81 ec d3 6a da 32 6e 0c 90 15 5c cb 26 |.<....j.2n...\.&| +000001c0 0a cd 1b b0 32 b4 a0 46 75 25 4f 5b 48 4f 55 d8 |....2..Fu%O[HOU.| +000001d0 57 25 41 67 0f 85 10 17 7c 7f 00 dd a9 a1 f3 60 |W%Ag....|......`| +000001e0 97 d1 5e de 9e 64 de 88 53 4a 06 33 84 6a fb 8b |..^..d..SJ.3.j..| +000001f0 fa 86 f8 64 37 a2 f5 b9 22 41 1a 49 ec 6b ef 2a |...d7..."A.I.k.*| +00000200 33 b3 58 1e 2a e3 ba e8 48 9e 1e 53 47 55 ee 1e |3.X.*...H..SGU..| +00000210 a2 27 86 bf 40 62 c0 0f 62 3e 71 61 3a b2 e7 57 |.'..@b..b>qa:..W| +00000220 6b 53 ae 0a 3f 24 8c 21 c2 93 6a 20 d2 55 a2 b4 |kS..?$.!..j .U..| +00000230 64 a7 88 cb 68 59 0e 05 5d 6d f0 60 97 70 2d c4 |d...hY..]m.`.p-.| +00000240 ec 5c 35 27 73 77 35 2e 6c 21 fa 65 f6 0b b5 5e |.\5'sw5.l!.e...^| +00000250 b2 a4 96 02 18 d6 a2 f6 49 46 36 9f 66 60 03 cb |........IF6.f`..| +00000260 83 30 88 f9 c6 a8 74 05 f3 5d a7 f9 |.0....t..]..| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000010 00 00 00 20 f3 c4 8f fd f6 a8 ed be d2 1a 1f 10 |... ............| +00000020 68 fb 61 be ea 6e 06 6e 7d 36 67 97 38 5c c4 48 |h.a..n.n}6g.8\.H| +00000030 3d cd db 08 7b 5f e7 31 a1 db 9c d8 e3 3c de 6b |=...{_.1.....<.k| +00000040 0a 97 bd 9f |....| +>>> Flow 8 (server to client) +00000000 00 00 00 20 b8 7c c2 ff 91 a0 53 5a 3b 2e 3f 2a |... .|....SZ;.?*| +00000010 c9 90 ff 9c ea 31 11 f3 e1 40 ca cd ef db 8c 9b |.....1...@......| +00000020 7f 38 12 c8 0b c6 cd 17 4e 6d e0 ca bb 60 36 cc |.8......Nm...`6.| +00000030 c0 91 fe af |....| +>>> Flow 9 (client to server) +00000000 00 00 00 30 8f 63 2f ae d6 94 50 e5 a3 b5 6f 80 |...0.c/...P...o.| +00000010 3b 17 23 a2 43 1e b6 ec 5d f3 50 6e 57 f5 eb 62 |;.#.C...].PnW..b| +00000020 33 da 73 c6 30 69 2a 11 59 57 a8 fd cc a6 79 0c |3.s.0i*.YW....y.| +00000030 d8 71 b5 b6 8c 58 ba 3a 4d 76 85 e4 5d 39 4e b6 |.q...X.:Mv..]9N.| +00000040 2a 35 0e 02 |*5..| +>>> Flow 10 (server to client) +00000000 00 00 00 20 bf 2c d5 b0 ad bf a3 3c aa 6c fb 96 |... .,.....<.l..| +00000010 de b8 22 4e 13 56 91 63 dc e8 12 2f ea 69 1c 28 |.."N.V.c.../.i.(| +00000020 7e b0 7b 93 0b 97 81 f1 57 01 93 af b9 98 a1 fb |~.{.....W.......| +00000030 10 71 55 b4 00 00 00 40 13 d4 89 83 56 7c e6 c2 |.qU....@....V|..| +00000040 3b bd c8 37 a5 57 d0 7e 74 b7 0e f5 0b 73 7b 1c |;..7.W.~t....s{.| +00000050 3a d8 1f 7b c5 81 ee 41 e6 9e d0 83 7a d6 22 93 |:..{...A....z.".| +00000060 33 1c fe 68 08 7a 7c 0e 56 c8 1f 4e fe 15 85 31 |3..h.z|.V..N...1| +00000070 16 4c 25 70 74 df 25 00 7b 45 28 66 5c ae 7f 95 |.L%pt.%.{E(f\...| +00000080 87 88 12 8e d7 d6 72 80 |......r.| +>>> Flow 11 (client to server) +00000000 00 00 01 60 1f a1 f9 a0 1c ed 30 d9 18 5a 75 9a |...`......0..Zu.| +00000010 fc fc 70 d6 d0 19 0d 43 c6 3a 4f c9 71 b5 c9 83 |..p....C.:O.q...| +00000020 6f dc ba 07 5b c7 7c 19 49 7b e1 e1 f4 66 aa d8 |o...[.|.I{...f..| +00000030 d5 34 3c 3b 47 b5 21 9c ff eb 5e 6c cb 6b c8 a3 |.4<;G.!...^l.k..| +00000040 38 51 34 02 6b 4e 2b 92 89 09 2f 5d 6e 8e 1d 00 |8Q4.kN+.../]n...| +00000050 08 70 91 fe ba 70 58 5d de 38 0a af c2 7e 3f 59 |.p...pX].8...~?Y| +00000060 ec 3a e0 b5 5a d7 51 bf 38 94 1d 11 12 3c 25 16 |.:..Z.Q.8....<%.| +00000070 66 8f 80 69 b2 de b9 22 6a da f9 f6 cb 5a 33 87 |f..i..."j....Z3.| +00000080 f3 c6 67 8f f1 08 0a fb c3 06 2d 3d 5d 4f f3 7b |..g.......-=]O.{| +00000090 a3 c7 29 6f df c8 10 3d e9 7b 76 52 07 2f 56 84 |..)o...=.{vR./V.| +000000a0 0e 5c 3b c3 1d 74 c4 44 11 a1 49 d7 13 a9 9c dc |.\;..t.D..I.....| +000000b0 86 bc 48 29 6b 4d 38 f7 8f 52 0f 0c 03 b7 dd 8c |..H)kM8..R......| +000000c0 a4 8f 92 32 67 d8 ab 96 c1 17 71 9b 96 55 6e f8 |...2g.....q..Un.| +000000d0 59 72 fc 1e f5 38 f5 64 00 32 88 bc 4f 14 01 c5 |Yr...8.d.2..O...| +000000e0 cb c4 c0 91 1c 2a 0b 9e 2d 10 da af c3 29 f7 fc |.....*..-....)..| +000000f0 33 ad 42 09 7a c8 9e d5 b2 1e 54 4f cd f4 e9 ba |3.B.z.....TO....| +00000100 8a 6b a7 3b 7d 64 25 5b e9 9a e8 5e 85 5a 0b e7 |.k.;}d%[...^.Z..| +00000110 af c5 9c 5d d9 f9 e5 c1 b3 c4 3d 36 3d c3 aa 0b |...]......=6=...| +00000120 53 dc e3 c9 93 f2 62 96 87 35 87 9d c0 72 54 68 |S.....b..5...rTh| +00000130 25 81 df 7f ff 72 e4 52 4b 5f 8c fb 33 51 33 95 |%....r.RK_..3Q3.| +00000140 9b e9 01 9b 0a 26 fa 66 48 97 f0 da e0 6b 14 0f |.....&.fH....k..| +00000150 a9 be 16 94 0f 65 60 07 98 4f fa f1 d2 61 8d bb |.....e`..O...a..| +00000160 69 88 43 cb 80 66 86 69 18 fe 09 01 bb e2 fb ff |i.C..f.i........| +00000170 0f d3 d9 c1 |....| +>>> Flow 12 (server to client) +00000000 00 00 01 40 c4 c6 41 32 a7 b7 6b c4 1a 89 52 ab |...@..A2..k...R.| +00000010 74 4c 3c a5 19 32 4d 16 3b 32 55 7c 05 d5 85 f3 |tL<..2M.;2U|....| +00000020 bd a6 3c 81 04 eb f6 62 24 88 a0 05 0e 41 4b cb |..<....b$....AK.| +00000030 ff 84 8a 2d dd 86 1a 17 f4 e9 b0 29 05 67 c4 6e |...-.......).g.n| +00000040 01 69 a4 18 b8 f5 75 a8 3c 03 08 a6 03 d9 76 e7 |.i....u.<.....v.| +00000050 55 b0 91 24 58 12 50 8e 19 a4 81 f2 85 95 9f 81 |U..$X.P.........| +00000060 8e 78 7d 01 97 b3 26 38 b8 5d a1 ef 97 a4 f6 7c |.x}...&8.].....|| +00000070 28 e8 f8 75 c9 30 b1 20 52 55 10 bd b8 1b 24 5c |(..u.0. RU....$\| +00000080 d5 8b 47 79 63 e0 09 18 5c c7 7f 37 f2 41 29 d1 |..Gyc...\..7.A).| +00000090 2f c1 d8 32 c0 f5 cd 96 0a 12 40 49 2c ac 2b 1c |/..2......@I,.+.| +000000a0 db 0c f3 4a 2c 93 d9 b3 74 25 1d 38 79 75 04 84 |...J,...t%.8yu..| +000000b0 a2 be a5 aa 67 ec d4 84 3a a4 a9 d8 9d 47 e6 63 |....g...:....G.c| +000000c0 1f be 5c 21 0e 6b 23 86 04 57 b9 ad db 15 2d 1b |..\!.k#..W....-.| +000000d0 ef 7f bb 5a fc bf f2 a7 94 fa 6b b1 b3 53 d8 7b |...Z......k..S.{| +000000e0 1f 18 03 14 63 b1 d9 33 2e 77 07 69 35 2f 9f 67 |....c..3.w.i5/.g| +000000f0 99 d4 65 1f 92 ef ff 92 39 c4 47 81 eb ba 50 f9 |..e.....9.G...P.| +00000100 85 10 59 af dc 16 55 53 92 69 78 7d d9 f1 42 72 |..Y...US.ix}..Br| +00000110 9a eb 3f 91 22 2f 07 a8 e4 3a be ed 60 a3 15 d4 |..?."/...:..`...| +00000120 3e 64 64 f7 fc 90 b2 a1 80 47 66 ac b0 38 61 fe |>dd......Gf..8a.| +00000130 6a 54 00 b7 b4 a9 14 b2 72 aa 50 ed 58 54 3a 70 |jT......r.P.XT:p| +00000140 e9 f0 bc f5 b8 fb 81 dc ef 07 d3 da b6 30 77 b4 |.............0w.| +00000150 fe 6d fd 1e |.m..| +>>> Flow 13 (client to server) +00000000 00 00 02 80 32 90 0b f3 b8 b9 d3 cd fb 29 ed 83 |....2........)..| +00000010 e2 c0 29 10 b1 e1 d0 01 b6 8e 77 07 2a ff 40 c5 |..).......w.*.@.| +00000020 c5 7d 84 86 90 43 75 d8 1c 42 fb b8 94 ca e9 68 |.}...Cu..B.....h| +00000030 d6 87 72 e5 2b f8 5f 34 c7 a9 fe 52 fb 59 73 a2 |..r.+._4...R.Ys.| +00000040 9d 34 85 16 69 0a a0 02 ef 02 7f 3f ac 1b 5f 49 |.4..i......?.._I| +00000050 2b 6c e5 95 6f 9f b8 52 6c 6c 4a 9d d5 2b f4 82 |+l..o..RllJ..+..| +00000060 4a 38 8b 7b b9 c7 4a 69 c0 1a 60 97 e5 34 60 25 |J8.{..Ji..`..4`%| +00000070 c7 8d 6f b5 76 17 ed 2a 53 01 4c af 73 6c 46 b0 |..o.v..*S.L.slF.| +00000080 90 94 b6 a1 b1 5d 73 72 d0 e8 c2 ea 8f c6 e3 f3 |.....]sr........| +00000090 a1 e7 a3 8f c1 10 99 55 1b 5c 29 91 e5 92 b6 23 |.......U.\)....#| +000000a0 56 9d fc ab 07 1d 3c 9a 93 06 f5 c6 bc f4 fa 9f |V.....<.........| +000000b0 b5 d4 34 d8 d8 fc b5 43 d6 dc b6 e4 b4 a3 dd 1c |..4....C........| +000000c0 8d 9c 73 3b 0f 77 9d 90 5a d0 93 12 5f c5 6f 86 |..s;.w..Z..._.o.| +000000d0 01 5f ae be 28 c6 1a 67 4d 28 a4 56 aa b0 03 db |._..(..gM(.V....| +000000e0 70 79 ea 2b 98 17 95 1b b2 9a b3 cb 60 e0 dc ff |py.+........`...| +000000f0 e3 78 44 80 fc d2 c2 78 49 25 18 ed 41 73 08 65 |.xD....xI%..As.e| +00000100 09 e6 78 73 52 44 58 d6 9a 5d aa ed 55 39 21 36 |..xsRDX..]..U9!6| +00000110 2d 1b 59 52 1a 81 da 21 52 f7 bb fa 69 3c 63 f4 |-.YR...!R...i%....,m..| +00000170 9b af 1e 4b 57 a8 f9 8e e0 e5 55 bd b5 97 16 c7 |...KW.....U.....| +00000180 fd a3 4a 89 d6 f8 41 74 d4 9c 00 6d d1 de 85 3e |..J...At...m...>| +00000190 24 d3 19 29 9a 4e ae 5f ab 1e 31 a7 2f 0a 9c ba |$..).N._..1./...| +000001a0 0d 63 8a 91 25 8a 7a bd a1 e9 71 e9 a1 49 a3 d4 |.c..%.z...q..I..| +000001b0 95 b5 90 95 be 1c 61 56 98 cb a5 03 7b 09 da 20 |......aV....{.. | +000001c0 4d bd 81 f3 82 6a 45 1f 05 b1 80 cb 92 d8 67 86 |M....jE.......g.| +000001d0 e1 ae 7a 8e a9 31 cc d2 2f 88 02 7e 3e be 57 a1 |..z..1../..~>.W.| +000001e0 80 e6 43 87 21 40 43 df e7 eb 84 97 77 79 ab 71 |..C.!@C.....wy.q| +000001f0 5d 40 10 d3 b9 5b 03 f6 89 58 f5 fc c4 0d 69 18 |]@...[...X....i.| +00000200 de ab 34 61 9f 61 f9 28 f6 05 fd 7a d4 ea e7 8d |..4a.a.(...z....| +00000210 bd 19 92 64 af 93 ad fb cd d4 ad b4 23 02 17 92 |...d........#...| +00000220 fb 05 b5 ec 9d 00 58 67 ca b2 e6 0c 36 e9 9c 76 |......Xg....6..v| +00000230 3e c5 b9 23 25 4f e0 bc c9 21 f4 fe d9 b0 d7 9c |>..#%O...!......| +00000240 b0 1a 2a ec 60 05 25 9a 73 1a 8d 80 58 b0 1d 20 |..*.`.%.s...X.. | +00000250 4a e6 4e 3d 1d ef da c3 71 9d 4b 56 b3 5b ea 59 |J.N=....q.KV.[.Y| +00000260 f2 65 c4 e3 68 e3 53 94 df 2b bd 11 80 db 54 53 |.e..h.S..+....TS| +00000270 2b 5f 9e b9 ab 79 43 6b 60 ba c9 89 df f0 2c 5b |+_...yCk`.....,[| +00000280 d9 98 28 92 d8 be 39 3f 54 3b 23 a7 85 78 29 e9 |..(...9?T;#..x).| +00000290 cb 30 4c 3a |.0L:| +>>> Flow 14 (server to client) +00000000 00 00 00 10 8b 86 3d ef 31 e4 8a 1c 9f 1f b8 a1 |......=.1.......| +00000010 fe 52 18 d2 18 99 0a 59 2b f8 96 5a 1b eb 14 52 |.R.....Y+..Z...R| +00000020 0c 12 69 1f |..i.| diff --git a/ssh/testdata/Client-MAC-hmac-sha2-256-etm@openssh.com b/ssh/testdata/Client-MAC-hmac-sha2-256-etm@openssh.com new file mode 100644 index 0000000000..661cd2013a --- /dev/null +++ b/ssh/testdata/Client-MAC-hmac-sha2-256-etm@openssh.com @@ -0,0 +1,288 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 8c 13 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 1d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |..hmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |etm@openssh.com.| +00000240 00 00 1d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |...hmac-sha2-256| +00000250 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000260 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 |....none....none| +00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 |..............;.| +00000280 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c b1 ee |.......n..f.&<..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 14 c7 e4 52 3b 4c eb 31 8d 51 |.........R;L.1.Q| +00000010 82 ea 18 db 06 bc 00 00 01 7a 73 6e 74 72 75 70 |.........zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 58 e9 46 d2 c0 7e |...,..... X.F..~| +00000010 a3 4f 8e f3 28 59 e0 fe 90 59 d0 b5 89 16 f2 d5 |.O..(Y...Y......| +00000020 ed 34 95 12 7a d4 e5 93 20 10 87 3c 23 dc 62 b8 |.4..z... ..<#.b.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 a4 93 85 fc 06 91 85 33 2f 53 |..... .......3/S| +00000080 74 98 42 64 13 12 f3 d3 ca 00 27 b9 d6 20 86 f5 |t.Bd......'.. ..| +00000090 7c 0d 36 09 6c 41 00 00 00 64 00 00 00 13 65 63 ||.6.lA...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 6f a7 f9 19 ca d8 75 |6...I... o.....u| +000000c0 73 fe ac 7e 84 5b 52 93 2c 21 e0 05 5e 1f dd 9c |s..~.[R.,!..^...| +000000d0 d0 0b 94 99 35 ea 8a 41 cc 00 00 00 21 00 fc 3f |....5..A....!..?| +000000e0 a5 7e d4 79 d9 d3 d2 fb a1 93 42 bb dc 10 41 f7 |.~.y......B...A.| +000000f0 2d f3 0a e0 79 b5 4f ba 50 8d 9d 36 58 0e 00 00 |-...y.O.P..6X...| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 b5 82 ec 4c |...........@...L| +00000120 b8 a2 ca ca 50 19 39 d5 90 fc 2f 4d f1 f0 b5 89 |....P.9.../M....| +00000130 36 c6 96 67 83 f4 a1 98 a2 d1 ac 7d e1 f6 57 8b |6..g.......}..W.| +00000140 1e 68 fe 61 75 25 97 92 ed e6 9d b0 86 19 86 f0 |.h.au%..........| +00000150 bf c2 b3 e7 b1 3b c8 29 d1 7f 40 27 63 7b 28 36 |.....;.)..@'c{(6| +00000160 e9 67 a4 f4 2c 7c fa ff 72 9b b1 42 44 73 5c b3 |.g..,|..r..BDs\.| +00000170 d0 e7 ce 6e 7e 6b 08 b4 e0 9f 3f 10 15 0d 63 73 |...n~k....?...cs| +00000180 a2 c2 7b f4 67 45 a7 cb 75 94 63 f2 fb d5 4b ef |..{.gE..u.c...K.| +00000190 0d a7 c0 8f be f4 20 28 c0 68 6e cb 62 0b b1 fd |...... (.hn.b...| +000001a0 2d f4 55 29 0c ad 24 9c b7 08 5b 90 d3 50 da ba |-.U)..$...[..P..| +000001b0 da 58 08 35 eb 18 62 8f a7 fd b5 0a d3 fe 46 81 |.X.5..b.......F.| +000001c0 37 71 90 fc 61 a6 1d ee 34 35 0c b0 a7 eb d6 fa |7q..a...45......| +000001d0 41 44 22 c0 f9 e5 a5 c3 a4 02 60 76 88 6a b6 85 |AD".......`v.j..| +000001e0 02 5e 76 cb 07 60 3e 17 6a c9 3e 95 c9 90 64 1a |.^v..`>.j.>...d.| +000001f0 ed ad ea 9a 34 29 fb 82 74 b6 07 96 f2 a4 99 88 |....4)..t.......| +00000200 7a 56 67 c6 0d b3 ec f1 0b 0e 31 ed 9b 3a 16 77 |zVg.......1..:.w| +00000210 cb 83 2c e8 6e 88 99 d6 fd f2 1c 2d fa 27 92 87 |..,.n......-.'..| +00000220 6e 22 fe 87 43 fa 25 89 50 23 23 db 53 b4 e7 66 |n"..C.%.P##.S..f| +00000230 f0 18 41 18 a8 b7 2e a0 c1 52 3b ca 0e 06 ba 34 |..A......R;....4| +00000240 27 73 4a ad f2 5f f9 23 ab b9 c9 7a 7d 9c 1d f4 |'sJ.._.#...z}...| +00000250 33 fe 25 3b 53 64 e2 34 1a 77 b4 52 68 51 31 52 |3.%;Sd.4.w.RhQ1R| +00000260 22 f5 8c 43 bd 47 6b ae 2e 24 76 b1 |"..C.Gk..$v.| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000010 00 00 00 20 e4 be cf 76 2e 02 af 1c 2c 33 a3 97 |... ...v....,3..| +00000020 f7 06 4b e4 4b e9 30 ee ef c6 1a dc 63 5e bf ee |..K.K.0.....c^..| +00000030 b3 f7 d3 d5 9d b9 34 f1 a1 f9 13 17 ed 18 8b 23 |......4........#| +00000040 ba 2c 7c ca |.,|.| +>>> Flow 8 (server to client) +00000000 00 00 00 20 e1 08 9f 23 5d 5f 65 3c ac 3a bd f3 |... ...#]_e<.:..| +00000010 f5 20 54 67 2b 6a 7e 59 66 f1 13 5d c0 cb 3a bd |. Tg+j~Yf..]..:.| +00000020 b5 fd b1 79 17 e5 bb 19 4c 7a 54 d2 c8 bb 66 ff |...y....LzT...f.| +00000030 9f 57 2b 40 |.W+@| +>>> Flow 9 (client to server) +00000000 00 00 00 30 f6 c8 7e 53 89 74 10 95 3c f6 0e 7f |...0..~S.t..<...| +00000010 a9 a8 5b 4e 10 78 2e 20 30 4a 79 a3 70 b5 ff 88 |..[N.x. 0Jy.p...| +00000020 a3 e7 00 22 08 79 39 1d bb ac f5 af ef d4 0a 70 |...".y9........p| +00000030 ad e8 f9 35 40 58 b1 ee 06 42 f6 6c 5d 73 85 0c |...5@X...B.l]s..| +00000040 46 b2 20 28 |F. (| +>>> Flow 10 (server to client) +00000000 00 00 00 20 da 29 5a 8d ab 81 5d ac de 3f 89 51 |... .)Z...]..?.Q| +00000010 24 af 69 1e 82 75 73 a6 a2 0c d1 c9 80 e5 08 45 |$.i..us........E| +00000020 45 08 20 51 ab 76 07 69 0b 04 08 6a f2 2f d1 0b |E. Q.v.i...j./..| +00000030 e0 1d f5 df 00 00 00 40 ab c7 21 89 b9 7d 78 bd |.......@..!..}x.| +00000040 75 28 e9 fe 9c 1e 57 61 af 1a 4c c7 11 07 57 47 |u(....Wa..L...WG| +00000050 d2 a8 63 0d c9 3a 8b 88 96 e9 02 d5 be 8b 1e 15 |..c..:..........| +00000060 12 5e ef 23 94 ae b6 b0 3a 40 06 a7 c1 43 10 95 |.^.#....:@...C..| +00000070 71 69 f4 8a 16 68 52 67 61 4a 13 fe 18 d4 90 eb |qi...hRgaJ......| +00000080 b4 f3 d8 0b e3 8c 14 f1 |........| +>>> Flow 11 (client to server) +00000000 00 00 01 60 05 8b 5a 67 80 5d c9 b4 51 2f 73 29 |...`..Zg.]..Q/s)| +00000010 36 11 92 42 5e 80 ae 50 0c c4 78 47 b3 fc 6e f0 |6..B^..P..xG..n.| +00000020 25 08 83 d8 4e dd d7 e5 33 ab 46 03 fe 11 08 c1 |%...N...3.F.....| +00000030 0b ca 28 ce 46 af 74 75 8a 29 44 d7 98 a5 58 30 |..(.F.tu.)D...X0| +00000040 7d 08 32 a0 39 dc 86 53 71 3d be 40 f9 27 0f bb |}.2.9..Sq=.@.'..| +00000050 5c 34 ea 75 43 64 b7 f8 e6 00 0a 0c 1f 2a c9 d5 |\4.uCd.......*..| +00000060 8a 0a 96 c0 af 14 af 34 b5 0a ee 4b a9 65 e7 42 |.......4...K.e.B| +00000070 72 36 8f 48 34 c6 08 26 3d 95 96 b6 92 c8 e3 d7 |r6.H4..&=.......| +00000080 b9 18 ab dc 65 cf 54 c5 d0 49 e6 3e 7f 7b bc 57 |....e.T..I.>.{.W| +00000090 f7 c7 c1 44 6c 51 c6 88 a2 81 e1 57 b8 a3 60 25 |...DlQ.....W..`%| +000000a0 7d 67 c5 02 d0 a1 95 76 d3 7f 57 6b 51 37 97 89 |}g.....v..WkQ7..| +000000b0 fc c3 29 d9 9a 44 94 ba 56 29 72 47 22 71 07 1e |..)..D..V)rG"q..| +000000c0 18 2a 26 5b 3d da 9a f8 09 99 f2 a5 23 8f 0e e1 |.*&[=.......#...| +000000d0 28 36 1f e7 14 02 6c 29 f8 d5 20 33 2d 86 49 c3 |(6....l).. 3-.I.| +000000e0 24 37 69 5c f9 07 11 e5 c9 31 fb 87 40 58 4d 80 |$7i\.....1..@XM.| +000000f0 62 a5 14 df 40 c4 7b b2 53 64 49 34 03 52 21 52 |b...@.{.SdI4.R!R| +00000100 f9 dc eb b9 e7 08 a0 05 03 8b 46 a8 af 0b a2 37 |..........F....7| +00000110 56 3c 1b ba 34 9a 6f 43 77 ed 9a 0a af c0 71 5f |V<..4.oCw.....q_| +00000120 0f 34 96 74 66 0e 59 71 fd 83 f3 ff 25 37 27 a6 |.4.tf.Yq....%7'.| +00000130 28 c3 02 ca f2 5c 4a 47 d3 d8 56 14 40 2a 59 9c |(....\JG..V.@*Y.| +00000140 7d 1b 87 d6 f2 90 3f 8a a0 0c e0 09 4c 99 91 5a |}.....?.....L..Z| +00000150 9d c6 96 2d eb 48 5e 3a 28 1e 0a 74 15 95 f8 a8 |...-.H^:(..t....| +00000160 8e f5 e9 b4 84 4c b0 4a 9a d8 1b 16 f7 7e 42 b5 |.....L.J.....~B.| +00000170 02 66 da a5 |.f..| +>>> Flow 12 (server to client) +00000000 00 00 01 40 1f 1c d0 2d f6 87 f4 42 20 3d b9 9d |...@...-...B =..| +00000010 cc 57 c1 82 a6 a7 ce 9d 53 a4 22 9a 5b dd 56 05 |.W......S.".[.V.| +00000020 54 b4 fb 8b 89 91 4b 23 f9 72 6c f6 ee 5b d9 dd |T.....K#.rl..[..| +00000030 d2 fd 74 3e 16 8a cd 66 1b dc d5 8c 56 0f 41 e3 |..t>...f....V.A.| +00000040 67 6c 8c d6 e0 92 34 59 e6 cf cf 23 a7 cb 5b 38 |gl....4Y...#..[8| +00000050 80 10 c8 e0 62 e8 13 04 9c 26 1e d8 74 3c a1 bb |....b....&..t<..| +00000060 78 c8 23 2e 7c 1d 25 33 8c e9 c3 6c 68 37 f4 0b |x.#.|.%3...lh7..| +00000070 6c ed 81 b6 fc 0a 19 b8 d6 50 9b 67 a0 c6 e9 33 |l........P.g...3| +00000080 c5 ad 7b e8 c7 37 e0 e5 11 88 3a 58 c1 1e 31 63 |..{..7....:X..1c| +00000090 7c 2b 04 73 b7 d4 4e 04 54 ed 5b b9 0e e2 8a 80 ||+.s..N.T.[.....| +000000a0 cf 00 7a fc 53 09 86 6e c2 38 f9 58 1f ca 3a 63 |..z.S..n.8.X..:c| +000000b0 c5 fa 97 30 e1 2e 1e d8 c5 7b 72 24 95 d6 ec e2 |...0.....{r$....| +000000c0 81 34 4f 0e fd 2a 49 aa 43 0f 86 a4 0b a2 58 98 |.4O..*I.C.....X.| +000000d0 69 34 2f 12 08 95 e6 eb 2b fd 9a 3f da 3a 37 4f |i4/.....+..?.:7O| +000000e0 75 2b 75 e7 97 f8 c7 2f 86 a6 b9 59 52 fb 42 c7 |u+u..../...YR.B.| +000000f0 2a ff 07 2f e9 9a c8 37 e2 9f 94 4f 48 72 e0 ff |*../...7...OHr..| +00000100 4b b6 55 39 4f 18 e8 2e da 7a 62 d7 b8 4b 23 64 |K.U9O....zb..K#d| +00000110 5e ef 6d e2 7a ef 5b 39 e8 01 7d a1 22 3c 9c d9 |^.m.z.[9..}."<..| +00000120 f3 bc 73 82 bc 37 68 fe 12 56 67 05 e4 9b df c8 |..s..7h..Vg.....| +00000130 7b 18 c5 b6 40 34 3f 5f 8a 4d 3f aa 68 17 b6 38 |{...@4?_.M?.h..8| +00000140 b8 77 71 bf d0 63 ea 0a 41 9a 54 1c df 8f 1a f8 |.wq..c..A.T.....| +00000150 54 0d 24 99 |T.$.| +>>> Flow 13 (client to server) +00000000 00 00 02 80 7e ad b5 a4 1f 0c 50 b0 d5 0d 4a 34 |....~.....P...J4| +00000010 99 a8 0c cc b7 22 5c b0 19 6a 61 48 1c eb 46 79 |....."\..jaH..Fy| +00000020 8c 63 bf 1b f7 08 39 2e 88 92 94 77 83 a4 b6 6c |.c....9....w...l| +00000030 56 ba e6 05 e7 d4 be 29 b5 3c 3b 06 7d ef 60 c8 |V......).<;.}.`.| +00000040 ac 6d fb 12 a7 a5 98 c8 58 ed 00 ad e3 08 93 9f |.m......X.......| +00000050 59 1f f7 81 2b 5b 69 97 4b 03 a2 86 34 e4 72 e8 |Y...+[i.K...4.r.| +00000060 19 f6 75 15 c9 01 8d 59 9f 19 82 9c 98 4b 26 d2 |..u....Y.....K&.| +00000070 f1 38 43 f7 4f b8 95 e5 79 69 a7 ac 7d 9d 58 3f |.8C.O...yi..}.X?| +00000080 b6 90 0e 14 d2 4b e5 b3 b1 0f ab 61 a9 c8 b7 5f |.....K.....a..._| +00000090 62 fe d6 ba 86 f9 f5 df 86 04 53 6d f2 05 b1 fe |b.........Sm....| +000000a0 7a c3 bc 56 89 9a b3 da 3a e3 79 fe f7 f0 ea ef |z..V....:.y.....| +000000b0 85 9c dc d0 d2 e0 91 cf b4 e7 ea 0b 8e a7 a6 79 |...............y| +000000c0 d1 aa bf 09 c6 ce 4b 53 a2 60 ab 69 de ed 77 a6 |......KS.`.i..w.| +000000d0 96 4a 05 e7 27 88 d7 4d bc 88 66 16 94 bd 49 94 |.J..'..M..f...I.| +000000e0 91 f1 b2 1f c1 b1 f9 ab 96 4e 25 01 e2 c4 24 9a |.........N%...$.| +000000f0 b8 5e 5d e8 44 6a bf 4a 04 44 7b d1 c6 40 a5 07 |.^].Dj.J.D{..@..| +00000100 0c f9 b5 79 71 93 e4 5a c6 d5 e9 1c f3 06 ca e8 |...yq..Z........| +00000110 12 5e e7 fd a3 6b 4b 5f 1b 6c 51 67 fe 6a 02 13 |.^...kK_.lQg.j..| +00000120 f8 68 d6 7a c2 55 d6 19 ef 26 1e 17 5d ae df 63 |.h.z.U...&..]..c| +00000130 51 27 bf 5b 4a 13 69 5f 18 12 03 fe c2 04 7b 84 |Q'.[J.i_......{.| +00000140 cb 35 ad fe d5 22 19 5a db 1d 07 49 a0 e1 03 85 |.5...".Z...I....| +00000150 3e e9 19 48 f9 12 e3 ec 83 d7 bc 6c 71 bd 02 93 |>..H.......lq...| +00000160 d5 bb dd 0a 1a 8d db 6c 65 fe 86 50 a0 38 dc 5f |.......le..P.8._| +00000170 34 3e a6 66 41 b7 1f 54 c1 e2 ea 91 c5 a3 43 0a |4>.fA..T......C.| +00000180 cd 15 2c 13 b2 56 50 02 a9 7f 8b b4 e4 0d 45 39 |..,..VP.......E9| +00000190 9f 65 4b f5 c5 ae 69 27 83 3c 7e d5 7c 9c 26 86 |.eK...i'.<~.|.&.| +000001a0 a4 20 f2 c0 84 cd fb 7d ce 81 9d a6 36 fa 91 b2 |. .....}....6...| +000001b0 f6 62 6f c7 5c 53 05 86 a4 c5 2f 89 97 8f 73 99 |.bo.\S..../...s.| +000001c0 5d 54 1f 26 9a 38 87 af be 2b 7e 24 b4 dc 85 62 |]T.&.8...+~$...b| +000001d0 9d b3 77 4a a6 52 ea ee f1 ae 5f a3 f5 4d f4 2b |..wJ.R...._..M.+| +000001e0 1d d2 60 67 a6 98 0d 67 8b f5 45 d7 29 7e 0c b7 |..`g...g..E.)~..| +000001f0 3f 01 29 3d e2 ee d0 2d 7d e4 3c cc bc 20 51 2a |?.)=...-}.<.. Q*| +00000200 45 1d 41 3b a2 b0 16 68 67 1f 43 1d 65 13 fe 8b |E.A;...hg.C.e...| +00000210 92 ec 2e c0 b2 95 31 65 93 36 75 a0 bf 62 a8 34 |......1e.6u..b.4| +00000220 b0 1d 1a 9b 2f 63 5a 63 75 bd be 3a f6 66 f3 24 |..../cZcu..:.f.$| +00000230 ff b4 d0 ae 36 2d 5e 86 98 53 41 51 18 ff ed 32 |....6-^..SAQ...2| +00000240 33 b2 fd 65 bb 5c 73 c7 f2 e1 f1 2d 0b f7 ee 57 |3..e.\s....-...W| +00000250 b2 35 33 f8 ac 23 cc 57 a7 7e 66 b5 2c e6 01 03 |.53..#.W.~f.,...| +00000260 d5 06 35 7d 9b f4 ca c0 06 73 8e 7e 7c 6b be d2 |..5}.....s.~|k..| +00000270 0f ae ff 94 91 0f bc 2f 9c e8 4a 4a 4b 0e 89 49 |......./..JJK..I| +00000280 c4 be 31 16 7b 16 1a 1d b8 68 7b 15 9e 3c 30 22 |..1.{....h{..<0"| +00000290 11 e1 43 51 |..CQ| +>>> Flow 14 (server to client) +00000000 00 00 00 10 b0 74 fc b1 64 3a 5c 86 ae 3d b3 03 |.....t..d:\..=..| +00000010 e4 8e 53 b4 12 13 2c f6 33 5e 61 f5 bf 2c 52 d5 |..S...,.3^a..,R.| +00000020 d7 2e ba 9a |....| diff --git a/ssh/testdata/Client-MAC-hmac-sha2-512 b/ssh/testdata/Client-MAC-hmac-sha2-512 new file mode 100644 index 0000000000..b7ff3dea82 --- /dev/null +++ b/ssh/testdata/Client-MAC-hmac-sha2-512 @@ -0,0 +1,286 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 6c 13 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...l....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 0d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 00 |..hmac-sha2-512.| +00000230 00 00 0d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |...hmac-sha2-512| +00000240 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 |....none....none| +00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 |..............;.| +00000260 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c b1 ee |.......n..f.&<..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 e1 a8 89 f3 af 88 04 2f 7c 4f |............./|O| +00000010 f3 c4 37 1c e1 db 00 00 01 7a 73 6e 74 72 75 70 |..7......zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 58 e9 46 d2 c0 7e |...,..... X.F..~| +00000010 a3 4f 8e f3 28 59 e0 fe 90 59 d0 b5 89 16 f2 d5 |.O..(Y...Y......| +00000020 ed 34 95 12 7a d4 e5 93 20 10 87 3c 23 dc 62 b8 |.4..z... ..<#.b.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0b 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 2a 5f d6 07 87 dd 29 ba b6 49 |..... *_....)..I| +00000080 07 91 7a 98 cc 9d 95 10 d4 36 ec 67 7b 6d a0 ed |..z......6.g{m..| +00000090 9a 45 ec 4c 92 27 00 00 00 63 00 00 00 13 65 63 |.E.L.'...c....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 48 00 00 00 20 4b c6 d6 d4 87 59 6a |6...H... K....Yj| +000000c0 5e 88 31 d4 bb 86 83 3a d9 32 ca 3d 88 8f a2 24 |^.1....:.2.=...$| +000000d0 f7 11 95 d5 7b 0c f4 df 14 00 00 00 20 11 8a 84 |....{....... ...| +000000e0 c6 b6 f2 0d d3 9f 6d 5f 14 e6 11 fe 84 59 4c 3e |......m_.....YL>| +000000f0 9a ce 66 7c c7 e6 37 f4 e7 bc f8 00 c0 00 00 00 |..f|..7.........| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 83 fc 29 15 |...........@..).| +00000120 23 ba ae cd 80 43 07 c9 38 91 cd c0 80 7f d3 29 |#....C..8......)| +00000130 fe 9a 5c 9e b4 ee 5c 23 d4 f2 af 52 7a 90 03 10 |..\...\#...Rz...| +00000140 53 b5 f4 b7 37 f7 1f ff bc 5f 97 d1 b4 1f 35 14 |S...7...._....5.| +00000150 75 23 7b f0 3b 6c 41 32 f1 f2 c4 dc b1 67 bf ed |u#{.;lA2.....g..| +00000160 aa 9d 3a 83 a0 55 4f 2f 93 15 58 0a 1e b9 0b 2c |..:..UO/..X....,| +00000170 53 6a df 59 a3 54 7e c3 6d 8b d0 d3 7b 03 25 14 |Sj.Y.T~.m...{.%.| +00000180 a2 66 d9 dc b6 2b 30 c7 77 03 1e 08 e2 ff b1 97 |.f...+0.w.......| +00000190 5a 17 46 c3 b0 37 40 1f 53 f4 3d 50 55 bb 21 67 |Z.F..7@.S.=PU.!g| +000001a0 f0 36 2a 33 ec dd cb 30 6c a8 c7 7f b6 23 83 27 |.6*3...0l....#.'| +000001b0 96 8e f4 6e f6 cd 65 a8 c9 d8 a9 53 53 e5 a9 e3 |...n..e....SS...| +000001c0 8f d6 7f 7a a0 d8 ae 4a fb 63 77 47 02 b7 7f c8 |...z...J.cwG....| +000001d0 52 f9 14 9e fa a9 bb 2b 6b f7 79 40 a7 25 dc ff |R......+k.y@.%..| +000001e0 11 89 96 3d 88 26 f9 bd 2f f3 d5 8b 6b b9 e8 63 |...=.&../...k..c| +000001f0 22 c1 93 2a ae 04 0b 75 9b 8c 9d 3c 35 b0 d5 e7 |"..*...u...<5...| +00000200 e0 b6 c7 95 6c 97 8c 25 70 96 d3 32 dd 18 b8 2c |....l..%p..2...,| +00000210 ed 63 f9 d6 5c 6f f7 78 e6 11 ef e4 1f 12 1f 45 |.c..\o.x.......E| +00000220 6f c6 b0 02 32 c4 05 fb 88 f5 ef 14 12 c9 26 73 |o...2.........&s| +00000230 9c 5e 11 1c fe c7 38 dc 6f de 2e ad 84 9c e9 de |.^....8.o.......| +00000240 1a a0 fc a9 9a f4 71 64 20 15 97 29 0f 5d 2e 4c |......qd ..).].L| +00000250 6c 56 55 5c d4 22 00 85 69 d8 c4 e5 1a 88 e4 14 |lVU\."..i.......| +00000260 57 6a 1f e2 59 8f 22 ef 1b 15 a1 e6 |Wj..Y.".....| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000010 00 00 00 20 d2 0b a7 43 38 68 d9 3a 68 2e 58 91 |... ...C8h.:h.X.| +00000020 1e 3c b9 ee ff 13 3a 39 35 5a aa 60 94 e1 7e 6a |.<....:95Z.`..~j| +00000030 69 93 bf 57 54 eb f2 af f2 f9 78 5a 00 1f 75 9a |i..WT.....xZ..u.| +00000040 d8 0d cd 54 |...T| +>>> Flow 8 (server to client) +00000000 00 00 00 20 bb 5d 5b 6f 48 ef de a5 e1 eb fd dd |... .][oH.......| +00000010 cd 68 e0 5b c0 fc a3 f2 b6 c6 b4 5b fa 17 0f a3 |.h.[.......[....| +00000020 a3 e6 57 d0 09 3e 1d 0f c8 be 8e d0 4e 56 b3 bc |..W..>......NV..| +00000030 a1 35 87 aa |.5..| +>>> Flow 9 (client to server) +00000000 00 00 00 30 1f cd 85 73 ad 59 b4 36 5b 48 bf d8 |...0...s.Y.6[H..| +00000010 7a 78 f3 6e 5f fc 11 58 74 99 a6 96 e9 2d ad cc |zx.n_..Xt....-..| +00000020 e2 bf 8f 08 ca 38 da 28 c6 d2 8b 7a 03 32 a6 e1 |.....8.(...z.2..| +00000030 85 d8 a6 99 4e 84 08 35 62 64 b2 c1 e2 16 0c 69 |....N..5bd.....i| +00000040 dd 6b f6 75 |.k.u| +>>> Flow 10 (server to client) +00000000 00 00 00 20 fb e8 98 9d 69 75 b6 98 1c 07 e6 72 |... ....iu.....r| +00000010 c7 d0 e3 19 7b 8e b5 a6 7c 6f 0d 7b 94 08 a3 41 |....{...|o.{...A| +00000020 32 3f 2a b6 15 e9 70 cb b2 ee 95 e0 5a 18 9f f6 |2?*...p.....Z...| +00000030 e9 22 67 2d 00 00 00 40 62 3f 31 90 60 c8 1d 2d |."g-...@b?1.`..-| +00000040 b9 1e 3f 70 46 6a b4 fe 60 fd d3 ae 2e 9a 78 83 |..?pFj..`.....x.| +00000050 c0 3f 68 cd 43 bb f9 fb 51 53 3b c6 12 e9 f2 fe |.?h.C...QS;.....| +00000060 2a 67 6a a4 5e 80 5d 1e 40 5c 2a f4 73 db a1 ce |*gj.^.].@\*.s...| +00000070 4d d2 d5 d9 44 4c ae 8b fb 7f 14 b0 08 1b 9d 6d |M...DL.........m| +00000080 36 28 5a a5 93 c1 c2 05 |6(Z.....| +>>> Flow 11 (client to server) +00000000 00 00 01 60 86 8c 58 89 d7 0a f9 26 c7 ec f5 43 |...`..X....&...C| +00000010 c1 14 47 83 c7 a6 e5 d7 22 d8 a3 65 fd 1d 6b ef |..G....."..e..k.| +00000020 03 a5 c8 2a aa 1b 9b 37 91 31 33 72 8b 6f cc cb |...*...7.13r.o..| +00000030 99 50 79 79 c2 f2 f3 0d d1 3c e8 22 ec 65 76 ab |.Pyy.....<.".ev.| +00000040 05 92 2c 15 83 f3 23 d0 3d 6b fa 44 87 c7 c6 0d |..,...#.=k.D....| +00000050 02 14 df 43 11 50 3a 63 14 c4 f2 31 ed 32 68 60 |...C.P:c...1.2h`| +00000060 c7 11 9c 14 15 8b 64 29 b9 99 eb 50 6f 7c cc b2 |......d)...Po|..| +00000070 d7 e1 63 be 47 fd b4 e4 82 16 40 67 f0 5a 0c 2c |..c.G.....@g.Z.,| +00000080 ad fd d6 d7 4d 64 ff 99 32 05 78 b9 77 7d 06 0e |....Md..2.x.w}..| +00000090 06 9a ef 53 90 e7 ef f5 1f d2 2c 47 fc 36 9b 7c |...S......,G.6.|| +000000a0 4c 82 34 2c 75 23 f5 23 46 97 9d a2 fb 91 f7 26 |L.4,u#.#F......&| +000000b0 6d 54 ba b7 48 d7 7b 9a 5d 3e aa ef da b1 ed 60 |mT..H.{.]>.....`| +000000c0 f7 a3 51 24 f0 46 19 e0 06 99 68 e0 a2 78 fc 98 |..Q$.F....h..x..| +000000d0 2d 97 21 89 87 45 3a 99 74 7d e1 ab 1f 3f 2b 41 |-.!..E:.t}...?+A| +000000e0 c0 a8 7f dd 80 c6 9e d0 b1 25 7d 3d 64 1b 9a 02 |.........%}=d...| +000000f0 ee 3a 92 0c 48 3f 9b cf 35 81 a2 22 61 71 a1 fc |.:..H?..5.."aq..| +00000100 eb 1d 14 c3 66 4a 7c 40 f9 81 95 14 88 8b a7 ea |....fJ|@........| +00000110 6c 42 04 cc 41 56 77 d7 ec 0a 6b d5 75 97 f0 82 |lB..AVw...k.u...| +00000120 8e bf b5 a4 c6 2c 61 6f ac 87 40 31 04 f5 66 71 |.....,ao..@1..fq| +00000130 2d d9 02 b2 eb 25 9e 30 49 5d db 26 db 93 02 a1 |-....%.0I].&....| +00000140 db 5c 3f 1b 29 4f 57 c0 22 ee 2f d4 4d ff 6f 0b |.\?.)OW."./.M.o.| +00000150 12 61 47 90 02 7d a2 27 ea 99 a9 5a e1 1f f8 73 |.aG..}.'...Z...s| +00000160 ea 60 7c c2 a8 2b e1 d5 0f 81 dd 41 a5 4c 09 a1 |.`|..+.....A.L..| +00000170 db d1 ff d3 |....| +>>> Flow 12 (server to client) +00000000 00 00 01 40 7b f3 dc aa a9 f8 f7 66 c6 09 47 08 |...@{......f..G.| +00000010 aa f3 2e 63 3a e0 5c 5b 75 2a b7 c3 c2 f1 2f cd |...c:.\[u*..../.| +00000020 c5 c1 91 87 d6 a2 55 d6 5b 8b 70 20 e0 b8 f2 6c |......U.[.p ...l| +00000030 e0 9d 3f da 6f 67 c6 51 48 1d ed d7 80 7d de 7c |..?.og.QH....}.|| +00000040 6e c9 0c 12 06 76 94 e8 47 85 39 45 1d 62 43 12 |n....v..G.9E.bC.| +00000050 f6 28 b5 19 10 08 88 16 43 06 69 eb 83 c9 f6 06 |.(......C.i.....| +00000060 3a 3b 4f fe cf 40 f8 91 b7 9f fc 9c 50 73 2d 3c |:;O..@......Ps-<| +00000070 a0 6b 99 af 20 c7 02 50 67 2d 51 eb 0c b5 d0 cf |.k.. ..Pg-Q.....| +00000080 b3 43 4c 1d a7 68 7e bf 81 2a c1 1f c0 6f 84 82 |.CL..h~..*...o..| +00000090 3d 1d b0 ab dd 4f 86 78 c8 b7 4e a3 90 12 85 81 |=....O.x..N.....| +000000a0 8c df eb 6f 24 82 2b 0c a6 fc 49 ce ed f8 9b a7 |...o$.+...I.....| +000000b0 2a fd e0 cd 3a de d1 53 2f e4 fd fd 07 0d 26 28 |*...:..S/.....&(| +000000c0 7f 24 81 f8 94 0c 81 b3 e2 6d 87 91 46 c4 fe 32 |.$.......m..F..2| +000000d0 81 9e ca b5 77 29 05 2e 3d de fc 32 53 ef 3f ea |....w)..=..2S.?.| +000000e0 72 0c 85 c6 cb 75 62 50 14 86 2d 6d 18 9b d4 f4 |r....ubP..-m....| +000000f0 dc 8a 5b b4 56 31 8f f8 3e 44 19 0f 27 ae 7b b0 |..[.V1..>D..'.{.| +00000100 10 6a 6a d4 db 99 de e2 ee ba b7 f1 00 c5 6f f9 |.jj...........o.| +00000110 8f 04 2a 10 48 0b 49 07 c1 f3 13 93 bf dd 4d da |..*.H.I.......M.| +00000120 f1 8f 9c 77 dc f5 79 c7 e4 5d be a8 1b 44 81 5f |...w..y..]...D._| +00000130 5b 95 12 c1 27 01 0e 48 61 bf 40 98 e9 8a a6 62 |[...'..Ha.@....b| +00000140 1f 4f ef c0 bb d8 c7 dc de 61 2d fd 4b 0e 09 00 |.O.......a-.K...| +00000150 10 b2 74 65 |..te| +>>> Flow 13 (client to server) +00000000 00 00 02 80 83 74 77 ab 01 57 c3 74 7c 1a 15 a6 |.....tw..W.t|...| +00000010 c6 0e 5a 90 f7 ed dd b1 b1 c3 0d 37 b4 0a 06 4b |..Z........7...K| +00000020 e4 f3 93 cf 1d 08 46 cf 19 55 d6 a4 5d 49 fe 8c |......F..U..]I..| +00000030 cf 62 66 9a ce 2f ef 7e e9 6f 36 1d 8c 88 e9 ee |.bf../.~.o6.....| +00000040 fb 0b 3b 59 fd 78 31 6e 3d 79 84 e0 d2 9f 7f 95 |..;Y.x1n=y......| +00000050 53 36 e9 11 8c c6 54 a0 b8 af 2e 8b 32 cd a8 2c |S6....T.....2..,| +00000060 13 2f f9 f7 a0 67 71 5b ea d0 ca e2 d9 b0 e3 62 |./...gq[.......b| +00000070 19 68 45 2d ef 61 e7 dc a8 a9 5e ca 31 83 90 28 |.hE-.a....^.1..(| +00000080 b2 32 2a e6 4e c3 8c e6 c7 12 cb 27 7f 87 26 7f |.2*.N......'..&.| +00000090 55 b7 9d a4 df 6e 31 1c 58 a4 9b e9 15 01 bb 1a |U....n1.X.......| +000000a0 da 21 9b 38 85 58 4f 78 41 a1 cf 0c 23 1d 51 58 |.!.8.XOxA...#.QX| +000000b0 dc 91 4e 88 27 85 90 b6 35 54 51 b6 4d 87 9a 25 |..N.'...5TQ.M..%| +000000c0 ce 30 0f d5 d8 79 a3 dc 69 b8 5b d6 67 57 16 0d |.0...y..i.[.gW..| +000000d0 fb 2b 11 53 e0 03 b3 6c 9b 5d 86 14 1e 4b eb 29 |.+.S...l.]...K.)| +000000e0 3e 4c ea 27 76 1a a3 af 8a 12 73 65 a5 ba e2 47 |>L.'v.....se...G| +000000f0 cc 34 db a3 19 23 5e a1 12 4c 1a fb a7 5b db b9 |.4...#^..L...[..| +00000100 38 40 d7 9e a3 2a 97 a1 14 54 47 03 a3 d6 d1 af |8@...*...TG.....| +00000110 19 89 3b 5b a3 8b d3 35 02 83 08 f9 1f fe 4c 4b |..;[...5......LK| +00000120 8b 59 e1 6b 04 d9 ec 5c ab 04 8b 1f 1b ea ca af |.Y.k...\........| +00000130 33 f8 4e 54 a6 de aa 9e 78 1c a1 fe e7 17 8e 14 |3.NT....x.......| +00000140 0e f7 a7 63 fb 36 82 f1 c8 6e 21 ca b7 ee ee 55 |...c.6...n!....U| +00000150 b1 cc 27 3c b5 63 c9 6f b8 73 71 64 be f5 80 98 |..'<.c.o.sqd....| +00000160 9b 47 4b bb 37 10 e4 3b 37 da 15 c4 4a 44 c6 79 |.GK.7..;7...JD.y| +00000170 96 3e ca 10 3f db 4a 5b 85 43 e8 1d f3 3d c6 ed |.>..?.J[.C...=..| +00000180 7e 01 5b b5 e8 17 98 78 ff 72 81 a8 6c 39 7b 64 |~.[....x.r..l9{d| +00000190 fa b9 d2 55 09 09 77 9f d4 51 db 32 eb 39 75 19 |...U..w..Q.2.9u.| +000001a0 0e 78 b4 f1 4c 1b 46 d0 d9 62 99 2a a9 a5 6c fb |.x..L.F..b.*..l.| +000001b0 8f 2b 75 e9 6f 03 a6 f3 29 68 c4 35 41 94 36 d2 |.+u.o...)h.5A.6.| +000001c0 f6 67 9f 00 b2 26 0a 97 2d 05 1b f9 ca 81 e0 a3 |.g...&..-.......| +000001d0 25 ab 0c 2f 4e 5e 7a 10 4a 04 68 1c c3 66 82 3f |%../N^z.J.h..f.?| +000001e0 4c 7b bf c4 0f a2 53 e2 b3 e8 8f 70 91 23 2d b6 |L{....S....p.#-.| +000001f0 d4 f7 fc ec da 1e 1a a3 05 18 c0 e5 41 de 32 43 |............A.2C| +00000200 c0 69 cd 8c 5d d2 74 76 7d 0c 3d fa 6f 2a 36 8c |.i..].tv}.=.o*6.| +00000210 dd 29 88 35 2e 5f ff 17 9e 4a 61 5a f3 ee b5 47 |.).5._...JaZ...G| +00000220 85 13 1f ac 02 8f 6c 41 89 9c a9 2b 12 eb ac 0f |......lA...+....| +00000230 11 b7 84 54 89 a0 c2 cc 75 91 e1 cf 44 19 f5 2d |...T....u...D..-| +00000240 e6 e5 c4 ec 99 54 a2 36 02 72 a7 dd a2 b7 a5 60 |.....T.6.r.....`| +00000250 c2 8b 97 72 7e 9f d2 7f 06 45 87 b9 f8 7d cc 00 |...r~....E...}..| +00000260 16 2f fd 09 7c d3 08 30 66 a5 32 d8 b3 6a eb b6 |./..|..0f.2..j..| +00000270 1f 35 76 5b d2 fb e6 79 81 7a 6a 0d ed 01 0c f4 |.5v[...y.zj.....| +00000280 86 d2 a8 8f e9 b1 43 16 10 a8 48 ca f5 ec 47 d0 |......C...H...G.| +00000290 53 96 95 7b |S..{| +>>> Flow 14 (server to client) +00000000 00 00 00 10 2c 6d e4 6b 21 cb f7 23 c0 3f 4b f0 |....,m.k!..#.?K.| +00000010 53 44 a7 ec 0c 5a e1 48 e2 d3 b7 56 c1 7d d6 50 |SD...Z.H...V.}.P| +00000020 6e f5 25 78 |n.%x| diff --git a/ssh/testdata/Client-MAC-hmac-sha2-512-etm@openssh.com b/ssh/testdata/Client-MAC-hmac-sha2-512-etm@openssh.com new file mode 100644 index 0000000000..944a6894ba --- /dev/null +++ b/ssh/testdata/Client-MAC-hmac-sha2-512-etm@openssh.com @@ -0,0 +1,288 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 02 8c 13 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 1d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |..hmac-sha2-512-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |etm@openssh.com.| +00000240 00 00 1d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |...hmac-sha2-512| +00000250 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000260 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 |....none....none| +00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 |..............;.| +00000280 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c b1 ee |.......n..f.&<..| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 c1 b9 0c 42 04 32 fd 2c 91 f4 |.........B.2.,..| +00000010 1a 72 5a b7 64 98 00 00 01 7a 73 6e 74 72 75 70 |.rZ.d....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 58 e9 46 d2 c0 7e |...,..... X.F..~| +00000010 a3 4f 8e f3 28 59 e0 fe 90 59 d0 b5 89 16 f2 d5 |.O..(Y...Y......| +00000020 ed 34 95 12 7a d4 e5 93 20 10 87 3c 23 dc 62 b8 |.4..z... ..<#.b.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 df c1 48 1c ad 81 eb 0f e1 c1 |..... ..H.......| +00000080 1c 98 0f 4d 0d ba 4b 5a 93 58 c4 5e e0 95 fe 47 |...M..KZ.X.^...G| +00000090 cd d7 9c f4 88 50 00 00 00 64 00 00 00 13 65 63 |.....P...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 39 3e 4f e9 fb 21 75 |6...I... 9>O..!u| +000000c0 61 6f 82 28 7d 45 34 45 95 04 0d fe 3a d7 50 e8 |ao.(}E4E....:.P.| +000000d0 84 77 01 d1 89 2e 76 56 a7 00 00 00 21 00 d0 8b |.w....vV....!...| +000000e0 6f 57 ec b6 12 3b 08 ba 69 be 09 0c 51 df 44 38 |oW...;..i...Q.D8| +000000f0 1f d6 27 d5 9f ba a6 60 40 1c 91 50 60 4a 00 00 |..'....`@..P`J..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 01 62 40 e5 |...........@.b@.| +00000120 62 01 aa 33 3f da e4 81 a4 96 cf a5 e8 80 b0 6e |b..3?..........n| +00000130 15 fd e6 3c de 9b 9d 57 ee a6 39 53 a4 a8 4a 88 |...<...W..9S..J.| +00000140 34 61 db 77 4a ec 54 7e 26 61 2d 58 d6 80 45 92 |4a.wJ.T~&a-X..E.| +00000150 99 8b 8b 9d 5b 24 9b cb 45 36 03 73 f5 33 26 73 |....[$..E6.s.3&s| +00000160 d0 d1 80 c3 76 e2 04 d3 a0 5e 0f e6 b0 8c aa 3f |....v....^.....?| +00000170 d6 e7 9b d9 37 17 76 f6 f0 4e 8a 41 54 6c 1b 4a |....7.v..N.ATl.J| +00000180 dd d1 11 44 5d 15 e5 0b 42 e5 f7 ca 58 d2 c2 84 |...D]...B...X...| +00000190 23 85 c1 7a a8 6b ad 56 b5 a5 87 a1 3a f6 2c 4b |#..z.k.V....:.,K| +000001a0 67 d3 67 bc 06 1c 19 8f 5e 7d 9d bf 74 7a df 48 |g.g.....^}..tz.H| +000001b0 3a 7b 1c ec dc 5b c9 d6 45 ba b2 5b f6 6b 46 86 |:{...[..E..[.kF.| +000001c0 28 c1 78 f0 9a f9 fc a1 69 67 b4 31 28 9c 84 ed |(.x.....ig.1(...| +000001d0 6e b3 3b bc 79 d5 2d 9b 03 c5 7f e3 0c db ea 7b |n.;.y.-........{| +000001e0 36 56 ff a3 34 bf ba f8 63 ed 0e 58 07 1c 87 f1 |6V..4...c..X....| +000001f0 27 b0 95 20 c9 5b 13 8a 83 eb 9f 48 a0 8b 8a 6e |'.. .[.....H...n| +00000200 9c 8c 56 c3 ba 84 3c dd c6 54 07 15 11 dc c6 4c |..V...<..T.....L| +00000210 3e 88 87 45 c8 9c 7b 9e a3 ab 28 6a 67 fa cc 1a |>..E..{...(jg...| +00000220 9d b4 26 65 42 1c a0 be c5 e7 22 7c ab b6 d5 b2 |..&eB....."|....| +00000230 74 82 0b 4e e1 5f 26 c0 c9 88 eb 0b 34 b3 07 84 |t..N._&.....4...| +00000240 0f 77 c1 8f 94 d9 07 1e a6 10 df fc b0 75 e2 76 |.w...........u.v| +00000250 ae 1c bb fb 15 1a c6 b4 2d 2e 83 d6 d9 fa 3e 2f |........-.....>/| +00000260 ee d3 fb 8e 5b c0 48 a4 79 d6 c6 a6 |....[.H.y...| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000010 00 00 00 20 c7 37 c8 07 1d 90 75 19 74 46 2c 01 |... .7....u.tF,.| +00000020 35 e7 67 f3 29 5a f1 77 7b 22 36 68 d6 de 84 75 |5.g.)Z.w{"6h...u| +00000030 3b e8 75 9e 8f bb d6 f6 5e 44 82 ef 0d 68 88 ac |;.u.....^D...h..| +00000040 c2 6d c8 fe |.m..| +>>> Flow 8 (server to client) +00000000 00 00 00 20 1d 6e c3 3a 53 aa 4d c7 45 43 21 56 |... .n.:S.M.EC!V| +00000010 69 d3 73 67 85 53 f3 9c ac 5d dc 0f ef 42 56 7c |i.sg.S...]...BV|| +00000020 33 04 29 3d a5 54 cf 58 3d b9 6d 28 27 20 92 61 |3.)=.T.X=.m(' .a| +00000030 bc 10 17 95 |....| +>>> Flow 9 (client to server) +00000000 00 00 00 30 b2 c3 9f 28 a0 06 1d b0 12 aa bc 15 |...0...(........| +00000010 e1 d7 38 5b 69 a5 f8 0b b6 73 98 0d cc c8 b5 cb |..8[i....s......| +00000020 77 25 ec dd 20 81 f4 70 c1 ce 01 c9 26 00 26 4c |w%.. ..p....&.&L| +00000030 8e 58 af 50 5c fb 7d cc de 1f 9a c0 76 c3 a9 6e |.X.P\.}.....v..n| +00000040 97 76 2e 91 |.v..| +>>> Flow 10 (server to client) +00000000 00 00 00 20 e1 86 c8 4f 25 26 a2 42 74 e3 4c 3d |... ...O%&.Bt.L=| +00000010 de dc 78 b2 e6 5c ed b4 b8 8c ff 54 9c d1 13 c4 |..x..\.....T....| +00000020 fb 3d 43 e7 19 e4 cb ad 50 a3 e0 db b1 d2 1d 66 |.=C.....P......f| +00000030 b8 20 37 46 00 00 00 40 be e8 62 86 43 85 39 36 |. 7F...@..b.C.96| +00000040 f4 7a 13 92 b9 31 71 9f f6 4a 9f 05 de a1 6f 49 |.z...1q..J....oI| +00000050 19 f6 77 3f 99 9f 20 b4 71 e6 9d 79 fc b2 62 f9 |..w?.. .q..y..b.| +00000060 07 3d 9e 9a 85 11 cd 2f 81 31 d2 1e 20 03 e4 55 |.=...../.1.. ..U| +00000070 1f c2 c7 43 4a a5 23 d9 48 79 19 bd 51 9c 1f 11 |...CJ.#.Hy..Q...| +00000080 e8 5e 55 cc 14 6b c8 fa |.^U..k..| +>>> Flow 11 (client to server) +00000000 00 00 01 60 76 ec cd 49 74 07 f7 35 3f fa 4f 68 |...`v..It..5?.Oh| +00000010 05 f1 39 8f 5b c4 75 8a 2c 65 81 25 39 6e b1 96 |..9.[.u.,e.%9n..| +00000020 90 72 b0 96 b8 b6 be 14 7a b4 e2 c0 04 75 da a2 |.r......z....u..| +00000030 d2 8c 9e d5 63 1b ba 16 bd da c6 fd 9e 4e 02 42 |....c........N.B| +00000040 37 4d 63 d7 2a f9 d2 f8 06 98 8b ce a2 2a 8a 9e |7Mc.*........*..| +00000050 84 11 15 f7 aa 7b 2f 07 29 d2 11 4a 07 ad c9 b3 |.....{/.)..J....| +00000060 6e 64 6c 5b ea 57 ee ad f4 ed 62 bc 2b fd f0 dd |ndl[.W....b.+...| +00000070 13 04 ac ea 02 f1 dc 67 a4 29 4b 8c 8d 5c 68 19 |.......g.)K..\h.| +00000080 2c 64 29 5e 12 d8 7f fe 0c 53 fb 5c 0e 3f 99 fe |,d)^.....S.\.?..| +00000090 2d e6 de 87 2c ef 74 fb 0b c7 ae 6e b0 40 35 57 |-...,.t....n.@5W| +000000a0 cd 00 17 fd 67 54 a4 73 88 55 9f 13 5a f8 a7 5b |....gT.s.U..Z..[| +000000b0 f9 25 55 cd 8d b6 1e 70 a1 f3 25 fc 07 da fa b1 |.%U....p..%.....| +000000c0 8c b2 ce 97 4d 10 9e 01 85 6a cc 9a 8d 7d 0f 80 |....M....j...}..| +000000d0 17 d9 a0 6b a8 22 59 e7 65 59 59 0c b7 7e 4c f3 |...k."Y.eYY..~L.| +000000e0 70 cd 58 3f e6 59 03 43 50 a6 63 98 26 3f d8 1e |p.X?.Y.CP.c.&?..| +000000f0 07 5e 24 53 8d 3c 13 a4 e2 48 6f 65 79 fc b6 73 |.^$S.<...Hoey..s| +00000100 3e ba 50 65 7a 4d 09 06 b8 a9 c2 a3 05 80 12 c2 |>.PezM..........| +00000110 66 5d dd 5f 05 e9 f5 c4 f2 b1 ff 0c 7f d5 22 a8 |f]._..........".| +00000120 ad b3 13 98 a7 49 e5 94 94 da 0f 56 f4 56 98 12 |.....I.....V.V..| +00000130 7d b2 a9 6b 17 7f a2 e0 ac 5b f1 e3 3e ad 72 cf |}..k.....[..>.r.| +00000140 0b 51 51 94 f5 81 7e ec 38 8b b6 94 22 99 b4 91 |.QQ...~.8..."...| +00000150 0e c1 2c 37 d9 e6 c2 3c ee 27 22 1c 08 a1 c1 92 |..,7...<.'".....| +00000160 bb f4 e4 bc d3 83 43 18 01 28 48 43 96 3c e7 9f |......C..(HC.<..| +00000170 c3 dc 79 ef |..y.| +>>> Flow 12 (server to client) +00000000 00 00 01 40 63 04 fd c7 19 d7 8d f5 fa c3 d7 a2 |...@c...........| +00000010 86 d1 f0 9f f0 9f 1b 03 3e 3a b4 92 22 ed cf 82 |........>:.."...| +00000020 72 e7 ae 8b 71 75 72 f1 99 80 93 a2 b8 f3 57 c3 |r...qur.......W.| +00000030 ae e9 90 54 33 54 72 31 c3 89 c7 f6 30 ac c9 3b |...T3Tr1....0..;| +00000040 d1 13 a0 b1 cd a8 cc bb 71 09 ba 13 e2 f8 71 3b |........q.....q;| +00000050 99 fb 96 dc 28 c0 55 55 45 90 85 73 f5 4c fc 93 |....(.UUE..s.L..| +00000060 fe c2 85 b2 5d aa 60 c8 5c 4f 9a 17 05 eb 2b 59 |....].`.\O....+Y| +00000070 99 5b 5d 86 0f e8 26 c0 30 dc 02 52 97 57 ed 4b |.[]...&.0..R.W.K| +00000080 e1 13 2d ed cb 96 66 b8 27 f1 94 b3 19 10 3b 75 |..-...f.'.....;u| +00000090 87 dc 07 c9 8e 26 7d e9 d7 c0 c1 66 4b e9 ee 3f |.....&}....fK..?| +000000a0 8d 5e 3b 1d 67 33 5e 50 09 67 b9 f8 9d d6 3f 2c |.^;.g3^P.g....?,| +000000b0 71 d8 23 c4 25 07 16 f5 e1 2c 2e ea 75 8f 1b ff |q.#.%....,..u...| +000000c0 b2 d4 1d 03 c0 03 5b 22 93 cb 57 11 6b 94 99 af |......["..W.k...| +000000d0 76 c0 7f ae eb 79 94 cc 1b 66 9a dd 30 58 1a 03 |v....y...f..0X..| +000000e0 14 ab 94 9f 3c 3e 2d a2 f3 01 0b b0 98 35 a9 ca |....<>-......5..| +000000f0 a1 d2 72 f0 80 55 49 6d 2e c2 b4 69 78 75 ff 5c |..r..UIm...ixu.\| +00000100 3f 01 4c e4 32 bc 13 12 cc c3 ad 88 3b 65 17 b6 |?.L.2.......;e..| +00000110 d2 09 d0 19 ef 38 a8 19 c6 88 0b 5a 51 5b 38 90 |.....8.....ZQ[8.| +00000120 e9 77 99 94 25 e5 ea 0d e3 60 e4 14 a3 84 6d 05 |.w..%....`....m.| +00000130 01 f8 c6 3f 21 04 e0 28 54 73 3a 83 e3 de d9 33 |...?!..(Ts:....3| +00000140 90 8a 13 6a 4a 78 cf 73 10 c5 4c 16 89 2b c8 e8 |...jJx.s..L..+..| +00000150 51 1a 48 84 |Q.H.| +>>> Flow 13 (client to server) +00000000 00 00 02 80 b7 6a 17 dc 1c 39 7f f6 4c 81 a4 0e |.....j...9..L...| +00000010 c9 23 5c 38 be 3a 2d c4 da 2b a4 f9 a1 17 d6 52 |.#\8.:-..+.....R| +00000020 4f f0 2a 6a 57 ec 2d 61 9b 46 fe 80 c4 b0 d0 2f |O.*jW.-a.F...../| +00000030 55 10 90 1d 9d 6c d6 08 8d 1b f5 7e f2 be 64 c7 |U....l.....~..d.| +00000040 70 7f b1 25 b9 c9 fe 7f a6 d0 2a fd 10 4f db 45 |p..%......*..O.E| +00000050 1d e4 46 7a a0 0c 80 bc cc 88 ff 49 98 e4 2f 35 |..Fz.......I../5| +00000060 ef bb bb df b1 a4 c3 41 f2 51 d6 2e fe fd a8 95 |.......A.Q......| +00000070 10 b3 11 43 db e9 1f 4f f3 45 36 8a a7 be 8b a4 |...C...O.E6.....| +00000080 6b 18 89 88 a9 66 74 33 87 ef 54 eb 98 9f d9 d9 |k....ft3..T.....| +00000090 36 b5 c4 9d 13 ee 4a 07 5b 25 b0 b3 28 ea 23 14 |6.....J.[%..(.#.| +000000a0 6a cb 1c ab 1f f4 47 be a3 de 66 1e bd 24 1f e8 |j.....G...f..$..| +000000b0 3a 1e bc 73 20 9e 7e 04 d4 b9 1f 0b 89 c7 fa 4e |:..s .~........N| +000000c0 5c 66 8a 4d 65 4d a1 c3 03 77 fa 20 a7 97 ea 74 |\f.MeM...w. ...t| +000000d0 a2 e8 ec 28 d1 8d 0f 41 4c 14 e1 0e a5 9a 5a a2 |...(...AL.....Z.| +000000e0 a1 1a d7 0c 01 0e 36 b0 a0 35 07 51 06 db e2 c5 |......6..5.Q....| +000000f0 35 c0 fe 6c 0b f7 fb 6f e7 c8 4b 13 64 a8 14 cc |5..l...o..K.d...| +00000100 8c f6 0a 21 b7 2d 9a 51 62 06 e3 c8 13 24 cf a3 |...!.-.Qb....$..| +00000110 55 c9 40 97 48 cf 1f c4 11 09 45 d1 0f 98 94 49 |U.@.H.....E....I| +00000120 59 70 c6 2c ad 42 9b 08 cb 14 da 05 49 b7 d9 4f |Yp.,.B......I..O| +00000130 48 77 5f 8d b5 4c 3f 2c 4e e2 1d 71 2e 89 0d ef |Hw_..L?,N..q....| +00000140 13 fb f6 56 f3 9f 39 40 d6 c9 72 85 95 15 f3 e3 |...V..9@..r.....| +00000150 17 54 ab 46 71 97 16 57 7c 4a dd aa f8 77 88 c1 |.T.Fq..W|J...w..| +00000160 68 12 25 1e 6e 9e 3b aa 23 29 f9 91 0d bd fc dd |h.%.n.;.#)......| +00000170 f3 a9 0f 43 95 79 87 3d cc f9 f1 b4 c9 f6 54 1f |...C.y.=......T.| +00000180 bd 66 ee f3 ee f0 70 49 2d 52 db 72 0b 53 a4 f6 |.f....pI-R.r.S..| +00000190 53 3a b7 5c 01 d8 c1 14 f7 7f a3 43 2d f6 2b 19 |S:.\.......C-.+.| +000001a0 d6 3d 71 f2 c7 03 ad 69 4f 9c 36 2e 46 3a 7d 8f |.=q....iO.6.F:}.| +000001b0 43 f6 3a ef cd ca f2 bc 95 ed 6b 77 55 f0 2e 7f |C.:.......kwU...| +000001c0 49 80 f7 11 89 54 26 69 b9 e6 d1 4a 96 dd ce aa |I....T&i...J....| +000001d0 f0 08 29 c0 c7 13 2c 6d 3d 82 93 26 6c 56 d1 f9 |..)...,m=..&lV..| +000001e0 77 b4 18 51 04 0a 68 46 bb af 65 20 e3 e8 b6 d7 |w..Q..hF..e ....| +000001f0 29 35 77 19 82 1e d1 c6 9c 03 e0 6f 9e 28 89 bb |)5w........o.(..| +00000200 bc 4c 66 a0 6f 54 40 96 8f 2b a9 1d 54 7d 6f 07 |.Lf.oT@..+..T}o.| +00000210 c8 72 6f 21 54 18 35 5d aa 6d 52 3c 6a 2f a0 14 |.ro!T.5].mRw..A| +00000280 3c ef 7a 60 25 96 ff 29 da 64 b7 e3 f7 27 49 d3 |<.z`%..).d...'I.| +00000290 d3 a6 27 dc |..'.| +>>> Flow 14 (server to client) +00000000 00 00 00 10 b3 2c 38 24 ac 1d 47 0c 73 18 d7 41 |.....,8$..G.s..A| +00000010 bc 0f 2c a4 d3 1b b3 3f f7 cb a0 8b 53 f5 58 d3 |..,....?....S.X.| +00000020 27 65 8a ba |'e..| diff --git a/ssh/testdata/Client-RunCommandFailed b/ssh/testdata/Client-RunCommandFailed new file mode 100644 index 0000000000..dc25ff53f3 --- /dev/null +++ b/ssh/testdata/Client-RunCommandFailed @@ -0,0 +1,390 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 71 96 a2 5b 69 96 28 ae 53 f1 |......q..[i.(.S.| +00000010 ec 6b 35 17 b7 7e 00 00 01 7a 73 6e 74 72 75 70 |.k5..~...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 ba af ab 3c 1d 65 de 9a 8c 4f |..... ...<.e...O| +00000080 1d 07 bd d2 5e 05 3a e5 fc 63 c4 90 e4 a3 73 cb |....^.:..c....s.| +00000090 85 af 6a d8 62 12 00 00 00 64 00 00 00 13 65 63 |..j.b....d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 69 56 4e 57 04 97 c7 |6...I... iVNW...| +000000c0 e2 6c 2c 23 49 e5 05 87 ef 3e bd 5a 76 b6 1d 40 |.l,#I....>.Zv..@| +000000d0 39 56 7c 34 0d 58 77 eb cf 00 00 00 21 00 de db |9V|4.Xw.....!...| +000000e0 50 7e f3 98 74 e6 52 8d f0 4b 69 b1 c7 57 74 46 |P~..t.R..Ki..WtF| +000000f0 f8 7d 08 b9 a4 35 47 39 97 5a db 88 8b 8d 00 00 |.}...5G9.Z......| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 88 31 36 6c |...........@.16l| +00000120 4d ee 00 c9 8d e4 96 1a 45 ef 12 ed 20 a2 58 b3 |M.......E... .X.| +00000130 0d c3 af 83 c5 1f be f2 06 06 7e ad 06 7a 63 23 |..........~..zc#| +00000140 c8 d3 d1 68 f5 6e 42 d9 4b 69 6e ed a6 be 7c 58 |...h.nB.Kin...|X| +00000150 69 d1 05 f5 11 d0 b1 e7 cf 6c f4 53 a0 c6 da a3 |i........l.S....| +00000160 f1 d9 87 ef aa 63 69 45 ba 95 a5 8b 8f ee df b1 |.....ciE........| +00000170 6d 0f af af 00 07 0c 0f b1 21 0e 0c 28 14 c2 b1 |m........!..(...| +00000180 32 74 a6 4a a9 6f ca 10 56 7a 05 77 5c ef b6 ac |2t.J.o..Vz.w\...| +00000190 b3 65 60 20 f4 38 9f bf cc a4 13 ea 2e f3 5e d0 |.e` .8........^.| +000001a0 74 81 f7 7d 6e 42 a5 42 28 d6 e4 ef ca 87 12 02 |t..}nB.B(.......| +000001b0 e4 57 9e 10 0a 76 a7 a1 6c 4d 3f 15 7e 47 36 01 |.W...v..lM?.~G6.| +000001c0 a9 9b b9 6f 71 01 90 3f 7f 70 27 e4 a8 14 4f 6e |...oq..?.p'...On| +000001d0 a5 d4 eb ac 95 59 50 fa da bd 9e a7 d2 aa 69 68 |.....YP.......ih| +000001e0 4c 2e d9 7d 9e 69 a9 4c de 13 fc d7 37 46 ce 3c |L..}.i.L....7F.<| +000001f0 24 59 0c 8c b6 2a 85 15 92 d0 88 74 ee 95 2e cb |$Y...*.....t....| +00000200 a9 93 25 51 fb a4 24 49 e2 d6 76 46 57 6d 2f 95 |..%Q..$I..vFWm/.| +00000210 ff 19 52 6f 94 2e 8e 45 18 1c 0f eb ca 39 0b a4 |..Ro...E.....9..| +00000220 de 31 13 8c fb 5e a0 ff 1a 96 e6 61 68 41 66 9f |.1...^.....ahAf.| +00000230 d4 33 47 1e 29 3d 55 db 54 b4 79 12 c2 6d 8e 07 |.3G.)=U.T.y..m..| +00000240 7a 37 6f 1d e2 d5 26 c3 77 b6 4d c8 45 08 2c f6 |z7o...&.w.M.E.,.| +00000250 40 44 fc 42 db e4 ba a1 db 37 8e 80 c5 12 e7 60 |@D.B.....7.....`| +00000260 26 3d 25 37 68 0b 4e 9b 20 bf ce 84 |&=%7h.N. ...| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000010 00 00 00 20 b2 7d e1 6f 74 5e 2b 69 99 fd 86 3b |... .}.ot^+i...;| +00000020 d5 7e 67 50 c9 a8 cb 99 2c a8 38 b5 e9 9f d9 f5 |.~gP....,.8.....| +00000030 2d 2c 3e 6a 07 19 4f dd f9 be 65 8f b7 a5 dd c4 |-,>j..O...e.....| +00000040 f4 79 ba 19 |.y..| +>>> Flow 8 (server to client) +00000000 00 00 00 20 b0 d5 c0 90 5d 48 f0 20 b3 58 0d be |... ....]H. .X..| +00000010 e4 58 24 5c a6 82 ef 4b c2 f3 0d f7 da f3 cf 7d |.X$\...K.......}| +00000020 0d 72 7d d3 1d e7 a4 18 f5 d0 f3 96 13 f8 93 4e |.r}............N| +00000030 64 14 00 4e |d..N| +>>> Flow 9 (client to server) +00000000 00 00 00 30 3b 5c f8 d8 84 31 9f c2 6a b2 03 ac |...0;\...1..j...| +00000010 26 04 ab 97 2c 96 04 2f da f0 de 46 13 b6 cc 08 |&...,../...F....| +00000020 2e 2c 1e 54 58 3e 5e 7c 51 4f ad 20 4a 3c 2e 35 |.,.TX>^|QO. J<.5| +00000030 96 f1 a7 c6 18 54 55 d7 c4 a1 cf 09 db ee 12 99 |.....TU.........| +00000040 04 77 ad 60 |.w.`| +>>> Flow 10 (server to client) +00000000 00 00 00 20 a1 63 c8 e1 c6 1b da 1b dd 06 ce 42 |... .c.........B| +00000010 8f a9 03 b7 f8 fe b6 b7 f6 10 f6 de 43 13 52 13 |............C.R.| +00000020 0a 47 f6 43 c2 28 a8 cd 5e 97 fa 0c e0 63 09 1f |.G.C.(..^....c..| +00000030 7e 00 45 bd 00 00 00 40 4f 38 87 c8 5c f5 f7 7d |~.E....@O8..\..}| +00000040 3e 84 3a ff b0 35 3c ad 69 d2 4e ae 8a 22 ce f0 |>.:..5<.i.N.."..| +00000050 79 25 b6 b5 20 b8 09 4e 84 3f b8 27 ea c9 df 2c |y%.. ..N.?.'...,| +00000060 b1 44 f2 25 bf 36 96 2c a3 83 22 95 e4 f6 91 78 |.D.%.6.,.."....x| +00000070 00 e4 0e ef 09 02 d0 7b 50 82 5a 89 79 8f 35 1b |.......{P.Z.y.5.| +00000080 b8 8f 1d eb c0 95 88 c4 |........| +>>> Flow 11 (client to server) +00000000 00 00 01 60 48 fb 31 ab 53 64 24 c8 bc 5a f0 49 |...`H.1.Sd$..Z.I| +00000010 c8 b8 7c ed ae 08 ff a1 49 35 22 60 d3 63 98 8c |..|.....I5"`.c..| +00000020 2d ee 0e 91 63 e4 b6 87 22 ed 84 bf 81 36 0a db |-...c..."....6..| +00000030 bd 54 e5 6c ac 48 0d 2c ff a8 c2 3f 45 81 31 b1 |.T.l.H.,...?E.1.| +00000040 b4 45 a1 36 ea e9 73 3d 5c 8e 1a 1b ec 81 f4 3d |.E.6..s=\......=| +00000050 b4 7d 9f 34 5c 39 78 5d 4b b5 77 a7 7a 1f 86 c4 |.}.4\9x]K.w.z...| +00000060 f0 eb f5 49 ec 4c a8 23 da 82 34 be 2d 72 05 cb |...I.L.#..4.-r..| +00000070 46 19 82 e7 ab e8 e4 54 05 1d 67 21 51 92 83 f5 |F......T..g!Q...| +00000080 b6 1a 6d ae a0 59 91 24 99 20 b6 c4 53 a4 ba ae |..m..Y.$. ..S...| +00000090 80 dc 58 37 a5 ce bb 00 19 06 4c a1 3f 10 ce 8e |..X7......L.?...| +000000a0 3e a5 57 66 18 59 7a a6 82 04 3f f4 3a e4 b0 14 |>.Wf.Yz...?.:...| +000000b0 ae 80 b5 27 e2 82 b1 4b 0e 06 19 51 a9 8f 76 4f |...'...K...Q..vO| +000000c0 88 33 1b cf ce ab 54 9f 7e 92 98 2b b2 6d 14 0a |.3....T.~..+.m..| +000000d0 cf 0b cd 29 96 cf 83 c2 5d aa 00 b7 89 32 e0 60 |...)....]....2.`| +000000e0 2c 24 3a 70 1a 03 82 55 a8 4a 34 7c c5 ac d3 e0 |,$:p...U.J4|....| +000000f0 9c 57 56 f0 b5 2f 09 83 96 50 dc 33 26 74 a1 ad |.WV../...P.3&t..| +00000100 24 05 11 44 20 13 88 63 bf 02 80 f4 3e 69 f8 ee |$..D ..c....>i..| +00000110 d1 29 fd 04 52 08 b9 34 4a d4 59 20 f7 47 b2 08 |.)..R..4J.Y .G..| +00000120 be a4 d8 ab 30 37 0a 32 a4 b2 a1 89 00 92 b4 f2 |....07.2........| +00000130 c7 7a 0e 18 d4 6c 34 a7 9b 00 c1 e6 64 f0 a3 04 |.z...l4.....d...| +00000140 dc 5d 88 8a ab df c6 0e cd 4e b5 0d 36 78 2a c8 |.].......N..6x*.| +00000150 71 1d a2 49 64 25 37 f8 50 2d f7 83 2d c1 3a 72 |q..Id%7.P-..-.:r| +00000160 97 28 e8 01 d7 c9 95 3b 61 3b 5c fc 08 88 09 30 |.(.....;a;\....0| +00000170 9f df 64 33 |..d3| +>>> Flow 12 (server to client) +00000000 00 00 01 40 80 ad d7 73 07 f1 91 7e 25 a9 a9 0e |...@...s...~%...| +00000010 76 80 19 96 ed 76 d2 08 e6 b7 0b 26 b2 4b 85 30 |v....v.....&.K.0| +00000020 1f 30 f9 27 a9 d8 ac fd be 52 f4 00 77 5e 0c 6b |.0.'.....R..w^.k| +00000030 32 35 c5 54 94 66 77 74 52 fe 92 4b 76 20 ee 99 |25.T.fwtR..Kv ..| +00000040 85 14 ee f4 7f b9 ac 1f 94 90 7f 6a 23 d4 1c a9 |...........j#...| +00000050 aa 9e 2a a9 cf 87 1d b9 29 7c 7f e0 ee 4b 3b f0 |..*.....)|...K;.| +00000060 c4 30 b2 45 ba 97 11 d0 3d 87 3e 4e 0b ea ae 7c |.0.E....=.>N...|| +00000070 62 39 85 cd 8d c2 6a 29 f8 2c 5d 26 c1 64 d1 96 |b9....j).,]&.d..| +00000080 30 86 c5 3f 0f be bf d9 a8 0b ab ad c8 20 fd e2 |0..?......... ..| +00000090 78 52 39 cc 6e 67 7a a3 4d 56 e6 1a e9 62 1f 0f |xR9.ngz.MV...b..| +000000a0 5e da 99 d7 4a a7 eb b4 b2 77 27 3e cb 93 56 62 |^...J....w'>..Vb| +000000b0 89 04 11 ce 41 ec 48 5c 57 96 df 68 e3 32 cb d0 |....A.H\W..h.2..| +000000c0 7d 4a c2 fe 08 ab 33 4b b3 11 68 cc 95 f5 b0 81 |}J....3K..h.....| +000000d0 cb f1 d7 8c a4 fe 58 7b 3e c9 9e c1 2d 32 cb 37 |......X{>...-2.7| +000000e0 c6 99 ac 34 1d d8 68 65 01 0f aa 68 cb c4 2d 24 |...4..he...h..-$| +000000f0 2f 8f 26 f9 01 35 e1 39 4a 3f 74 59 3f 09 09 28 |/.&..5.9J?tY?..(| +00000100 5f 00 14 59 31 a4 34 2d 2f 19 c7 04 8f bc 23 b8 |_..Y1.4-/.....#.| +00000110 9d 9e c6 60 fa bd ce ea 17 4d 72 fd e3 15 61 22 |...`.....Mr...a"| +00000120 9e a7 71 2e f1 62 42 ce 0c 39 91 43 e5 f5 42 aa |..q..bB..9.C..B.| +00000130 f7 e7 9a 6d 64 56 a6 aa e2 0b 88 a4 a4 b4 35 57 |...mdV........5W| +00000140 05 5e 3d 1f af fb 90 00 86 61 6d a1 ee 41 55 0a |.^=......am..AU.| +00000150 81 5b a5 a7 |.[..| +>>> Flow 13 (client to server) +00000000 00 00 02 80 b7 54 4c 5a 9f 90 75 44 1e c1 cc bd |.....TLZ..uD....| +00000010 0c 59 d1 da 90 0b 33 eb f2 cd 0e 5a 6f 2f e4 66 |.Y....3....Zo/.f| +00000020 db b7 ca 64 de 6e d5 b0 a9 9f 77 e2 4e 8a 3f 44 |...d.n....w.N.?D| +00000030 ea bf ee ac 3e 51 23 e8 07 c6 90 cc ec eb 51 2e |....>Q#.......Q.| +00000040 71 36 b0 b2 72 85 06 16 22 c2 58 ed 46 4e d7 3c |q6..r...".X.FN.<| +00000050 58 3d 56 66 6d 86 c5 75 d0 fb d1 f5 8a 10 22 52 |X=Vfm..u......"R| +00000060 4f fc 1e fb 0a 14 ca 3c 84 12 36 65 4a ac a7 4b |O......<..6eJ..K| +00000070 d8 ed fa 35 15 ef 9f ba f0 cb a5 81 a4 36 5d 21 |...5.........6]!| +00000080 57 b1 e1 4a 77 aa b9 19 78 1d 87 7d 3a c4 67 c7 |W..Jw...x..}:.g.| +00000090 3c b4 97 1d 46 55 5f e6 37 c8 31 ef 84 ea f6 ba |<...FU_.7.1.....| +000000a0 6d 96 ab 60 5b 5c 16 d3 fa d9 52 b2 3a 2b bb 0f |m..`[\....R.:+..| +000000b0 fa ce b6 3a fe a4 a7 9f 17 43 1a 98 37 a0 d2 b1 |...:.....C..7...| +000000c0 9d 0f 9c 25 47 19 ce 7b 4a 76 fb a8 67 0c 74 93 |...%G..{Jv..g.t.| +000000d0 73 fd 02 fb 5d 3c 74 20 d3 00 e2 c5 af 12 12 4e |s...]m ...f...| +00000190 87 cd 14 66 69 07 f0 4c 6c 7b a2 e7 02 db e9 49 |...fi..Ll{.....I| +000001a0 5b 32 d8 b0 6b 73 6b 17 44 ef 57 c2 27 ae 10 9c |[2..ksk.D.W.'...| +000001b0 06 c3 61 f1 ce 59 b4 49 1c aa 7b 73 ab b4 e1 c4 |..a..Y.I..{s....| +000001c0 97 8b 2c 2d 8f 89 60 98 a3 cd f0 7e 8b a1 2f 47 |..,-..`....~../G| +000001d0 a4 17 b6 f4 43 5f ec 35 5d 8f ee fe 77 cc cd 37 |....C_.5]...w..7| +000001e0 67 1f 19 07 cc b0 7e c7 a9 51 d9 1b 73 e1 b4 62 |g.....~..Q..s..b| +000001f0 49 42 b4 0b cf 25 28 33 9c ce 0f 95 51 a4 a1 ef |IB...%(3....Q...| +00000200 93 2b b4 c5 b1 d9 05 84 ac 1c ee 7c 29 04 9d 8d |.+.........|)...| +00000210 04 41 a1 5c 16 88 7a aa 05 dc 0b 14 b3 9b db 22 |.A.\..z........"| +00000220 ab 18 5a 3d 0c cc 02 4f b6 30 4c c2 1e c8 7f e2 |..Z=...O.0L.....| +00000230 37 85 25 89 b2 cc 1e 16 2f 74 80 0e f7 72 b4 d5 |7.%...../t...r..| +00000240 f1 7d 84 ce 96 ff de f0 9a 81 30 bd 59 c6 e4 5f |.}........0.Y.._| +00000250 fc f9 2a 72 bf 5e 92 0c 86 a7 44 14 97 c8 ce 86 |..*r.^....D.....| +00000260 41 57 99 f2 fe db a4 9f 2a 3e e8 c7 bf f9 ae 2f |AW......*>...../| +00000270 d8 46 12 9e 87 08 30 77 f7 e8 82 77 e9 f2 47 d8 |.F....0w...w..G.| +00000280 03 ad c5 ac de 04 9d 07 82 d0 3f 12 94 e1 0b eb |..........?.....| +00000290 52 db 4c 91 |R.L.| +>>> Flow 14 (server to client) +00000000 00 00 00 10 47 09 41 6b 56 6e 4b b4 d8 9f 51 ee |....G.AkVnK...Q.| +00000010 e8 48 00 3c e5 65 9a e0 20 51 43 07 e7 6d 6d ab |.H.<.e.. QC..mm.| +00000020 78 59 fa 12 |xY..| +>>> Flow 15 (client to server) +00000000 00 00 00 20 bd da 9f 00 ab 16 8e 65 c9 ab 3c 20 |... .......e..< | +00000010 ca 3a 95 9b a2 ef c3 a4 7a 42 39 1f 3c b8 8d 05 |.:......zB9.<...| +00000020 cd 00 d4 4b 0c 9e 98 e6 d1 35 35 bb 2d 38 1b cb |...K.....55.-8..| +00000030 b1 45 af 54 |.E.T| +>>> Flow 16 (server to client) +00000000 00 00 01 b0 3c 0c 4d 38 96 7b 16 27 2c 1c 86 7a |....<.M8.{.',..z| +00000010 21 5d 43 ab 42 e7 44 42 98 01 45 22 18 69 1e 9b |!]C.B.DB..E".i..| +00000020 67 36 27 bc 7d fd 83 c8 27 4e 8a 8d d9 8c cf 32 |g6'.}...'N.....2| +00000030 75 c0 50 3b 2f e7 9c ee b0 b7 45 20 b3 78 0c 7e |u.P;/.....E .x.~| +00000040 58 05 b9 7b a7 80 a8 61 02 94 f9 b3 31 7e 06 2e |X..{...a....1~..| +00000050 c0 34 9f 0e 77 82 40 5b 1f 23 08 75 a3 f0 bc 7a |.4..w.@[.#.u...z| +00000060 bd 42 0e 9b ba 67 59 ff c4 f0 02 84 09 56 f2 9a |.B...gY......V..| +00000070 1f 4b 5a 6f 3f c0 9f 12 a0 1e 27 48 74 ae 82 7a |.KZo?.....'Ht..z| +00000080 5d 86 44 0f ce 1d 8f 49 89 01 3b 1a ae 27 54 1d |].D....I..;..'T.| +00000090 29 93 b9 50 11 86 55 91 c9 2d a5 e4 f8 3b 79 ea |)..P..U..-...;y.| +000000a0 59 92 37 3d 13 bd 04 22 5d 87 5a 56 77 b9 90 b8 |Y.7=..."].ZVw...| +000000b0 ce d2 6e 66 71 9f da d3 98 16 13 83 d1 2e 6c 51 |..nfq.........lQ| +000000c0 50 40 49 11 73 3b a7 cb 43 2b ef b4 51 6a a5 8a |P@I.s;..C+..Qj..| +000000d0 6e 5c 70 78 c9 ab e1 9d 55 8e aa be 42 de b9 6e |n\px....U...B..n| +000000e0 54 26 a6 09 c1 e0 c1 20 50 42 5b e7 ab a3 2c a3 |T&..... PB[...,.| +000000f0 28 ca eb 66 df a3 12 ce 0d 14 eb 02 5a bb 61 74 |(..f........Z.at| +00000100 f3 d6 d8 eb d8 b0 b7 02 13 25 c7 ea 8a 2b a5 28 |.........%...+.(| +00000110 af 3d 52 06 02 5f 96 35 61 39 c0 74 77 a9 2b f9 |.=R.._.5a9.tw.+.| +00000120 4c df f9 c2 cc 01 1c 52 f2 36 f4 6b 53 d7 28 e0 |L......R.6.kS.(.| +00000130 d6 d1 41 00 89 07 bd 18 45 9a 73 11 88 20 87 7c |..A.....E.s.. .|| +00000140 32 cc cd e2 9e 66 ee 41 ac 4d eb b5 88 ad 4d 4e |2....f.A.M....MN| +00000150 ba ef 70 79 72 dc 11 da 8f b9 4a fa c2 56 9c 5e |..pyr.....J..V.^| +00000160 76 3b 51 9d ec 83 e9 a5 10 d5 c8 d7 82 6a 8a 31 |v;Q..........j.1| +00000170 95 41 10 4b 6e e7 32 82 f9 c0 df 4b 5f 5e 5a bd |.A.Kn.2....K_^Z.| +00000180 9e 44 c9 7b f7 84 ee db 63 ab 0a 41 58 ee b3 13 |.D.{....c..AX...| +00000190 f1 75 43 03 37 e5 b4 e6 34 a9 82 23 93 a1 31 eb |.uC.7...4..#..1.| +000001a0 84 6e 39 73 0c f6 e5 8d 25 39 84 d8 68 bd 25 28 |.n9s....%9..h.%(| +000001b0 30 91 82 df 34 48 15 2b 5c 18 43 7d be 57 35 f3 |0...4H.+\.C}.W5.| +000001c0 21 ef 72 4e 00 00 00 90 00 ec e6 93 b2 94 6e a8 |!.rN..........n.| +000001d0 29 13 38 01 18 cc 57 b0 e5 f3 98 78 45 b1 3f dc |).8...W....xE.?.| +000001e0 da 1d cf 90 81 6d dc 78 fc a6 91 0a 18 e5 9a 35 |.....m.x.......5| +000001f0 45 b9 01 5d 96 70 09 0f 2e 2e d1 e1 52 ca 8b 95 |E..].p......R...| +00000200 cc bb 4b f2 48 07 dc 9e 23 8e d4 55 7d 8e f2 dc |..K.H...#..U}...| +00000210 c5 c5 64 30 c3 53 b0 60 ae 02 73 6a d9 1d 6e 8d |..d0.S.`..sj..n.| +00000220 19 fe 10 37 7f 02 54 c7 eb 90 6d 59 64 b2 b0 12 |...7..T...mYd...| +00000230 b2 17 5c d7 93 58 d3 fd 91 c8 03 15 db ae 7b 5b |..\..X........{[| +00000240 7a 6d 48 a6 71 52 27 62 c4 a7 dc 24 17 b4 10 39 |zmH.qR'b...$...9| +00000250 23 dd 12 ac ee e5 2a 79 1f ae 8f 48 8a 52 6f e3 |#.....*y...H.Ro.| +00000260 a2 a0 89 92 4d 9f d1 07 00 00 00 90 19 33 eb 86 |....M........3..| +00000270 ca 90 27 dd f2 d5 12 5a db 67 c2 a4 48 d7 1a 60 |..'....Z.g..H..`| +00000280 e8 f8 76 c8 eb ce 38 52 85 c6 28 10 0a 28 5e e3 |..v...8R..(..(^.| +00000290 d9 b0 25 93 9a 43 1e e2 84 38 01 3f 0c ed 9e e0 |..%..C...8.?....| +000002a0 28 9e 78 19 cf 80 3a 74 b3 d3 a1 b1 a1 0e 86 d5 |(.x...:t........| +000002b0 84 20 61 c7 e1 5e 67 a0 4e ec 46 3a 1b 90 fb b0 |. a..^g.N.F:....| +000002c0 a5 02 7b ec 27 32 61 8e b7 59 0a 23 90 94 1d 62 |..{.'2a..Y.#...b| +000002d0 c4 4d 05 a1 bf 0c 20 67 d6 d6 c0 44 8e 89 22 68 |.M.... g...D.."h| +000002e0 09 4f b8 a9 fd 69 88 d5 58 6f 13 f7 49 d6 70 4f |.O...i..Xo..I.pO| +000002f0 81 af 1d ae aa 84 54 bf e3 58 a4 b8 7b 4c ee 5f |......T..X..{L._| +00000300 e2 47 85 3b 27 67 53 43 56 ea 6e da 00 00 00 20 |.G.;'gSCV.n.... | +00000310 6d 18 7a 70 80 da ff dc a7 8c e9 d3 33 2f ec 3a |m.zp........3/.:| +00000320 dd 7e 23 6a 43 c2 e9 03 c6 e4 39 e3 77 bb 1c f7 |.~#jC.....9.w...| +00000330 ef a1 94 89 24 d0 7b d4 1f 31 36 fa 98 8f 62 ff |....$.{..16...b.| +>>> Flow 17 (client to server) +00000000 00 00 00 30 cc c0 9b c6 ae 48 24 b4 33 e3 3f 92 |...0.....H$.3.?.| +00000010 d9 17 7b 71 4f 8f bf a2 b1 d1 90 a0 89 47 9a 79 |..{qO........G.y| +00000020 5c cf f3 4b 7c 34 32 19 de 96 f6 b6 b7 9d 73 46 |\..K|42.......sF| +00000030 da fe 55 23 05 96 f9 77 b1 cc 89 a6 48 b7 ca 75 |..U#...w....H..u| +00000040 23 c7 49 e5 |#.I.| +>>> Flow 18 (server to client) +00000000 00 00 00 10 3e 02 d8 74 5e 40 d7 a8 38 1b 03 e0 |....>..t^@..8...| +00000010 ab 0e 98 ef 01 fb 1e 3c da d6 0f 31 3a 04 2c ba |.......<...1:.,.| +00000020 72 ee 32 53 00 00 00 10 50 dd ef 50 51 74 0b 46 |r.2S....P..PQt.F| +00000030 9c 88 f2 a1 00 78 be 80 fb 10 2f 2c f9 d7 23 e8 |.....x..../,..#.| +00000040 1f 3d c6 9f fc c4 c7 48 |.=.....H| +>>> Flow 19 (client to server) +00000000 00 00 00 10 35 1c 30 9d aa 28 26 d4 47 65 71 fa |....5.0..(&.Geq.| +00000010 4b 72 e4 52 9c 0f 6a 15 ee 80 7d 6c 97 ff d7 a4 |Kr.R..j...}l....| +00000020 e7 49 21 3c |.I!<| +>>> Flow 20 (server to client) +00000000 00 00 00 40 d9 d3 30 de 6a b4 f2 d0 07 ce 27 f2 |...@..0.j.....'.| +00000010 fa 2d e4 34 c2 0b 6f 35 98 50 62 41 a9 71 86 0a |.-.4..o5.PbA.q..| +00000020 7b 5c 3f 1b 1f ae 05 f7 bd 3e f2 97 71 25 5e 1e |{\?......>..q%^.| +00000030 71 74 78 20 43 d1 9e d0 6c 25 ad 4c 26 5f ee 2c |qtx C...l%.L&_.,| +00000040 e0 59 5f 5d ae 31 c2 a9 fc f3 78 9f d9 2b c6 17 |.Y_].1....x..+..| +00000050 d8 c5 a0 63 00 00 00 20 f6 36 de b1 2a 17 65 7e |...c... .6..*.e~| +00000060 e1 66 d3 ab 24 d0 68 05 84 eb 0a 0f 0d b1 f2 96 |.f..$.h.........| +00000070 57 74 49 59 42 6b 26 89 73 71 67 82 b3 4b 35 34 |WtIYBk&.sqg..K54| +00000080 c3 4b 0e 59 16 57 f6 36 00 00 00 10 6a 6b 9b 1a |.K.Y.W.6....jk..| +00000090 85 cd 1f b2 51 23 69 f3 18 a9 55 14 d7 6f 7b 6f |....Q#i...U..o{o| +000000a0 c4 90 06 cc 94 c2 33 5f c5 f0 8a 10 00 00 00 10 |......3_........| +000000b0 87 fb 74 53 68 f5 f3 c3 ec 73 44 ae 86 94 12 05 |..tSh....sD.....| +000000c0 2b 04 e6 67 ee 0a 9a 33 6a 35 2a fa a3 3c 94 dc |+..g...3j5*..<..| +>>> Flow 21 (client to server) +00000000 00 00 00 10 29 d9 ef 45 13 d3 41 09 86 a9 e4 aa |....)..E..A.....| +00000010 45 38 3f b0 91 dd 22 55 c2 93 c3 81 af f7 9a bb |E8?..."U........| +00000020 f9 eb 76 d9 |..v.| diff --git a/ssh/testdata/Client-RunCommandStdin b/ssh/testdata/Client-RunCommandStdin new file mode 100644 index 0000000000..52e4c667d4 --- /dev/null +++ b/ssh/testdata/Client-RunCommandStdin @@ -0,0 +1,379 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 64 86 77 7e 76 82 f2 e7 86 2b |......d.w~v....+| +00000010 a5 81 1b d0 ff 0f 00 00 01 7a 73 6e 74 72 75 70 |.........zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 08 eb 48 43 1d 8d 9e c3 22 a8 |..... ..HC....".| +00000080 f5 e0 e5 7a 5d 2f 8b 30 1c d2 7a ab 4c 30 f1 ab |...z]/.0..z.L0..| +00000090 cb ad bc b6 ea 52 00 00 00 64 00 00 00 13 65 63 |.....R...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 79 e0 ee 82 b2 42 7f |6...I... y....B.| +000000c0 2b 1a 7b ed 79 6e 52 a2 3c 88 41 d3 12 58 01 c5 |+.{.ynR.<.A..X..| +000000d0 73 2e a5 25 91 e9 1a 3e a6 00 00 00 21 00 d7 c2 |s..%...>....!...| +000000e0 5e 6f db 86 7d 5c 32 90 6f 5c 35 34 29 5e dc 25 |^o..}\2.o\54)^.%| +000000f0 5d d8 78 4d f4 e0 05 9b 91 fb e9 62 f8 2d 00 00 |].xM.......b.-..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 5d ac ac 46 |...........@]..F| +00000120 29 52 48 3f 5c 86 e8 a5 67 eb 49 bb 04 7b 53 14 |)RH?\...g.I..{S.| +00000130 e6 ac 9a 5d f7 c4 7a 91 95 8b 92 9b ee 67 60 8a |...]..z......g`.| +00000140 2d bb 42 2e cd 93 06 0b 38 b4 9c dd fe 76 bc ad |-.B.....8....v..| +00000150 be d7 86 54 62 02 12 83 a4 80 fa 4e 0f 72 32 d6 |...Tb......N.r2.| +00000160 fa 2e a6 d0 b4 74 ac 39 e3 b8 19 fa d6 c3 e8 da |.....t.9........| +00000170 06 d8 a0 0f 80 b5 2a 45 fd b7 48 4b 92 25 8f 40 |......*E..HK.%.@| +00000180 5d f5 2f f7 e6 c9 64 7b 83 e5 5e 72 e8 6f d5 a3 |]./...d{..^r.o..| +00000190 c7 71 ac 65 d0 a1 ef c0 47 b9 d6 f7 a5 01 ea b2 |.q.e....G.......| +000001a0 d1 4c 02 2f 63 3f bc 4f dd bf 4c 5b 36 f6 92 e6 |.L./c?.O..L[6...| +000001b0 ee 06 bb de 7c 50 f1 fe 6f 5f e3 9b 2b e4 2f 80 |....|P..o_..+./.| +000001c0 93 c4 31 c3 20 3d 26 08 5c 59 b9 d5 a1 94 3b 78 |..1. =&.\Y....;x| +000001d0 8b 55 67 98 10 98 61 2e 23 fa 7c f3 d8 2f f6 08 |.Ug...a.#.|../..| +000001e0 b5 61 d1 f7 69 04 8b 8f fa 19 b6 a2 40 13 4c 62 |.a..i.......@.Lb| +000001f0 5f b4 a7 7d 37 7d 65 98 63 1e 09 17 31 c4 89 5b |_..}7}e.c...1..[| +00000200 fb ca 39 4d 27 02 06 40 c4 98 c5 7b fe e6 4d 39 |..9M'..@...{..M9| +00000210 db 50 6c 1d d5 4f ba f8 78 4c bc e7 34 41 01 b0 |.Pl..O..xL..4A..| +00000220 73 43 96 bf 3c f0 3a 79 a5 89 bc af c4 eb 65 99 |sC..<.:y......e.| +00000230 be 86 bc 87 8c 03 8f fd da c1 b1 7c f7 d5 2c 1d |...........|..,.| +00000240 54 90 09 8f 5e a2 70 2a e1 bc 3b 8d 78 66 a8 da |T...^.p*..;.xf..| +00000250 50 49 6b 2b 0a 3e 1f 7c df cf b8 09 73 41 fb bb |PIk+.>.|....sA..| +00000260 5f fe 71 29 97 cb fc 37 d2 24 3c e1 |_.q)...7.$<.| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000010 00 00 00 20 9e 34 d3 26 28 27 55 93 34 f9 5e ae |... .4.&('U.4.^.| +00000020 e1 7a 27 1c 40 5b 56 12 9c 3e 1f 03 94 32 93 f9 |.z'.@[V..>...2..| +00000030 c7 aa 97 8e 16 2d e2 3a 90 b8 35 84 50 48 99 33 |.....-.:..5.PH.3| +00000040 48 7f 05 bc |H...| +>>> Flow 8 (server to client) +00000000 00 00 00 20 5b b8 76 03 9c 01 33 bd 3d d9 88 38 |... [.v...3.=..8| +00000010 14 c6 77 a8 13 65 56 59 9d 64 72 40 52 93 ae 62 |..w..eVY.dr@R..b| +00000020 60 bd 25 18 01 e3 af 5a 72 cc 50 6f fc 64 91 24 |`.%....Zr.Po.d.$| +00000030 54 1c d7 65 |T..e| +>>> Flow 9 (client to server) +00000000 00 00 00 30 52 d5 40 ea f8 b8 a6 c5 1e 83 6a 68 |...0R.@.......jh| +00000010 cb 50 f6 c8 53 36 96 16 69 7e 72 8f c0 96 69 4f |.P..S6..i~r...iO| +00000020 41 c6 6c c3 c0 1c 5f e8 df 6d 29 51 67 ce 1e e1 |A.l..._..m)Qg...| +00000030 82 43 04 1b 81 4d 16 68 61 c8 55 df c5 e9 f3 79 |.C...M.ha.U....y| +00000040 6a 81 35 b9 |j.5.| +>>> Flow 10 (server to client) +00000000 00 00 00 20 2b 18 da 28 ec f2 d0 ed 92 04 a2 b8 |... +..(........| +00000010 bd 99 ed fe 2c 35 3b 85 f0 4e ea 2f 3d 80 a3 3a |....,5;..N./=..:| +00000020 13 68 51 24 72 65 53 ec 5d d5 12 ab 35 ed fc 0c |.hQ$reS.]...5...| +00000030 5a 1b 5c 9f 00 00 00 40 03 8e 14 ef d1 a7 a9 7c |Z.\....@.......|| +00000040 9d b8 a0 04 d4 12 4c ce f9 e5 10 65 2c 86 e2 fc |......L....e,...| +00000050 2b 21 36 86 a3 9f 2f 19 0e 60 85 0f f7 2b 0b 76 |+!6.../..`...+.v| +00000060 ba 30 49 ed d1 6b 20 88 83 00 41 53 b9 95 29 d6 |.0I..k ...AS..).| +00000070 9a 25 f8 85 dc 82 d8 88 96 68 b0 02 66 9e 9e a9 |.%.......h..f...| +00000080 4a 4f 10 a1 9f 12 6d 7e |JO....m~| +>>> Flow 11 (client to server) +00000000 00 00 01 60 1d 10 ce 49 2e 9b bf 10 f3 09 db 5b |...`...I.......[| +00000010 1b 59 61 10 01 c3 62 94 22 58 05 8f be 75 51 a1 |.Ya...b."X...uQ.| +00000020 25 cc 44 70 e4 c1 8d 9c 4a 50 7b e2 e5 f8 91 d5 |%.Dp....JP{.....| +00000030 ec 69 2b 90 c8 ca f5 fd 98 f5 8b b6 13 b2 0d 43 |.i+............C| +00000040 d7 fe 05 3d fc 14 7a 7d e0 61 8e d0 e9 c0 1c 22 |...=..z}.a....."| +00000050 83 3a 28 7f 27 c1 2b e3 60 24 05 cb 0b f2 78 c6 |.:(.'.+.`$....x.| +00000060 cb 2b 54 ab 9f d2 aa 0b af 24 22 3e 7f 9d c1 cf |.+T......$">....| +00000070 2a 31 79 59 10 77 3d a1 fb b7 1b c4 dd f5 da 05 |*1yY.w=.........| +00000080 ba 71 cc 54 7b 7c fd f0 b7 fa 1a 73 1f a4 66 a6 |.q.T{|.....s..f.| +00000090 15 c2 b8 dd 6b 79 cd d7 36 6c 8b 3c 13 c1 e3 42 |....ky..6l.<...B| +000000a0 eb fa 19 41 48 96 c0 a4 7c 55 2b 32 c6 02 52 30 |...AH...|U+2..R0| +000000b0 ce 99 54 52 a2 d4 90 f7 a7 42 93 85 17 2a 8d be |..TR.....B...*..| +000000c0 b6 a8 cf af ea 59 54 46 ad ee 22 48 2d 65 86 fc |.....YTF.."H-e..| +000000d0 37 90 59 24 64 30 cf 76 64 22 d8 e4 81 d1 d6 96 |7.Y$d0.vd"......| +000000e0 53 99 7b c6 6f 41 a1 73 b7 5f 41 9b 57 33 13 da |S.{.oA.s._A.W3..| +000000f0 ef 33 09 09 5a a8 19 8d 6e 86 94 4f e6 ab c6 1c |.3..Z...n..O....| +00000100 61 b8 5d 49 31 2c ef ce 64 2b 7b 97 bb 2b 6b f1 |a.]I1,..d+{..+k.| +00000110 43 67 6b e6 82 59 99 7a 9a a1 95 c1 4a 9c 78 55 |Cgk..Y.z....J.xU| +00000120 11 2d 12 00 c8 5b 2a 39 29 38 f0 52 10 01 cc 59 |.-...[*9)8.R...Y| +00000130 59 e6 5e f1 33 3d 53 d4 88 7a 23 10 ad b5 7c 34 |Y.^.3=S..z#...|4| +00000140 d3 fb 6e 0c 96 8b 29 b2 18 3a 1c 78 b4 39 75 bc |..n...)..:.x.9u.| +00000150 1f 3d 70 a6 90 8d 0d 7b 43 9c 1d 2f e8 37 c9 6e |.=p....{C../.7.n| +00000160 b1 ec 53 2d 3a 8b a6 6f 05 28 6c 4e f1 74 99 f3 |..S-:..o.(lN.t..| +00000170 17 0c 55 14 |..U.| +>>> Flow 12 (server to client) +00000000 00 00 01 40 39 fb e2 c2 9f 0e 62 a1 03 24 c6 fc |...@9.....b..$..| +00000010 9e 5a a2 21 3c ba 0b 2e 10 a1 f2 05 4e 48 77 a4 |.Z.!<.......NHw.| +00000020 5a 89 20 27 04 47 c8 87 a5 77 71 88 b3 03 94 ff |Z. '.G...wq.....| +00000030 5b a3 8e 54 8e ac 50 38 91 93 5c aa 1b 25 fa a9 |[..T..P8..\..%..| +00000040 2a 0f 43 95 ff 5c 63 fd d4 0b 6c bc 07 5e 34 c9 |*.C..\c...l..^4.| +00000050 20 be 92 3c 94 c6 86 2d 37 4d cf d1 c0 2b e6 f8 | ..<...-7M...+..| +00000060 3c b2 00 a5 02 f3 99 43 65 87 18 6f e1 f8 e6 95 |<......Ce..o....| +00000070 21 0d c7 53 fd 4c 1a 99 8e 17 43 cd c7 ab a7 2b |!..S.L....C....+| +00000080 bb e8 cf 26 d6 01 d5 42 e1 56 4e 78 18 68 19 61 |...&...B.VNx.h.a| +00000090 a1 6f b2 c8 1a 3c f6 46 c7 86 7f 17 ad e5 a0 86 |.o...<.F........| +000000a0 66 05 69 d4 cc aa 4c 69 d1 1d 34 a6 86 aa 0c 33 |f.i...Li..4....3| +000000b0 c0 92 e5 67 8d 96 ba d9 2c dc 66 aa c8 1f ca 45 |...g....,.f....E| +000000c0 7a 16 0f a8 59 ee ff f0 ee da e5 53 e0 40 d1 f3 |z...Y......S.@..| +000000d0 eb f5 1a a7 5f 35 98 9f c3 c2 1b 7e 5b 46 6a b9 |...._5.....~[Fj.| +000000e0 e3 d7 1f 47 08 0f ae 01 84 05 d6 fb fb 64 74 d3 |...G.........dt.| +000000f0 0b 00 93 0d b3 62 5b de 13 f9 2d 25 df fd dd 0e |.....b[...-%....| +00000100 d7 58 40 75 6e 7e 37 9d 10 9f ef 2e d6 8a c5 e8 |.X@un~7.........| +00000110 fb ea cc 98 20 f0 2b d9 83 7e e2 0b ec b1 31 33 |.... .+..~....13| +00000120 a8 da ae 4c f9 e7 c6 ae d4 da 84 83 3d de 96 91 |...L........=...| +00000130 68 8b 9b 4c 8e 5b d5 ab df 59 e6 34 6d c7 74 3c |h..L.[...Y.4m.t<| +00000140 c9 83 54 0e d4 0c ad 32 90 21 a4 67 2b c2 77 73 |..T....2.!.g+.ws| +00000150 bb 14 4a 40 |..J@| +>>> Flow 13 (client to server) +00000000 00 00 02 80 6b dc 4d 3a 42 c1 a6 00 5c c5 85 f5 |....k.M:B...\...| +00000010 e2 81 95 fd bf 21 f4 38 9f 3b fd 79 ad 34 c0 b6 |.....!.8.;.y.4..| +00000020 a4 22 b0 66 5e c1 2a 21 bf 44 b5 63 18 ea cf f1 |.".f^.*!.D.c....| +00000030 5c e6 2b 5a 29 9e e0 a5 ef c8 20 72 d9 c6 d9 87 |\.+Z)..... r....| +00000040 cf 0e 44 75 d0 ef 85 81 a0 32 85 8e 6c 44 68 63 |..Du.....2..lDhc| +00000050 cd c1 02 28 54 ad 04 36 f7 1c e9 bc 8b b4 87 3f |...(T..6.......?| +00000060 a6 a9 6e b3 8d e5 aa 49 a0 59 c3 20 52 45 60 e7 |..n....I.Y. RE`.| +00000070 9d a7 ff cf 8d da 50 0c 05 54 7d 68 1a d6 86 7d |......P..T}h...}| +00000080 20 8e a9 1f 25 8c 5e 95 4e 04 0d f6 61 04 08 af | ...%.^.N...a...| +00000090 a8 9f 40 d9 42 da fd ff 29 6c e3 9c a7 65 65 e0 |..@.B...)l...ee.| +000000a0 59 d8 94 06 c1 30 75 b2 55 17 bf a7 6b eb 18 8d |Y....0u.U...k...| +000000b0 2c f4 f5 79 db 32 cc c8 d2 f6 e7 f1 fe 43 cb b2 |,..y.2.......C..| +000000c0 8f 15 13 db 8d 32 86 85 c0 67 96 f0 1c 0e ca c1 |.....2...g......| +000000d0 e6 98 a2 d1 8d 20 a2 1c 56 9b b7 bc 4a 78 17 77 |..... ..V...Jx.w| +000000e0 8e 42 c2 4a 72 0a c1 ec 10 2e 85 63 60 03 72 73 |.B.Jr......c`.rs| +000000f0 76 c0 d6 b2 ea bc 51 d0 48 3c 52 6f 11 a6 16 7e |v.....Q.H2.d4.0!....| +00000140 49 21 60 e4 48 d7 1f e5 b9 c3 2d f6 10 90 79 75 |I!`.H.....-...yu| +00000150 22 da 99 45 9b b1 70 c1 70 1a ba 1e 10 60 cb e3 |"..E..p.p....`..| +00000160 61 bb 66 a0 96 49 a0 db bb e1 bc b6 b9 e1 00 6e |a.f..I.........n| +00000170 90 f3 70 66 b3 36 89 62 f3 22 f7 87 3e 35 8c 48 |..pf.6.b."..>5.H| +00000180 bc 08 86 38 46 e4 a9 f2 24 3a bf a4 e6 d1 14 72 |...8F...$:.....r| +00000190 3e aa 05 b1 f3 99 44 92 db c2 65 6c 66 73 ad 0e |>.....D...elfs..| +000001a0 06 46 eb f3 3e b1 7e e0 91 d5 9b 60 a6 83 d2 7a |.F..>.~....`...z| +000001b0 2f 0a 63 16 c5 e9 b2 9d 76 93 33 79 52 6b 68 2b |/.c.....v.3yRkh+| +000001c0 f0 33 5d 8e 03 e8 14 a3 06 a0 a6 1a 60 2b 0c ed |.3].........`+..| +000001d0 90 30 47 9e b0 06 29 cb bd 9a 89 96 38 1a 4d 3c |.0G...).....8.M<| +000001e0 6d 6c 2c 72 7c 1d d5 6c ca 33 67 cd 7f 60 97 f6 |ml,r|..l.3g..`..| +000001f0 fa 01 b3 09 25 9b 53 74 16 fd 3d 1e 04 f4 21 f4 |....%.St..=...!.| +00000200 9a bb 31 10 41 43 ac 0f 2c df ba ed 26 a1 6c 4e |..1.AC..,...&.lN| +00000210 e5 7a 84 41 1f b0 49 22 58 2e 6e 12 61 26 8d d1 |.z.A..I"X.n.a&..| +00000220 fd e2 02 22 be b5 f0 38 f1 98 08 4b c1 02 95 26 |..."...8...K...&| +00000230 f4 9e 5b 0b 2c d7 66 cc 9e 64 ae f5 b7 fd a3 ac |..[.,.f..d......| +00000240 46 1d 93 18 4e d2 1c 4b e1 04 08 38 80 06 ef 18 |F...N..K...8....| +00000250 fe 94 c4 5a 9c f0 31 b4 05 9b c7 6d 8b bf 54 6c |...Z..1....m..Tl| +00000260 d4 a8 de b7 06 cb 0a 1f 3e d5 d7 58 04 45 31 98 |........>..X.E1.| +00000270 c2 18 fb 52 07 94 5b 00 81 11 78 59 89 7f 08 04 |...R..[...xY....| +00000280 0b b8 33 77 c8 3f e6 7c 9c 6a 69 93 8f ca ab 51 |..3w.?.|.ji....Q| +00000290 45 35 73 bc |E5s.| +>>> Flow 14 (server to client) +00000000 00 00 00 10 1c ee 37 ff bf dc 6b df 57 e9 ac cc |......7...k.W...| +00000010 6f 5d d6 ab 59 ef 4b c6 af 0c 92 f6 47 3d bf d1 |o]..Y.K.....G=..| +00000020 c1 e6 32 c4 |..2.| +>>> Flow 15 (client to server) +00000000 00 00 00 20 de 33 33 34 9b 87 56 87 bd 97 7c 98 |... .334..V...|.| +00000010 e3 ed 3d c0 01 36 f1 e8 ae 2f c6 b8 17 fd f1 76 |..=..6.../.....v| +00000020 5d 0b b4 bf 02 a5 e5 29 b5 73 4b 3c 6f 1b e1 96 |]......).sK>> Flow 16 (server to client) +00000000 00 00 01 b0 de 69 a3 8d 82 59 80 44 93 86 81 25 |.....i...Y.D...%| +00000010 6c ba 46 d6 80 fe e3 2e de 4c 48 3e 90 1c 89 21 |l.F......LH>...!| +00000020 3d c9 3e 8c 33 81 95 1a a0 4d 32 8a 41 48 f7 11 |=.>.3....M2.AH..| +00000030 e3 83 70 a6 f3 d7 a2 2a 0b cd aa a6 0c f7 e3 b0 |..p....*........| +00000040 cb 01 f3 21 45 59 dd d3 69 9c d1 2c a5 21 8c 07 |...!EY..i..,.!..| +00000050 e3 eb c8 66 f2 fe 50 7e 7e c1 ca cb 2c 48 8e d4 |...f..P~~...,H..| +00000060 b7 14 6f 5f 7c a0 59 10 f9 b5 40 56 93 8c ec 2a |..o_|.Y...@V...*| +00000070 55 6b 21 7d 0e 51 a1 ab e5 af e5 7f 46 93 ef 6a |Uk!}.Q......F..j| +00000080 3d 8d d5 07 de 0d c8 91 fd 1b 9c 6b 21 ab de ad |=..........k!...| +00000090 df d5 96 1a 3d e1 28 37 28 4d f9 85 ff 3e e7 aa |....=.(7(M...>..| +000000a0 ff f9 20 9a 71 fc ae d9 22 7f c3 f0 c0 4a d4 94 |.. .q..."....J..| +000000b0 49 20 b9 96 81 d1 06 e4 bb 4f 1a ee 15 78 a2 82 |I .......O...x..| +000000c0 66 a5 53 7f 8e 58 05 7f f8 0c 4b 6f 62 70 2e f1 |f.S..X....Kobp..| +000000d0 e9 c5 0e b8 3c d3 18 db 43 48 34 92 cc 31 a9 9f |....<...CH4..1..| +000000e0 3c 0b e6 e4 33 0c 5a 94 cb 26 4a 4b 5b 15 2b e3 |<...3.Z..&JK[.+.| +000000f0 c6 e4 ab d9 6f c9 f2 dd 24 5b 96 7c 07 e3 f9 e4 |....o...$[.|....| +00000100 12 2b 68 1f c5 99 c4 cf a2 0e 54 9e a6 98 3f df |.+h.......T...?.| +00000110 5d 8e db f6 58 27 31 3b 38 50 e2 53 d4 b9 44 c7 |]...X'1;8P.S..D.| +00000120 7d a9 db 42 ee ab 72 45 21 59 4a 0b 5d d0 d3 ea |}..B..rE!YJ.]...| +00000130 06 e4 d0 ce 54 7e a4 93 06 78 d4 9c d4 09 05 e2 |....T~...x......| +00000140 a9 1c 5e 43 12 22 bd 1a a4 a8 55 79 de 30 ce ef |..^C."....Uy.0..| +00000150 43 47 30 91 06 0b 79 5b f3 c6 7c 4a 68 14 12 0b |CG0...y[..|Jh...| +00000160 59 f0 04 55 a2 cb eb 42 1c 05 2c d6 ab 60 2e e7 |Y..U...B..,..`..| +00000170 52 f1 41 40 73 ab 95 69 c6 82 31 31 59 11 16 48 |R.A@s..i..11Y..H| +00000180 f7 eb a5 56 a8 63 17 92 d8 66 c2 f1 49 93 a2 49 |...V.c...f..I..I| +00000190 ec 3d a4 ef 39 e5 77 8a d8 eb 49 48 38 7a e6 e3 |.=..9.w...IH8z..| +000001a0 3b e0 7a 75 38 f7 ad 5c a2 cf ad a2 98 9e d5 38 |;.zu8..\.......8| +000001b0 47 a5 d8 44 94 ae 97 ac 4a 97 81 fb 7a 2a 4f f3 |G..D....J...z*O.| +000001c0 a3 87 f9 a9 00 00 00 90 d5 ba 6e 9c 3e 0b 29 1b |..........n.>.).| +000001d0 09 ab f6 43 d1 4a 13 3c 75 45 02 bd 31 20 7c b1 |...C.J.u.| +000002a0 3c c9 90 7b ab 19 90 26 a1 5f 7e b4 e8 24 1d 34 |<..{...&._~..$.4| +000002b0 05 e2 d7 2d 17 55 0b 47 e3 29 87 bb 81 4f 76 93 |...-.U.G.)...Ov.| +000002c0 a3 0b 6e 63 e8 c4 a5 a0 61 b3 ba b2 b8 0a f7 03 |..nc....a.......| +000002d0 cb d3 7f c6 35 7e 69 1f 5b 91 e5 93 58 a2 3d 4c |....5~i.[...X.=L| +000002e0 c9 06 44 53 c1 2e aa 5c 65 5d a0 0c d0 a0 d8 32 |..DS...\e].....2| +000002f0 70 a8 03 4c b2 3f 85 d4 e9 78 52 af 8b 94 d4 0f |p..L.?...xR.....| +00000300 fe cc a3 31 05 92 33 7e 40 94 ba 25 00 00 00 20 |...1..3~@..%... | +00000310 1f c4 99 b3 51 18 54 f4 33 a0 90 c4 bc 9e df 80 |....Q.T.3.......| +00000320 24 a8 a4 c6 3a 9e 7a 5d 64 5e 25 7e 2e 1a 98 60 |$...:.z]d^%~...`| +00000330 43 82 eb c2 b3 24 96 46 c5 42 cd d6 54 e0 17 96 |C....$.F.B..T...| +>>> Flow 17 (client to server) +00000000 00 00 00 20 fd 7b d7 39 c9 84 b4 cf fc 82 4e 15 |... .{.9......N.| +00000010 53 3b 3f 64 f7 90 7d 40 a5 56 b6 e7 ad 6d 18 aa |S;?d..}@.V...m..| +00000020 da 46 96 40 cf f7 96 27 74 a1 aa 3c 39 b9 76 04 |.F.@...'t..<9.v.| +00000030 2d 92 ef 9d |-...| +>>> Flow 18 (server to client) +00000000 00 00 00 10 8c 56 4b 63 cc dd 40 d0 40 0e a8 61 |.....VKc..@.@..a| +00000010 a5 ba a4 3e 28 99 cc 37 0b 27 c5 aa a6 0b ed 4e |...>(..7.'.....N| +00000020 06 53 38 06 00 00 00 10 b1 a0 98 9a 6d 23 8a f0 |.S8.........m#..| +00000030 fa 38 5a a4 17 c3 fe 02 69 fb 35 b7 8e a9 8e e8 |.8Z.....i.5.....| +00000040 db b6 46 85 0b d4 1a 96 00 00 00 10 90 47 1b 0e |..F..........G..| +00000050 d7 78 59 26 9a e6 39 50 96 0f 37 75 36 64 42 3e |.xY&..9P..7u6dB>| +00000060 f8 be 07 50 ff 9b e0 f2 d5 43 57 8f 00 00 00 20 |...P.....CW.... | +00000070 25 12 68 a9 cd 82 aa 22 9b 04 a6 59 ee ce e6 55 |%.h...."...Y...U| +00000080 bc cd c6 36 56 c0 f0 f6 ed e6 55 94 2d 58 e5 c4 |...6V.....U.-X..| +00000090 aa e1 a7 0e c4 e0 54 43 b3 35 3a 61 7e 93 57 d2 |......TC.5:a~.W.| +000000a0 00 00 00 10 f6 5d 9a 65 16 63 a3 bd 21 39 44 e9 |.....].e.c..!9D.| +000000b0 40 b7 43 a1 e1 6b 96 e9 94 62 56 68 0e a3 c4 0f |@.C..k...bVh....| +000000c0 4f 8f ce 76 |O..v| +>>> Flow 19 (client to server) +00000000 00 00 00 10 ce 59 b5 fa e5 e1 0e d5 23 4b 20 e4 |.....Y......#K .| +00000010 85 78 b0 81 94 b7 cf 55 10 9c e6 a2 d2 90 c9 ef |.x.....U........| +00000020 a0 4f 29 df |.O).| diff --git a/ssh/testdata/Client-RunCommandStdinError b/ssh/testdata/Client-RunCommandStdinError new file mode 100644 index 0000000000..d64cd4606c --- /dev/null +++ b/ssh/testdata/Client-RunCommandStdinError @@ -0,0 +1,384 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 91 dc 0a e4 8a 02 3f 85 3d 7c |............?.=|| +00000010 da c1 a4 65 8c c0 00 00 01 7a 73 6e 74 72 75 70 |...e.....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 93 30 ff 28 0e 4b fd 97 29 c1 |..... .0.(.K..).| +00000080 c2 72 4f 8d 43 45 1e 47 4e 18 98 b8 ff 7d 0c 7b |.rO.CE.GN....}.{| +00000090 74 29 5f d7 10 50 00 00 00 64 00 00 00 13 65 63 |t)_..P...d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 5e ef b7 32 d9 83 b6 |6...I... ^..2...| +000000c0 c4 94 9f b6 f5 fa 6f e6 62 b1 24 f2 75 dc 85 c7 |......o.b.$.u...| +000000d0 bc 96 db 47 a7 73 cf a7 22 00 00 00 21 00 c0 72 |...G.s.."...!..r| +000000e0 64 20 e7 2b a0 c6 c6 94 f2 f7 13 cb 0f 72 5c 6f |d .+.........r\o| +000000f0 24 0f cc 45 48 c8 2f 1c 06 87 b9 80 87 71 00 00 |$..EH./......q..| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 a1 8f 67 4f |...........@..gO| +00000120 82 9f 36 14 75 18 ad 2f ad b4 5f a8 96 56 4e ac |..6.u../.._..VN.| +00000130 36 4d 49 4d 0f c9 0c 90 d7 6e f1 1d e4 7d 9c ed |6MIM.....n...}..| +00000140 25 44 6f 8d 75 1c 87 8c bc 1d 92 24 1c 65 a0 0c |%Do.u......$.e..| +00000150 57 87 9b cc 7a 5e 61 f0 07 f4 fd 45 e3 c4 cf 99 |W...z^a....E....| +00000160 7e f7 f9 ed d5 41 47 6b d5 52 a6 01 ef a8 9b e3 |~....AGk.R......| +00000170 68 2f 62 c3 62 9b 13 4e cc 2b f1 11 4e 82 d3 9c |h/b.b..N.+..N...| +00000180 ee 45 0e eb 1a 25 48 b5 f6 02 d7 d3 02 a0 dc a6 |.E...%H.........| +00000190 99 c5 54 b6 44 aa eb d2 6b c8 c3 32 2b 4c 14 0f |..T.D...k..2+L..| +000001a0 d5 3c 56 83 1c 6e e1 82 0b 58 cc 74 9e ab 8b 8d |...d..L.....| +000001c0 03 14 b7 7b 34 8e 84 b7 e9 de d2 50 72 91 a5 f1 |...{4......Pr...| +000001d0 ba 44 bc 92 88 50 76 f9 5c 04 74 6b ab d2 cf 87 |.D...Pv.\.tk....| +000001e0 84 de 02 4e 0b 8c 2d 21 ad 39 95 6b 09 c3 25 8f |...N..-!.9.k..%.| +000001f0 ac e4 e4 a2 02 8e 51 3a d9 90 22 ed d0 4b 76 39 |......Q:.."..Kv9| +00000200 ab 57 b0 8a 3b a9 9f 74 2b 4a a1 c2 4c b8 ba 83 |.W..;..t+J..L...| +00000210 e0 db 27 ea f9 5a e5 43 d0 d3 85 7f b4 a2 a6 da |..'..Z.C........| +00000220 a6 5b 30 e6 0d 92 06 d2 82 d7 4f 5d 71 55 b0 65 |.[0.......O]qU.e| +00000230 73 b5 18 f5 a1 f0 16 10 f9 51 d5 79 7c dc 89 00 |s........Q.y|...| +00000240 99 82 df 46 96 46 3f bc 1d 26 73 a0 43 c6 28 99 |...F.F?..&s.C.(.| +00000250 bb 42 6d 4d 00 28 cd ad 1a d9 d3 77 6b 43 fe 61 |.BmM.(.....wkC.a| +00000260 ac 1d 72 b8 4c eb 41 26 8f 4a 25 c5 |..r.L.A&.J%.| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000010 00 00 00 20 f2 d8 f4 53 66 14 39 f3 c0 d8 24 17 |... ...Sf.9...$.| +00000020 57 cd 8e d6 e1 71 67 2b 9a b5 09 90 f6 df 8f 49 |W....qg+.......I| +00000030 eb ba f8 0b 07 c6 27 59 9d 71 c2 cf 9a 1b de c4 |......'Y.q......| +00000040 ad 93 8e 32 |...2| +>>> Flow 8 (server to client) +00000000 00 00 00 20 59 4c e5 f1 52 d9 66 cb c0 50 eb b8 |... YL..R.f..P..| +00000010 ad c5 20 27 38 4a 8a 21 37 bf 5f a9 ff cd e2 cb |.. '8J.!7._.....| +00000020 90 70 b3 a7 7f c2 ac 10 b6 25 3e b3 d4 6d a6 72 |.p.......%>..m.r| +00000030 67 71 e5 b8 |gq..| +>>> Flow 9 (client to server) +00000000 00 00 00 30 ad fb ee af 44 74 3a 93 4c f8 e9 0f |...0....Dt:.L...| +00000010 24 2f cf 70 80 71 d5 10 c7 ed d6 fc db 0c c8 a6 |$/.p.q..........| +00000020 0d 98 a6 77 65 dc 0c d0 a5 5e e9 f9 40 e2 a7 df |...we....^..@...| +00000030 50 7b 9d 52 ce ff 7e be 47 ba 81 9c 1a 93 32 ae |P{.R..~.G.....2.| +00000040 72 60 cf 6e |r`.n| +>>> Flow 10 (server to client) +00000000 00 00 00 20 84 cc 13 22 4b aa 47 5b df bf b4 bb |... ..."K.G[....| +00000010 83 d0 a8 f8 0c 80 d5 8c 4e fc a6 cd c0 c6 54 9a |........N.....T.| +00000020 dd 5e d2 26 67 3e 58 58 44 20 c5 8b 1e 91 d5 18 |.^.&g>XXD ......| +00000030 78 a4 c3 aa 00 00 00 40 6a dd 9f 25 9d ca 06 38 |x......@j..%...8| +00000040 13 48 ce e6 00 22 54 7d 84 16 1c 87 e4 af bd 18 |.H..."T}........| +00000050 25 31 d7 c4 a2 d0 fa ab 88 4a 13 f2 4a 73 55 86 |%1.......J..JsU.| +00000060 e2 b2 df 23 6b c0 79 89 67 ef d3 ce 0a aa 68 80 |...#k.y.g.....h.| +00000070 9c 4e 32 66 4b 11 af b8 ac 93 26 ff 8f e0 fa 0c |.N2fK.....&.....| +00000080 46 e4 72 f2 4d 81 72 c7 |F.r.M.r.| +>>> Flow 11 (client to server) +00000000 00 00 01 60 ca 58 ed 67 4c 9c 16 e9 60 22 a1 63 |...`.X.gL...`".c| +00000010 c4 8a 40 71 d0 d6 20 fc bc af cf b7 27 c8 89 cf |..@q.. .....'...| +00000020 84 5a f7 18 32 f8 85 9a 9f 87 92 bc 44 5e 71 83 |.Z..2.......D^q.| +00000030 80 48 cc 63 fa b4 06 39 a9 a0 dc 54 b3 b2 9e f9 |.H.c...9...T....| +00000040 e5 99 dd 32 ff b8 61 3b de 73 5e b4 31 da ac de |...2..a;.s^.1...| +00000050 f7 4b f9 64 e4 19 46 56 31 0d 08 b7 4b c8 58 cc |.K.d..FV1...K.X.| +00000060 a7 cf cd 5a 6c 3c 98 67 bf fc 29 de d0 22 5e de |...Zl<.g..).."^.| +00000070 66 d3 f1 5e 03 70 dc 0f 39 0b df bf 65 65 17 d5 |f..^.p..9...ee..| +00000080 24 55 29 c4 fc c8 69 e9 fd a1 47 9f 9b fc e8 10 |$U)...i...G.....| +00000090 33 1f b5 c2 68 02 03 b7 22 80 79 b3 63 34 a1 59 |3...h...".y.c4.Y| +000000a0 33 bb bd 4c 13 c7 d9 92 3b 96 d8 35 5a 1f 72 e2 |3..L....;..5Z.r.| +000000b0 c2 4d e8 cf 8b 54 ea 42 9b 09 9d 0d 4e ef 40 85 |.M...T.B....N.@.| +000000c0 12 fa 6d af 3d 54 e9 89 86 e4 70 e0 67 d5 5c 5b |..m.=T....p.g.\[| +000000d0 95 c1 8b 53 7e 78 ce da 40 aa 54 e3 51 e3 8d f6 |...S~x..@.T.Q...| +000000e0 8c d6 a8 62 a8 ba 4e e6 15 92 11 6c f1 f4 0c f6 |...b..N....l....| +000000f0 e3 15 ba db 39 54 44 f0 f1 c2 34 4b 77 e2 6a a8 |....9TD...4Kw.j.| +00000100 e4 1d 5d 62 77 12 7e 6a 3b 4a 86 04 db ef 47 95 |..]bw.~j;J....G.| +00000110 c8 8e ba 6a 2c d2 ce 98 04 5f 8b d2 03 dc a3 e8 |...j,...._......| +00000120 f4 42 0f 2c c1 b9 f3 9a ba b1 b1 6d d2 33 a4 f2 |.B.,.......m.3..| +00000130 2b d1 b2 f2 3c 94 e9 60 fd f9 97 66 d4 b0 12 86 |+...<..`...f....| +00000140 35 da 1a d1 c4 8b 42 c8 b2 95 13 46 60 6c 09 08 |5.....B....F`l..| +00000150 09 6c f1 5e a7 57 07 8f 82 a9 7e ce 91 4b 13 a9 |.l.^.W....~..K..| +00000160 1d e5 78 90 77 3d 49 b6 b3 7b 35 c1 fe d7 51 0c |..x.w=I..{5...Q.| +00000170 e6 d7 cb c2 |....| +>>> Flow 12 (server to client) +00000000 00 00 01 40 c7 5d dd 71 eb 2f 24 ac d0 f3 f6 27 |...@.].q./$....'| +00000010 ed 22 2d f4 89 c0 7c 3d ee 9f d0 d1 ab 3e a1 ef |."-...|=.....>..| +00000020 d3 7b 07 eb e0 e5 63 a3 a0 99 ec 9d d0 00 8e fb |.{....c.........| +00000030 35 c7 45 75 2c d3 78 44 7f 0c c2 eb 2d 14 de cd |5.Eu,.xD....-...| +00000040 c6 69 db e3 d0 6e 60 08 da 92 9d 37 9d d4 bd e3 |.i...n`....7....| +00000050 6f 16 34 77 f6 d5 62 04 28 7c 6a 9d 9c b6 78 d0 |o.4w..b.(|j...x.| +00000060 3e 6c 19 ba 04 77 5a a5 8d 54 aa 1a 1e f8 c6 58 |>l...wZ..T.....X| +00000070 99 b0 79 03 53 73 65 aa 33 e6 6d 90 e9 87 05 be |..y.Sse.3.m.....| +00000080 cd 67 bf bc ca f5 a5 55 39 61 76 2e 88 2d f8 3e |.g.....U9av..-.>| +00000090 4b 33 f7 52 22 08 04 a7 d5 bf 75 35 c4 bf a1 f1 |K3.R".....u5....| +000000a0 6e 22 6c 84 7a 82 2e 95 b3 87 c3 3e 2f 10 2b fb |n"l.z......>/.+.| +000000b0 cb 8a 03 2b 52 ce 9c 08 38 3c 3e 18 58 2e 7b 63 |...+R...8<>.X.{c| +000000c0 42 dd 21 54 d2 a1 bf e6 11 1e 53 e7 c1 6f a8 fe |B.!T......S..o..| +000000d0 7a af 6f c6 59 89 43 b8 ce 75 c8 e0 04 59 2f 31 |z.o.Y.C..u...Y/1| +000000e0 d4 c2 93 2e 09 b3 18 a6 2f 95 46 45 8b 70 75 b4 |......../.FE.pu.| +000000f0 57 f2 b6 cf 63 0f aa 77 9e 25 ea 0a 2c d8 7f e4 |W...c..w.%..,...| +00000100 9d fc 65 2e 8b db 01 02 8e d8 3e 4b c2 1e 1d 04 |..e.......>K....| +00000110 fa 9d d0 97 2d f5 8a a6 d7 e9 74 3e e1 ad e8 fe |....-.....t>....| +00000120 16 71 30 75 31 3b 55 14 fb 37 da e6 16 25 2e 4e |.q0u1;U..7...%.N| +00000130 84 43 ae 55 bc b7 55 f0 ea 13 4c 8d 2a 7b a5 e4 |.C.U..U...L.*{..| +00000140 af c2 4c 96 de 67 c2 e1 f4 15 d6 d7 42 f9 e1 c0 |..L..g......B...| +00000150 13 41 c5 93 |.A..| +>>> Flow 13 (client to server) +00000000 00 00 02 80 d6 4c 40 1d b4 1a 9d 98 a9 48 44 3e |.....L@......HD>| +00000010 d7 14 80 f7 85 17 49 0a a8 00 ab d3 56 16 40 77 |......I.....V.@w| +00000020 bb ac 18 bc 0b 02 1d 02 f3 21 3b ed 7d 9c e3 33 |.........!;.}..3| +00000030 75 6b bf cb dc b4 aa 65 92 b4 f8 d3 52 ea ad c9 |uk.....e....R...| +00000040 fb 4b 51 95 7a ab 0b 5d b7 99 12 21 df 18 67 5d |.KQ.z..]...!..g]| +00000050 8e fe 2f 6c 58 43 95 55 3e f4 c7 94 d5 1f ce a6 |../lXC.U>.......| +00000060 c7 ac cf fb a9 20 2e 7a 34 77 70 02 5c d8 4f a6 |..... .z4wp.\.O.| +00000070 24 3e c8 fe ec 8f d5 ce 0b 38 bc 1e 78 7d 8d 05 |$>.......8..x}..| +00000080 ed 20 b1 d2 b5 5f f3 4c 66 cb 8b 74 77 ad 8f e2 |. ..._.Lf..tw...| +00000090 ae c0 ce c3 82 33 f4 5a dd 41 90 a5 48 79 f2 7f |.....3.Z.A..Hy..| +000000a0 dc 0f 1a e4 fa 3b ee 08 e3 cd b0 4b af 2d 20 6e |.....;.....K.- n| +000000b0 6e b2 48 d1 f6 01 c8 8b 56 45 dc c9 2f cf a3 1c |n.H.....VE../...| +000000c0 61 3f 2b 69 07 19 a7 a7 3c b5 ed d0 b4 c1 2b ef |a?+i....<.....+.| +000000d0 fe fe bd ce 09 9f c7 97 f4 1f f3 12 af 66 cb 8f |.............f..| +000000e0 0e 9a d3 15 bc 01 76 83 4a 75 7e 1d cc ef a5 50 |......v.Ju~....P| +000000f0 08 d9 c0 07 fa 59 03 72 73 99 17 85 b6 7d 6f 21 |.....Y.rs....}o!| +00000100 9b 80 4f 4e 5b 23 56 29 64 f4 10 67 48 ed 22 7f |..ON[#V)d..gH.".| +00000110 51 32 b3 b2 cb 51 d2 ba 93 4c 5f 4e e1 cd 55 fa |Q2...Q...L_N..U.| +00000120 03 10 e6 c7 f1 3e 63 2e 27 b4 60 e7 77 13 b8 a9 |.....>c.'.`.w...| +00000130 9b 61 b1 3b b7 ad af 30 b4 a3 20 ba b2 44 d3 ad |.a.;...0.. ..D..| +00000140 ed db f4 2d 4e fc 8b 2c 6c bf 74 ba 67 cf 03 cd |...-N..,l.t.g...| +00000150 36 ed ff 40 76 05 31 b6 75 c8 20 f2 a8 0e 22 a5 |6..@v.1.u. ...".| +00000160 48 18 e8 98 88 aa b8 23 fd 60 e0 f3 1f 35 e5 5a |H......#.`...5.Z| +00000170 a1 f7 6d 7a 3f f1 61 63 af 63 b3 7e 2d 19 3b ac |..mz?.ac.c.~-.;.| +00000180 8f 5e f6 eb cd 01 ec 2e 69 64 de c5 37 62 ec 94 |.^......id..7b..| +00000190 66 27 ad 47 70 b5 95 15 19 50 44 53 65 99 04 16 |f'.Gp....PDSe...| +000001a0 dd bf 8a a7 35 97 89 95 ec 91 09 a7 7f eb 14 c4 |....5...........| +000001b0 7e 30 6d 2b 54 0a 2c d0 bc 7d 29 b7 da 47 a0 27 |~0m+T.,..})..G.'| +000001c0 3b 38 1e 6c 74 9e e5 96 8c d9 34 2b 36 72 cb f9 |;8.lt.....4+6r..| +000001d0 4e 5e 3d 81 59 8e 16 56 8b ea dc e1 91 e1 4f af |N^=.Y..V......O.| +000001e0 a9 ec 53 3d b9 3a 26 25 2e d9 cf 00 cd 82 5f 2a |..S=.:&%......_*| +000001f0 31 f5 4c 75 83 6a 1f cb a0 a8 4d 1f ca 56 09 24 |1.Lu.j....M..V.$| +00000200 f1 ea ca dc a2 de 53 c5 b8 01 7f 8e 67 ec ea 78 |......S.....g..x| +00000210 e5 87 27 cf 19 d2 e1 7f 6d 9c b4 93 c2 a4 8b b2 |..'.....m.......| +00000220 c2 2f 44 bc 56 01 65 c3 ee 0c 46 5b e9 31 f9 a3 |./D.V.e...F[.1..| +00000230 cd 10 f7 75 c7 88 96 b6 ad c2 1c 9b 03 dd 87 c0 |...u............| +00000240 e4 e3 5e d1 5b 37 e4 b3 87 b6 d8 20 c1 3e af 9f |..^.[7..... .>..| +00000250 58 da 0d 96 e8 d9 70 71 7e 4f a1 34 40 67 71 cd |X.....pq~O.4@gq.| +00000260 b4 da d3 33 0c e3 6a 5b 90 c9 c3 dc ff 65 03 a7 |...3..j[.....e..| +00000270 72 f2 ab 67 af c9 4a 82 cf 80 56 c4 81 f3 30 05 |r..g..J...V...0.| +00000280 ea 94 c3 c9 8f 72 27 72 02 05 3b 6a 6e 54 86 d2 |.....r'r..;jnT..| +00000290 15 84 76 8d |..v.| +>>> Flow 14 (server to client) +00000000 00 00 00 10 36 f0 bd b2 99 54 73 9e 88 f3 23 88 |....6....Ts...#.| +00000010 aa ab f2 04 1d 99 d7 41 d7 5c d5 ec 80 bb d7 81 |.......A.\......| +00000020 c5 1d 3f e0 |..?.| +>>> Flow 15 (client to server) +00000000 00 00 00 20 82 76 b3 44 58 78 4b aa 00 c7 18 94 |... .v.DXxK.....| +00000010 c9 71 2a 38 c7 88 da 52 54 ee fc 5f fd 2a 5e 62 |.q*8...RT.._.*^b| +00000020 c2 9f 1d d5 59 b9 f6 12 90 31 8b 9d 76 59 99 ca |....Y....1..vY..| +00000030 b4 a5 ac 9c |....| +>>> Flow 16 (server to client) +00000000 00 00 01 b0 a6 db 72 29 3a c0 3d 7a f7 35 bc c9 |......r):.=z.5..| +00000010 e5 c5 f8 41 d3 d7 e3 29 a8 73 17 69 bb 8a ed 0e |...A...).s.i....| +00000020 b5 00 1f a2 2e 00 c0 06 06 02 e0 c8 39 ad 11 c3 |............9...| +00000030 62 ab 11 a6 70 c7 c4 bc e3 c5 e4 f8 3d 99 08 77 |b...p.......=..w| +00000040 03 5c 98 db 50 24 39 82 56 2e d6 91 85 b3 b1 bc |.\..P$9.V.......| +00000050 0b 2d c5 da a5 00 9d 49 ea dd 95 da aa 91 95 3d |.-.....I.......=| +00000060 d7 82 23 d4 eb 5f 11 e8 d5 a3 15 d9 d9 38 03 ba |..#.._.......8..| +00000070 5d 82 22 56 1c fb 77 70 be d0 5c 7b e7 06 32 de |]."V..wp..\{..2.| +00000080 ba 83 05 d4 ea 52 53 bc 47 a7 60 90 68 5e 44 61 |.....RS.G.`.h^Da| +00000090 ca 7a 84 bf fa ae 19 87 b0 d7 bb 3f 5f 90 26 19 |.z.........?_.&.| +000000a0 99 f0 7d af 65 21 9a 90 7d 0e db c8 95 91 69 f2 |..}.e!..}.....i.| +000000b0 4e 6c 9b cc e6 15 9c bd ca 2f 1f 58 8a 27 06 3d |Nl......./.X.'.=| +000000c0 40 a9 88 57 e8 6b ab 89 13 ea 66 4b 4c 1b 37 51 |@..W.k....fKL.7Q| +000000d0 25 e0 8a 9d 71 0b f2 23 1b cb 8c 54 5b d9 87 61 |%...q..#...T[..a| +000000e0 42 ba de df 20 19 0d 06 a8 bd ba 64 6a bb c8 f5 |B... ......dj...| +000000f0 ea b9 58 21 1d 6d 4e a6 b3 1e 8b c3 50 5c 44 9e |..X!.mN.....P\D.| +00000100 a3 6d a8 46 5f 5b 78 9f 72 7c 3d 6c 40 d8 5b c3 |.m.F_[x.r|=l@.[.| +00000110 51 9a 54 d3 53 8e bb f2 b8 84 39 1f 35 62 8d 5a |Q.T.S.....9.5b.Z| +00000120 2c 87 ab d5 cb f6 ba f7 46 9d cf c2 70 7b cf a1 |,.......F...p{..| +00000130 ea a9 12 d2 b9 4f e2 36 ae 8d 16 da b4 87 c0 69 |.....O.6.......i| +00000140 84 61 e6 4e cc 04 33 a7 08 c5 90 04 b0 7c db e7 |.a.N..3......|..| +00000150 6b 7a 49 b7 ab 0d 8d a7 df 5c 82 fa c1 8e 46 3a |kzI......\....F:| +00000160 9c 48 d6 a0 19 79 bb 61 07 c2 6e 00 02 ec 9b d2 |.H...y.a..n.....| +00000170 d6 b8 ab 90 3a 5c 6b 96 96 c7 1a b4 5a 57 a8 05 |....:\k.....ZW..| +00000180 f5 bd a0 39 43 4c fe 6e 78 53 d4 ca e8 9a 8d 5a |...9CL.nxS.....Z| +00000190 e7 cb 48 83 f8 25 f9 97 b7 9d f0 b4 c2 51 2e e4 |..H..%.......Q..| +000001a0 ed ef 74 b1 96 a5 82 c0 16 4c da cc bd af 75 aa |..t......L....u.| +000001b0 fd 45 b1 9e e6 6d 5a 29 86 81 7b 7f 9f 46 bd 2d |.E...mZ)..{..F.-| +000001c0 72 ee 6f 15 00 00 00 90 66 56 3c 9b 7a 5b 15 92 |r.o.....fV<.z[..| +000001d0 31 8f ae e9 5c 26 0e 38 6e e8 fb 03 9a b0 be 53 |1...\&.8n......S| +000001e0 62 10 2b 1f 8e 98 0d b5 aa 00 0a 0b 58 91 4b f1 |b.+.........X.K.| +000001f0 04 84 25 3d 02 94 a0 6e 12 73 ae cf eb 12 4e 5e |..%=...n.s....N^| +00000200 f8 2b 5a 28 ba 99 c0 fb c3 4f a0 7b a1 c3 69 5e |.+Z(.....O.{..i^| +00000210 81 28 d2 99 ee e2 ea 1c d8 eb be 18 bc d0 ce 3b |.(.............;| +00000220 18 17 7d 5c 9b 03 86 6d 92 7e c8 48 3f 91 99 bc |..}\...m.~.H?...| +00000230 ff 94 74 30 db bd 3a 80 49 cf 05 e4 57 d8 28 d9 |..t0..:.I...W.(.| +00000240 e8 85 7b 9e da 9b 6d 71 4f 06 46 37 d8 52 bc e9 |..{...mqO.F7.R..| +00000250 65 ac 3f 6d 88 97 8c 2f 50 ae 9a f0 7a ce 22 f9 |e.?m.../P...z.".| +00000260 4d cd 1f ca a8 8e c3 af 00 00 00 90 00 bf 0f 5c |M..............\| +00000270 29 b7 f4 6f 3e 7f 3c f2 b7 09 3e 38 5d 2f bd 2f |)..o>.<...>8]/./| +00000280 5d 97 6a 67 7f 6a 70 ed 4d d0 1c 98 84 f3 e8 9b |].jg.jp.M.......| +00000290 82 33 d7 c3 3f 9c 2e 9a 15 43 d5 76 97 ae 72 6a |.3..?....C.v..rj| +000002a0 03 9e c4 41 2d fb f8 65 69 d5 a6 7f df ca e3 04 |...A-..ei.......| +000002b0 d1 20 52 2c 9b e2 dd e1 67 2e fe 80 4a 80 54 78 |. R,....g...J.Tx| +000002c0 d0 f6 62 46 fd 22 06 3d d5 25 a1 17 7a 1d e7 7b |..bF.".=.%..z..{| +000002d0 47 79 52 bc 1a 14 c8 c7 0a de 25 3b 4c c0 77 86 |GyR.......%;L.w.| +000002e0 ca 97 c2 89 3d 21 c2 bf 78 e8 5e 8c 30 4a 34 f4 |....=!..x.^.0J4.| +000002f0 2f 34 de 51 e7 ea 1e 94 e0 28 7b af e2 2e 54 ff |/4.Q.....({...T.| +00000300 cf 47 b2 73 6b 17 b9 7d 09 bb c8 68 00 00 00 20 |.G.sk..}...h... | +00000310 3f 1f 61 6c f7 5e 1c a9 cd 93 3f 6a 52 5b f6 25 |?.al.^....?jR[.%| +00000320 19 19 88 52 fb c3 3a 36 b8 db 1e 06 c0 2a 86 ac |...R..:6.....*..| +00000330 c8 dc 45 66 81 55 02 d2 18 f7 8a c4 bb 80 2f 05 |..Ef.U......../.| +>>> Flow 17 (client to server) +00000000 00 00 00 20 4a b5 13 b3 01 5e b2 ac ed 1f 0c 21 |... J....^.....!| +00000010 e0 6f f3 e7 14 27 92 fc 9d 21 30 81 7c 60 d5 f7 |.o...'...!0.|`..| +00000020 2f 0d 25 30 d6 52 d5 3d 03 3c 2f 43 91 c2 19 35 |/.%0.R.=.>> Flow 18 (server to client) +00000000 00 00 00 10 8a 9c 6f 94 6a 34 1c 85 51 99 45 5d |......o.j4..Q.E]| +00000010 38 cb 3c 2f 89 b9 13 6c 44 9e 1c c2 76 ef fa fb |8.>> Flow 19 (client to server) +00000000 00 00 00 10 45 98 28 66 01 cb 3f 87 05 30 0d 06 |....E.(f..?..0..| +00000010 d6 e9 78 62 91 83 1a 7f 2e cf f3 62 83 bc 93 01 |..xb.......b....| +00000020 1b 8e d6 76 |...v| +>>> Flow 20 (server to client) +00000000 00 00 00 10 ee bf 95 ff 89 6f 01 6d 4f 70 e1 65 |.........o.mOp.e| +00000010 07 c5 ed 56 ed f9 0a 83 3c a0 31 32 30 a2 37 d9 |...V....<.120.7.| +00000020 47 e9 c8 16 00 00 00 20 ce d9 83 eb 5b 25 83 ef |G...... ....[%..| +00000030 7a 56 fe 9f 1e 2b a1 d1 7d ea 3a 87 e6 3c 9b b0 |zV...+..}.:..<..| +00000040 96 43 b1 10 db e0 86 29 f3 48 b2 9c e6 06 ef b8 |.C.....).H......| +00000050 4b a3 75 73 c7 fa 34 f4 00 00 00 10 eb 24 05 ad |K.us..4......$..| +00000060 0d 9f c3 e6 18 1b 8f c7 0c 42 cc 3f 82 e7 dd bd |.........B.?....| +00000070 d4 ba a8 a8 2e 04 48 9c 56 47 b6 97 |......H.VG..| +>>> Flow 21 (client to server) +00000000 00 00 00 10 5d 70 5d 74 78 30 52 d8 48 95 f5 64 |....]p]tx0R.H..d| +00000010 76 ee 72 a0 83 8d 77 ab 55 44 6e 16 b9 fd 43 d4 |v.r...w.UDn...C.| +00000020 88 56 39 7c |.V9|| diff --git a/ssh/testdata/Client-RunCommandSuccess b/ssh/testdata/Client-RunCommandSuccess new file mode 100644 index 0000000000..4c6dde2124 --- /dev/null +++ b/ssh/testdata/Client-RunCommandSuccess @@ -0,0 +1,384 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 dc 07 d1 17 47 7a f4 20 3f c1 |..........Gz. ?.| +00000010 b1 db 89 6d f9 df 00 00 01 7a 73 6e 74 72 75 70 |...m.....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0b 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 88 0a 16 48 22 e9 9c 1d 70 a7 |..... ...H"...p.| +00000080 5d c5 24 8d ad b1 93 70 0e 49 71 83 02 1b 35 83 |].$....p.Iq...5.| +00000090 dd 29 b3 2d 8e 1b 00 00 00 63 00 00 00 13 65 63 |.).-.....c....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 48 00 00 00 20 7f a8 0b f4 ff 07 80 |6...H... .......| +000000c0 25 b0 a0 24 68 d2 5e b9 5e 8d f8 bd b1 62 84 e0 |%..$h.^.^....b..| +000000d0 0a 96 2a da 89 6b 63 25 eb 00 00 00 20 62 6f 60 |..*..kc%.... bo`| +000000e0 e7 df bc 16 7d fe ec 7b 0e fe 35 5f 8f 87 4b 15 |....}..{..5_..K.| +000000f0 33 a9 82 b9 7f 96 e7 56 42 71 32 dd 39 00 00 00 |3......VBq2.9...| +00000100 00 00 00 00 00 00 00 00 00 00 00 0c 0a 15 00 00 |................| +00000110 00 00 00 00 00 00 00 00 00 00 01 40 86 df 12 01 |...........@....| +00000120 f3 52 98 e5 9e 2e 8c 47 a5 21 b1 04 91 46 9b 22 |.R.....G.!...F."| +00000130 52 6f 37 dc 1c eb d2 79 fa ee a1 6d 7f 3b 15 a2 |Ro7....y...m.;..| +00000140 58 58 c9 61 16 05 5c 94 a9 2d 46 df ca b6 9f c3 |XX.a..\..-F.....| +00000150 36 67 7a a8 ef f6 91 bd 1b 2b 10 8e 6e 19 b1 7b |6gz......+..n..{| +00000160 c0 a5 25 05 11 cf 8c da b9 5c ed b4 6b cd d7 e1 |..%......\..k...| +00000170 d3 ce 63 58 d5 3b 14 df 05 e0 76 2b 49 63 01 fe |..cX.;....v+Ic..| +00000180 12 be 71 1e 8c 9c e4 fa 32 0a 1b 09 df 5e 3b 42 |..q.....2....^;B| +00000190 da f1 dc bd c2 b6 82 2b 30 13 f4 f2 2a 73 3f 00 |.......+0...*s?.| +000001a0 15 fc a0 5b 30 99 5c c0 af 1f 17 2e aa be 2c 22 |...[0.\.......,"| +000001b0 08 4d 25 a6 5f 11 52 64 26 74 a7 4b 8d 72 94 32 |.M%._.Rd&t.K.r.2| +000001c0 59 d4 b4 cc 43 81 e1 7a 84 f8 b4 e9 d9 49 02 79 |Y...C..z.....I.y| +000001d0 30 67 45 ab 99 f2 fd de 7a f5 27 29 41 91 09 f5 |0gE.....z.')A...| +000001e0 62 5c a4 57 44 d3 29 53 a0 9a 39 99 a0 57 15 3a |b\.WD.)S..9..W.:| +000001f0 d5 2d 9b fe 95 cb 04 2d 2e 6e ba b5 4b 34 f9 58 |.-.....-.n..K4.X| +00000200 f4 41 61 ce 45 dd c5 63 f7 0c 77 bc 41 1e bc 74 |.Aa.E..c..w.A..t| +00000210 89 90 87 29 c0 08 f6 e2 47 7d 68 7b 7d 18 44 8d |...)....G}h{}.D.| +00000220 1b d1 92 96 89 5d 03 57 bc cd cb 09 95 c4 53 4c |.....].W......SL| +00000230 48 b0 3e 3b 6b 41 b7 31 25 b9 60 97 bf e9 aa e8 |H.>;kA.1%.`.....| +00000240 cc 84 6a 4c eb e2 0f b2 4b 0c 09 17 df 6e 2d 75 |..jL....K....n-u| +00000250 5b cb 5b 72 a2 22 b8 d1 39 bc 28 38 9b 7e fc 4d |[.[r."..9.(8.~.M| +00000260 a5 ad 82 5e 52 00 19 ed 73 ba 36 9c |...^R...s.6.| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000010 00 00 00 20 9d d9 70 30 b0 7c cb 37 d7 25 2e 0b |... ..p0.|.7.%..| +00000020 da 94 33 9b 14 74 a0 d4 86 79 3f 2f fb 7f 5b 23 |..3..t...y?/..[#| +00000030 91 43 23 17 1d 68 3e 7c 5a 78 23 67 32 84 e4 4a |.C#..h>|Zx#g2..J| +00000040 a7 8e 6f c5 |..o.| +>>> Flow 8 (server to client) +00000000 00 00 00 20 3e 5d 5a 2a 3d bc e0 77 7a bd 7b a6 |... >]Z*=..wz.{.| +00000010 1d 7a d0 f9 10 97 23 5c a4 01 f5 9b 6c e9 80 04 |.z....#\....l...| +00000020 3b 67 f4 1e b8 80 e9 1d d6 3a 78 44 06 53 90 29 |;g.......:xD.S.)| +00000030 f8 98 24 38 |..$8| +>>> Flow 9 (client to server) +00000000 00 00 00 30 81 9f d7 49 5e 0f 6a 14 24 8a ef a6 |...0...I^.j.$...| +00000010 48 ca b6 ce aa c5 b8 cd de cb ba b0 12 d8 da 6c |H..............l| +00000020 da 9b d1 47 e9 10 a5 24 49 93 51 7e 1e f7 1b f0 |...G...$I.Q~....| +00000030 32 15 31 b1 e3 18 03 c9 af 9c d1 33 61 57 b4 d1 |2.1........3aW..| +00000040 89 0f 11 7a |...z| +>>> Flow 10 (server to client) +00000000 00 00 00 20 99 a3 35 0c ea 77 9c 26 89 4b 9b 54 |... ..5..w.&.K.T| +00000010 dd 01 45 00 81 47 ac ba 25 b3 34 1c 2a d5 34 79 |..E..G..%.4.*.4y| +00000020 12 38 22 45 6f ba 34 79 0e c6 c8 da 31 21 92 01 |.8"Eo.4y....1!..| +00000030 c9 b7 4f 80 00 00 00 40 b3 83 7c 21 94 43 ae 31 |..O....@..|!.C.1| +00000040 c6 9f b5 08 28 66 c9 af 51 77 76 db 22 45 92 c2 |....(f..Qwv."E..| +00000050 b2 83 26 65 58 a4 30 d1 61 7d bd 33 dc 69 bc 60 |..&eX.0.a}.3.i.`| +00000060 c7 8e 8c d4 7b 67 fa e9 96 ba 49 83 da 79 20 bd |....{g....I..y .| +00000070 91 18 93 71 45 a5 dd 95 7b d6 b4 fe 59 a4 33 22 |...qE...{...Y.3"| +00000080 ef d1 d0 b8 2f a1 75 f1 |..../.u.| +>>> Flow 11 (client to server) +00000000 00 00 01 60 d9 89 e7 4c a7 4c 5d 60 f3 48 2d 70 |...`...L.L]`.H-p| +00000010 52 31 0f 3d e8 40 c3 f2 4b 9d 3a b0 1e 63 3e 02 |R1.=.@..K.:..c>.| +00000020 51 8f 1d 4d 58 4c d1 59 96 3c 41 66 af 72 ee 30 |Q..MXL.Y...| +000000d0 d7 b2 a5 e3 7c 0c e8 d4 24 22 ff 37 61 df 34 b5 |....|...$".7a.4.| +000000e0 f4 78 79 e1 bd 4b cf 31 87 cd d7 dd d2 9b ac 55 |.xy..K.1.......U| +000000f0 99 cf 25 bb a7 a1 5d 00 ad 67 27 d5 1d 2c cf b0 |..%...]..g'..,..| +00000100 1b bf 0f 58 55 57 3c 7c be e7 22 e9 68 0e 17 0f |...XUW<|..".h...| +00000110 04 cd af 94 34 19 1a 06 be 1c 40 0d 65 00 5a d2 |....4.....@.e.Z.| +00000120 97 16 65 8e 5d 5a fe 71 5b a7 be b8 18 70 9a de |..e.]Z.q[....p..| +00000130 43 70 18 8f 82 3d 3a cd f8 d5 a5 26 27 5e fd 63 |Cp...=:....&'^.c| +00000140 7d b9 df e0 d6 b2 58 34 68 29 14 1c bd ae 21 9f |}.....X4h)....!.| +00000150 8e f5 41 d9 48 61 cd ea f4 fa 74 a0 6e c2 35 35 |..A.Ha....t.n.55| +00000160 6a 78 53 09 aa cc 73 f9 97 66 be 66 b4 c8 68 ac |jxS...s..f.f..h.| +00000170 39 3e 16 28 |9>.(| +>>> Flow 12 (server to client) +00000000 00 00 01 40 89 e5 0b 8a 65 f0 2f 87 3c 6f 05 9a |...@....e./...9Z.7.......#.| +000000e0 53 e8 b3 1b 43 b5 cd f2 19 17 60 39 0e f8 7d e8 |S...C.....`9..}.| +000000f0 49 ac a3 f6 2f 5a a2 d3 63 5e 41 59 62 47 89 56 |I.../Z..c^AYbG.V| +00000100 13 4c e7 21 4f eb 22 1b 9b 9a 29 42 ad b0 d0 57 |.L.!O."...)B...W| +00000110 ec 45 2d cc 4e 48 2f 15 0e cf f2 fb 2f 17 f1 d7 |.E-.NH/...../...| +00000120 9c 00 3f 5c e0 ef 7c d9 3f f7 32 09 58 86 1f c8 |..?\..|.?.2.X...| +00000130 c4 d3 4b 3a 1c 55 47 47 db f9 51 81 f1 81 c6 3f |..K:.UGG..Q....?| +00000140 05 73 d2 c8 29 8a 28 3c 37 e6 94 fe 2a df d7 19 |.s..).(<7...*...| +00000150 2d 9d 1c 0f |-...| +>>> Flow 13 (client to server) +00000000 00 00 02 80 87 27 0f b1 28 b4 15 4f 8c 56 9a 47 |.....'..(..O.V.G| +00000010 b9 f8 1a 4b d3 01 fd c1 4f 6b b1 71 9b c3 df 9d |...K....Ok.q....| +00000020 95 7d 3a 3a 9e f0 1e 7d 17 ef f4 c8 1e c4 4e c4 |.}::...}......N.| +00000030 41 86 85 1a 07 ca 4a fd 78 9a 16 b0 d8 dc 6a f3 |A.....J.x.....j.| +00000040 6b ae 5c 5a 47 07 aa a2 63 bc 92 62 9d dc 94 a0 |k.\ZG...c..b....| +00000050 30 87 34 8c 67 63 c3 f8 3d ed 1c ea 6f cc 35 e2 |0.4.gc..=...o.5.| +00000060 49 ce d0 71 26 a9 e8 75 3e 9a 8d c9 d4 0c 58 ae |I..q&..u>.....X.| +00000070 2e bf f0 31 71 1a bc 51 0d bf 6d 9d 7d 07 1d 21 |...1q..Q..m.}..!| +00000080 be 40 ae 2a 0f 9f b1 5d c6 54 62 8d 8f 83 01 a9 |.@.*...].Tb.....| +00000090 7a fb 85 2e 73 af f1 4f 46 2e 7e 31 c8 1d c1 82 |z...s..OF.~1....| +000000a0 63 53 12 ed e3 df ba 22 34 b9 6c e7 a1 bf 2a ba |cS....."4.l...*.| +000000b0 9e 6b a8 e6 d7 38 0c 90 8a 94 13 a9 7e 5c 28 94 |.k...8......~\(.| +000000c0 0d 81 79 67 15 e0 3b 76 78 e6 30 c6 df 1b 9f 69 |..yg..;vx.0....i| +000000d0 79 5a db 10 f6 0e da 15 e4 f3 f1 cc e1 c9 3a 9b |yZ............:.| +000000e0 c1 ad 8d 14 d7 40 c3 7e 82 6a 92 ef b1 08 db 3e |.....@.~.j.....>| +000000f0 1c 97 3b b3 ea 6f fc 81 fa 69 a8 fb 49 3b 9b ad |..;..o...i..I;..| +00000100 62 4c 80 ea 8f 02 60 ef b9 81 28 27 6b db f1 15 |bL....`...('k...| +00000110 0e 16 00 7a e3 66 4a fc a9 9a 7c e6 98 05 fa 31 |...z.fJ...|....1| +00000120 be f4 63 5a 7b 53 9e 76 5a 23 21 65 74 76 76 e5 |..cZ{S.vZ#!etvv.| +00000130 eb f0 8a 58 dc f5 5b 8f 16 1e 6b 33 29 4b 6d 57 |...X..[...k3)KmW| +00000140 86 b7 e0 ca 6c c3 8d bd 55 64 c4 7d 09 26 ec 02 |....l...Ud.}.&..| +00000150 9d cc 2d 88 03 7a a3 7f 25 65 9d b5 6f 0c 57 42 |..-..z..%e..o.WB| +00000160 0f 15 ab 83 a4 2d b9 fd 4d 4a 66 2c b0 5c 8f 0c |.....-..MJf,.\..| +00000170 18 72 d1 ee d6 de c1 46 32 ed 6b d5 c1 0d 27 2f |.r.....F2.k...'/| +00000180 89 36 49 f0 b7 58 46 37 02 57 bb 43 cb 1e 86 64 |.6I..XF7.W.C...d| +00000190 4b b6 d7 ca 60 cd c2 24 af 2e 08 26 94 d6 0d ef |K...`..$...&....| +000001a0 3e 0a 3d 27 cb 8e 66 96 59 30 0d 74 65 8e ef 5f |>.='..f.Y0.te.._| +000001b0 73 e0 ef 63 db 14 81 84 18 89 fb b9 6c 02 c9 1f |s..c........l...| +000001c0 77 8c ef d9 11 10 74 70 4d a2 a2 70 53 c7 b9 67 |w.....tpM..pS..g| +000001d0 8e b1 8a fa 2d b4 96 0a 61 ac 66 63 9c 22 21 de |....-...a.fc."!.| +000001e0 2e 95 86 ba 65 1c cd ba 80 24 f8 19 72 8d 26 be |....e....$..r.&.| +000001f0 2f fd 74 70 8f 5a dd cc f1 58 23 05 a9 4e 42 40 |/.tp.Z...X#..NB@| +00000200 0d 07 b9 47 39 e2 c0 9b ec b4 20 97 bf 23 4e 1e |...G9..... ..#N.| +00000210 3d c8 6a bd 44 8f b1 a6 61 b5 d5 d2 d3 45 87 df |=.j.D...a....E..| +00000220 fc a0 02 c3 ca 5e e3 a0 97 d1 dd 98 02 2b 60 2a |.....^.......+`*| +00000230 f2 4e 32 89 af ca e5 7d 69 64 6f be 47 dc ea 0d |.N2....}ido.G...| +00000240 cc fb f5 7b 13 eb 7c 1b 46 6f 36 dc d9 15 5a 26 |...{..|.Fo6...Z&| +00000250 5a aa d8 ef 89 4e 1f af 29 66 5e 06 6f a5 2e 44 |Z....N..)f^.o..D| +00000260 90 e3 a7 9f ab 9e 4c be e2 b8 c3 0d 6c f2 fe 54 |......L.....l..T| +00000270 43 8f 97 92 1c b0 12 f6 20 cc 6e c2 4e f5 a7 45 |C....... .n.N..E| +00000280 1a 69 81 b2 c1 c1 d4 44 a5 5e d9 52 50 aa ec 5f |.i.....D.^.RP.._| +00000290 fc 33 d7 eb |.3..| +>>> Flow 14 (server to client) +00000000 00 00 00 10 50 fd 0d ad 67 a9 cc 51 32 a1 e1 b6 |....P...g..Q2...| +00000010 9d 17 bf 4b 36 2e 50 68 93 66 fe ca 21 94 de 0a |...K6.Ph.f..!...| +00000020 49 98 2a 9f |I.*.| +>>> Flow 15 (client to server) +00000000 00 00 00 20 cf fb b1 6b 60 01 2b b2 38 a8 96 52 |... ...k`.+.8..R| +00000010 c3 d2 60 39 68 05 90 50 c8 58 f9 04 50 1e fa 4d |..`9h..P.X..P..M| +00000020 82 6c c3 a3 a3 e8 77 e5 21 2f 9e 8c 5c 2e 13 2e |.l....w.!/..\...| +00000030 7f da b2 b5 |....| +>>> Flow 16 (server to client) +00000000 00 00 01 b0 d4 7d 0d b2 34 72 1f fe 93 b5 c8 e7 |.....}..4r......| +00000010 fd 02 23 9a 9a 15 38 56 95 3e 7c 8b 3e ae fb 95 |..#...8V.>|.>...| +00000020 bc f0 d3 8b c9 b4 13 83 79 89 da 70 29 72 cb b4 |........y..p)r..| +00000030 7e 11 ed 61 ca 6a df 8c 43 b2 0c e5 b5 34 82 f9 |~..a.j..C....4..| +00000040 91 d0 98 af 35 f3 60 4f e0 cf 5f 73 98 e1 d0 fe |....5.`O.._s....| +00000050 92 17 58 d0 b8 92 06 8f da 35 a6 3d 2b 5c 2a 80 |..X......5.=+\*.| +00000060 00 62 bf 3c b7 e8 72 4f 2b 29 ea 82 f5 2b da 56 |.b.<..rO+)...+.V| +00000070 07 6f a1 d1 7d 82 8e 53 98 e9 62 49 19 41 24 82 |.o..}..S..bI.A$.| +00000080 b4 9c f3 b0 9a 07 af 27 87 f5 a9 1f f7 b5 45 37 |.......'......E7| +00000090 1a 97 b8 2c 5e 35 2e bf 0a 04 fa c8 ef c1 d0 b2 |...,^5..........| +000000a0 86 ce e2 1c 48 bf e3 38 22 88 21 f7 59 dc d6 3a |....H..8".!.Y..:| +000000b0 00 c6 8f 8c ba db 75 97 11 6f 7e 57 10 56 98 47 |......u..o~W.V.G| +000000c0 92 b5 83 dc 6a 9d 30 a3 be e6 f4 50 a0 8b 67 e0 |....j.0....P..g.| +000000d0 a3 f0 4d 7c b3 d1 77 ad 02 18 59 55 94 42 93 3b |..M|..w...YU.B.;| +000000e0 c1 0f 16 22 13 9e 59 47 56 10 1a 2d 9f 52 42 45 |..."..YGV..-.RBE| +000000f0 70 2f ea 93 be 0a 71 8e d1 bb ba 11 e5 f5 de 77 |p/....q........w| +00000100 ab b1 86 47 e9 61 c1 bf 93 43 8d cc 01 02 2c 66 |...G.a...C....,f| +00000110 bc 23 88 cb 94 ee 35 89 26 18 31 52 b8 8f e0 8d |.#....5.&.1R....| +00000120 f6 77 be e4 11 ed f9 04 0f 18 88 85 b2 b3 45 66 |.w............Ef| +00000130 e5 e3 14 7a 97 c6 2d 73 ff ae f0 29 ba 23 04 76 |...z..-s...).#.v| +00000140 7a 2f 23 9b cc a5 bf b2 d5 bc b8 ac 74 ff 0b 53 |z/#.........t..S| +00000150 59 74 66 27 f8 74 84 3f f3 93 4b 3b 35 1f 01 1a |Ytf'.t.?..K;5...| +00000160 02 e9 52 ab 00 e9 99 7f 20 a2 04 ec fe 90 76 b9 |..R..... .....v.| +00000170 db ac 06 e6 db 5e cb fe d9 9e 45 b1 29 bd 21 d5 |.....^....E.).!.| +00000180 60 ba 40 cf 53 12 f7 69 35 77 9f e0 47 32 c2 94 |`.@.S..i5w..G2..| +00000190 32 be 57 02 06 6f 53 02 a2 1f 58 63 0a a4 f3 03 |2.W..oS...Xc....| +000001a0 c6 d3 8c 88 b8 35 62 b9 d0 2a 86 5a d6 22 2b 7a |.....5b..*.Z."+z| +000001b0 18 44 e2 6b 92 5b 1f 7f c6 ea 6a 79 f7 33 7b 51 |.D.k.[....jy.3{Q| +000001c0 0a 1a ec 8c 00 00 00 90 65 4e ec 89 d9 c8 9e 01 |........eN......| +000001d0 7c cd 40 92 0e 8c 50 75 12 96 d5 a5 70 f4 b5 64 ||.@...Pu....p..d| +000001e0 0e 55 54 f9 f3 88 20 b5 2f e1 67 0f d9 75 93 6e |.UT... ./.g..u.n| +000001f0 20 b2 d3 3b 2b 52 02 67 30 45 7e c5 34 28 f6 82 | ..;+R.g0E~.4(..| +00000200 59 19 c4 9b 03 b6 65 3b 25 67 71 83 e8 0a d6 7d |Y.....e;%gq....}| +00000210 4c 42 5c 42 93 e2 fb e1 a2 cc a8 4e 0a d5 eb ff |LB\B.......N....| +00000220 3b 55 d2 03 26 00 42 9e 17 72 44 83 4f 6d f2 0c |;U..&.B..rD.Om..| +00000230 22 31 22 f1 85 d5 9f ff a1 51 68 b3 7b cc b3 9f |"1"......Qh.{...| +00000240 66 99 74 6f 99 0d 53 0a 24 c5 54 7e a6 60 00 e9 |f.to..S.$.T~.`..| +00000250 cb 39 71 3a ad b2 e3 ca 76 e5 e6 2c 7f 7d 77 87 |.9q:....v..,.}w.| +00000260 82 21 a9 6a 0a 57 ac 27 00 00 00 90 18 1d e4 d6 |.!.j.W.'........| +00000270 44 9c 1a e7 1e 99 a8 b8 8a 54 93 dc 2e 50 c5 66 |D........T...P.f| +00000280 9a a8 ce af 07 4c 44 9e ea 9d c2 63 23 69 1f 42 |.....LD....c#i.B| +00000290 17 9e f5 dd c1 0f cd 91 eb da d8 83 1f 98 cd fa |................| +000002a0 59 c3 ca 4f 9c 9c 85 35 94 33 ba ba 09 b2 68 40 |Y..O...5.3....h@| +000002b0 dd ee 09 7b 1d e8 d2 37 d7 3e 06 42 fb c7 55 ce |...{...7.>.B..U.| +000002c0 2d ca a9 b2 4b 56 2c 9f 76 bc 27 19 06 47 bc 29 |-...KV,.v.'..G.)| +000002d0 c0 c3 4e 1c 81 98 4c a4 49 ae f7 52 7f 46 be 0b |..N...L.I..R.F..| +000002e0 75 6a 6a 9c 30 b7 34 78 0d c9 93 9c 89 0e 67 65 |ujj.0.4x......ge| +000002f0 14 22 7b 79 c1 a6 0c 75 ab 30 96 a9 04 e2 1b 13 |."{y...u.0......| +00000300 99 a7 b9 88 c4 84 0b 57 f0 9a 29 69 00 00 00 20 |.......W..)i... | +00000310 67 0c 13 d8 78 95 1b 3d f9 cf 26 80 ce ff 40 70 |g...x..=..&...@p| +00000320 0f 15 03 18 79 7d 5d 33 20 45 2e 9b 97 41 80 64 |....y}]3 E...A.d| +00000330 8f ef ae 86 0d 4b 52 e2 b8 5e 15 cd 35 f4 b8 14 |.....KR..^..5...| +>>> Flow 17 (client to server) +00000000 00 00 00 20 fd 6b 23 76 51 05 80 af fd e9 75 6e |... .k#vQ.....un| +00000010 5a 96 45 4c 7f 9f 1b d0 2a 9d 00 e6 3f 85 cd fb |Z.EL....*...?...| +00000020 96 ec 22 bf 57 96 eb b8 86 0b b2 28 1f 9f cd c8 |..".W......(....| +00000030 b4 15 9c a5 |....| +>>> Flow 18 (server to client) +00000000 00 00 00 10 e3 23 a4 6c 50 ce 4f 93 55 39 92 e8 |.....#.lP.O.U9..| +00000010 4b c3 e9 ea 62 db 80 b3 06 7b 9a de 17 03 32 88 |K...b....{....2.| +00000020 d4 e8 54 15 00 00 00 10 9a 12 25 5d 1d 44 be 73 |..T.......%].D.s| +00000030 8c 2b 4b 9f 67 c6 62 8b be 5c 8b a8 19 34 b0 5c |.+K.g.b..\...4.\| +00000040 23 36 73 d9 c2 20 59 22 |#6s.. Y"| +>>> Flow 19 (client to server) +00000000 00 00 00 10 86 c2 d4 c9 9a 3d b3 5f 13 72 8c f3 |.........=._.r..| +00000010 7e 48 cd 11 83 48 d1 58 0b aa 69 f0 1b c7 0a 24 |~H...H.X..i....$| +00000020 4c 02 28 5e |L.(^| +>>> Flow 20 (server to client) +00000000 00 00 00 10 78 b8 b8 1f 67 a3 c5 f2 7e fa 2b 66 |....x...g...~.+f| +00000010 fe 5f 7c 4d 49 44 10 10 24 8b 05 96 a6 58 ec 33 |._|MID..$....X.3| +00000020 48 68 dd e5 00 00 00 20 1d 38 50 c5 93 14 4b d2 |Hh..... .8P...K.| +00000030 02 ef 87 03 7a 40 db 11 fb e6 04 0f d8 cd 08 e4 |....z@..........| +00000040 8f 1f 92 27 ab 1b 41 26 27 ef d0 ba ae f2 9c 84 |...'..A&'.......| +00000050 ec a7 f5 56 96 84 d3 77 00 00 00 10 95 92 ef a7 |...V...w........| +00000060 34 59 ec 10 22 02 8b cc 6c 6b 24 2d 9d ec ed 4f |4Y.."...lk$-...O| +00000070 b6 e6 1f 88 47 cd 61 d7 f1 8e 6f b3 |....G.a...o.| +>>> Flow 21 (client to server) +00000000 00 00 00 10 17 67 0b d7 13 55 5f 3e 1a cc e9 ec |.....g...U_>....| +00000010 7e 01 5f 68 c6 e4 6c 8c 7a b3 ab 4d 82 8e 6d cc |~._h..l.z..M..m.| +00000020 d2 08 a0 72 |...r| diff --git a/ssh/testdata/Client-WindowChange b/ssh/testdata/Client-WindowChange new file mode 100644 index 0000000000..4d1b7f2e5d --- /dev/null +++ b/ssh/testdata/Client-WindowChange @@ -0,0 +1,428 @@ +>>> Flow 1 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (client to server) +00000000 00 00 03 2c 11 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...,....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 c9 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 2d |roup14-sha1,ext-| +000000c0 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 63 |info-c,kex-stric| +000000d0 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-c-v00@openssh.| +000000e0 63 6f 6d 00 00 00 57 65 63 64 73 61 2d 73 68 61 |com...Wecdsa-sha| +000000f0 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 73 61 |2-nistp256,ecdsa| +00000100 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000110 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 |cdsa-sha2-nistp5| +00000120 32 31 2c 73 73 68 2d 72 73 61 2c 73 73 68 2d 64 |21,ssh-rsa,ssh-d| +00000130 73 73 2c 73 73 68 2d 65 64 32 35 35 31 39 00 00 |ss,ssh-ed25519..| +00000140 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +00000160 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000170 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +00000180 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000190 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +000001a0 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +000001b0 00 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 |.laes128-gcm@ope| +000001c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d |nssh.com,aes256-| +000001d0 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000001e0 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 |chacha20-poly130| +000001f0 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 |5@openssh.com,ae| +00000200 73 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d |s128-ctr,aes192-| +00000210 63 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 |ctr,aes256-ctr..| +00000220 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |.nhmac-sha2-256-| +00000230 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000240 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 |hmac-sha2-512-et| +00000250 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000260 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 |ac-sha2-256,hmac| +00000270 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 |-sha2-512,hmac-s| +00000280 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 |ha1,hmac-sha1-96| +00000290 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 |...nhmac-sha2-25| +000002a0 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-etm@openssh.co| +000002b0 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |m,hmac-sha2-512-| +000002c0 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +000002d0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d |hmac-sha2-256,hm| +000002e0 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 |ac-sha2-512,hmac| +000002f0 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d |-sha1,hmac-sha1-| +00000300 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f |96....none....no| +00000310 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 d7 |ne..............| +00000320 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 3c |;........n..f.&<| +>>> Flow 4 (server to client) +00000000 00 00 04 9c 0a 14 75 05 5e fa cc cb df 9d c2 fb |......u.^.......| +00000010 e7 7b 02 f5 23 0c 00 00 01 7a 73 6e 74 72 75 70 |.{..#....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 73 2c 6b 65 78 2d 73 74 72 69 |-info-s,kex-stri| +00000180 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000190 2e 63 6f 6d 00 00 00 2d 72 73 61 2d 73 68 61 32 |.com...-rsa-sha2| +000001a0 2d 35 31 32 2c 72 73 61 2d 73 68 61 32 2d 32 35 |-512,rsa-sha2-25| +000001b0 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +000001c0 74 70 32 35 36 00 00 00 6c 63 68 61 63 68 61 32 |tp256...lchacha2| +000001d0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000001e0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000001f0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000200 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000210 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000220 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +00000230 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 61 32 |h.com...lchacha2| +00000240 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000250 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000260 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000270 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 2d 67 |256-ctr,aes128-g| +00000280 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 |cm@openssh.com,a| +00000290 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 73 |es256-gcm@openss| +000002a0 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d 36 34 |h.com....umac-64| +000002b0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000002c0 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 6f 70 |,umac-128-etm@op| +000002d0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000002e0 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e |ha2-256-etm@open| +000002f0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +00000300 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 |2-512-etm@openss| +00000310 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 31 2d |h.com,hmac-sha1-| +00000320 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |etm@openssh.com,| +00000330 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 68 2e |umac-64@openssh.| +00000340 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f 70 65 |com,umac-128@ope| +00000350 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000360 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000370 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 00 00 |-512,hmac-sha1..| +00000380 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 6f 70 |..umac-64-etm@op| +00000390 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 |enssh.com,umac-1| +000003a0 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-etm@openssh.c| +000003b0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000003c0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000003d0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +000003e0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +000003f0 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f 70 65 |mac-sha1-etm@ope| +00000400 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d 36 34 |nssh.com,umac-64| +00000410 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 |@openssh.com,uma| +00000420 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e 63 6f |c-128@openssh.co| +00000430 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c |m,hmac-sha2-256,| +00000440 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d |hmac-sha2-512,hm| +00000450 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e 65 2c |ac-sha1....none,| +00000460 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |zlib@openssh.com| +00000470 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 6f 70 |....none,zlib@op| +00000480 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 00 00 |enssh.com.......| +00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +>>> Flow 5 (client to server) +00000000 00 00 00 2c 06 1e 00 00 00 20 aa 80 4b 53 a8 4b |...,..... ..KS.K| +00000010 4c 0f fa ac a3 b8 5f 64 7d 36 42 e7 1d 56 45 7e |L....._d}6B..VE~| +00000020 2b ac e0 f9 e7 60 f5 d7 55 37 b8 cc 87 3c 23 dc |+....`..U7...<#.| +>>> Flow 6 (server to client) +00000000 00 00 01 04 0a 1f 00 00 00 68 00 00 00 13 65 63 |.........h....ec| +00000010 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000020 36 00 00 00 08 6e 69 73 74 70 32 35 36 00 00 00 |6....nistp256...| +00000030 41 04 8b d1 dd c3 a2 af 65 c5 b1 7e 0d 88 0e 10 |A.......e..~....| +00000040 3b 52 4a 43 b7 3c ed e9 9a 89 5d 2b 05 74 b7 7e |;RJC.<....]+.t.~| +00000050 2b 1e 12 dd 2c 78 71 53 be eb f6 4e 5d 19 cf 98 |+...,xqS...N]...| +00000060 d0 25 2d 4a a3 4a 15 2c 50 10 67 80 6d 2e d9 fa |.%-J.J.,P.g.m...| +00000070 84 a8 00 00 00 20 09 26 d1 6a ec 8b d5 e1 5d 31 |..... .&.j....]1| +00000080 0d 61 37 f0 77 6c 5a 61 82 23 c4 73 5a b0 97 cc |.a7.wlZa.#.sZ...| +00000090 e1 59 81 a5 c3 08 00 00 00 64 00 00 00 13 65 63 |.Y.......d....ec| +000000a0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +000000b0 36 00 00 00 49 00 00 00 20 77 50 81 87 7d 3c 67 |6...I... wP..}.......G..| +00000190 50 5f 0d 78 e8 35 28 43 37 38 f4 eb 1b 41 9e e5 |P_.x.5(C78...A..| +000001a0 f0 95 9a ad 5f 62 9d b2 74 17 ac c2 6a c7 80 df |...._b..t...j...| +000001b0 73 57 64 36 fa 89 36 fe 09 55 63 35 a6 a2 2a 47 |sWd6..6..Uc5..*G| +000001c0 8b 99 93 b0 60 b0 eb ea ac b3 fd fc 28 db f7 c6 |....`.......(...| +000001d0 6c 29 10 ec ed 82 e1 ad f1 a0 a2 db db 62 9b e4 |l)...........b..| +000001e0 a6 f6 b0 72 11 4b ab 70 da d6 50 3a 65 ed dd 19 |...r.K.p..P:e...| +000001f0 79 45 05 14 2b 8b cd 30 2b 5d 8b 23 9c b6 26 d3 |yE..+..0+].#..&.| +00000200 d9 6b 87 d0 03 2b cb b1 2f 58 0f 90 29 dd d9 78 |.k...+../X..)..x| +00000210 69 e1 98 e4 16 be dc fa e3 6c 24 e5 91 49 16 bf |i........l$..I..| +00000220 82 7a 03 9c a4 fc cd 8d 6b b6 75 22 ee b3 fc 18 |.z......k.u"....| +00000230 b3 67 8a 06 57 ff 0e fd 2d 59 35 9c f4 03 40 e9 |.g..W...-Y5...@.| +00000240 85 ad 02 df 94 33 83 49 54 0c 12 ac 5b 3a 37 93 |.....3.IT...[:7.| +00000250 d7 ef e7 cf 64 9e c0 c6 bb b4 2d d9 e5 e1 c8 41 |....d.....-....A| +00000260 2b b0 66 79 75 40 14 fc d9 47 8d 77 |+.fyu@...G.w| +>>> Flow 7 (client to server) +00000000 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000010 00 00 00 20 40 7c 85 82 54 d4 6b 43 ef 1b 15 3f |... @|..T.kC...?| +00000020 6b 5a 90 a1 00 2b 01 78 68 14 6d c6 90 6e 81 1d |kZ...+.xh.m..n..| +00000030 cb ad 10 b4 54 26 c8 3b 4e 73 bf b3 b7 7a 73 d0 |....T&.;Ns...zs.| +00000040 cb 70 14 ad |.p..| +>>> Flow 8 (server to client) +00000000 00 00 00 20 0e 55 84 9a 12 31 19 b1 6d 6a 8a b0 |... .U...1..mj..| +00000010 22 b1 fa fd eb 38 5e b2 86 e2 ee 2d 9f 4b 9c 8f |"....8^....-.K..| +00000020 92 40 85 78 62 57 57 bd 6d b0 cf 6d 35 59 93 68 |.@.xbWW.m..m5Y.h| +00000030 fd 2a 3e 8e |.*>.| +>>> Flow 9 (client to server) +00000000 00 00 00 30 8c bb 20 77 46 9e 4b ea d8 a9 61 33 |...0.. wF.K...a3| +00000010 3a 50 5f de 73 48 70 4b 7d 68 3d d6 69 90 7d ea |:P_.sHpK}h=.i.}.| +00000020 4d 28 76 98 10 37 18 59 fb 0a fb 5d ba d6 de 46 |M(v..7.Y...]...F| +00000030 c9 ab fe 00 a1 22 1c 99 4d 4f f7 c2 5c 9d 9b 32 |....."..MO..\..2| +00000040 98 f1 74 24 |..t$| +>>> Flow 10 (server to client) +00000000 00 00 00 20 49 37 69 04 52 bc 14 3b 4e 97 c3 f1 |... I7i.R..;N...| +00000010 34 18 68 0d aa cb 86 1d ab fd 0b e3 b7 b2 cd 77 |4.h............w| +00000020 47 f9 f4 5a 4e de 6e 6b ce 0c 44 0e 14 a5 00 89 |G..ZN.nk..D.....| +00000030 9d 1e 69 98 00 00 00 40 6a 47 4c ab 5f 82 ca d9 |..i....@jGL._...| +00000040 a3 86 74 0e 51 f3 ac aa 95 54 98 ed d1 5a 2a 7d |..t.Q....T...Z*}| +00000050 eb ed 7f 43 22 f7 c8 ef 92 a6 c6 17 97 71 eb b5 |...C"........q..| +00000060 25 09 b0 9a 13 a6 67 8c 00 20 ad ff 1e b2 e4 a2 |%.....g.. ......| +00000070 16 2f 4b 45 be 18 50 4d 7b bc de 8d 72 2a 65 02 |./KE..PM{...r*e.| +00000080 7c 38 60 56 28 0c 8f 2c ||8`V(..,| +>>> Flow 11 (client to server) +00000000 00 00 01 60 78 f4 d7 ba f1 c0 90 d7 b2 20 59 a1 |...`x........ Y.| +00000010 fa b9 ce 0d c8 2d 5b e6 b1 51 55 11 ef 8b b4 75 |.....-[..QU....u| +00000020 72 57 fc 2f 77 b0 2b c8 b5 5a 78 71 8a 2b 53 69 |rW./w.+..Zxq.+Si| +00000030 e9 b0 ed 73 33 9b 2b d7 99 da 89 53 d0 53 9a 6b |...s3.+....S.S.k| +00000040 ac 33 21 c2 82 a8 5a b0 3f 9c 24 6d 69 1d 11 02 |.3!...Z.?.$mi...| +00000050 b1 4b 2b 26 12 ea 53 53 5a ac f2 e0 10 8e 72 0c |.K+&..SSZ.....r.| +00000060 53 59 97 d2 7f 56 46 4d 4a a5 76 1a 69 ed 8f 9f |SY...VFMJ.v.i...| +00000070 d4 10 09 11 ad d4 7a ea 83 1c 2b 60 5a 03 2b 0e |......z...+`Z.+.| +00000080 8a fa ab fa cf 3a c9 53 77 8a 74 90 b7 0b 25 bf |.....:.Sw.t...%.| +00000090 dd 86 93 6c c6 50 72 a5 7d 9a 18 d5 29 ca 54 51 |...l.Pr.}...).TQ| +000000a0 b9 66 df 87 95 e6 85 4b 9e 6c 63 64 e2 f7 db 02 |.f.....K.lcd....| +000000b0 8d 5a 11 a3 25 ba 80 1b a4 77 7c fc d2 72 85 dc |.Z..%....w|..r..| +000000c0 63 a7 55 50 9f 63 a6 df 9a a2 24 57 8d 2b c2 63 |c.UP.c....$W.+.c| +000000d0 76 cd 3f 86 8c fe df 78 ba 7d a6 61 5b 7c 92 a3 |v.?....x.}.a[|..| +000000e0 66 21 53 9b 47 82 3a 41 6a ff 67 ad 13 8e b0 19 |f!S.G.:Aj.g.....| +000000f0 69 c9 bc 1e 32 bc 1a 00 27 cc 40 fb cb 5f 58 cc |i...2...'.@.._X.| +00000100 03 d6 2f a5 b5 db c3 1d 53 13 3b 86 33 75 32 26 |../.....S.;.3u2&| +00000110 5a 46 1e 8d 06 95 4e cf f6 d9 d2 a1 ac 85 c4 b2 |ZF....N.........| +00000120 06 ae 47 be 55 b8 5e ed 11 7d 23 a5 94 5c f9 df |..G.U.^..}#..\..| +00000130 0a e9 4e 31 cf f5 6c 3e 44 0a ff c7 b7 94 e5 43 |..N1..l>D......C| +00000140 44 de ef d2 bc e4 80 3b 4c 82 7b f2 45 e6 be ce |D......;L.{.E...| +00000150 98 70 9b 5c 7e 7b 53 0d 5d d7 fb fa b0 e3 ef fe |.p.\~{S.].......| +00000160 bd 7d 1a 05 08 8b 91 11 e1 f2 37 6f 14 f6 72 c9 |.}........7o..r.| +00000170 ff 94 54 77 |..Tw| +>>> Flow 12 (server to client) +00000000 00 00 01 40 69 84 1e c5 bd fb dd 15 6e e8 c4 da |...@i.......n...| +00000010 66 42 67 9d a9 ea 0d ac ba 2e ff d0 c2 1b ea a3 |fBg.............| +00000020 1a 29 a2 5f df c8 57 cf ce 7a e4 39 70 6d 4c 83 |.)._..W..z.9pmL.| +00000030 7a 4a 9d 08 71 3f 9d 80 27 1f 6e 0e 98 bd 2e 7f |zJ..q?..'.n.....| +00000040 af c7 43 a1 f1 25 6b a7 2c 0e f8 21 01 6b c0 29 |..C..%k.,..!.k.)| +00000050 bb c8 8c 6d b1 a0 f3 60 03 72 8e b4 b6 ca d1 d9 |...m...`.r......| +00000060 6d e3 54 3f dc cf 0a 16 c9 de cb 57 67 ca 21 ba |m.T?.......Wg.!.| +00000070 49 fe 08 35 55 e9 4f b4 df 10 b8 03 ae be d0 1b |I..5U.O.........| +00000080 f7 2f 06 83 10 22 6f b2 78 d6 e4 05 31 e2 78 03 |./..."o.x...1.x.| +00000090 3b ed e5 5f 6a 71 a4 17 9e 65 7d 83 26 1c f8 e2 |;.._jq...e}.&...| +000000a0 99 39 d9 2b fb 79 80 f7 7b b4 cf d7 90 ef 52 ad |.9.+.y..{.....R.| +000000b0 e5 d2 5c b2 62 b1 cd 35 5a df 8d af 7b 05 a0 ca |..\.b..5Z...{...| +000000c0 da f7 e6 37 3e 72 29 14 8d 2d 43 ed 91 77 13 07 |...7>r)..-C..w..| +000000d0 a1 a5 72 36 94 0c 26 76 da 2f 51 0b 6c 0a 8a 20 |..r6..&v./Q.l.. | +000000e0 84 1e fc 5c f4 91 5d 93 14 44 92 f0 50 4c 09 92 |...\..]..D..PL..| +000000f0 e7 9c 7e aa 12 8c 41 02 c7 ea 13 2a 6b ea 94 3a |..~...A....*k..:| +00000100 a5 84 e1 e3 bc 0c 28 03 c0 27 24 1b 34 36 c8 dc |......(..'$.46..| +00000110 5b 7b d7 da 09 1a b1 a9 fd d6 a6 b6 30 97 48 e7 |[{..........0.H.| +00000120 16 00 91 8e a1 5b f6 5a 5d 9a bd 32 76 6a 25 18 |.....[.Z]..2vj%.| +00000130 79 dd 27 c8 6d 57 3e a0 ec bd 7a 32 9c 0e 32 71 |y.'.mW>...z2..2q| +00000140 e1 58 fa ea 45 31 b4 29 7e 3c dd c2 c9 f4 cb ee |.X..E1.)~<......| +00000150 4e 12 fc 9e |N...| +>>> Flow 13 (client to server) +00000000 00 00 02 80 6b 7c e4 1f 18 c8 f5 92 93 19 ff d8 |....k|..........| +00000010 54 e5 08 c3 b5 c9 4e 2f 4d 54 c2 28 2b 86 b4 52 |T.....N/MT.(+..R| +00000020 bb 4d 17 6d d2 f0 ca b9 f2 08 a6 e8 d0 41 20 1a |.M.m.........A .| +00000030 80 97 90 c7 ac f6 09 ac 9c af 17 4d 3b dc 47 fe |...........M;.G.| +00000040 7f 8c e5 9c a0 92 f7 36 3c 5f 57 05 56 66 01 00 |.......6<_W.Vf..| +00000050 49 e6 3a fe a6 bc 4d 93 cf cd f9 9a 5c ab a4 12 |I.:...M.....\...| +00000060 ff 33 fd 1c d2 cf 4d e4 e4 58 55 a3 f6 5a 8e b2 |.3....M..XU..Z..| +00000070 0d 66 69 a5 08 25 0e 5e f8 1b ed 6d 1a f9 db 86 |.fi..%.^...m....| +00000080 b0 e3 69 a1 30 b3 53 ff c3 83 cd 80 e2 8a 9a f3 |..i.0.S.........| +00000090 18 1f 28 82 95 65 6f 54 09 5e e7 bc 41 c1 9d 47 |..(..eoT.^..A..G| +000000a0 aa 3f 48 84 a0 00 5b a9 c8 aa 1b ea 21 28 7d 52 |.?H...[.....!(}R| +000000b0 83 09 f0 67 f1 ef 61 99 93 54 be 9e 14 04 3d db |...g..a..T....=.| +000000c0 a7 e6 d6 62 e3 dd fe a8 f1 87 4f 5c 59 bf 6a c2 |...b......O\Y.j.| +000000d0 1f 3f d6 76 68 93 7d a8 a0 42 6f d5 f2 fe b4 c8 |.?.vh.}..Bo.....| +000000e0 a6 03 5e cc f1 d0 f7 0a 82 4b ae 80 b6 b4 ef 9a |..^......K......| +000000f0 81 02 74 90 16 0f 29 c2 8b 22 dc c6 5c cb ed 98 |..t...).."..\...| +00000100 ae 93 ef 88 f7 2e 36 6c 2b f3 d4 16 29 9c 56 98 |......6l+...).V.| +00000110 76 c2 ad 55 04 ee 55 a9 75 f0 97 9b 37 41 35 64 |v..U..U.u...7A5d| +00000120 7a 97 df 8c 22 57 e5 05 ae 3f da e6 c1 22 33 00 |z..."W...?..."3.| +00000130 1f 1b 6c 76 da a3 0a fa 31 1c 64 bc af a8 83 a9 |..lv....1.d.....| +00000140 a1 48 73 ec 03 ed ff 2b 87 5d 14 2f 69 bc 30 93 |.Hs....+.]./i.0.| +00000150 9f 9c f9 01 f6 c7 a9 50 8a 5a 2e 99 ce 9b 13 75 |.......P.Z.....u| +00000160 22 60 d7 00 9b 37 c0 21 33 e4 25 c2 5c a2 4b 74 |"`...7.!3.%.\.Kt| +00000170 4e 33 fc 78 f5 90 86 bd b0 b5 ae 7a 9e 49 62 7d |N3.x.......z.Ib}| +00000180 47 ff 64 8d 4a 0e fe 05 5b f0 0d 59 eb 91 2d 20 |G.d.J...[..Y..- | +00000190 d0 af b0 7f b3 8f c1 1f 8c 4f f5 f8 0f 9a 7b 5a |.........O....{Z| +000001a0 28 51 ff d2 6e 1c 78 70 92 fc c3 70 3c ee 71 93 |(Q..n.xp...p<.q.| +000001b0 59 7e 9d 45 00 0e 72 d2 9c 84 15 0d f3 f9 ee ad |Y~.E..r.........| +000001c0 42 bb 2c 0c cd 19 f1 b5 4c 5b 60 0c cc f0 60 6e |B.,.....L[`...`n| +000001d0 d2 cc 28 5b 94 0a d7 4c 19 2b d1 e2 1c 08 fb 97 |..([...L.+......| +000001e0 7b 51 e9 9c 40 39 dd 89 67 8b 78 c7 79 30 27 6d |{Q..@9..g.x.y0'm| +000001f0 83 7e 4a 31 96 2f 36 fe a8 d8 f5 fe 3f b7 fb 5b |.~J1./6.....?..[| +00000200 b6 4a 00 9b 49 04 90 3d b8 ea 78 92 87 45 43 80 |.J..I..=..x..EC.| +00000210 d4 fa fe 0a 50 f4 20 fa 3a 03 43 9b 91 1a 08 7e |....P. .:.C....~| +00000220 c0 37 01 82 5c 95 ac e9 d8 3e 4b 0f 8c 36 9b f9 |.7..\....>K..6..| +00000230 e4 52 35 65 7c 3b 35 5d 0d d5 10 f5 e0 89 38 b8 |.R5e|;5]......8.| +00000240 c3 1d 5e ef 5f 0e 5f 89 19 1d 74 63 2c 7b 39 cd |..^._._...tc,{9.| +00000250 bf db 5a b3 57 ea 84 71 bb cf 3c 41 48 51 26 f7 |..Z.W..q..>> Flow 14 (server to client) +00000000 00 00 00 10 0c 85 7b 40 43 04 6a 12 9e 51 88 54 |......{@C.j..Q.T| +00000010 df 07 90 e4 5a 46 d1 be 3e d7 7b 99 cf 72 9f f9 |....ZF..>.{..r..| +00000020 4b 9e 81 d2 |K...| +>>> Flow 15 (client to server) +00000000 00 00 00 20 d9 01 09 b1 72 36 f8 2d bc 3e 1f 0d |... ....r6.-.>..| +00000010 76 14 1f 64 27 e8 91 8a 48 2a 18 89 9a 30 c9 09 |v..d'...H*...0..| +00000020 9d 43 8a f7 b4 c7 44 50 cf af 99 40 27 0b 83 9b |.C....DP...@'...| +00000030 c0 6b 64 2c |.kd,| +>>> Flow 16 (server to client) +00000000 00 00 01 b0 4f 02 f1 4d 54 96 2b 46 e8 7b 92 24 |....O..MT.+F.{.$| +00000010 d7 3c 88 09 ea 22 a2 a0 20 55 a1 cd d3 bd ce d5 |.<...".. U......| +00000020 1d 98 76 24 84 b2 03 dd 5e c9 90 b1 3f ff 24 29 |..v$....^...?.$)| +00000030 8e 0e 73 fb 30 92 5e 0f 50 f3 af 51 01 a2 9e 72 |..s.0.^.P..Q...r| +00000040 d6 5e 91 1b e8 8a 99 7c eb 90 78 34 03 ca c8 da |.^.....|..x4....| +00000050 ef ec 87 72 71 78 31 86 df 4d 48 88 fe 36 b6 42 |...rqx1..MH..6.B| +00000060 9a 6a 71 b4 85 36 25 9e 71 11 f6 91 bc a6 1a 6c |.jq..6%.q......l| +00000070 af 2d cc d0 0d eb 57 2f 18 85 43 4b 17 59 3f 2f |.-....W/..CK.Y?/| +00000080 3c a8 ac 9f 42 94 46 1e f8 dd 68 c9 bf 2c cb be |<...B.F...h..,..| +00000090 90 72 1d c7 90 8d db 5b 36 4c 8b 70 2c 68 98 cf |.r.....[6L.p,h..| +000000a0 fe 43 92 27 51 f1 3a bd 4b c6 fc b4 fa 6e f0 31 |.C.'Q.:.K....n.1| +000000b0 25 ed 98 91 10 bd a1 58 e0 6e f8 84 cf 2d e3 d7 |%......X.n...-..| +000000c0 b2 1b e7 fe 60 cc 6e 83 46 53 12 51 4e 65 e7 01 |....`.n.FS.QNe..| +000000d0 45 f8 66 80 9d a9 6b a4 38 6f c2 ff 75 79 cf fc |E.f...k.8o..uy..| +000000e0 22 7f 52 df 7a 34 3d 02 66 f4 d7 7f fe 5f 68 fc |".R.z4=.f...._h.| +000000f0 f9 96 84 ae 5c cc 08 9e 11 a8 44 ac a7 3e 4a a1 |....\.....D..>J.| +00000100 db 6b e6 db 55 33 47 8e 3b 08 92 04 80 ae 12 81 |.k..U3G.;.......| +00000110 cf 1e d0 6d 58 58 82 a0 a1 68 fb 58 81 5b 5c 20 |...mXX...h.X.[\ | +00000120 5e d5 fd 87 5d 2c 0c 25 a8 ca e5 6e 3c 98 d6 c5 |^...],.%...n<...| +00000130 4e 3c 7e 05 33 60 94 27 0f f6 9c 5d 05 c4 76 d6 |N<~.3`.'...]..v.| +00000140 7b f7 41 45 5a cb ca f8 3e 15 d5 5d 29 5b 69 92 |{.AEZ...>..])[i.| +00000150 ce b9 fe fa 75 4e 52 53 64 87 dd 39 dc 46 e1 cd |....uNRSd..9.F..| +00000160 1e 3a c4 2c 0a 71 fa 40 85 7f 87 b9 4b 71 bc 1e |.:.,.q.@....Kq..| +00000170 9e 78 62 d5 08 45 06 ef 25 0a 19 bc 8c 3b 19 72 |.xb..E..%....;.r| +00000180 6b 28 7c a1 34 47 23 de f1 5c 10 8b fa 94 07 dc |k(|.4G#..\......| +00000190 66 5e 6c eb 52 66 a0 cb cc 11 c3 ab 93 a2 42 b7 |f^l.Rf........B.| +000001a0 65 c7 12 46 aa d2 68 5b 4c 64 e1 98 53 09 3a 28 |e..F..h[Ld..S.:(| +000001b0 ed 43 46 2d 99 fc 2b fa 87 2c 7e ba 1a 5d c3 80 |.CF-..+..,~..]..| +000001c0 35 a3 5b 72 00 00 00 90 96 29 a5 5e 18 84 39 42 |5.[r.....).^..9B| +000001d0 7d 94 92 76 f5 65 7a 08 f1 36 fe 09 f2 81 71 6e |}..v.ez..6....qn| +000001e0 f6 ae f5 32 41 dd 5a 04 f4 3f b8 f4 01 fb 17 c9 |...2A.Z..?......| +000001f0 24 55 4c c8 e6 73 bf 66 0e e6 49 b3 16 99 30 1f |$UL..s.f..I...0.| +00000200 6a ee 91 1d c6 00 93 24 12 56 85 57 40 75 43 97 |j......$.V.W@uC.| +00000210 19 d1 31 bb 8a a1 e4 ec c9 a0 d7 74 31 44 ec fb |..1........t1D..| +00000220 bf 79 c9 89 12 33 f1 f8 bb 9b 98 a8 f8 8a 48 e7 |.y...3........H.| +00000230 26 00 ab 14 58 a2 6f 21 69 38 1e 57 df ae ad c6 |&...X.o!i8.W....| +00000240 c1 a4 d8 a3 57 5f 17 8b b2 2b 13 d4 be 6b 05 53 |....W_...+...k.S| +00000250 c2 f6 6f 33 5f 08 a6 47 f8 a8 be 8a 5b 65 a2 43 |..o3_..G....[e.C| +00000260 6f 19 c0 05 8a 02 f5 7b 00 00 00 90 6f a4 e1 46 |o......{....o..F| +00000270 74 3f 74 79 ea 45 8f 42 4d ba 33 de 37 5b 8d ff |t?ty.E.BM.3.7[..| +00000280 a7 b4 65 a4 1c 8c cf 68 c9 67 7e 6b 4e d1 da a3 |..e....h.g~kN...| +00000290 35 90 77 54 c5 62 1b 39 7d 9a 48 97 ab 0e f6 97 |5.wT.b.9}.H.....| +000002a0 b3 86 a8 2d 51 b3 59 a0 48 d5 cc e4 87 8d d0 2e |...-Q.Y.H.......| +000002b0 90 3b ed ed 91 c8 81 00 9e c9 74 1b b6 fd 7c ca |.;........t...|.| +000002c0 e4 f5 7d e5 f9 f6 b8 7d cd 6c 23 d7 83 92 ad 64 |..}....}.l#....d| +000002d0 55 f8 40 3e ae 64 f5 30 95 c0 c6 7e a2 bd 11 ce |U.@>.d.0...~....| +000002e0 1e 1a 64 df 0a 65 62 e9 eb b6 f9 2f 95 3d 46 63 |..d..eb..../.=Fc| +000002f0 d9 7e 0c 78 0a 83 54 fc c1 b6 f0 d4 2f 18 fe 55 |.~.x..T...../..U| +00000300 5c 05 4c ac ed 0f d6 41 a8 f3 c1 a4 00 00 00 20 |\.L....A....... | +00000310 86 88 fb 2a f2 29 4e 93 f1 90 00 bd bd 3f 50 c5 |...*.)N......?P.| +00000320 12 25 db 34 a2 0c 69 32 b3 12 76 8b e8 c9 0d b0 |.%.4..i2..v.....| +00000330 3c a3 00 e2 55 e0 25 52 f0 b2 57 f2 95 20 72 a7 |<...U.%R..W.. r.| +>>> Flow 17 (client to server) +00000000 00 00 00 40 fe a3 fe 4c 44 96 eb 42 4e 72 32 99 |...@...LD..BNr2.| +00000010 f5 0f a2 c9 3c 38 72 2a 4f fd b4 e5 77 7e 6c ba |....<8r*O...w~l.| +00000020 80 b9 4f 2d ea 28 86 63 5e 40 be 8b 71 b8 f1 07 |..O-.(.c^@..q...| +00000030 a1 6c 01 17 94 f9 9c a6 eb a1 a1 a8 e1 3f eb b8 |.l...........?..| +00000040 62 e1 bd ee 1b 6d 81 59 b9 ab df 3e fb 22 ca cc |b....m.Y...>."..| +00000050 6d 43 89 f0 |mC..| +>>> Flow 18 (server to client) +00000000 00 00 00 10 5e 6c 9c 59 08 98 1e ce 9d 06 50 c5 |....^l.Y......P.| +00000010 9c c8 69 f6 30 08 4a 2e 48 35 0b 17 e2 7c 1e 67 |..i.0.J.H5...|.g| +00000020 51 71 39 ba |Qq9.| +>>> Flow 19 (client to server) +00000000 00 00 00 30 12 74 3c 3a e9 1e 09 af 05 09 8e a0 |...0.t<:........| +00000010 a0 72 4b 1a 74 08 76 76 07 10 72 a7 35 77 7d a0 |.rK.t.vv..r.5w}.| +00000020 d5 04 ce 36 9f c8 3a ee a3 56 66 26 5d 9c f9 f7 |...6..:..Vf&]...| +00000030 01 55 bd b8 9c 9b f7 3d 3f 8b 4f 2e 03 99 b6 8a |.U.....=?.O.....| +00000040 df 29 6d b6 00 00 00 20 7b 3b 63 96 e4 3e ee 63 |.)m.... {;c..>.c| +00000050 e8 9c bf 16 ff db 89 0c 59 3f 07 96 ef c5 5e 12 |........Y?....^.| +00000060 aa 3d 74 d2 1f 8e 63 08 4f 7f 79 89 42 bd 6e 7b |.=t...c.O.y.B.n{| +00000070 ea 7e 90 42 7c ba 6a 99 |.~.B|.j.| +>>> Flow 20 (server to client) +00000000 00 00 00 10 02 06 3c 48 7d 57 92 fa 00 c1 60 7b |......>> Flow 21 (client to server) +00000000 00 00 00 20 6d f2 c2 17 b0 7a a0 9e 3e 8b db 86 |... m....z..>...| +00000010 8e 93 cd 81 2b 10 e7 fe d2 da e8 7c eb c1 ba 81 |....+......|....| +00000020 1c e3 9c 89 f2 c2 d1 d3 97 ef 8d ae 15 61 31 92 |.............a1.| +00000030 92 82 5b a3 |..[.| +>>> Flow 22 (server to client) +00000000 00 00 00 50 8f 11 22 32 77 0f 87 e1 02 88 57 4e |...P.."2w.....WN| +00000010 d5 4b f6 da 2f 53 68 dc 56 67 4b bc 87 86 0d d4 |.K../Sh.VgK.....| +00000020 54 84 4b 9f e6 e4 56 e3 3f 60 e1 2b 94 77 bc 2a |T.K...V.?`.+.w.*| +00000030 2d 58 68 ed db 5b ed dd b1 3c 7a cf ec 16 16 56 |-Xh..[...#.G..&v......| +000001c0 17 2b 77 34 2a ab d1 59 c4 77 2b d0 58 85 11 92 |.+w4*..Y.w+.X...| +000001d0 30 7f 1e 64 46 ae 5f e3 cb 52 40 94 72 28 51 9a |0..dF._..R@.r(Q.| +000001e0 00 00 00 20 2f b4 e5 20 8e f8 4a 2d 5a 4c b3 28 |... /.. ..J-ZL.(| +000001f0 86 96 3d 99 7f 85 7d de 0d 40 56 02 7b a7 cd db |..=...}..@V.{...| +00000200 f2 d6 a4 bc 1d 67 01 dd ed c8 ea 1d af db 76 49 |.....g........vI| +00000210 72 b1 e2 e9 00 00 00 10 5b 3b 00 10 92 95 a5 86 |r.......[;......| +00000220 a3 65 14 09 7a 24 3e 5f a7 21 b3 07 c5 3d 74 52 |.e..z$>_.!...=tR| +00000230 57 38 02 c0 b8 17 b9 40 |W8.....@| +>>> Flow 23 (client to server) +00000000 00 00 00 10 9e d9 60 2b be 0c 8d 11 62 28 e7 3d |......`+....b(.=| +00000010 a5 b5 0a c5 92 66 ad 2f aa 28 f4 d2 7e 9c eb 73 |.....f./.(..~..s| +00000020 42 c3 7d 29 |B.})| diff --git a/ssh/testdata/Client-username b/ssh/testdata/Client-username new file mode 100644 index 0000000000..d9443d6edd --- /dev/null +++ b/ssh/testdata/Client-username @@ -0,0 +1 @@ +nicola \ No newline at end of file diff --git a/ssh/testdata/Server-Cipher-aes128-ctr b/ssh/testdata/Server-Cipher-aes128-ctr new file mode 100644 index 0000000000..311a791993 --- /dev/null +++ b/ssh/testdata/Server-Cipher-aes128-ctr @@ -0,0 +1,371 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 0a 61 65 73 31 32 38 2d 63 74 72 00 00 00 0a 61 |.aes128-ctr....a| +00000110 65 73 31 32 38 2d 63 74 72 00 00 00 6e 68 6d 61 |es128-ctr...nhma| +00000120 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +00000130 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000140 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000160 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000170 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +00000180 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 |mac-sha1-96...nh| +00000190 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +000001a0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +000001b0 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +000001c0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +000001d0 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +000001e0 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +000001f0 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000200 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000210 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 9f b2 1b ad bc fe e0 8c 8f fc |...<............| +00000010 8d 73 b5 64 34 e6 00 00 01 7a 73 6e 74 72 75 70 |.s.d4....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 0c 6e 91 a3 54 b3 |...,..... .n..T.| +00000650 15 c7 d5 76 a6 14 45 29 ad d8 73 a1 f1 67 31 ca |...v..E)..s..g1.| +00000660 ad d3 95 a7 7b 62 1c 43 97 57 00 00 00 00 00 00 |....{b.C.W......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 ee a0 9c c6 be 90 37 5d 28 ba ea |.... ......7](..| +00000130 a8 41 a5 72 c8 5e 4d 2d 23 c4 f9 26 88 44 60 fc |.A.r.^M-#..&.D`.| +00000140 30 d9 da 91 6a 00 00 01 14 00 00 00 0c 72 73 61 |0...j........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 9e 2f 40 |-sha2-512...../@| +00000160 89 ad 33 60 e3 ee e8 b6 95 e4 0f a5 21 5e 03 17 |..3`........!^..| +00000170 24 25 14 56 44 c6 83 0b 2b d2 f4 c6 40 5d be 87 |$%.VD...+...@]..| +00000180 66 e9 dc d6 e2 41 7a ec 58 99 ae f6 ae 20 3a 3a |f....Az.X.... ::| +00000190 a0 02 43 61 0f e9 d8 65 3d a2 5d cb 85 0c 88 49 |..Ca...e=.]....I| +000001a0 64 29 80 a9 34 ba ee 3d bc 72 06 fc 9e bb 53 9d |d)..4..=.r....S.| +000001b0 5c 3d 12 15 fb 71 a5 d6 8b eb bb c7 50 ef 75 d2 |\=...q......P.u.| +000001c0 1d 74 b2 d5 fe 3f ab 8e 29 f7 e9 ae 37 76 3e 27 |.t...?..)...7v>'| +000001d0 61 a7 1c b7 38 5f 41 bc 17 f1 69 0f a1 3c a6 41 |a...8_A...i..<.A| +000001e0 e9 b6 e0 c6 ae 8e d6 c8 36 40 c9 af 7a b8 0e 6c |........6@..z..l| +000001f0 6b 6b d6 ee bb ba 12 44 97 71 0c a8 d2 15 1b b4 |kk.....D.q......| +00000200 fd e8 53 1d 8d f4 30 35 cf 24 cc 81 af 46 3a 37 |..S...05.$...F:7| +00000210 c0 08 89 c3 92 e1 0d 50 e6 8f ea 3a f3 d8 50 a3 |.......P...:..P.| +00000220 c4 44 35 20 0e f5 20 c6 38 a1 d3 8f 1e 57 f1 e7 |.D5 .. .8....W..| +00000230 e9 00 17 8b 4b 52 98 d9 ca 87 f0 85 06 1d a8 df |....KR..........| +00000240 a0 59 06 6e f5 a9 38 70 70 12 fe 85 c7 7b a8 ac |.Y.n..8pp....{..| +00000250 d0 c0 d9 59 c0 ef 31 89 99 4c 4c 1f 3f a3 63 9c |...Y..1..LL.?.c.| +00000260 a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc 62 b8 |.....W.5...<#.b.| +00000270 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000280 00 00 00 f0 8f e7 54 01 dc c2 69 c7 1a 4c c5 07 |......T...i..L..| +00000290 c5 90 cc 8c 03 89 94 83 89 81 a7 f6 97 81 b7 48 |...............H| +000002a0 27 71 31 22 87 01 e0 90 de 4c 02 77 19 82 c9 ed |'q1".....L.w....| +000002b0 fd ea 58 75 a6 2a 99 87 f4 8b fa 1b fb 3f 79 1c |..Xu.*.......?y.| +000002c0 f5 9c 0f e9 b4 b0 13 b9 31 3c ec 6e fd 16 9f 57 |........1<.n...W| +000002d0 de 64 ba 66 3b 8f 70 ae 07 1c 0a 1b 43 ab 7d f2 |.d.f;.p.....C.}.| +000002e0 5f c2 b6 0d cf cf 46 65 f5 16 af 53 26 01 53 86 |_.....Fe...S&.S.| +000002f0 21 24 2a 4f 18 e6 2d 8a e4 c2 6c 00 4f ed e3 b6 |!$*O..-...l.O...| +00000300 88 16 f9 9c f1 bd 8a 17 77 5b 6c 0b 01 1d c0 a6 |........w[l.....| +00000310 59 05 f3 5a 9c 62 07 85 c5 c2 c5 f5 ff 58 aa 76 |Y..Z.b.......X.v| +00000320 59 c3 6b 96 92 d4 6a cc 10 fd e6 af 88 6b 78 f8 |Y.k...j......kx.| +00000330 4b 72 86 ab 84 84 e1 4d 1a b7 23 be 33 a5 6c 28 |Kr.....M..#.3.l(| +00000340 0a d9 59 5f 33 59 1d 4f 56 1c 0e de 5f e9 1d 6d |..Y_3Y.OV..._..m| +00000350 fe 4c 32 b5 07 e2 ac 94 c4 90 8b 63 ee a6 24 8c |.L2........c..$.| +00000360 e3 0a aa 63 a1 5f c4 d6 ea 2f 4a 74 6e db 72 66 |...c._.../Jtn.rf| +00000370 65 bc c3 ce 98 5d bd 2f 13 29 43 54 d2 d8 b5 ef |e....]./.)CT....| +00000380 65 bf 18 6a 47 af 18 c6 c9 2d 12 bf f3 4c f7 40 |e..jG....-...L.@| +00000390 b7 36 a4 3b |.6.;| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 00 00 00 20 49 40 5f 03 37 89 eb 9b fa 71 fe a1 |... I@_.7....q..| +00000020 78 ab 3d 45 60 40 d1 b8 91 3e 82 7a eb ec 1c 52 |x.=E`@...>.z...R| +00000030 f2 7a d3 f8 34 34 5e 43 20 b2 90 cb 03 09 16 14 |.z..44^C .......| +00000040 ca a1 4d f3 5b 13 cb d4 5a c5 17 29 e4 2a f5 a1 |..M.[...Z..).*..| +00000050 a7 09 e1 5d |...]| +>>> Flow 7 (server to client) +00000000 00 00 00 20 ad 29 ef 88 42 c2 d2 1b 38 c0 90 c7 |... .)..B...8...| +00000010 bc 48 d5 d2 be 88 13 66 d2 0a c6 88 98 f5 a0 e4 |.H.....f........| +00000020 fd db 4b a3 9a 55 d3 38 90 65 a2 24 88 30 7b c4 |..K..U.8.e.$.0{.| +00000030 2b c0 a5 ca 93 aa d1 19 ab c9 68 60 41 2b d4 ea |+.........h`A+..| +00000040 a2 32 19 4d |.2.M| +>>> Flow 8 (client to server) +00000000 00 00 00 30 e3 be cc fc 04 be 85 d3 8d 50 d5 5f |...0.........P._| +00000010 b3 9a 90 df ad 8d fb 88 bb c6 a8 7c 2e 2a b9 94 |...........|.*..| +00000020 00 02 3f 41 af 25 0a a1 c0 53 9f 47 31 f9 f5 41 |..?A.%...S.G1..A| +00000030 8a cf 78 b3 06 de 8d 33 fb 57 99 83 89 25 64 ef |..x....3.W...%d.| +00000040 44 52 2d 79 d4 9d a3 57 82 5a 90 ce d1 15 31 6c |DR-y...W.Z....1l| +00000050 16 c9 94 f8 |....| +>>> Flow 9 (server to client) +00000000 00 00 00 20 ce 3b 43 06 c8 25 9c 23 e0 77 a4 0f |... .;C..%.#.w..| +00000010 90 cb 33 b0 56 95 83 a0 b8 2d 28 38 71 f6 d4 d4 |..3.V....-(8q...| +00000020 e6 05 a3 e7 19 94 3e b1 c1 0e d3 5e ef 87 6b 87 |......>....^..k.| +00000030 dd e0 dc b5 b4 c4 f1 49 e8 6b c9 ec 7a 82 ae 5d |.......I.k..z..]| +00000040 b3 cc 86 5c |...\| +>>> Flow 10 (client to server) +00000000 00 00 01 60 55 08 67 d8 12 56 7f 1d 18 a5 5e 78 |...`U.g..V....^x| +00000010 80 11 86 fe bc 1b 5f 22 b3 e8 82 18 48 6c 2d 26 |......_"....Hl-&| +00000020 0e 2f 03 07 09 ed 58 f2 ae 1f 9d 01 47 f5 cb da |./....X.....G...| +00000030 89 04 c3 4c c6 ed 95 37 1f 72 11 74 a0 12 f2 1e |...L...7.r.t....| +00000040 d4 ef 7b a2 59 2a cc d3 c1 58 4e 46 83 92 04 3a |..{.Y*...XNF...:| +00000050 c7 e3 f7 16 ec f1 32 7a 5a 48 90 79 2d e1 3b c8 |......2zZH.y-.;.| +00000060 17 55 b9 7a 58 ba 70 61 31 53 3e 3a 8f ab 7f f9 |.U.zX.pa1S>:....| +00000070 5a 98 d5 90 4b d8 ae a6 8e fc fc ff a1 63 5f 6a |Z...K........c_j| +00000080 94 8c 62 e5 5b d9 67 bf 95 95 6a 7f ce 62 02 15 |..b.[.g...j..b..| +00000090 8c 79 a6 63 7c d1 e8 99 39 99 cd 7a 1c e0 da 44 |.y.c|...9..z...D| +000000a0 0c cd 06 62 60 97 52 83 71 d3 56 aa dc 8d c7 0e |...b`.R.q.V.....| +000000b0 9e 01 5a cc a7 d5 1a 3d a0 48 e3 8f 34 83 de 95 |..Z....=.H..4...| +000000c0 a5 6e 9d 34 de a1 ce a3 8f 3d 2e bb fd d8 e9 b6 |.n.4.....=......| +000000d0 12 04 0a 7f 89 e5 23 c5 3c 17 ca 17 0f 2b b8 1f |......#.<....+..| +000000e0 8e 83 38 a8 f3 d6 50 2f d7 0f 5b e5 07 00 8b 7b |..8...P/..[....{| +000000f0 0c 2d 52 0a b5 e0 93 6a 47 f7 8c f3 3a 62 30 3d |.-R....jG...:b0=| +00000100 54 8b 0a f7 f3 f9 34 7e 21 9b c5 a8 5b b7 af eb |T.....4~!...[...| +00000110 3b 6b 65 0b 88 3d 5f da e2 33 6c dd 2f b6 14 2b |;ke..=_..3l./..+| +00000120 45 4b f2 c6 3d 19 55 e1 63 5e 56 c4 92 8b 47 9c |EK..=.U.c^V...G.| +00000130 c1 1c b7 7b 7e 4c 86 a3 97 bc 82 dd 1f 2d ba c2 |...{~L.......-..| +00000140 a5 ba 90 79 6f 79 84 12 a7 4a 91 a7 f9 c7 a7 57 |...yoy...J.....W| +00000150 8b 1c 44 5d 47 55 60 17 92 b4 2a ee 1b 27 02 4c |..D]GU`...*..'.L| +00000160 1d 61 f3 76 52 fd 52 f0 96 0d 69 f6 cb 0e db df |.a.vR.R...i.....| +00000170 90 9d 57 e2 e9 2e e2 97 18 b5 4e 17 f1 7f 95 b5 |..W.......N.....| +00000180 d9 88 78 ad |..x.| +>>> Flow 11 (server to client) +00000000 00 00 01 40 ad f3 80 c6 bd 36 25 9b f4 e5 98 ac |...@.....6%.....| +00000010 57 d9 ab 5d e9 f2 04 db 57 08 a3 7f 27 69 05 36 |W..]....W...'i.6| +00000020 53 de ad 3c de 79 38 10 ff 87 62 7a 91 1a b0 5d |S..<.y8...bz...]| +00000030 69 e0 ee 3f fd 24 20 5c a6 08 dd 96 88 04 13 bf |i..?.$ \........| +00000040 d3 3c 62 ba 01 0c 50 a2 83 f9 85 30 cb e4 d7 09 |..@{...fK0.'.|(| +000000a0 14 37 d2 77 5a 1a d1 83 d7 16 ff f3 a0 6d 22 67 |.7.wZ........m"g| +000000b0 41 cc 30 cd 52 e1 1f de e1 5d b2 06 5a 24 3b 7f |A.0.R....]..Z$;.| +000000c0 17 75 30 22 4a 3c 6f 71 2f e6 22 22 a1 1a b6 d8 |.u0"J>> Flow 12 (client to server) +00000000 00 00 02 80 0c 87 bd b0 2f 97 08 9d a8 dc 01 e0 |......../.......| +00000010 b7 4b 17 6d cf 3c 9e ad db 5f f1 04 7d 73 a5 8e |.K.m.<..._..}s..| +00000020 40 4b 52 da 46 08 d4 39 0a cc f8 1f 28 f4 b9 40 |@KR.F..9....(..@| +00000030 3c 27 d5 c6 93 90 af 12 93 79 b0 69 d9 70 f8 3c |<'.......y.i.p.<| +00000040 1c 2d 1c dd 86 49 f0 72 e4 21 d5 04 5d 0b f1 71 |.-...I.r.!..]..q| +00000050 5b 6e 9d 59 11 11 ef 49 0c 24 03 04 08 98 53 b1 |[n.Y...I.$....S.| +00000060 3a 36 df 35 30 5f 27 26 f9 6a 66 35 c5 fb c5 ed |:6.50_'&.jf5....| +00000070 e4 d9 88 95 9c 2c 04 f2 49 c5 b3 25 17 ae 89 27 |.....,..I..%...'| +00000080 6a 7a 59 38 b0 bb f3 fd c1 1b a2 32 a9 3a 8b 0a |jzY8.......2.:..| +00000090 81 50 f4 4c 7b 92 4d d3 06 49 81 46 ba ea c8 54 |.P.L{.M..I.F...T| +000000a0 4e 23 04 4b 8f 68 ef 39 75 39 b6 d3 07 81 05 7f |N#.K.h.9u9......| +000000b0 4f c8 cc b9 ee 14 e7 0b 9d 21 1e 37 e2 f4 c9 8d |O........!.7....| +000000c0 d7 8a e4 9a b3 8c 9c 36 85 41 a1 e3 21 c1 dd b8 |.......6.A..!...| +000000d0 93 f9 d1 27 51 e9 43 0b a5 29 e7 86 d6 13 18 c7 |...'Q.C..)......| +000000e0 e0 cd 2a 6a 57 47 72 55 56 99 3f ce 52 fa bc c7 |..*jWGrUV.?.R...| +000000f0 eb 39 1c 9d 8b bc f3 81 11 66 ee 66 c0 00 8c 1c |.9.......f.f....| +00000100 ae 5e 91 6e d1 4e cd 29 59 2a d0 d7 a7 39 a1 8a |.^.n.N.)Y*...9..| +00000110 ea 1f 66 5c 78 e9 a7 3d a6 d0 a2 44 9c 98 1c e3 |..f\x..=...D....| +00000120 2f 66 5a 3e 76 8d 5e 18 73 8b b4 4d c0 a0 36 96 |/fZ>v.^.s..M..6.| +00000130 b0 90 e7 75 6f f3 66 fc e5 43 16 76 23 ff 28 ff |...uo.f..C.v#.(.| +00000140 00 90 78 05 5d 96 de 1c b8 20 d8 f3 72 32 7c 8c |..x.].... ..r2|.| +00000150 f8 15 b8 67 80 be 65 10 f9 a4 94 d6 b0 4b 07 ff |...g..e......K..| +00000160 5b f6 c3 46 22 76 a3 24 40 c3 22 0b 70 5c b3 fe |[..F"v.$@.".p\..| +00000170 07 5f 96 de d8 55 d0 f8 39 22 8d 41 a5 03 47 1d |._...U..9".A..G.| +00000180 09 0b f9 f5 49 3f bc 76 ac bb b9 80 25 d0 4f 71 |....I?.v....%.Oq| +00000190 58 49 56 b7 bf e5 04 26 73 2d 35 d8 7d 17 e4 b0 |XIV....&s-5.}...| +000001a0 fc d6 45 1f 7a 35 9e 3c 82 7b 5f 8c f2 56 7d ed |..E.z5.<.{_..V}.| +000001b0 7c eb 90 e7 eb 27 be 3d 04 50 8b b1 a2 c6 ae 23 ||....'.=.P.....#| +000001c0 a7 6d ec 3d 71 71 bc ac e0 a0 67 d8 54 1f ea c4 |.m.=qq....g.T...| +000001d0 37 8a e6 b6 0e 19 7e 51 97 bd 74 d3 a9 5b 1e d7 |7.....~Q..t..[..| +000001e0 83 97 fc 3d 5e 0b e6 44 59 58 ed bf 9c 0c b7 ba |...=^..DYX......| +000001f0 86 96 77 c9 c7 02 2e 01 f3 ff 08 31 c6 16 9e d3 |..w........1....| +00000200 aa 5f 1b aa e3 14 d7 85 35 4f 07 10 90 37 1a 91 |._......5O...7..| +00000210 75 9a 11 f3 c5 7d 6e 16 24 51 2c 20 87 d6 cf 6c |u....}n.$Q, ...l| +00000220 cb ea f8 52 ba ae 5d 7d 7f 13 2e 1c 11 ba 64 7d |...R..]}......d}| +00000230 b4 61 cd 5d e1 a4 93 c0 c6 98 e1 01 71 d7 fb f7 |.a.]........q...| +00000240 8a 3c 78 5a 9d 9f 30 a5 be 54 38 d0 ff 92 5b 2c |.....7l.m..| +00000260 0e 40 32 7a a6 54 de 47 64 97 2d 53 2d 62 e9 01 |.@2z.T.Gd.-S-b..| +00000270 57 b9 bb 22 f6 b7 9e 33 31 e9 79 b6 93 ec 85 59 |W.."...31.y....Y| +00000280 85 94 0d 2b 71 e8 ac bc 2a 02 bd 36 e7 1f 01 62 |...+q...*..6...b| +00000290 d0 b7 68 a2 83 7f 98 ae 51 1c dc 6c ae ff cf ce |..h.....Q..l....| +000002a0 ed 10 bc 51 |...Q| +>>> Flow 13 (server to client) +00000000 00 00 00 10 cc f2 e2 26 dc c2 96 3d 6e 40 1f d7 |.......&...=n@..| +00000010 33 44 8c 63 4c 1a 93 d5 21 50 01 9a 82 b3 05 c3 |3D.cL...!P......| +00000020 ba 37 38 79 d0 2e de 3c 8d fc 27 93 ab 2f d3 99 |.78y...<..'../..| +00000030 a0 b9 8b fb |....| +>>> Flow 14 (client to server) +00000000 00 00 00 20 73 19 05 32 37 f9 65 1e 33 8e 71 49 |... s..27.e.3.qI| +00000010 13 5e bd 69 20 c7 01 0e 02 66 6f bc 64 26 78 67 |.^.i ....fo.d&xg| +00000020 a3 0d ea 3a be 2a 01 5f 5b 62 4b 58 61 a2 6a 85 |...:.*._[bKXa.j.| +00000030 76 cf d2 19 da cb d4 f0 ec 7d a0 8b 56 c6 30 d9 |v........}..V.0.| +00000040 34 3d 3c c0 |4=<.| +>>> Flow 15 (server to client) +00000000 00 00 00 20 d3 75 9d df 03 74 2b 7f 76 b4 91 6d |... .u...t+.v..m| +00000010 b0 dc db dc e4 45 50 8b 3f 61 18 2e d5 44 c5 bf |.....EP.?a...D..| +00000020 96 ce b7 e7 2f 6a c5 7a 09 b1 68 95 b6 7f 94 e4 |..../j.z..h.....| +00000030 91 4e 49 d1 ab 82 18 44 48 1f 4a 3c 51 58 89 2b |.NI....DH.J>> Flow 16 (client to server) +00000000 00 00 00 20 d2 4b 02 a1 a9 b5 83 53 3a 5a 85 8f |... .K.....S:Z..| +00000010 f0 6a f2 84 0f ee 76 10 cf 95 1f f7 47 a4 11 7f |.j....v.....G...| +00000020 f1 0b 14 49 47 0e f4 e1 f1 51 00 10 3f a1 4a c4 |...IG....Q..?.J.| +00000030 9e e9 bd 56 82 13 8c 38 7b b2 ff 24 26 d6 1d b3 |...V...8{..$&...| +00000040 cf da bf 95 |....| +>>> Flow 17 (server to client) +00000000 00 00 00 10 f2 92 67 d8 3a 97 ac 30 0a a0 d8 c3 |......g.:..0....| +00000010 4a 55 0b f8 27 f8 23 48 37 c1 d2 42 c6 1a 0d b7 |JU..'.#H7..B....| +00000020 49 28 50 4c c9 d0 f0 e1 d8 81 81 8b 70 dd fc d4 |I(PL........p...| +00000030 a9 fd 7b 5e 00 00 00 20 a5 cd 27 e3 dc 14 10 80 |..{^... ..'.....| +00000040 5e a4 25 e8 ab 04 1d dc 5f 6a 56 9c db 08 c1 df |^.%....._jV.....| +00000050 00 81 d8 c0 3e 5d e0 32 61 36 b7 24 bb fb 5a 14 |....>].2a6.$..Z.| +00000060 fb 36 36 66 df 9a 78 99 5b ea 85 d5 fc 64 9e 95 |.66f..x.[....d..| +00000070 4d dd aa b5 84 d8 9b 6f 00 00 00 10 6f bf e1 29 |M......o....o..)| +00000080 58 6b 83 64 8e 15 f3 c1 ac 9d 05 20 6a 1a f8 9a |Xk.d....... j...| +00000090 a9 d7 9f 68 73 3f 38 05 d6 37 1c 22 31 0e 2a ef |...hs?8..7."1.*.| +000000a0 31 a8 0f a3 3f 15 d1 51 8e ce b2 f3 |1...?..Q....| +>>> Flow 18 (client to server) +00000000 00 00 00 10 b2 9e b9 78 aa fa 04 6d 04 74 da a5 |.......x...m.t..| +00000010 eb db c2 91 cd 52 7d df cb 17 f5 da 06 3c c7 18 |.....R}......<..| +00000020 ba 0b 56 8c 65 a5 ad 96 12 cc b0 51 d9 e0 15 b4 |..V.e......Q....| +00000030 ac 2c 73 cd 00 00 00 10 a2 3c 74 ef f4 f6 21 5d |.,s......>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 3c 0e 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...<....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 16 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |.aes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 00 00 00 16 61 65 73 31 32 |ssh.com....aes12| +00000120 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |8-gcm@openssh.co| +00000130 6d 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 |m...nhmac-sha2-2| +00000140 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000150 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000160 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000170 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 |,hmac-sha2-256,h| +00000180 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 |mac-sha2-512,hma| +00000190 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 |c-sha1,hmac-sha1| +000001a0 2d 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 |-96...nhmac-sha2| +000001b0 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-256-etm@openssh| +000001c0 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 |.com,hmac-sha2-5| +000001d0 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |12-etm@openssh.c| +000001e0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000001f0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 |,hmac-sha2-512,h| +00000200 6d 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 |mac-sha1,hmac-sh| +00000210 61 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 |a1-96....none...| +00000220 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 00 |.none...........| +00000230 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 |...;........n..f| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 1a 85 c3 d4 67 0b 31 85 01 47 |...<......g.1..G| +00000010 32 71 3f 30 88 0e 00 00 01 7a 73 6e 74 72 75 70 |2q?0.....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 72 73 61 2d 73 68 61 32 |.com....rsa-sha2| +000001a0 2d 35 31 32 2d 63 65 72 74 2d 76 30 31 40 6f 70 |-512-cert-v01@op| +000001b0 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 |enssh.com,rsa-sh| +000001c0 61 32 2d 32 35 36 2d 63 65 72 74 2d 76 30 31 40 |a2-256-cert-v01@| +000001d0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d |openssh.com,rsa-| +000001e0 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 68 61 |sha2-512,rsa-sha| +000001f0 32 2d 32 35 36 2c 73 73 68 2d 65 64 32 35 35 31 |2-256,ssh-ed2551| +00000200 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 |9-cert-v01@opens| +00000210 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 68 61 |sh.com,ecdsa-sha| +00000220 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 74 2d |2-nistp256-cert-| +00000230 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |v01@openssh.com,| +00000240 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 |ecdsa-sha2-nistp| +00000250 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |384-cert-v01@ope| +00000260 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +00000270 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 65 72 |ha2-nistp521-cer| +00000280 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +00000290 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 |m,sk-ssh-ed25519| +000002a0 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002b0 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 |h.com,sk-ecdsa-s| +000002c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000002d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000002e0 6d 2c 73 73 68 2d 65 64 32 35 35 31 39 2c 65 63 |m,ssh-ed25519,ec| +000002f0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000300 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +00000310 74 70 33 38 34 2c 65 63 64 73 61 2d 73 68 61 32 |tp384,ecdsa-sha2| +00000320 2d 6e 69 73 74 70 35 32 31 2c 73 6b 2d 73 73 68 |-nistp521,sk-ssh| +00000330 2d 65 64 32 35 35 31 39 40 6f 70 65 6e 73 73 68 |-ed25519@openssh| +00000340 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 68 |.com,sk-ecdsa-sh| +00000350 61 32 2d 6e 69 73 74 70 32 35 36 40 6f 70 65 6e |a2-nistp256@open| +00000360 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 28 37 75 94 8b 24 |...,..... (7u..$| +00000650 40 84 bd 06 2f cb e4 51 5f e6 01 99 0b 86 52 13 |@.../..Q_.....R.| +00000660 40 77 3c 96 03 84 38 40 f2 57 00 00 00 00 00 00 |@w<...8@.W......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 0b 12 16 5d 67 97 a1 dd 1f e5 8c |.... ...]g......| +00000130 fb 78 16 1d 9d 8a 50 df 95 18 37 e8 3f 4d 70 3e |.x....P...7.?Mp>| +00000140 14 6b 29 29 02 00 00 01 14 00 00 00 0c 72 73 61 |.k)).........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 2a 82 a0 |-sha2-512....*..| +00000160 df f3 9d fb 8a 80 af 82 d2 c0 17 9b a6 a5 fb d2 |................| +00000170 4e e4 12 23 ee 38 91 1b 3e 34 fd d6 5e 81 f9 93 |N..#.8..>4..^...| +00000180 83 49 e1 86 af be fa 7e ba ab e3 ef ff 7d f8 4e |.I.....~.....}.N| +00000190 14 f1 c0 c3 8c 70 88 21 3d a0 d1 2c bc f0 31 c6 |.....p.!=..,..1.| +000001a0 d3 3d c3 cf ea 5c 9c 88 13 62 2d a1 dd 19 9c 7c |.=...\...b-....|| +000001b0 c1 d5 a9 08 29 93 4b 77 46 9c 75 1f 86 e6 a9 59 |....).KwF.u....Y| +000001c0 be 2c 4e 17 62 f8 d8 87 2c 96 10 11 c6 83 4f 71 |.,N.b...,.....Oq| +000001d0 15 59 61 be b3 1c 60 87 47 1f 85 a9 0d f6 02 87 |.Ya...`.G.......| +000001e0 5f 72 2c fc 5c c0 05 e0 d1 60 56 20 96 e7 83 85 |_r,.\....`V ....| +000001f0 c2 08 89 f2 c2 52 54 0a ad 6a cd e5 ac 25 70 13 |.....RT..j...%p.| +00000200 71 75 e2 35 2f 7e 43 ea 2f 1d 84 1f df b3 28 3e |qu.5/~C./.....(>| +00000210 d2 a2 3f da 12 4d 97 67 de c2 53 77 89 49 a9 eb |..?..M.g..Sw.I..| +00000220 39 75 b8 ad 5c d2 7c f4 f5 12 2c 8f df 0f e1 c0 |9u..\.|...,.....| +00000230 3b 53 35 b5 5e b5 66 be 8d 13 cb d9 a8 62 10 de |;S5.^.f......b..| +00000240 69 90 37 c2 31 03 89 82 02 3e a2 9c 6a e2 dc cd |i.7.1....>..j...| +00000250 fb 0c 39 54 4e 2a c6 80 0d cb d0 b1 7c 57 e2 35 |..9TN*......|W.5| +00000260 b8 cc 87 3c 23 dc 62 b8 d2 60 16 9a fa 2f 75 ab |...<#.b..`.../u.| +00000270 00 00 00 0c 0a 15 91 6a 58 d9 74 91 88 35 d2 5e |.......jX.t..5.^| +00000280 00 00 00 f0 18 d0 fa d3 02 c9 c3 76 31 7d b6 fd |...........v1}..| +00000290 6c 91 fe 0e 2e 8f 48 96 98 df ba 1f b1 71 ef f2 |l.....H......q..| +000002a0 01 f1 22 87 ab 8b 01 73 72 51 84 f1 7c f3 78 4c |.."....srQ..|.xL| +000002b0 ab ac 94 ee d2 fc 1b c1 3d e3 ad d1 bf c7 fa fc |........=.......| +000002c0 f9 3c bc 79 e8 0f 75 b1 53 df 11 56 00 2c 7c ae |.<.y..u.S..V.,|.| +000002d0 32 af 3e 79 1b 01 33 89 0c 14 87 7d 91 f2 f9 02 |2.>y..3....}....| +000002e0 47 84 09 ec d5 56 e3 e0 73 21 88 42 cc ea e4 86 |G....V..s!.B....| +000002f0 e3 e7 96 6f 27 d0 db b9 fb 87 2c cd 00 30 eb f4 |...o'.....,..0..| +00000300 db 75 11 a8 b4 a9 a9 b0 35 f7 61 ed 1e d7 9f 3d |.u......5.a....=| +00000310 24 a8 42 73 78 d3 f3 07 cf 8d 75 95 ed 22 a8 6a |$.Bsx.....u..".j| +00000320 ee 4b c6 17 a9 24 db 35 d1 b0 19 55 fd ee 6d aa |.K...$.5...U..m.| +00000330 9f db b5 ad 61 1c 8b 6c 86 8b 64 ef 43 26 24 a1 |....a..l..d.C&$.| +00000340 ee e9 f7 75 88 a3 f5 6b 4d 66 65 54 c8 c7 12 b5 |...u...kMfeT....| +00000350 35 c9 b3 1c ce 4f 35 2b 55 88 f1 72 c0 e5 d3 f3 |5....O5+U..r....| +00000360 a0 5e e8 9a 03 e0 3c f5 1b 9d ed 76 27 88 ec fc |.^....<....v'...| +00000370 82 e1 64 61 f0 12 be 5b fe 3c 7b 7b 9f 6f d7 57 |..da...[.<{{.o.W| +00000380 2e 60 a5 4e |.`.N| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 00 00 00 20 98 a5 f6 a1 1f 09 31 a9 fb c0 3c c0 |... ......1...<.| +00000020 75 59 9f 11 f8 66 ac 45 22 af 27 4e e6 3a 8a 9b |uY...f.E".'N.:..| +00000030 b4 eb 56 55 74 ac 87 2f d3 ab 6c 3f 61 78 31 31 |..VUt../..l?ax11| +00000040 a9 8a a4 07 |....| +>>> Flow 7 (server to client) +00000000 00 00 00 20 19 82 1d 4d 75 27 8a d1 a2 0c c8 ed |... ...Mu'......| +00000010 63 92 81 99 cd a5 5b ed 0d ca b1 80 a4 d6 53 f5 |c.....[.......S.| +00000020 cb d6 59 de a8 d9 ad 1a fa 98 8e 54 1b fc 32 7d |..Y........T..2}| +00000030 01 ac ab a4 |....| +>>> Flow 8 (client to server) +00000000 00 00 00 30 d8 dc aa 44 2c d5 16 4a 65 dd 87 b7 |...0...D,..Je...| +00000010 b9 b3 1b c6 77 6f 56 dd 53 8d c1 47 d0 85 c4 ae |....woV.S..G....| +00000020 df ec 78 55 03 53 38 26 00 17 08 d6 c0 3b 8e 30 |..xU.S8&.....;.0| +00000030 ec 2e 6f 68 35 2d 2e 00 cd d8 15 fe c6 5f fb 55 |..oh5-......._.U| +00000040 66 2c 4a c1 |f,J.| +>>> Flow 9 (server to client) +00000000 00 00 00 20 7a 82 61 f1 7d 7e 93 20 a4 36 6e ef |... z.a.}~. .6n.| +00000010 07 11 52 32 96 d0 79 3c 0a b8 30 03 9e a9 83 a2 |..R2..y<..0.....| +00000020 4c 0e cc 78 8a 7f 47 0f 65 13 d8 67 81 f1 e2 e3 |L..x..G.e..g....| +00000030 ce 68 06 d1 |.h..| +>>> Flow 10 (client to server) +00000000 00 00 01 60 60 67 cc a0 37 9b c6 79 6b 2e 23 66 |...``g..7..yk.#f| +00000010 e8 e9 cb b0 c7 3b 1a 35 44 af 28 70 1e a6 83 28 |.....;.5D.(p...(| +00000020 d1 a2 b1 b2 f8 00 20 97 f9 a6 2b 51 04 4c 4d d7 |...... ...+Q.LM.| +00000030 3b 0f 3e ac 91 52 07 1a a1 d7 ba 8f 15 17 d6 d1 |;.>..R..........| +00000040 2d ec 2d 15 14 87 82 0a 74 ae 09 bc f5 7c 2d 06 |-.-.....t....|-.| +00000050 21 d9 6d 02 62 73 55 b0 e3 b7 2e 7a a2 f6 c5 d3 |!.m.bsU....z....| +00000060 ff 4a 72 71 95 75 0d 21 81 55 a5 9a 99 61 5a bd |.Jrq.u.!.U...aZ.| +00000070 48 20 e2 01 59 6c 2e f1 81 33 0f 83 e5 46 60 00 |H ..Yl...3...F`.| +00000080 64 10 86 15 20 bd ab 06 b9 71 e7 ff 4f 46 24 72 |d... ....q..OF$r| +00000090 3c a4 11 0e a9 b3 4e 2e 96 3e 5e 11 29 96 12 1c |<.....N..>^.)...| +000000a0 dd 17 b7 21 cf b2 b8 6e 62 35 b6 c8 64 17 af 39 |...!...nb5..d..9| +000000b0 e3 3b 03 e1 fb c8 0b 21 8e 3d f7 65 ce 22 09 3f |.;.....!.=.e.".?| +000000c0 0d cc 36 a4 63 95 bf 1e fd bf 22 80 8c 47 f7 06 |..6.c....."..G..| +000000d0 07 bb 7e 20 5c f8 ea 34 88 7f 3a 7a 74 4d 0e e6 |..~ \..4..:ztM..| +000000e0 fe bd 57 c7 6d 60 36 7d 0d 8e 6a 1c c4 d9 11 c0 |..W.m`6}..j.....| +000000f0 85 cf 36 16 71 03 f4 1e f8 9d fa b7 2b 03 4d 4b |..6.q.......+.MK| +00000100 a9 03 65 91 b4 09 e6 d4 86 a4 d3 5a e0 ae 21 7a |..e........Z..!z| +00000110 81 6c 28 83 73 ec d6 83 d6 5c 8c fd c0 5c a3 ca |.l(.s....\...\..| +00000120 0f cb 87 34 f1 11 21 f1 79 38 18 dd f0 44 cb 81 |...4..!.y8...D..| +00000130 ab 0c 79 06 8f 90 11 bf a3 14 24 90 2c 93 56 d8 |..y.......$.,.V.| +00000140 32 3d 48 ff d3 1d 6d a2 43 db 6b 2b 43 13 90 0a |2=H...m.C.k+C...| +00000150 e5 65 3c e3 2f 11 6a 1c d8 50 44 db 49 01 39 7e |.e<./.j..PD.I.9~| +00000160 47 0a 29 28 a1 4c 15 5c 42 72 6d e1 f0 8d cc 04 |G.)(.L.\Brm.....| +00000170 28 ed 02 a4 |(...| +>>> Flow 11 (server to client) +00000000 00 00 01 40 be ec 8e dc 76 c0 68 60 c4 2a f4 47 |...@....v.h`.*.G| +00000010 24 a7 48 07 c4 82 53 80 55 d9 cd d6 ff 44 68 13 |$.H...S.U....Dh.| +00000020 60 40 88 74 d0 d4 97 99 d6 a1 30 cf 20 bd 15 7a |`@.t......0. ..z| +00000030 88 04 43 45 33 5c 59 1e a8 ff 97 f3 da ff a8 9f |..CE3\Y.........| +00000040 8c 9f 3f 7b a6 29 1e b6 ee 19 33 ba 1b 98 e3 da |..?{.)....3.....| +00000050 f0 a2 39 cc 75 f9 74 ca 05 da 7a ef 3a 56 e1 41 |..9.u.t...z.:V.A| +00000060 6f a6 7b 88 a8 e6 63 1d 33 12 41 0b ed 4f 1d 9e |o.{...c.3.A..O..| +00000070 0a aa 54 93 be 84 8e 0a 46 10 be a3 92 ac 27 d0 |..T.....F.....'.| +00000080 fe bb 17 de 52 56 00 3d 20 73 51 06 b8 23 f8 d4 |....RV.= sQ..#..| +00000090 23 30 bc 7f 4a 92 32 e9 a7 f4 c6 de c3 f7 d4 f0 |#0..J.2.........| +000000a0 f9 79 4e 97 d8 62 94 82 06 22 3b 29 01 28 3a 53 |.yN..b...";).(:S| +000000b0 91 a2 5c 56 82 18 b5 a0 3b 3e 45 2e f0 e2 7a 80 |..\V....;>E...z.| +000000c0 71 e0 5a 6f 06 09 f4 db 2d fa 2b a0 9a 54 fc 14 |q.Zo....-.+..T..| +000000d0 ce d4 5f a1 bc 84 c6 89 87 28 86 5b 89 55 3c 53 |.._......(.[.U>> Flow 12 (client to server) +00000000 00 00 02 80 d3 dc f3 0a b9 5b ce b5 1e 20 5c 63 |.........[... \c| +00000010 2e 16 f7 34 b2 fe a7 4e e9 d1 03 34 d1 cc 78 39 |...4...N...4..x9| +00000020 4d 95 34 e2 55 55 e1 1f a8 2d 04 eb 60 7b 4d a7 |M.4.UU...-..`{M.| +00000030 e6 be ee 6e 90 89 f6 56 dd 8e 01 fb 11 09 c3 62 |...n...V.......b| +00000040 e7 36 a5 cf b3 72 8b fe 33 01 a5 cb 98 53 df af |.6...r..3....S..| +00000050 35 d4 40 1e 42 ba be 4a 7c 7e d0 e0 2f 95 f3 72 |5.@.B..J|~../..r| +00000060 ce 8f ba 91 49 72 f8 54 5d 17 0b c9 90 d2 83 e9 |....Ir.T].......| +00000070 ad 99 db 6c d1 67 c0 7a a1 c8 b8 9e 7f a4 11 b9 |...l.g.z........| +00000080 3e fd 27 15 78 1c 9a 8d 66 90 bd 49 c1 cc 64 d5 |>.'.x...f..I..d.| +00000090 ea 52 54 bd 3d d7 c1 b6 70 86 68 4e 55 4a e2 c0 |.RT.=...p.hNUJ..| +000000a0 bf ec c7 31 6e ee 58 4c 0a 17 e2 4f 60 dd aa 50 |...1n.XL...O`..P| +000000b0 5d 7f 4b 3a 11 ae 57 ef a2 5a 77 49 0d 10 db e3 |].K:..W..ZwI....| +000000c0 4d e2 f8 f5 8e 50 c3 fa ce 74 51 9d 5c e5 fa 46 |M....P...tQ.\..F| +000000d0 d8 15 08 e3 fb 0e 49 57 f6 cc 57 50 00 79 5e ad |......IW..WP.y^.| +000000e0 4e 2a 61 ca 96 ba 17 20 76 78 b9 be 1f 24 63 3c |N*a.... vx...$c<| +000000f0 86 2d 6d ee 96 44 a5 94 14 52 75 a1 54 51 24 44 |.-m..D...Ru.TQ$D| +00000100 7d d7 51 50 b4 63 20 06 ab 1a 91 0d ce 2c fd 7e |}.QP.c ......,.~| +00000110 17 d7 39 ab 5e 4e 9a 54 02 a1 5f 0a 5e bb df aa |..9.^N.T.._.^...| +00000120 ee c9 34 a3 ea 48 c8 72 ce 8e 9d 63 1b 31 c1 df |..4..H.r...c.1..| +00000130 f9 56 a5 ab 6b c2 30 9a 18 4f d4 14 6d d6 cf b9 |.V..k.0..O..m...| +00000140 d0 77 eb e4 5b 73 2d 02 e0 4c f2 99 e9 a3 dd 79 |.w..[s-..L.....y| +00000150 d7 0a 5c c5 8d 8c 57 5c 39 62 96 2d bb c4 c7 12 |..\...W\9b.-....| +00000160 07 d3 d5 ea be d3 81 77 8f c1 cb f1 70 dd 12 2b |.......w....p..+| +00000170 f1 fa 2c 2f 01 f1 b5 80 1e 3c 7a cb 9f 35 05 9c |..,/...........=.| +00000250 61 d7 34 94 98 51 00 54 d8 f3 d0 2b 58 8f 7a d7 |a.4..Q.T...+X.z.| +00000260 5d ce 00 44 e1 ed 99 ca 87 60 e8 3f 1c de fa d6 |]..D.....`.?....| +00000270 f1 7a 0f 84 8b 18 cd cf 73 1c 29 cc 59 69 a4 cb |.z......s.).Yi..| +00000280 e1 8c 5f 31 72 71 56 4f 7c 57 e1 b1 64 13 2a 91 |.._1rqVO|W..d.*.| +00000290 fd 22 a4 69 |.".i| +>>> Flow 13 (server to client) +00000000 00 00 00 10 2d 8e 62 ed f7 f9 83 6c 4c 2e 39 72 |....-.b....lL.9r| +00000010 03 80 a1 f9 15 6e 9e 70 80 52 17 fd e4 6c f7 54 |.....n.p.R...l.T| +00000020 c5 3d a1 a3 |.=..| +>>> Flow 14 (client to server) +00000000 00 00 00 20 ce 6c 2b 55 12 9c 4f 28 e0 da c8 1a |... .l+U..O(....| +00000010 63 37 53 7c ab 03 e5 13 54 a5 92 32 cf 48 06 9f |c7S|....T..2.H..| +00000020 d0 46 24 88 5c db dd da 71 77 1e 49 ae 8a 00 a7 |.F$.\...qw.I....| +00000030 1f 95 97 ff |....| +>>> Flow 15 (server to client) +00000000 00 00 00 20 a6 e1 c2 71 a8 9e 61 5b 2f 14 78 3b |... ...q..a[/.x;| +00000010 38 ab 1f 9e 64 1e 9b 75 df 01 73 8c a4 7f d6 b6 |8...d..u..s.....| +00000020 a2 8c 50 11 47 aa 93 21 64 a6 e9 0e 37 a3 67 62 |..P.G..!d...7.gb| +00000030 2b 50 f5 87 |+P..| +>>> Flow 16 (client to server) +00000000 00 00 00 20 6b 72 64 f6 6f e5 86 9c 52 ff 11 9e |... krd.o...R...| +00000010 f6 8c f1 07 b7 3c 44 6c d1 db 20 b6 7e 40 03 10 |.........`..a.6...=.| +00000030 b3 29 55 27 00 00 00 10 70 0c fa bd 6a 64 2e 30 |.)U'....p...jd.0| +00000040 7d 9f 48 67 fb 62 e4 3f b3 df ab 38 75 e3 e9 b5 |}.Hg.b.?...8u...| +00000050 65 b0 f2 a6 76 fa 5c 1c |e...v.\.| +>>> Flow 17 (server to client) +00000000 00 00 00 10 01 34 1e 80 d5 6a be c4 8b 47 1e 41 |.....4...j...G.A| +00000010 a1 e4 75 a7 d0 9a 87 0b 4d 03 2c 88 71 13 39 ac |..u.....M.,.q.9.| +00000020 fc 61 23 a2 00 00 00 20 20 c0 16 b1 9a fd 93 8c |.a#.... .......| +00000030 99 de d7 3f 37 e7 14 5c 77 74 0c 67 f0 0c 2c f7 |...?7..\wt.g..,.| +00000040 ce 4b 94 80 28 fb 36 7d 0f 07 a1 1a 13 7a c3 04 |.K..(.6}.....z..| +00000050 20 03 e3 d4 49 b3 f3 31 00 00 00 10 1c 2b e6 b2 | ...I..1.....+..| +00000060 64 bd 29 92 38 da d4 c7 9b 56 e4 2f 24 07 64 f2 |d.).8....V./$.d.| +00000070 2f a4 aa 3d 6c b8 ed 23 5e d4 f0 a7 |/..=l..#^...| +>>> Flow 18 (client to server) +00000000 00 00 00 10 72 63 60 78 96 0e 7e 04 44 19 b4 36 |....rc`x..~.D..6| +00000010 e1 61 0c ef 86 94 8a df d1 e6 7f 99 cc 2e cc a6 |.a..............| +00000020 d9 97 50 b5 00 00 00 30 b9 0d 54 84 af 23 16 f1 |..P....0..T..#..| +00000030 0f a3 50 03 fc 5d 0b d3 13 ee fe ef a5 29 e0 46 |..P..].......).F| +00000040 1c 7e 23 44 5e cd dd 73 97 23 16 47 96 60 ae f6 |.~#D^..s.#.G.`..| +00000050 ce 76 ac 35 c3 1c ba 1a 40 f6 d2 2b 90 ac 8e 1a |.v.5....@..+....| +00000060 77 76 8f 45 be e8 c7 da |wv.E....| diff --git a/ssh/testdata/Server-Cipher-aes192-ctr b/ssh/testdata/Server-Cipher-aes192-ctr new file mode 100644 index 0000000000..3e0e922c5a --- /dev/null +++ b/ssh/testdata/Server-Cipher-aes192-ctr @@ -0,0 +1,375 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 0a 61 65 73 31 39 32 2d 63 74 72 00 00 00 0a 61 |.aes192-ctr....a| +00000110 65 73 31 39 32 2d 63 74 72 00 00 00 6e 68 6d 61 |es192-ctr...nhma| +00000120 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +00000130 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000140 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000160 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000170 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +00000180 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 |mac-sha1-96...nh| +00000190 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +000001a0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +000001b0 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +000001c0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +000001d0 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +000001e0 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +000001f0 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000200 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000210 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 0f 14 8e c1 7e da e3 72 31 e7 |...<......~..r1.| +00000010 3e 93 6a 33 27 93 00 00 01 7a 73 6e 74 72 75 70 |>.j3'....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 72 73 61 2d 73 68 61 32 |.com....rsa-sha2| +000001a0 2d 35 31 32 2d 63 65 72 74 2d 76 30 31 40 6f 70 |-512-cert-v01@op| +000001b0 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 |enssh.com,rsa-sh| +000001c0 61 32 2d 32 35 36 2d 63 65 72 74 2d 76 30 31 40 |a2-256-cert-v01@| +000001d0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d |openssh.com,rsa-| +000001e0 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 68 61 |sha2-512,rsa-sha| +000001f0 32 2d 32 35 36 2c 73 73 68 2d 65 64 32 35 35 31 |2-256,ssh-ed2551| +00000200 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 |9-cert-v01@opens| +00000210 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 68 61 |sh.com,ecdsa-sha| +00000220 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 74 2d |2-nistp256-cert-| +00000230 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |v01@openssh.com,| +00000240 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 |ecdsa-sha2-nistp| +00000250 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |384-cert-v01@ope| +00000260 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +00000270 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 65 72 |ha2-nistp521-cer| +00000280 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +00000290 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 |m,sk-ssh-ed25519| +000002a0 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002b0 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 |h.com,sk-ecdsa-s| +000002c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000002d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000002e0 6d 2c 73 73 68 2d 65 64 32 35 35 31 39 2c 65 63 |m,ssh-ed25519,ec| +000002f0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000300 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +00000310 74 70 33 38 34 2c 65 63 64 73 61 2d 73 68 61 32 |tp384,ecdsa-sha2| +00000320 2d 6e 69 73 74 70 35 32 31 2c 73 6b 2d 73 73 68 |-nistp521,sk-ssh| +00000330 2d 65 64 32 35 35 31 39 40 6f 70 65 6e 73 73 68 |-ed25519@openssh| +00000340 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 68 |.com,sk-ecdsa-sh| +00000350 61 32 2d 6e 69 73 74 70 32 35 36 40 6f 70 65 6e |a2-nistp256@open| +00000360 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 cc 98 aa 02 da 4b |...,..... .....K| +00000650 6b 2d cf e0 d6 6f c0 e9 00 26 cc be 58 02 9b 02 |k-...o...&..X...| +00000660 e6 2d 84 2a 9c 62 cf 66 c5 0e 00 00 00 00 00 00 |.-.*.b.f........| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 ee a0 9c c6 be 90 37 5d 28 ba ea |.... ......7](..| +00000130 a8 41 a5 72 c8 5e 4d 2d 23 c4 f9 26 88 44 60 fc |.A.r.^M-#..&.D`.| +00000140 30 d9 da 91 6a 00 00 01 14 00 00 00 0c 72 73 61 |0...j........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 27 18 6e |-sha2-512....'.n| +00000160 9b 94 de 2e 11 f0 fa d8 2c 47 2d 5e 6c 78 c0 a9 |........,G-^lx..| +00000170 e1 f5 31 05 eb b4 be ac fe bb 86 15 e8 ad d1 c3 |..1.............| +00000180 89 78 61 c7 d9 70 03 80 2c 62 29 21 e1 80 c9 ca |.xa..p..,b)!....| +00000190 b8 58 6a 3b af 21 d5 48 fd fb 09 8c 91 d3 1e e2 |.Xj;.!.H........| +000001a0 66 ec 8f 8b 92 71 02 78 00 a9 a2 5d 0b 85 77 fd |f....q.x...]..w.| +000001b0 17 03 12 f4 76 29 31 96 78 42 32 93 1c 12 51 6b |....v)1.xB2...Qk| +000001c0 f6 37 8d 66 83 ab ba 14 3e 36 c2 84 46 76 a0 2e |.7.f....>6..Fv..| +000001d0 ca d3 42 4b d1 a1 bf 3e 9a 5b 0a 8e 42 80 6b 91 |..BK...>.[..B.k.| +000001e0 e1 a3 9f 50 3c ae 25 41 39 63 85 98 fb 9a 1c 15 |...P<.%A9c......| +000001f0 47 99 01 65 00 57 3e 36 a6 5a 73 b6 6f 1e d2 a4 |G..e.W>6.Zs.o...| +00000200 02 76 14 e4 c4 5c af f5 a6 59 4c 2b 8b 51 fb fc |.v...\...YL+.Q..| +00000210 0f be c0 6f 78 c1 76 2f e5 49 80 58 8a e3 2a 61 |...ox.v/.I.X..*a| +00000220 21 9b b7 e0 8e 48 28 06 71 21 10 53 d0 0b 20 5e |!....H(.q!.S.. ^| +00000230 df df 04 37 96 aa 4b f6 ce 31 94 0b 40 fc 10 20 |...7..K..1..@.. | +00000240 e2 49 22 2f ea 9e 99 de ce aa db 15 cf 48 9c fe |.I"/.........H..| +00000250 1b 4a 68 59 ec cc 8c 03 52 c5 d3 3f 75 a3 63 9c |.JhY....R..?u.c.| +00000260 a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc 62 b8 |.....W.5...<#.b.| +00000270 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000280 00 00 00 f0 7f f8 36 72 e1 47 90 55 75 aa 61 ec |......6r.G.Uu.a.| +00000290 a3 e9 5a e5 67 55 1c 72 49 dc 2b 3a e0 92 44 40 |..Z.gU.rI.+:..D@| +000002a0 20 31 62 4e 59 62 cc 7a 46 c1 ed ff 26 5b b4 b2 | 1bNYb.zF...&[..| +000002b0 46 10 f8 ad 34 9e 09 d5 10 cb d1 97 f9 07 3a 51 |F...4.........:Q| +000002c0 0d 8f f9 cf 50 de 7e 0d 18 b0 bf 10 9e 6a b1 b2 |....P.~......j..| +000002d0 98 9b 0f 93 79 87 c9 76 b8 34 1b d4 a6 86 46 4c |....y..v.4....FL| +000002e0 6a 96 94 d4 13 62 e5 39 66 5f 4f ce 4c c4 4e 0a |j....b.9f_O.L.N.| +000002f0 db fc 56 39 5f 0b d3 cb 4c 55 39 bd e8 b6 c9 fc |..V9_...LU9.....| +00000300 3b b9 af 2b 4f ff 93 96 c9 22 1a bb 60 00 41 21 |;..+O...."..`.A!| +00000310 1d 6e 39 a8 9e 7e be f3 de 70 66 5e 4e 11 c9 83 |.n9..~...pf^N...| +00000320 f0 28 0c 1d b2 d2 2e cf 9c 6b d0 7d e6 e4 c5 4a |.(.......k.}...J| +00000330 16 2c 49 3f bc a8 42 05 f7 6e 46 d8 d6 d7 87 cb |.,I?..B..nF.....| +00000340 16 e8 9b 9b 2a c1 c7 5d c1 5a 73 2e 54 f9 0f 5e |....*..].Zs.T..^| +00000350 6c 22 00 2d 94 0f 6e 98 d9 64 de 91 45 28 b0 b7 |l".-..n..d..E(..| +00000360 30 df 98 95 81 15 f3 96 a2 1d fb eb 74 8a fe 8e |0...........t...| +00000370 44 58 ea 65 15 dc b7 dc 84 ff bb 78 f8 4f 43 aa |DX.e.......x.OC.| +00000380 0a 61 3f b1 5f 00 a5 cc ce 5c 64 09 4e 23 09 f0 |.a?._....\d.N#..| +00000390 13 bd 0f 21 |...!| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 00 00 00 20 70 24 8a 2e 6a 2d 53 b9 4a 62 ff 36 |... p$..j-S.Jb.6| +00000020 08 13 7d 0d f2 73 5c 23 f3 d4 29 e5 c5 8c e6 d3 |..}..s\#..).....| +00000030 9a 57 81 22 27 0c 83 f6 92 e1 72 f5 6c 98 b6 9f |.W."'.....r.l...| +00000040 58 52 90 6f 9d c1 83 6b 7e ca f7 8c 11 28 02 d2 |XR.o...k~....(..| +00000050 d3 70 59 bc |.pY.| +>>> Flow 7 (server to client) +00000000 00 00 00 20 74 c6 8d 30 31 01 9b b4 9a a2 91 e0 |... t..01.......| +00000010 3e ac 6e d1 b7 a3 e2 1c 8c e0 d9 5d b3 01 21 91 |>.n........]..!.| +00000020 1e e4 d4 cf c6 05 d3 0c 6c 72 57 cd 4d d0 de 95 |........lrW.M...| +00000030 10 2e 6f 04 b8 1b 67 7f f7 b1 4b 34 4a c1 42 f3 |..o...g...K4J.B.| +00000040 46 95 83 c4 |F...| +>>> Flow 8 (client to server) +00000000 00 00 00 30 a0 08 04 4f b2 01 ec 68 ab cc 4c 1b |...0...O...h..L.| +00000010 88 96 d7 74 43 43 97 be e4 1a f0 35 77 0a 4f c4 |...tCC.....5w.O.| +00000020 62 aa 67 2f e7 c0 9c 52 c0 d3 3f 74 5d e8 e8 d5 |b.g/...R..?t]...| +00000030 1a 33 64 30 5f ac 11 15 65 92 98 ed 2c 87 2e 7c |.3d0_...e...,..|| +00000040 78 8f fa 9d 5a 00 61 8c c9 8f c4 71 24 fd 48 17 |x...Z.a....q$.H.| +00000050 87 c7 c7 62 |...b| +>>> Flow 9 (server to client) +00000000 00 00 00 20 ce 92 cd f3 06 c0 e3 24 a1 38 61 83 |... .......$.8a.| +00000010 d2 3d 7e ee d7 01 8e 47 b2 5b 98 44 d7 61 01 47 |.=~....G.[.D.a.G| +00000020 d3 cf 6d 83 91 ef d7 ee f2 e0 b3 53 ea c9 ac 90 |..m........S....| +00000030 d8 6b fb 16 91 82 ce ea 39 08 ae af bc 5c 5c b0 |.k......9....\\.| +00000040 89 17 34 8b |..4.| +>>> Flow 10 (client to server) +00000000 00 00 01 60 fd d2 93 68 9c b0 e8 77 22 76 cc 30 |...`...h...w"v.0| +00000010 ba 1e 7c 25 ec 69 85 d9 cc 63 7a f8 07 f4 d5 b8 |..|%.i...cz.....| +00000020 15 5c 94 01 26 6d c1 3a 6c fb 24 d8 ae 88 b0 eb |.\..&m.:l.$.....| +00000030 76 00 e9 0c bd cf 6b 47 11 5a 60 8e 1b 7e d8 61 |v.....kG.Z`..~.a| +00000040 fd 40 30 0b 80 55 0b 42 ec 6a 44 df 95 31 61 6e |.@0..U.B.jD..1an| +00000050 a5 9b 4e 38 02 8e f8 d0 60 f1 fa 20 de 3c 01 c0 |..N8....`.. .<..| +00000060 c8 8a 14 89 df 7c b5 bd 3b d5 fd c6 c7 b1 6c 8d |.....|..;.....l.| +00000070 a8 e1 5c ea b0 d2 30 f5 8e 2f 4f 9d 8c 4f 80 c7 |..\...0../O..O..| +00000080 84 4e 93 d7 9f 08 4a 04 5f 47 e1 e1 44 9e 3e 4a |.N....J._G..D.>J| +00000090 d4 41 60 15 f5 78 19 c4 5c ef 6e fa 82 3b 9d 71 |.A`..x..\.n..;.q| +000000a0 7f 47 6c cf e0 ea 49 3b 97 c0 97 c4 d9 c8 81 21 |.Gl...I;.......!| +000000b0 4d b0 42 22 67 9e 0f 41 93 12 d0 a3 26 79 f6 f6 |M.B"g..A....&y..| +000000c0 8f f9 e0 59 64 67 76 02 cb e7 6f e2 fa 67 9b 7b |...Ydgv...o..g.{| +000000d0 2c a7 f4 fa 20 9e 0f 58 34 57 e2 78 fd c8 71 81 |,... ..X4W.x..q.| +000000e0 5c e7 8c 3b e2 23 b5 35 2e 37 ee 5d d6 6d 4d 88 |\..;.#.5.7.].mM.| +000000f0 f6 89 33 72 04 22 93 58 05 4d a7 27 ab 7f c9 5c |..3r.".X.M.'...\| +00000100 3e aa 6b 8f 0e f9 c4 91 7a 41 a1 6c 85 d4 1e 9b |>.k.....zA.l....| +00000110 8e 7d 6a 5b 97 4c c1 ae 34 d5 d8 04 44 28 2c b3 |.}j[.L..4...D(,.| +00000120 59 18 3e 7b 36 b1 1b 2f 32 9a 55 55 c4 35 2b b9 |Y.>{6../2.UU.5+.| +00000130 f3 8d 5f 65 1a a6 da 6f 08 11 6e 87 e2 6b 58 0a |.._e...o..n..kX.| +00000140 08 f1 a1 25 2c 19 d0 5e 10 04 25 af e2 37 86 f2 |...%,..^..%..7..| +00000150 06 ff 49 4c 30 1d 57 fa 58 1d 8c 66 ad 9f 20 fe |..IL0.W.X..f.. .| +00000160 69 5e 8e f9 34 3c bf 46 f6 bf 74 15 0b bd 54 88 |i^..4<.F..t...T.| +00000170 f1 96 f3 77 f5 15 4f 08 53 91 6d 3c 10 ce 49 d2 |...w..O.S.m<..I.| +00000180 de 68 8e c7 |.h..| +>>> Flow 11 (server to client) +00000000 00 00 01 40 dd 55 13 1d 76 09 2d c1 26 ff 17 d5 |...@.U..v.-.&...| +00000010 74 55 e3 6f 01 79 00 88 92 74 05 af 2b de 61 c2 |tU.o.y...t..+.a.| +00000020 cc 9f 47 75 b7 4c 53 8a 1a b1 94 c2 c7 20 1f a1 |..Gu.LS...... ..| +00000030 3d 6e 10 b6 d2 c4 1a 79 ef d1 bd 07 4b b6 25 9e |=n.....y....K.%.| +00000040 25 0a 5c b7 e2 41 34 bb b7 00 9d c4 bd 59 f1 b3 |%.\..A4......Y..| +00000050 29 e2 9b 8a 16 3b be 9e 26 53 7f 14 79 80 e8 71 |)....;..&S..y..q| +00000060 fd 98 26 b9 a7 13 ca 6f 3d b7 7b 3b 95 ac f0 25 |..&....o=.{;...%| +00000070 21 54 2f 68 18 de 38 33 d7 f8 1f e3 88 8f 20 db |!T/h..83...... .| +00000080 4e 63 63 5b eb 31 f9 70 21 ce b5 86 51 7f bf 37 |Ncc[.1.p!...Q..7| +00000090 d3 a5 b4 4e 18 4b 28 90 a2 ef e1 02 4a be a4 4e |...N.K(.....J..N| +000000a0 e0 bc 15 7e 13 ee 9e b9 22 3b 3f 74 a9 42 b2 87 |...~....";?t.B..| +000000b0 af cf 6f 4c af 56 5a 2a c1 db d1 67 e9 2d 85 06 |..oL.VZ*...g.-..| +000000c0 4b 85 1d 77 a3 76 0e 49 80 3c ba 2f 46 43 4f de |K..w.v.I.<./FCO.| +000000d0 b3 9b 08 22 4a 05 1e 07 f7 4e de d9 77 cf 5d 27 |..."J....N..w.]'| +000000e0 ed 93 32 bd ee f8 81 61 5a 2c 3b 83 9c fb 3c 1c |..2....aZ,;...<.| +000000f0 c8 bf 9b 5f 95 61 4d d6 5e 5a 7d d4 db c8 3a 69 |..._.aM.^Z}...:i| +00000100 0f b0 4f 6c 76 bd 4d f1 5a 10 1f 4d 45 5b b4 aa |..Olv.M.Z..ME[..| +00000110 5b ed 56 1e 3d 25 26 5a 9d 24 45 9e e5 9f 1c 98 |[.V.=%&Z.$E.....| +00000120 c2 7f 86 01 56 6b d6 52 b2 be 07 7f 9a bc 24 48 |....Vk.R......$H| +00000130 72 48 78 4d 45 13 43 f3 08 9d f6 fe 50 73 46 f3 |rHxME.C.....PsF.| +00000140 40 43 14 a8 21 ae d8 75 97 53 bd 2e f4 1b cc 64 |@C..!..u.S.....d| +00000150 f0 86 8a aa 7d bf 03 ca 02 fb 86 46 f2 a2 33 70 |....}......F..3p| +00000160 51 a6 37 a8 |Q.7.| +>>> Flow 12 (client to server) +00000000 00 00 02 80 c5 99 fd 9d 4a 70 42 6b f4 c4 c0 81 |........JpBk....| +00000010 e6 32 69 1c 39 ef ee 50 e2 60 36 8c 03 5d 32 70 |.2i.9..P.`6..]2p| +00000020 5f 48 13 a7 77 25 2e 22 0c ec 3d c8 fa 4f b0 62 |_H..w%."..=..O.b| +00000030 ed 7f 0f f4 5a b9 90 54 9e a4 59 d9 de bc 74 a2 |....Z..T..Y...t.| +00000040 bf 0f 32 f9 e8 f9 30 a8 5c c9 60 b7 ea 45 77 d1 |..2...0.\.`..Ew.| +00000050 75 e5 35 ec 68 0b 32 b3 b1 dc 1c 64 06 7b c0 b7 |u.5.h.2....d.{..| +00000060 30 ca fc 0a 51 64 5a f8 b2 75 66 01 6e 8f 93 de |0...QdZ..uf.n...| +00000070 6d c3 4a 61 9c 09 a6 9d 49 4d ea 7a 53 eb db ed |m.Ja....IM.zS...| +00000080 1d fb 74 6b 2e ca f8 a4 96 6b 9e 1c 90 e5 76 bb |..tk.....k....v.| +00000090 3b c0 92 bd 52 ae 46 5a e4 63 e5 d9 f2 df 6f 42 |;...R.FZ.c....oB| +000000a0 b2 8f ad 2d 5f fc 74 41 bc 02 7a 49 8a 6e 4f d1 |...-_.tA..zI.nO.| +000000b0 b6 bf 86 01 3f a0 a6 d0 82 ca 36 f8 b0 a4 56 89 |....?.....6...V.| +000000c0 50 2e 15 27 82 e0 3e 61 22 c7 92 52 8b ab 0a 0a |P..'..>a"..R....| +000000d0 aa 74 22 a0 7b 45 f2 7f 4b f8 ea 6a dc ac 01 77 |.t".{E..K..j...w| +000000e0 fb 47 8c 73 20 45 ca ee a4 2f bb 21 27 29 0f fb |.G.s E.../.!')..| +000000f0 95 72 b4 64 cb a9 92 c5 68 9f 4c 0d fd ae 16 f3 |.r.d....h.L.....| +00000100 eb 1d 10 88 00 4c 05 65 37 29 9f a5 92 e2 66 bf |.....L.e7)....f.| +00000110 05 35 21 e9 28 21 ad 0a b2 ed 8e 9d 4a e7 f2 7f |.5!.(!......J...| +00000120 49 e7 2a 3b 1a 1e 2e f6 2f d1 f3 71 b6 33 28 75 |I.*;..../..q.3(u| +00000130 2b ca 32 1a af fd ce 8a 08 67 6b fa 9b 36 5c 59 |+.2......gk..6\Y| +00000140 92 22 07 97 9b 67 c6 0a f2 bc 12 a0 05 a3 53 8f |."...g........S.| +00000150 9e c0 9f 0c 25 6c be a9 50 eb d8 61 91 c9 1b 29 |....%l..P..a...)| +00000160 87 de e4 4a 7a 0d 11 ca 46 c2 90 1d 59 b1 d4 42 |...Jz...F...Y..B| +00000170 aa 6a 9e 73 f7 6d af d3 d5 e1 13 af 4d 8f 80 d0 |.j.s.m......M...| +00000180 b5 bb 5a 8c 5e f4 da 58 ab cf 69 e8 2f 48 f2 e3 |..Z.^..X..i./H..| +00000190 a0 f8 2a 63 72 dd 07 c3 bc 32 cc 05 91 60 76 6e |..*cr....2...`vn| +000001a0 89 be 1a 8e 20 cc d5 e4 2e 5f 87 43 f4 48 90 23 |.... ...._.C.H.#| +000001b0 af 9b 31 d2 f9 b4 81 4a bb 59 60 d7 01 08 30 18 |..1....J.Y`...0.| +000001c0 4e c9 6d 1b a4 bd da 14 1f b9 11 db d6 cf af e1 |N.m.............| +000001d0 b2 99 c2 7c 0b 00 53 07 5f 1b b1 9e 9c d8 2e 2f |...|..S._....../| +000001e0 e4 52 32 2a c1 5a c3 f2 ba 8a dc a7 2a 14 a6 08 |.R2*.Z......*...| +000001f0 6c dd 21 27 ee df 61 2e 85 63 3d 9d ac 42 d2 45 |l.!'..a..c=..B.E| +00000200 b0 63 a5 0f 5a cd 8e 57 a2 44 17 20 51 71 4f d2 |.c..Z..W.D. QqO.| +00000210 51 40 cf 76 85 79 69 fe 0c 11 b8 ba 2b c4 61 97 |Q@.v.yi.....+.a.| +00000220 ee 44 9f 6a a0 2e 72 0b 17 f8 f4 5f 2d 67 c5 34 |.D.j..r...._-g.4| +00000230 9c 71 91 3d 4e ad 2f e6 e9 10 25 9b 12 dc 82 f0 |.q.=N./...%.....| +00000240 74 75 71 6a 3d 47 db 6e e1 0c d9 1f 97 6b c8 95 |tuqj=G.n.....k..| +00000250 8f bb 6a 03 0e 9a cb bf af 81 3b 74 37 d2 00 a0 |..j.......;t7...| +00000260 db fd 7f 5e cd 8b 4b 43 d2 76 77 5b 2b e6 9b 05 |...^..KC.vw[+...| +00000270 c3 95 d4 48 ab 72 cb fe ca f6 ea 2c 46 76 9c 91 |...H.r.....,Fv..| +00000280 5c 23 23 7f f5 5b 05 57 98 d5 7a c1 7e 05 ff 38 |\##..[.W..z.~..8| +00000290 68 55 34 35 6f 4b ed 86 87 85 55 1f d5 c8 a1 e4 |hU45oK....U.....| +000002a0 70 40 5d f1 |p@].| +>>> Flow 13 (server to client) +00000000 00 00 00 10 86 47 fc 3e d3 bb 60 43 60 a7 74 dd |.....G.>..`C`.t.| +00000010 b9 26 8c 0f b9 3f a0 a6 84 d0 76 45 80 f0 43 fd |.&...?....vE..C.| +00000020 85 d3 85 89 f8 4a 4a 8a 14 a8 1d 79 13 78 4e 74 |.....JJ....y.xNt| +00000030 63 dd d2 73 |c..s| +>>> Flow 14 (client to server) +00000000 00 00 00 20 69 ab 1d 32 16 a6 e6 8a ab 6b e7 a8 |... i..2.....k..| +00000010 d6 c4 76 5b a6 70 f1 35 1a ac d3 e2 de 90 72 3f |..v[.p.5......r?| +00000020 d1 7a 12 3c f1 f6 21 73 47 40 d6 a0 2d df 75 27 |.z.<..!sG@..-.u'| +00000030 f0 2c 86 94 27 8d bf c9 8e ff 4b 7b 86 08 c7 95 |.,..'.....K{....| +00000040 10 7c 12 a1 |.|..| +>>> Flow 15 (server to client) +00000000 00 00 00 20 98 06 72 a1 fd cd af e6 6d 35 26 ca |... ..r.....m5&.| +00000010 26 b6 98 79 7b 6c 61 12 fa 7d 1e ed 26 b9 51 0e |&..y{la..}..&.Q.| +00000020 cf dd ce cd 6a 7d 37 3e 98 78 18 fa 82 a2 c8 92 |....j}7>.x......| +00000030 6a c7 3b dc 76 58 fe c2 eb 5d 11 53 49 20 61 74 |j.;.vX...].SI at| +00000040 32 35 a7 c9 |25..| +>>> Flow 16 (client to server) +00000000 00 00 00 20 b8 88 f7 08 66 9e a6 7d 7d e2 a3 a5 |... ....f..}}...| +00000010 8d e6 75 4c c5 57 71 fa 21 1d c8 15 00 51 05 7a |..uL.Wq.!....Q.z| +00000020 69 c1 6c 6a 7a 4e 2e 15 64 55 45 eb 45 5b 0e 42 |i.ljzN..dUE.E[.B| +00000030 d9 7a 3c da 6c 0e 1b c3 29 e9 02 87 5b 52 3c 24 |.z<.l...)...[R<$| +00000040 a7 c4 1f a3 |....| +>>> Flow 17 (server to client) +00000000 00 00 00 10 31 c2 32 97 35 78 a4 49 e4 34 72 4b |....1.2.5x.I.4rK| +00000010 09 04 f3 d6 9a b0 50 59 81 d4 e8 53 ec d3 2c 25 |......PY...S..,%| +00000020 f2 fe 2a d5 d2 61 9a 4f 16 09 2d 24 84 78 2e fc |..*..a.O..-$.x..| +00000030 27 19 00 10 |'...| +>>> Flow 18 (client to server) +00000000 00 00 00 10 a4 96 22 57 95 c4 71 49 4e 45 bc 15 |......"W..qINE..| +00000010 92 2f f8 33 81 37 bc 01 9a 58 f5 8a 9e eb ee 9a |./.3.7...X......| +00000020 ba 39 d5 bd da c0 dc 7d 31 8a f7 13 6c 81 f8 a2 |.9.....}1...l...| +00000030 fa 37 e4 2a |.7.*| +>>> Flow 19 (server to client) +00000000 00 00 00 20 a6 82 38 26 b3 fa 14 3f fd 12 08 a1 |... ..8&...?....| +00000010 60 0b 53 4d 3e eb be 4d 7f d0 dc 29 00 59 75 d7 |`.SM>..M...).Yu.| +00000020 3b 31 9d 28 ac a5 34 02 ac fe ad ac f2 de 13 49 |;1.(..4........I| +00000030 00 9e 5b 96 d1 12 8d 0f 7a a5 55 fe 5c ad 11 5c |..[.....z.U.\..\| +00000040 74 b1 cd 00 00 00 00 10 71 b8 a1 a1 33 53 62 37 |t.......q...3Sb7| +00000050 08 72 fb 75 50 d2 04 c7 2d 8f 42 12 fc 3f ef 69 |.r.uP...-.B..?.i| +00000060 d5 f2 16 12 72 38 cb 33 d2 69 8c 13 5a a9 2e ae |....r8.3.i..Z...| +00000070 0c 1d 59 b0 4f ff 0b f3 |..Y.O...| +>>> Flow 20 (client to server) +00000000 00 00 00 10 17 06 5c c4 29 66 5b 83 51 db a0 c3 |......\.)f[.Q...| +00000010 97 cd ea a5 8c bb a7 bf 3d 34 5a 94 6b 50 6e a9 |........=4Z.kPn.| +00000020 10 27 cf 8c 62 a6 49 93 a3 b4 03 6d cb f3 df 9b |.'..b.I....m....| +00000030 31 4a 70 cb 00 00 00 30 72 a8 ea c6 79 50 d7 de |1Jp....0r...yP..| +00000040 8f 95 de 61 b0 68 56 d2 66 d2 70 1f 6a 95 d0 29 |...a.hV.f.p.j..)| +00000050 db 21 e3 1e c4 75 59 d6 55 8a f7 a0 51 96 26 3b |.!...uY.U...Q.&;| +00000060 1e 61 17 bd 52 7b 66 9c 40 1a 97 2f d7 9d 3f d9 |.a..R{f.@../..?.| +00000070 59 4e a9 24 26 ba 0d 08 7e d8 1a 11 73 c4 bf 69 |YN.$&...~...s..i| +00000080 48 e1 f2 cc 48 fa 1a 65 |H...H..e| diff --git a/ssh/testdata/Server-Cipher-aes256-ctr b/ssh/testdata/Server-Cipher-aes256-ctr new file mode 100644 index 0000000000..4202e79ff2 --- /dev/null +++ b/ssh/testdata/Server-Cipher-aes256-ctr @@ -0,0 +1,371 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 0a 61 65 73 32 35 36 2d 63 74 72 00 00 00 0a 61 |.aes256-ctr....a| +00000110 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 |es256-ctr...nhma| +00000120 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +00000130 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000140 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +00000150 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000160 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000170 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +00000180 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 |mac-sha1-96...nh| +00000190 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +000001a0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +000001b0 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +000001c0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +000001d0 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +000001e0 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +000001f0 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000200 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000210 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 3f 3d e1 b4 ea 68 64 36 7a e7 |...<..?=...hd6z.| +00000010 1c fb bd 83 b8 35 00 00 01 7a 73 6e 74 72 75 70 |.....5...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 08 9b 92 b0 ed db |...,..... ......| +00000650 12 86 80 ac b7 df 9c 11 5b 6e 18 80 8b 63 ed 1e |........[n...c..| +00000660 8f b8 7b b5 71 8d a8 69 eb 44 00 00 00 00 00 00 |..{.q..i.D......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 ee a0 9c c6 be 90 37 5d 28 ba ea |.... ......7](..| +00000130 a8 41 a5 72 c8 5e 4d 2d 23 c4 f9 26 88 44 60 fc |.A.r.^M-#..&.D`.| +00000140 30 d9 da 91 6a 00 00 01 14 00 00 00 0c 72 73 61 |0...j........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 5b 16 ee |-sha2-512....[..| +00000160 f2 6a 63 b8 f3 10 3c a5 d8 ab 1f 72 b5 50 67 42 |.jc...<....r.PgB| +00000170 d5 d8 02 b1 5b 7e 66 a0 1a 34 0f 8d a9 44 8a 36 |....[~f..4...D.6| +00000180 ce d5 f2 fc 48 18 dd 37 67 68 03 47 b8 14 7e 7f |....H..7gh.G..~.| +00000190 11 b8 e4 08 f5 c7 9b 28 25 2b 15 e3 89 ea e8 b3 |.......(%+......| +000001a0 a8 69 e1 f5 78 3e f1 57 bc e9 f5 92 5e 3d fc 76 |.i..x>.W....^=.v| +000001b0 d9 cc b7 9c 4e 42 c1 9a b3 bd d7 72 4b e1 79 02 |....NB.....rK.y.| +000001c0 60 01 18 0d f0 91 af 48 7a dd 07 89 15 12 e1 6d |`......Hz......m| +000001d0 e2 fe 6c 1b 42 20 29 cd 4d 61 b0 5a 04 8f c1 cd |..l.B ).Ma.Z....| +000001e0 a0 0b 37 2f 3f 7d ff 31 37 37 78 37 37 57 b1 7f |..7/?}.177x77W..| +000001f0 60 d0 ef 3f 0a 48 70 d7 73 b0 c9 a7 f7 62 6c 71 |`..?.Hp.s....blq| +00000200 28 d6 9d 12 56 78 54 44 59 59 04 b4 33 b3 19 ca |(...VxTDYY..3...| +00000210 05 51 21 3d da 5a 03 e3 ad d8 8d 53 d0 2f 15 02 |.Q!=.Z.....S./..| +00000220 3a b2 28 5f ab 3f 18 74 58 40 1d 4b 85 60 a1 f6 |:.(_.?.tX@.K.`..| +00000230 66 49 52 2b cd 45 2f 98 1d 53 47 73 9b 86 5b df |fIR+.E/..SGs..[.| +00000240 7c 7b 0d ff 5c 26 ab 72 27 7f 8d f1 e7 a6 58 a8 ||{..\&.r'.....X.| +00000250 f3 37 cd 92 96 e4 39 6d db f1 18 d8 71 a3 63 9c |.7....9m....q.c.| +00000260 a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc 62 b8 |.....W.5...<#.b.| +00000270 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000280 00 00 00 f0 ac be 8b d3 c1 a0 f3 d9 4a d7 3f fc |............J.?.| +00000290 bf df ea 53 4d 92 a9 97 d4 ce 6f 25 11 8b 1a 1b |...SM.....o%....| +000002a0 15 ae 59 07 f6 71 41 fc fe 70 39 47 7c d1 bb ff |..Y..qA..p9G|...| +000002b0 77 ff c2 31 9d f8 56 b1 6b 72 ff d4 e9 b0 8e ec |w..1..V.kr......| +000002c0 12 6d 66 ae 84 3c 0f 5f 22 14 d5 89 91 87 e3 b1 |.mf..<._".......| +000002d0 10 a8 33 b4 fe 6c 32 48 b6 16 b3 2c 64 0f 66 b9 |..3..l2H...,d.f.| +000002e0 ed 03 03 a9 f5 d6 1c 71 96 79 d0 59 0a 6e bc f5 |.......q.y.Y.n..| +000002f0 22 cb 99 3d 1f b9 0b 32 e4 88 8b 08 e7 14 81 b2 |"..=...2........| +00000300 3a 62 d3 fa dd 1d 52 4d 2b 51 2f f8 b6 b8 9c 92 |:b....RM+Q/.....| +00000310 a2 11 94 d6 07 88 3b b1 40 b1 21 c4 03 0b 29 8a |......;.@.!...).| +00000320 8a a1 58 db 66 30 0a 8b 64 5d 38 c0 90 14 58 53 |..X.f0..d]8...XS| +00000330 f4 9b 33 c3 30 61 d9 3a 32 7a 54 93 87 30 a5 b4 |..3.0a.:2zT..0..| +00000340 31 d6 29 5f 99 24 bc 14 e2 94 14 d9 fb dc c3 15 |1.)_.$..........| +00000350 9a b6 38 ed 32 14 2f 62 f0 06 75 b4 2f 61 78 c6 |..8.2./b..u./ax.| +00000360 71 9d 79 25 66 01 b1 89 db fe 96 5f a4 4f a9 be |q.y%f......_.O..| +00000370 d4 a2 9c a3 7a ec 89 a5 bb 13 ee 34 96 c3 1f 31 |....z......4...1| +00000380 af e4 0c 37 47 47 23 76 13 c4 0a 49 c3 91 55 0b |...7GG#v...I..U.| +00000390 f6 e3 1d da |....| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 00 00 00 20 31 2a f4 5b 79 8d 08 ac 21 91 05 b4 |... 1*.[y...!...| +00000020 7f d0 8f a2 70 ab 7b c0 a0 6a 87 d4 56 fd 51 41 |....p.{..j..V.QA| +00000030 dd b9 08 18 ec 20 67 fc 40 8e 2c 11 ab 4e ae 1f |..... g.@.,..N..| +00000040 11 c1 52 7e a8 58 b9 be 9a 2a 44 85 67 73 6e 08 |..R~.X...*D.gsn.| +00000050 3a 8d f7 4d |:..M| +>>> Flow 7 (server to client) +00000000 00 00 00 20 82 c5 c8 4a 7b 62 8a 09 44 54 ea 06 |... ...J{b..DT..| +00000010 a3 8e 2a 89 39 ca 24 5b 4d c9 23 93 20 23 8c 5d |..*.9.$[M.#. #.]| +00000020 7c a6 ad 7f 6e 3a f4 8f 69 21 22 50 7b 1e fc c3 ||...n:..i!"P{...| +00000030 8c 3a ba 52 5b 41 49 0c 54 55 10 d4 3d 7b fb c6 |.:.R[AI.TU..={..| +00000040 1d 2e 56 3a |..V:| +>>> Flow 8 (client to server) +00000000 00 00 00 30 e7 fb eb e5 2b 1c 55 ec 00 c9 a8 59 |...0....+.U....Y| +00000010 f9 84 53 72 fa 15 70 ba 70 10 59 eb 0e 67 30 e9 |..Sr..p.p.Y..g0.| +00000020 5d 60 36 52 59 66 f6 f5 fe 93 f3 a8 10 2d 20 10 |]`6RYf.......- .| +00000030 93 cb 96 f1 00 39 28 cf c4 13 a9 3a c2 cf d0 53 |.....9(....:...S| +00000040 24 cf e4 1f 0c 0d 12 5a 29 22 d1 55 64 aa c8 57 |$......Z)".Ud..W| +00000050 a6 d7 87 ec |....| +>>> Flow 9 (server to client) +00000000 00 00 00 20 83 45 64 7f a1 2c 57 5a 0c ce 1c 14 |... .Ed..,WZ....| +00000010 92 10 96 b8 e1 2c df 67 32 4d 55 84 b9 40 04 5e |.....,.g2MU..@.^| +00000020 07 1d 7d 49 2d 99 08 20 1a a0 0b 59 28 e6 b4 d0 |..}I-.. ...Y(...| +00000030 e1 1f 11 eb 07 d1 bc ca f1 de 6c d6 da e2 6a 1c |..........l...j.| +00000040 64 8e f3 9a |d...| +>>> Flow 10 (client to server) +00000000 00 00 01 60 ba 25 a1 ab 17 3d 46 64 77 28 de 3d |...`.%...=Fdw(.=| +00000010 c8 5d 85 30 ef e7 72 bd 67 fb d5 17 18 80 de 91 |.].0..r.g.......| +00000020 f0 61 66 3c af 67 39 d5 ef c2 e0 47 eb 1f a3 7c |.af<.g9....G...|| +00000030 3b 29 c2 e7 1c 48 6f 9a 3c 35 0a fc cc 8b 02 ed |;)...Ho.<5......| +00000040 ac 18 83 de 54 2b 6a 4b b8 c0 d4 f1 5a 98 52 85 |....T+jK....Z.R.| +00000050 1f 54 6d 76 2c 36 8a b9 f8 a6 cf 4b 25 05 d5 52 |.Tmv,6.....K%..R| +00000060 50 bd 34 cf ac de a3 39 91 ba 63 8a df 98 a0 9d |P.4....9..c.....| +00000070 ac 56 9a 06 a0 c5 cb 97 31 7a eb 6c f8 21 ff d9 |.V......1z.l.!..| +00000080 79 83 6f c8 74 c6 7f ae d9 23 80 d9 db 96 f7 d1 |y.o.t....#......| +00000090 a6 ec a5 aa 81 9b ac 75 02 9d 2e 71 f4 05 8c e2 |.......u...q....| +000000a0 37 18 51 48 c5 07 91 12 f9 17 87 64 64 1e 3f e9 |7.QH.......dd.?.| +000000b0 24 c6 8b 6d 90 55 5e 09 cb f3 69 ba a5 a1 56 85 |$..m.U^...i...V.| +000000c0 3f 72 b0 9c f2 39 b0 11 06 4b 2e bf e2 62 ea 91 |?r...9...K...b..| +000000d0 d4 40 8b e4 4d b4 7b 81 a7 71 3d f5 06 84 a5 07 |.@..M.{..q=.....| +000000e0 77 43 94 cb ec 7f 89 52 56 0a b7 32 66 54 2e cc |wC.....RV..2fT..| +000000f0 55 8d 2b f9 1b bc ea 9a 22 f5 0a dc 69 19 ad 3c |U.+....."...i..<| +00000100 f1 b4 98 06 99 03 67 af 1d ba 23 87 9c 67 76 c9 |......g...#..gv.| +00000110 b3 5b 9e 65 70 43 40 cf 5c 9a 83 83 33 01 c4 50 |.[.epC@.\...3..P| +00000120 4d 7d e5 36 b4 7b 05 a2 ef 1c 76 c1 10 e3 06 25 |M}.6.{....v....%| +00000130 05 b9 e9 45 69 b0 8f e8 f6 4a 40 62 14 42 8c 8a |...Ei....J@b.B..| +00000140 8d ba 20 5f 29 c5 c4 ec 90 bd f3 9c 63 ee 53 b1 |.. _).......c.S.| +00000150 b9 0e 17 f3 cf fc aa 55 99 19 9e 3f 9d df 35 13 |.......U...?..5.| +00000160 04 64 b2 13 9a e1 29 5d c7 05 02 91 31 07 34 15 |.d....)]....1.4.| +00000170 dc 25 9a 72 81 f7 3e 20 7f a0 74 78 c7 10 a1 37 |.%.r..> ..tx...7| +00000180 2b 7e 08 e8 |+~..| +>>> Flow 11 (server to client) +00000000 00 00 01 40 68 bd 13 45 a6 c4 37 46 00 c6 5b 8b |...@h..E..7F..[.| +00000010 0f 83 93 4b 57 2b 5b 3b 90 15 4a ff a0 eb 9c 3e |...KW+[;..J....>| +00000020 1b 78 af 36 4a 8c 25 75 5b 86 e3 a4 b3 a9 16 b5 |.x.6J.%u[.......| +00000030 f5 b3 a6 fe d8 5f 9d fd 07 10 16 50 51 ea 74 a3 |....._.....PQ.t.| +00000040 14 69 67 7d bc c6 cd c9 87 c4 a8 c0 85 2d 96 cd |.ig}.........-..| +00000050 6e 73 58 bc 90 13 63 60 96 69 c0 f8 18 dc c8 7f |nsX...c`.i......| +00000060 87 19 89 00 b4 19 56 6b 20 a4 c6 28 f2 1b db 06 |......Vk ..(....| +00000070 af 80 73 4f 7d 9b 2f 8f c7 5f 66 07 ed b8 43 d2 |..sO}./.._f...C.| +00000080 0e 05 47 5a 9e 84 83 a8 2b 41 a2 33 28 f2 0f b3 |..GZ....+A.3(...| +00000090 65 4c 98 1a 67 02 72 3f d2 c4 41 7f 96 6a b6 b0 |eL..g.r?..A..j..| +000000a0 1b ec c6 c7 18 42 41 a7 71 25 56 bc 6b 19 17 b2 |.....BA.q%V.k...| +000000b0 66 96 47 bf 60 68 b1 e0 7f ec e5 2d 85 e5 c7 e5 |f.G.`h.....-....| +000000c0 f5 18 42 7b dc d9 76 cc d1 68 37 13 1f ec b2 ad |..B{..v..h7.....| +000000d0 e9 43 d4 cf e1 6e 7c 52 fd 69 59 14 27 6c c7 41 |.C...n|R.iY.'l.A| +000000e0 2e fe ab 28 c9 6a 2e 80 9c a4 f3 a5 34 ab be 10 |...(.j......4...| +000000f0 f5 5d 5d 29 40 4a 33 68 6b 8a af 36 17 56 4c dc |.]])@J3hk..6.VL.| +00000100 22 27 df fd 77 6d 90 ed ff 44 d6 b6 ff a9 21 b7 |"'..wm...D....!.| +00000110 19 c6 d4 ac b2 23 17 2c 90 cd 89 c7 d8 25 d6 63 |.....#.,.....%.c| +00000120 59 40 ae b3 cc 26 d5 48 79 8d b0 4b a7 16 39 c2 |Y@...&.Hy..K..9.| +00000130 73 75 5b 06 cc 2d 2d c7 b0 aa ff 0c 18 ae f4 a8 |su[..--.........| +00000140 7b 6f 56 35 91 53 82 99 62 09 76 fa ba 37 6c be |{oV5.S..b.v..7l.| +00000150 81 da 49 8f 6c 84 71 df 2c ba d4 f2 b1 82 05 06 |..I.l.q.,.......| +00000160 76 37 f9 2e |v7..| +>>> Flow 12 (client to server) +00000000 00 00 02 80 a3 29 0b bc c9 13 ee c5 5c 02 fb a5 |.....)......\...| +00000010 5a 36 b8 69 bd 41 f3 26 0c dd 6f 17 2d 3c 2f 67 |Z6.i.A.&..o.-...NPr....Z.| +00000030 e8 0d 32 6f 2a 4e b4 0b d6 b5 6a 8f 8b 7f fe 1b |..2o*N....j.....| +00000040 b1 e7 bf 59 50 76 b2 99 65 49 45 54 37 e1 33 42 |...YPv..eIET7.3B| +00000050 38 94 7b 9c b0 48 63 1e ce 06 7e 8e 1f c9 4c cb |8.{..Hc...~...L.| +00000060 11 4a 36 85 34 95 d7 f7 69 ee bc 65 97 ea ef 12 |.J6.4...i..e....| +00000070 04 97 33 d2 98 68 bc 3d 4b 02 fe f2 68 50 ce 62 |..3..h.=K...hP.b| +00000080 88 08 c3 7d 07 34 be e2 2e 40 83 f8 bc 91 d8 1b |...}.4...@......| +00000090 75 25 25 42 a3 fd 2a ce 96 8a 55 ce b1 eb 60 30 |u%%B..*...U...`0| +000000a0 6f 19 d7 86 40 90 c0 2d ee 94 4e 96 11 14 de c5 |o...@..-..N.....| +000000b0 1b 07 28 6a 4b 5b 26 bc a9 28 a2 43 f7 a4 0e 9c |..(jK[&..(.C....| +000000c0 74 c3 9c 8e 3e d8 4e ad 9c 5d e1 ba 1b d6 ea b0 |t...>.N..]......| +000000d0 07 d8 45 4f 6e 64 2f f3 ce 3d 8d 08 7b 6a 5f d7 |..EOnd/..=..{j_.| +000000e0 f1 5d e1 19 3d 1a 9e da e4 3f 3c 5e 7f 54 a8 3f |.]..=....?<^.T.?| +000000f0 de ed 0c 6d ea 9e ec 44 d8 cf 2d c1 3e 71 bb 5c |...m...D..-.>q.\| +00000100 4d 63 3b 47 e6 c2 bb cb 8b c2 53 0d 6e 31 61 b9 |Mc;G......S.n1a.| +00000110 77 58 64 40 d6 67 95 7f 70 ae 92 e0 a2 3a 8f 4c |wXd@.g..p....:.L| +00000120 9a ff e8 29 ea b2 cb a5 3b cb 3b d9 95 4d e9 44 |...)....;.;..M.D| +00000130 80 83 e7 78 40 d6 08 59 2a b8 39 d2 1e e0 90 64 |...x@..Y*.9....d| +00000140 db a4 b2 2a 3a cd d3 5a 65 af 80 94 4e 82 b3 42 |...*:..Ze...N..B| +00000150 27 f1 e8 b9 5c 9e 09 d6 f7 fd 16 db a8 bc a4 28 |'...\..........(| +00000160 c7 d8 23 31 bc 35 41 f9 03 91 1d fd 38 0b 78 0f |..#1.5A.....8.x.| +00000170 77 d3 e1 63 54 c0 9a 0f 62 4c ef 40 11 50 55 bc |w..cT...bL.@.PU.| +00000180 5d 99 ab b5 6c 75 d4 aa 0f 47 97 51 15 10 8a c2 |]...lu...G.Q....| +00000190 8a c3 96 72 1f 37 2b b0 a0 b5 0c 6a 8f 2e 91 14 |...r.7+....j....| +000001a0 64 6d 35 ca 3c d0 11 aa e2 d5 10 c3 f4 8e 04 98 |dm5.<...........| +000001b0 97 1d cc e9 c4 a2 b5 b0 f8 eb 34 12 1b 18 9a 97 |..........4.....| +000001c0 0f e8 fb 1a 26 08 8a b4 c2 82 08 f6 85 8f d6 45 |....&..........E| +000001d0 29 bb 96 45 b0 e9 ac 83 e4 18 56 d5 2a 75 09 22 |)..E......V.*u."| +000001e0 5e 31 ce af e3 09 13 c7 4f 23 1a e7 28 2a 74 10 |^1......O#..(*t.| +000001f0 05 e1 e3 ff 6a 3a 63 e0 6d 1e c0 ce 59 68 74 ae |....j:c.m...Yht.| +00000200 24 9b fb 79 c6 f7 6a 87 2c 39 46 4c 1b 4c c3 30 |$..y..j.,9FL.L.0| +00000210 66 b9 ad f5 6c 54 5b f3 e4 fa 23 26 16 b4 39 a6 |f...lT[...#&..9.| +00000220 95 4e b3 f6 bf 82 21 2e 3d 92 47 b6 6a 5d b2 1b |.N....!.=.G.j]..| +00000230 35 1d 6a 37 e7 54 88 a8 dc 37 45 a8 46 0a 43 15 |5.j7.T...7E.F.C.| +00000240 31 e4 d2 2d f3 22 c7 d6 fc d5 c4 f8 f6 b5 eb 7c |1..-.".........|| +00000250 17 11 54 24 c6 d9 04 63 a5 c2 6a a3 93 18 a3 cc |..T$...c..j.....| +00000260 d8 a9 82 9b 08 2b 14 a1 53 12 49 11 c1 f0 90 cc |.....+..S.I.....| +00000270 f1 e8 02 ca b2 98 01 93 37 cc 35 27 81 99 c5 f8 |........7.5'....| +00000280 28 cf d4 35 15 9f 4c a9 88 d5 eb 64 49 11 a5 5a |(..5..L....dI..Z| +00000290 28 0a 0f e6 32 92 07 24 c9 10 a5 d2 8d 74 9b 11 |(...2..$.....t..| +000002a0 31 b7 0b 61 |1..a| +>>> Flow 13 (server to client) +00000000 00 00 00 10 bb dd 8a 5c 74 eb 33 c9 6b 2a 3c 72 |.......\t.3.k*>> Flow 14 (client to server) +00000000 00 00 00 20 4e d8 ad 7d 89 64 c1 a2 8e 59 6a 5d |... N..}.d...Yj]| +00000010 82 be e0 e8 39 98 d6 6d ea 1f 97 a7 34 13 0f 6a |....9..m....4..j| +00000020 41 1c c6 32 03 31 b3 42 83 37 0b af 44 ab 67 e4 |A..2.1.B.7..D.g.| +00000030 9c 8f ea c0 ab 57 d1 aa 2a d1 33 ce b0 2b 4e 5f |.....W..*.3..+N_| +00000040 ce 33 46 ab |.3F.| +>>> Flow 15 (server to client) +00000000 00 00 00 20 8d 83 1c 71 38 f6 c1 94 d8 1b d3 7d |... ...q8......}| +00000010 ea fa 78 f2 ba 1b 4c c0 e2 73 85 c9 f1 0d ac 31 |..x...L..s.....1| +00000020 74 5a 48 5a f9 f0 a0 b8 5e 61 8f a7 f8 0f a8 dd |tZHZ....^a......| +00000030 2c 2b 0c 6c 32 28 0c ae 14 4e 3a b6 97 e5 f4 f6 |,+.l2(...N:.....| +00000040 48 26 e6 7e |H&.~| +>>> Flow 16 (client to server) +00000000 00 00 00 20 da 69 73 19 70 6f a2 89 3f af 6e bf |... .is.po..?.n.| +00000010 2b 22 ea ff c6 70 1f fe b5 cf 4f ef df 8c f2 9e |+"...p....O.....| +00000020 2f 15 81 0b e5 a2 33 fb 30 1b 14 9a 33 33 29 5d |/.....3.0...33)]| +00000030 5d 92 ba d0 d4 0d 21 a3 95 ca 3d 47 ed 1a 1f 16 |].....!...=G....| +00000040 09 f3 28 66 00 00 00 10 1f 45 34 0b f8 ee 2d 15 |..(f.....E4...-.| +00000050 df f7 7b 28 7b ec f5 13 21 b3 b8 c4 35 c6 03 d4 |..{({...!...5...| +00000060 82 cc 9e 9e 52 aa fd f1 5d 27 21 c1 cd 57 69 2c |....R...]'!..Wi,| +00000070 39 2e 4d d7 dc 83 3d c6 |9.M...=.| +>>> Flow 17 (server to client) +00000000 00 00 00 10 2c df 91 e7 7b 63 5d ac 7c e5 46 91 |....,...{c].|.F.| +00000010 a7 ce 87 2f 2b cf a2 b5 bc 05 6c 59 e1 75 11 71 |.../+.....lY.u.q| +00000020 4e 26 b8 84 9d cf c8 74 b3 7e 2d 1d 66 cc 23 2a |N&.....t.~-.f.#*| +00000030 fb 5b e9 60 00 00 00 20 92 61 11 5e 4f bb 93 e6 |.[.`... .a.^O...| +00000040 e7 bd fc 0b ff 87 47 a9 45 2b f1 77 4b 47 6e f7 |......G.E+.wKGn.| +00000050 da eb 68 54 48 c0 eb 76 12 ac 32 21 c5 57 ba 49 |..hTH..v..2!.W.I| +00000060 56 a4 eb ca c0 88 5b 84 3e 16 f4 d8 b4 80 05 c0 |V.....[.>.......| +00000070 f8 81 72 76 d7 47 9e eb 00 00 00 10 1c 61 a8 26 |..rv.G.......a.&| +00000080 a3 c9 20 70 3e e1 b2 97 0c 6f 58 dc 6f 81 29 20 |.. p>....oX.o.) | +00000090 2e fb 4c 24 0c ee 56 1f 7f 8d 55 e7 9b 98 db 95 |..L$..V...U.....| +000000a0 e6 88 32 05 56 1c dd cc ff f6 ac bc |..2.V.......| +>>> Flow 18 (client to server) +00000000 00 00 00 10 3c 66 4b ba 52 73 8b fb af e8 dd 79 |....>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 3c 0e 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...<....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 16 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |.aes256-gcm@open| +00000110 73 73 68 2e 63 6f 6d 00 00 00 16 61 65 73 32 35 |ssh.com....aes25| +00000120 36 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |6-gcm@openssh.co| +00000130 6d 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 |m...nhmac-sha2-2| +00000140 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000150 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000160 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000170 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 |,hmac-sha2-256,h| +00000180 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 |mac-sha2-512,hma| +00000190 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 |c-sha1,hmac-sha1| +000001a0 2d 39 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 |-96...nhmac-sha2| +000001b0 2d 32 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-256-etm@openssh| +000001c0 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 |.com,hmac-sha2-5| +000001d0 31 32 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |12-etm@openssh.c| +000001e0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |om,hmac-sha2-256| +000001f0 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 |,hmac-sha2-512,h| +00000200 6d 61 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 |mac-sha1,hmac-sh| +00000210 61 31 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 |a1-96....none...| +00000220 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 00 00 |.none...........| +00000230 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 |...;........n..f| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 a5 fe 68 21 8d e6 f2 5c 52 3e |...<....h!...\R>| +00000010 79 b3 39 f7 30 7d 00 00 01 7a 73 6e 74 72 75 70 |y.9.0}...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 06 57 cc 45 ea cf |...,..... .W.E..| +00000650 b6 da 72 ef 60 bd f7 69 ce 6d b8 1e db 3e 9d ea |..r.`..i.m...>..| +00000660 9c 50 04 69 43 2e fd 4f 86 19 00 00 00 00 00 00 |.P.iC..O........| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 0b 12 16 5d 67 97 a1 dd 1f e5 8c |.... ...]g......| +00000130 fb 78 16 1d 9d 8a 50 df 95 18 37 e8 3f 4d 70 3e |.x....P...7.?Mp>| +00000140 14 6b 29 29 02 00 00 01 14 00 00 00 0c 72 73 61 |.k)).........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 8d b6 e4 |-sha2-512.......| +00000160 8e 4f b7 8c 46 1f 0c d0 65 a5 de 3b 9f 87 d9 9c |.O..F...e..;....| +00000170 51 bf eb d6 a5 b0 f6 2a 62 a9 98 f0 57 68 2c ee |Q......*b...Wh,.| +00000180 7c c9 89 1e 8b 98 52 db 81 28 1e 8d 2a 04 10 a8 ||.....R..(..*...| +00000190 87 9a 8e 76 10 18 dc bc f2 6e 73 73 96 aa 4e ee |...v.....nss..N.| +000001a0 04 44 db c2 f8 80 9a 75 13 fe 83 63 e4 8c 61 23 |.D.....u...c..a#| +000001b0 d4 8e 84 75 c2 2d 40 29 14 06 1f 93 08 0a 32 99 |...u.-@)......2.| +000001c0 85 1e d7 c7 8c 05 52 42 cd 6b f6 8c 4f 22 49 08 |......RB.k..O"I.| +000001d0 5b 6e c4 5d a7 b1 82 ba 34 d1 8a a6 4c 09 ab 82 |[n.]....4...L...| +000001e0 97 72 c9 43 fe a9 b2 43 66 c9 e5 9f 4e ee 5b 4c |.r.C...Cf...N.[L| +000001f0 1e 0f 36 12 8d e8 de e2 ba 9a 17 04 a2 10 15 86 |..6.............| +00000200 73 d5 6d 1c 31 98 65 26 2c f5 f8 77 ae bc 4a 29 |s.m.1.e&,..w..J)| +00000210 68 a7 bc 87 ef b7 ff c6 03 06 c9 64 1d 8c 6f ed |h..........d..o.| +00000220 31 e1 6f bf 2e f6 de ba 9f 5e c2 56 db 9e 41 3d |1.o......^.V..A=| +00000230 4a e7 f9 48 32 a3 85 6b 4b 53 14 dd 6d 78 e2 93 |J..H2..kKS..mx..| +00000240 7d ec 81 20 40 cd 81 c9 85 56 53 ff eb b9 d9 d8 |}.. @....VS.....| +00000250 41 fd 9b a6 99 d4 de 5c f9 8d 56 4e 66 57 e2 35 |A......\..VNfW.5| +00000260 b8 cc 87 3c 23 dc 62 b8 d2 60 16 9a fa 2f 75 ab |...<#.b..`.../u.| +00000270 00 00 00 0c 0a 15 91 6a 58 d9 74 91 88 35 d2 5e |.......jX.t..5.^| +00000280 00 00 00 f0 e5 69 42 d5 80 d3 a7 be ed 63 0b d9 |.....iB......c..| +00000290 e5 9c 0d d5 f0 ba 6e 7f 04 91 a2 eb 90 80 57 29 |......n.......W)| +000002a0 6d 58 20 24 f2 b3 59 23 df 1e 6b f6 26 7a 88 77 |mX $..Y#..k.&z.w| +000002b0 fa d6 25 39 76 1a 78 59 72 66 c5 3b 77 f0 f6 6a |..%9v.xYrf.;w..j| +000002c0 5d 67 39 45 71 2d d0 0d 0b b5 cd dc d5 e1 f0 e8 |]g9Eq-..........| +000002d0 d0 cc 68 99 3c 9f eb 8b 2d c3 d0 1c 25 4a 83 b8 |..h.<...-...%J..| +000002e0 98 ae 6b 08 a0 83 a2 81 48 b1 97 a8 eb 9e a4 be |..k.....H.......| +000002f0 e5 8d fb 81 09 0c 1e c7 6e df 6c 25 8e f3 c6 e8 |........n.l%....| +00000300 34 de 91 94 d6 dd 5f 38 ea 6c 07 43 c4 6b d2 bf |4....._8.l.C.k..| +00000310 76 9f a5 dd 68 e7 27 00 fd 5d c7 13 4e 31 6b fd |v...h.'..]..N1k.| +00000320 dd 75 4e 6f 63 5a 97 fd b7 d0 fa 0b ba af 3f 22 |.uNocZ........?"| +00000330 b2 b2 7e a2 a0 0b 67 a8 63 eb 56 cb 28 21 b6 d1 |..~...g.c.V.(!..| +00000340 f3 46 03 37 8e 01 8f 16 8e ab ba a8 29 90 33 d8 |.F.7........).3.| +00000350 4e 08 1f 0c 14 17 81 18 0b b6 14 10 dd b1 f7 30 |N..............0| +00000360 bc a7 67 d1 4b dd e1 a9 8c fb 93 23 d1 a9 a8 37 |..g.K......#...7| +00000370 38 19 39 41 96 5a 2d 47 f4 29 d5 18 47 0c a6 b8 |8.9A.Z-G.)..G...| +00000380 61 6c d7 36 |al.6| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 00 00 00 20 ad 9d 36 a4 0f 00 79 55 07 5c 16 4f |... ..6...yU.\.O| +00000020 d1 81 81 ef 9e 9c ca 24 14 95 60 37 50 cc ea 6d |.......$..`7P..m| +00000030 21 97 57 9d db cb e7 b1 62 2e 3b 11 af 12 d1 54 |!.W.....b.;....T| +00000040 39 0a 65 4a |9.eJ| +>>> Flow 7 (server to client) +00000000 00 00 00 20 14 7b bb ce 69 cc 73 ac 84 a0 33 d9 |... .{..i.s...3.| +00000010 54 a5 97 be c9 ae 7f 8b e1 93 89 67 5b d0 44 71 |T..........g[.Dq| +00000020 e7 25 eb ac e3 a3 99 e3 47 df 21 f0 cf 2a 43 0f |.%......G.!..*C.| +00000030 22 a9 74 7d |".t}| +>>> Flow 8 (client to server) +00000000 00 00 00 30 db bd 32 16 97 cc 1c 49 eb fe be 0c |...0..2....I....| +00000010 1c 1c a8 33 ef 47 3b b1 ed 1d 9c 39 cc 7a 0b c0 |...3.G;....9.z..| +00000020 fb b0 06 1e 6f 4a 19 98 df bb eb 91 c7 ce fd e3 |....oJ..........| +00000030 fb 48 28 6c b6 ee a3 24 bb 28 b9 14 6c a1 52 ef |.H(l...$.(..l.R.| +00000040 e6 b6 6b 26 |..k&| +>>> Flow 9 (server to client) +00000000 00 00 00 20 7c de 98 fb 91 0d 28 d1 67 12 34 60 |... |.....(.g.4`| +00000010 be 73 e2 c0 7c 4b 4c ff 28 05 91 f0 3a eb b6 99 |.s..|KL.(...:...| +00000020 66 e4 1c 06 13 fb e3 03 b0 1d 45 54 5d 28 8b 76 |f.........ET](.v| +00000030 10 2a 50 d7 |.*P.| +>>> Flow 10 (client to server) +00000000 00 00 01 60 2c ae cd 7c 1d 1c 07 bb 28 65 d1 d9 |...`,..|....(e..| +00000010 92 07 12 d7 19 48 d3 e3 7f 02 02 ef 4b 6f 8f 68 |.....H......Ko.h| +00000020 1c e1 fd 76 04 90 8c 8a e9 14 d7 60 50 45 fe 70 |...v.......`PE.p| +00000030 7d c4 2a 80 0d 01 f1 ae 25 55 20 2b 53 c0 fa 1c |}.*.....%U +S...| +00000040 b9 a4 c1 9f 67 b3 98 12 6e 4d e0 bf 68 9c ed 09 |....g...nM..h...| +00000050 c3 10 fa 33 36 85 82 a2 ea 45 89 77 bb 07 a1 39 |...36....E.w...9| +00000060 79 81 12 47 71 90 71 f2 51 cf 7e 66 76 7c fd b0 |y..Gq.q.Q.~fv|..| +00000070 e1 33 16 99 37 89 56 e7 e6 a0 43 46 d9 7f 08 f9 |.3..7.V...CF....| +00000080 e2 fb 91 11 ec 2f eb 02 d6 93 c6 67 fe ae 3e 6e |...../.....g..>n| +00000090 48 12 a3 ed f9 45 29 35 00 f5 43 09 9e 8f a5 a2 |H....E)5..C.....| +000000a0 ae 13 41 99 f9 49 e2 cf 5d 00 48 a8 ea de 12 a2 |..A..I..].H.....| +000000b0 0d 15 e6 e3 34 ec ee e5 a8 22 a6 01 5e e9 9c dc |....4...."..^...| +000000c0 7e 9a 77 8c 6f 37 77 0c 2f 39 2d 10 66 f8 2e 4c |~.w.o7w./9-.f..L| +000000d0 4d e3 8f 98 dd 48 89 5d 2c ed f8 dc 1b 7f 3c 29 |M....H.],.....<)| +000000e0 bf d6 6b b0 06 91 f7 0a 46 34 db 1f ef 75 19 4f |..k.....F4...u.O| +000000f0 e6 a2 4d 27 ca 04 9c 5d 75 e4 6d ae e6 a6 3d e6 |..M'...]u.m...=.| +00000100 37 e2 89 65 08 e6 b4 1d d6 9c 1a e8 b9 e5 e6 05 |7..e............| +00000110 33 31 1e a0 89 9d 2e ab ef 0c 9e 69 70 93 5c 8b |31.........ip.\.| +00000120 f0 e7 41 ca ed 14 2d 71 da 10 43 80 96 5a c7 5d |..A...-q..C..Z.]| +00000130 9f eb 87 bd 41 8b b4 ca ac 6c 9c f6 b3 6f 1a 32 |....A....l...o.2| +00000140 04 f7 ad eb ff 34 1e b5 72 35 5b dd 27 42 44 5f |.....4..r5[.'BD_| +00000150 91 2c 46 36 b4 69 42 26 b9 88 61 e5 1f 36 c8 aa |.,F6.iB&..a..6..| +00000160 42 37 33 e5 41 ca 2b fe 2a a2 98 25 cb 3e fa 45 |B73.A.+.*..%.>.E| +00000170 0c 2c 3b b3 |.,;.| +>>> Flow 11 (server to client) +00000000 00 00 01 40 6b d3 45 0f 8b 21 02 85 75 77 2a fd |...@k.E..!..uw*.| +00000010 57 db fd 77 a2 92 1c 04 5c 64 49 3d 9a b0 be 3f |W..w....\dI=...?| +00000020 42 77 0f 78 74 88 e0 af 77 12 82 22 dc 92 c3 0a |Bw.xt...w.."....| +00000030 df b0 09 35 dd 95 00 74 1d bb 48 73 f1 52 ba 19 |...5...t..Hs.R..| +00000040 fb 22 a4 5d 8b ef 5f 1b e1 81 ca c0 d4 6f 15 b6 |.".].._......o..| +00000050 38 ad f5 43 cd 42 c5 37 74 9a 2d aa 58 80 c2 61 |8..C.B.7t.-.X..a| +00000060 75 ca c5 e3 9f 89 ff 99 de d2 d1 d7 4d a5 d9 24 |u...........M..$| +00000070 0e bd 1f c4 ed 38 2c 1d 69 df f5 b6 9c 67 0c a2 |.....8,.i....g..| +00000080 13 ad 25 f6 1b df 40 fe 4e 99 44 de da 4e 46 60 |..%...@.N.D..NF`| +00000090 dc 3c 2e 39 c2 a9 01 d9 cb 27 11 9f de ef 33 3c |.<.9.....'....3<| +000000a0 30 66 27 03 33 ac 84 d1 71 5b 14 e0 e8 38 35 b0 |0f'.3...q[...85.| +000000b0 dd 06 e9 02 bb c7 3b 38 fb 5e bd 58 a8 19 c3 6c |......;8.^.X...l| +000000c0 21 fc 39 fc 1d 66 b2 09 3c 31 37 97 9f a8 26 8f |!.9..f..<17...&.| +000000d0 50 f5 de 8d 4d e9 93 ea 2e 24 0b 60 51 8a 94 62 |P...M....$.`Q..b| +000000e0 f9 ef 87 62 cd 24 3d 23 4d ec a4 4a 7d f3 d8 c7 |...b.$=#M..J}...| +000000f0 26 ec ba b9 ff 85 38 aa 20 80 36 f1 b9 2f a4 79 |&.....8. .6../.y| +00000100 9a cb fe cb f0 42 71 81 12 9f cc 1d a2 9d a1 68 |.....Bq........h| +00000110 c7 fa 37 d2 21 99 bc 74 0d bf e2 26 83 98 ce 2d |..7.!..t...&...-| +00000120 4a 3a 40 d3 54 50 0d ab 4f dd 5f c7 fa 83 a4 cb |J:@.TP..O._.....| +00000130 21 ed a6 84 c2 76 88 06 10 08 8f c2 22 08 b0 e7 |!....v......"...| +00000140 9d 37 62 b7 8f a1 64 50 ee 31 f9 39 eb 19 61 1e |.7b...dP.1.9..a.| +00000150 bd 7c e9 42 |.|.B| +>>> Flow 12 (client to server) +00000000 00 00 02 80 8a ac aa 9f bd 7e 24 83 9f 22 21 f7 |.........~$.."!.| +00000010 8a e0 9e ab 31 7b 10 a6 b5 4c fa 30 72 f3 d3 f7 |....1{...L.0r...| +00000020 57 a6 d8 4d 06 62 0a ee e6 5d 2a 93 55 7b ca 07 |W..M.b...]*.U{..| +00000030 46 2e 22 87 25 fa bd d1 71 45 53 a6 bf 47 67 51 |F.".%...qES..GgQ| +00000040 8a 2e bb fe 20 fb 16 b5 c2 7a 89 95 25 51 80 81 |.... ....z..%Q..| +00000050 70 34 7a 1a b6 67 04 91 71 34 8c 7d 3d 03 7a 75 |p4z..g..q4.}=.zu| +00000060 46 47 d1 98 7a df 63 27 25 85 5c 60 d8 e5 f3 64 |FG..z.c'%.\`...d| +00000070 f9 8c 10 7c c5 78 d4 78 7e 99 dd 28 50 fe f7 b1 |...|.x.x~..(P...| +00000080 be d6 a8 2f 85 cf 89 8b ba cd 14 91 f5 d8 0b e1 |.../............| +00000090 12 7c 20 e5 a6 40 77 14 7b 84 9d 34 95 ee 46 ec |.| ..@w.{..4..F.| +000000a0 5f a4 34 d5 68 10 5d 9d 14 6e 68 5a 5e ed 07 a7 |_.4.h.]..nhZ^...| +000000b0 e9 f6 f6 a6 0b 66 25 f1 bd 17 ea b0 0f 4b 9b 34 |.....f%......K.4| +000000c0 4d a2 cf b1 8b 3d 3f 62 47 6b cb fb 79 33 af 07 |M....=?bGk..y3..| +000000d0 e5 40 86 49 04 af 93 ee c8 89 62 71 49 ad eb 6b |.@.I......bqI..k| +000000e0 cc d1 93 58 6c e6 a3 2a 63 ce 44 81 4f 04 8d 08 |...Xl..*c.D.O...| +000000f0 93 4f b5 9a ae 6d 61 36 80 30 a7 f3 be eb 0e 75 |.O...ma6.0.....u| +00000100 ba 5a dc ff 64 df ff 31 87 62 ba 7b ee 66 65 24 |.Z..d..1.b.{.fe$| +00000110 47 c9 98 93 1b 58 19 8b a9 3c 22 ec ff 84 0e 80 |G....X...<".....| +00000120 79 e0 8d ee 39 86 8e 34 fe c9 66 dd ca 53 48 d6 |y...9..4..f..SH.| +00000130 5a 82 6d aa 3f 36 14 cb fa 72 b3 4a 26 ed d0 53 |Z.m.?6...r.J&..S| +00000140 78 47 4a 5d 07 6e bf 6a 6e 36 d1 2f 2a aa f1 c3 |xGJ].n.jn6./*...| +00000150 33 03 10 3a 9c 41 a7 68 ee a5 a3 52 da 9d 30 5d |3..:.A.h...R..0]| +00000160 18 f8 45 de e6 4d 65 b4 a5 c3 47 11 22 b3 1d 55 |..E..Me...G."..U| +00000170 aa d5 04 11 b1 2e ca 4a ca 51 aa aa f3 eb 43 55 |.......J.Q....CU| +00000180 1d b7 48 3f 1c ee f5 35 66 c0 4c fa cd 6b f2 8f |..H?...5f.L..k..| +00000190 bd b3 72 51 dc d8 a5 9e e4 44 34 cf 6b cf 2f 77 |..rQ.....D4.k./w| +000001a0 f9 fc 3e 7b 9e 39 9d 49 56 eb 13 8a 81 4d 8c bd |..>{.9.IV....M..| +000001b0 ff 37 74 ed ec 53 e7 5b e6 25 10 8a c5 d5 2e 8a |.7t..S.[.%......| +000001c0 96 9c 91 f2 56 d3 c3 9d 5e 58 ca 54 69 ea e1 e9 |....V...^X.Ti...| +000001d0 75 97 98 dc c8 ee f9 86 87 81 28 f8 38 e4 f5 40 |u.........(.8..@| +000001e0 3b 35 68 7d 65 2f ea 43 80 65 c7 a6 e3 ac ac 54 |;5h}e/.C.e.....T| +000001f0 e0 f2 0a f0 bd 7c bf c5 9a 3d 7d f4 18 05 70 37 |.....|...=}...p7| +00000200 df 9a 7e 6c 12 2a 44 7e 63 cf 28 64 ee 74 d8 79 |..~l.*D~c.(d.t.y| +00000210 46 16 90 ad f9 51 d0 99 f8 b0 af 4f f5 41 5e 32 |F....Q.....O.A^2| +00000220 bb 0b c7 45 be b5 9d e8 8a 8a 7c 2e 4d 65 92 77 |...E......|.Me.w| +00000230 36 42 c7 63 0d e6 7d 62 94 ac 74 14 8f 50 c9 49 |6B.c..}b..t..P.I| +00000240 db 6a 81 30 c9 ca 09 23 00 8a 67 94 13 68 b9 00 |.j.0...#..g..h..| +00000250 0b 86 16 e6 78 4c 4a 5f 24 ab c4 c8 61 53 3e 24 |....xLJ_$...aS>$| +00000260 1e 1d a4 86 ff c7 a2 3d 67 8a 77 74 51 5e d6 b0 |.......=g.wtQ^..| +00000270 f2 eb 91 c8 f4 23 f1 52 98 e2 0b 7a 2b fe 03 5c |.....#.R...z+..\| +00000280 d1 4d 16 90 f6 36 82 83 0e b6 d5 bc c9 8d 7a e7 |.M...6........z.| +00000290 f3 f5 3f 3e |..?>| +>>> Flow 13 (server to client) +00000000 00 00 00 10 84 0f 6a be 07 16 11 46 34 10 54 d3 |......j....F4.T.| +00000010 94 40 d4 c2 d5 c5 79 1b ff 9b b0 56 d8 c4 84 47 |.@....y....V...G| +00000020 07 a0 b1 e8 |....| +>>> Flow 14 (client to server) +00000000 00 00 00 20 92 78 01 4b 86 92 8e 08 da ce 22 d0 |... .x.K......".| +00000010 e0 3c 7f 0b da c3 a7 e2 5a f5 85 92 2d 25 3e 2f |.<......Z...-%>/| +00000020 83 02 f9 54 14 9d 02 ed 59 98 01 8b 50 21 73 17 |...T....Y...P!s.| +00000030 21 61 18 61 |!a.a| +>>> Flow 15 (server to client) +00000000 00 00 00 20 39 ee 58 cc ca f3 be 50 2a 01 a8 da |... 9.X....P*...| +00000010 85 14 c1 bc 73 75 0a 41 8f 37 bd 9f ca e6 5d 13 |....su.A.7....].| +00000020 64 df de 6c f5 6f 53 aa 1b d6 c2 49 41 2a 78 53 |d..l.oS....IA*xS| +00000030 59 42 0b dc |YB..| +>>> Flow 16 (client to server) +00000000 00 00 00 20 9d 1c 4b ff 21 7e ff d6 d6 4f 2b d3 |... ..K.!~...O+.| +00000010 b9 5c b8 0e 90 1f c5 3b 6e cf 46 ca 86 1c 63 92 |.\.....;n.F...c.| +00000020 0d e9 8c 81 2b 4e 83 54 1b 53 ed 5b af e6 4c 0a |....+N.T.S.[..L.| +00000030 70 ff 52 ac |p.R.| +>>> Flow 17 (server to client) +00000000 00 00 00 10 4d 3e 97 34 94 1f 81 cc ba e0 4e 5d |....M>.4......N]| +00000010 a6 26 b6 0d 42 c2 80 ff cb 8b af c1 e8 86 a9 cc |.&..B...........| +00000020 32 c5 06 b4 |2...| +>>> Flow 18 (client to server) +00000000 00 00 00 10 ca ff 56 ca 5e 07 0d 92 c2 3a d6 c3 |......V.^....:..| +00000010 fd cd 41 11 4a dc 1e 44 a1 92 a7 10 a6 ac 3c 85 |..A.J..D......<.| +00000020 8d 01 c0 73 |...s| +>>> Flow 19 (server to client) +00000000 00 00 00 20 c3 1e aa 5e 54 d9 77 4e c0 17 42 8c |... ...^T.wN..B.| +00000010 68 76 a0 e2 58 ad 19 5b 7d bb 33 b9 f2 44 b7 fb |hv..X..[}.3..D..| +00000020 c8 c0 43 5a 48 d1 99 93 6d 08 e3 79 d3 0b ba e9 |..CZH...m..y....| +00000030 32 da 0e 3a 00 00 00 10 6b 22 8a 18 4f eb c1 a4 |2..:....k"..O...| +00000040 8d 9c 90 ac 5a 8c 88 d0 0d 91 89 f4 9b 4f 29 72 |....Z........O)r| +00000050 99 da 65 dc 91 fa 39 12 |..e...9.| +>>> Flow 20 (client to server) +00000000 00 00 00 10 ae de a7 19 b2 48 d8 f9 93 71 c7 10 |.........H...q..| +00000010 a0 32 17 3c b1 5a 72 89 dd 75 74 26 cf c7 fe e6 |.2.<.Zr..ut&....| +00000020 a9 9b c3 ba 00 00 00 30 af 31 71 7b 2c 36 c5 5b |.......0.1q{,6.[| +00000030 58 18 e5 6e e5 ca 87 dc ca 84 4d a3 ce 58 53 fa |X..n......M..XS.| +00000040 92 19 43 43 d0 d7 87 ba 1e cf d4 85 a7 51 0f 3c |..CC.........Q.<| +00000050 63 2c 40 2b 8a 11 a1 70 f3 e0 c5 c8 74 7b 98 3c |c,@+...p....t{.<| +00000060 2a ca d6 42 d9 4a ca 70 |*..B.J.p| diff --git a/ssh/testdata/Server-Cipher-chacha20-poly1305@openssh.com b/ssh/testdata/Server-Cipher-chacha20-poly1305@openssh.com new file mode 100644 index 0000000000..7a6ba170da --- /dev/null +++ b/ssh/testdata/Server-Cipher-chacha20-poly1305@openssh.com @@ -0,0 +1,348 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 4c 10 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...L....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 1d 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 |.chacha20-poly13| +00000110 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 |05@openssh.com..| +00000120 00 1d 63 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 |..chacha20-poly1| +00000130 33 30 35 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |305@openssh.com.| +00000140 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 |..nhmac-sha2-256| +00000150 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000160 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |,hmac-sha2-512-e| +00000170 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 |tm@openssh.com,h| +00000180 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 |mac-sha2-256,hma| +00000190 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d |c-sha2-512,hmac-| +000001a0 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 |sha1,hmac-sha1-9| +000001b0 36 00 00 00 6e 68 6d 61 63 2d 73 68 61 32 2d 32 |6...nhmac-sha2-2| +000001c0 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +000001d0 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +000001e0 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +000001f0 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2c 68 |,hmac-sha2-256,h| +00000200 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c 68 6d 61 |mac-sha2-512,hma| +00000210 63 2d 73 68 61 31 2c 68 6d 61 63 2d 73 68 61 31 |c-sha1,hmac-sha1| +00000220 2d 39 36 00 00 00 04 6e 6f 6e 65 00 00 00 04 6e |-96....none....n| +00000230 6f 6e 65 00 00 00 00 00 00 00 00 00 00 00 00 00 |one.............| +00000240 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac fa 66 ef 26 |.;........n..f.&| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 2f bb 9d 31 3c f6 4b 3a f6 0d |...<../..1<.K:..| +00000010 67 3d 11 38 47 ac 00 00 01 7a 73 6e 74 72 75 70 |g=.8G....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 72 73 61 2d 73 68 61 32 |.com....rsa-sha2| +000001a0 2d 35 31 32 2d 63 65 72 74 2d 76 30 31 40 6f 70 |-512-cert-v01@op| +000001b0 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 |enssh.com,rsa-sh| +000001c0 61 32 2d 32 35 36 2d 63 65 72 74 2d 76 30 31 40 |a2-256-cert-v01@| +000001d0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d |openssh.com,rsa-| +000001e0 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 68 61 |sha2-512,rsa-sha| +000001f0 32 2d 32 35 36 2c 73 73 68 2d 65 64 32 35 35 31 |2-256,ssh-ed2551| +00000200 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 |9-cert-v01@opens| +00000210 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 68 61 |sh.com,ecdsa-sha| +00000220 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 74 2d |2-nistp256-cert-| +00000230 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |v01@openssh.com,| +00000240 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 |ecdsa-sha2-nistp| +00000250 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |384-cert-v01@ope| +00000260 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +00000270 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 65 72 |ha2-nistp521-cer| +00000280 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +00000290 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 |m,sk-ssh-ed25519| +000002a0 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002b0 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 |h.com,sk-ecdsa-s| +000002c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000002d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000002e0 6d 2c 73 73 68 2d 65 64 32 35 35 31 39 2c 65 63 |m,ssh-ed25519,ec| +000002f0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000300 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +00000310 74 70 33 38 34 2c 65 63 64 73 61 2d 73 68 61 32 |tp384,ecdsa-sha2| +00000320 2d 6e 69 73 74 70 35 32 31 2c 73 6b 2d 73 73 68 |-nistp521,sk-ssh| +00000330 2d 65 64 32 35 35 31 39 40 6f 70 65 6e 73 73 68 |-ed25519@openssh| +00000340 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 68 |.com,sk-ecdsa-sh| +00000350 61 32 2d 6e 69 73 74 70 32 35 36 40 6f 70 65 6e |a2-nistp256@open| +00000360 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 4e 27 64 f4 e8 fc |...,..... N'd...| +00000650 67 3f af ae 8a 52 f9 24 b1 5f 94 66 50 45 7f 0d |g?...R.$._.fPE..| +00000660 d6 20 27 1d a4 c7 fd 73 11 10 00 00 00 00 00 00 |. '....s........| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 ff ec 54 dc ab 52 0c 2d 52 a3 59 |.... ..T..R.-R.Y| +00000130 23 6e 66 82 13 07 d6 15 51 c2 16 9e 9e cf 19 87 |#nf.....Q.......| +00000140 ce 55 7a ff 54 00 00 01 14 00 00 00 0c 72 73 61 |.Uz.T........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 86 8d 77 |-sha2-512......w| +00000160 71 30 c2 20 38 79 34 3b 63 2d ff bb b7 e4 2d d2 |q0. 8y4;c-....-.| +00000170 6c 2f 8c f9 24 bb ec 67 29 c1 68 82 87 22 05 c3 |l/..$..g).h.."..| +00000180 2c 51 bd 40 cb 41 31 6b c7 6c 91 18 34 ef 2d 36 |,Q.@.A1k.l..4.-6| +00000190 5f ac dc 1f a5 c8 6a 19 4d 66 60 07 d5 66 06 dd |_.....j.Mf`..f..| +000001a0 4a de d9 b9 26 25 24 bd e2 74 78 7f 76 cb 49 1b |J...&%$..tx.v.I.| +000001b0 a5 90 11 53 60 81 79 dc 6b ea ad c0 ed f8 00 df |...S`.y.k.......| +000001c0 47 c6 34 28 30 e0 52 93 43 90 ea b5 7b f1 90 52 |G.4(0.R.C...{..R| +000001d0 4b 3f cc 04 67 22 62 47 e7 76 d2 48 2b 42 eb 71 |K?..g"bG.v.H+B.q| +000001e0 20 c6 78 56 b1 93 51 d3 e0 cc 84 36 73 96 07 15 | .xV..Q....6s...| +000001f0 83 40 19 18 a6 59 76 dd 4c 1d a9 92 b2 09 3d f3 |.@...Yv.L.....=.| +00000200 2d ce a3 d9 b7 03 81 67 d0 35 67 7f ca 62 eb 7e |-......g.5g..b.~| +00000210 4b 95 99 56 54 45 80 ff 08 8f 84 6e 17 4e c0 d6 |K..VTE.....n.N..| +00000220 7f d5 20 19 cf 41 a0 60 c5 43 bf ed 1c dc a1 8c |.. ..A.`.C......| +00000230 f6 1c d8 a0 fc 77 42 b0 33 e4 5c e4 4a 9f b1 03 |.....wB.3.\.J...| +00000240 3b a7 67 ba 35 13 1e a2 f9 21 9d bd e2 9a 61 99 |;.g.5....!....a.| +00000250 c9 79 57 ef 45 c1 38 2d 13 e9 b6 03 9a 35 b8 cc |.yW.E.8-.....5..| +00000260 87 3c 23 dc 62 b8 d2 60 16 9a fa 2f 75 ab 91 6a |.<#.b..`.../u..j| +00000270 00 00 00 0c 0a 15 58 d9 74 91 88 35 d2 5e 6a 43 |......X.t..5.^jC| +00000280 e9 fd be e0 a8 88 43 08 39 f2 b3 a9 b8 fc 74 e9 |......C.9.....t.| +00000290 97 1f 43 c1 be 5b 78 66 ee 6f e4 e4 76 96 da 34 |..C..[xf.o..v..4| +000002a0 b0 d1 d8 a1 8b 47 bb bd 65 76 4a e9 06 14 09 de |.....G..evJ.....| +000002b0 c9 78 37 da 28 98 a9 57 df 1d 99 21 40 77 27 da |.x7.(..W...!@w'.| +000002c0 2e e7 3d e2 97 49 65 90 be 7c 84 45 98 38 10 73 |..=..Ie..|.E.8.s| +000002d0 19 86 4e 6a b8 7d 72 49 37 3d 62 5f b8 3b 00 f1 |..Nj.}rI7=b_.;..| +000002e0 ab 65 8e 13 81 45 e2 3e 6a d1 3e b4 72 b6 2e 9a |.e...E.>j.>.r...| +000002f0 a4 9f ec 3d e1 2c b2 68 ce a8 ad 94 28 6c bf 46 |...=.,.h....(l.F| +00000300 bc cd 04 d7 94 54 25 69 fb e2 1c 93 fe 1f 21 e0 |.....T%i......!.| +00000310 f7 83 ef 55 64 8e c5 53 48 04 8f f0 fd 84 53 16 |...Ud..SH.....S.| +00000320 f6 a4 a6 e0 33 10 59 d6 51 da 8c 32 85 42 e3 ae |....3.Y.Q..2.B..| +00000330 3b ac 1a 73 63 9f 7c a8 8b fb 98 72 2d 34 d9 73 |;..sc.|....r-4.s| +00000340 cc cb ed 98 04 a3 1a 91 e3 09 b0 c1 a9 5b 7f 7a |.............[.z| +00000350 3e 97 18 43 9b 76 d7 74 6f eb 77 ef f3 68 2b 47 |>..C.v.to.w..h+G| +00000360 af 9f 7a fd 8e 17 82 63 85 a3 51 61 0c 58 92 de |..z....c..Qa.X..| +00000370 7c c9 12 11 4c c4 e0 9c a0 64 e8 60 12 3e 2a b0 ||...L....d.`.>*.| +00000380 61 05 1f 8e |a...| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 f4 1d aa 81 13 aa 95 f2 74 5a ef fa 56 d8 28 9b |........tZ..V.(.| +00000020 cd 8b 78 0a 0a 10 c0 5d e4 20 93 bb 80 08 7f e1 |..x....]. ......| +00000030 55 ac f0 96 19 23 2a 7f 39 f3 4c a9 |U....#*.9.L.| +>>> Flow 7 (server to client) +00000000 0f f5 fa 4c 34 ba a0 94 1a dd 85 58 de 60 57 8c |...L4......X.`W.| +00000010 cf d9 39 06 5d 92 6d 99 61 18 c5 c7 52 38 7b 6b |..9.].m.a...R8{k| +00000020 f4 03 2a e5 53 63 f3 41 74 57 0b 4d |..*.Sc.AtW.M| +>>> Flow 8 (client to server) +00000000 91 dd 46 d5 ee 69 4e 52 4e 28 51 a2 b6 b4 d6 86 |..F..iNRN(Q.....| +00000010 fc f6 4b d9 19 25 68 23 0b 95 7c 92 30 69 d5 72 |..K..%h#..|.0i.r| +00000020 6a 90 aa fb 87 7a cd a6 fe c9 9f 7d 37 66 31 d5 |j....z.....}7f1.| +00000030 ad 78 56 c4 26 ed b6 25 78 ad 1a 54 f9 44 12 6f |.xV.&..%x..T.D.o| +00000040 b1 04 d0 51 |...Q| +>>> Flow 9 (server to client) +00000000 36 d5 2f c4 9f dc 14 d9 39 64 70 7e 51 89 a5 b6 |6./.....9dp~Q...| +00000010 ce 7d 6a df 14 a8 c4 06 c9 04 92 67 14 bc 7e bc |.}j........g..~.| +00000020 af 6d ad b4 f6 90 5e 6e 06 3e d7 16 |.m....^n.>..| +>>> Flow 10 (client to server) +00000000 2a 7d 77 58 f3 6d 2a a1 a5 28 65 93 67 24 e1 1c |*}wX.m*..(e.g$..| +00000010 ea 29 03 93 78 c2 dc f6 2d 93 05 8b d7 ff a4 e8 |.)..x...-.......| +00000020 2b 9a 5e 59 dd 88 72 80 89 01 33 1b ef 65 68 f4 |+.^Y..r...3..eh.| +00000030 53 f2 8c ab 04 eb 5b 14 c5 55 f6 35 ca 9f be da |S.....[..U.5....| +00000040 ab e8 29 e5 6d bf 96 3a 44 10 16 3b 21 e1 a1 96 |..).m..:D..;!...| +00000050 c1 f2 91 36 99 a3 6e 39 83 a9 4c ca b6 ab a8 2d |...6..n9..L....-| +00000060 f9 6a a8 cb 40 3e c2 1e 4b 92 e1 19 08 6c 33 ea |.j..@>..K....l3.| +00000070 5e 42 b8 ac c4 52 3a 34 0d 08 1f fd 41 f1 c4 f3 |^B...R:4....A...| +00000080 40 d9 69 bb 62 c5 da 4d f7 7d ac 48 ae 89 6b 0c |@.i.b..M.}.H..k.| +00000090 b8 c0 1a 29 db d2 61 ee c1 5f bb 67 40 ac a1 81 |...)..a.._.g@...| +000000a0 32 0a 5c 17 2d b6 d6 eb 55 c2 9c 10 67 6b 31 4d |2.\.-...U...gk1M| +000000b0 99 40 3a 20 21 80 68 29 03 94 61 90 4b dc 13 e1 |.@: !.h)..a.K...| +000000c0 65 28 b9 21 e9 63 6d fd fe 6c f3 3d 66 06 4b 4c |e(.!.cm..l.=f.KL| +000000d0 ad 92 ca 07 15 c2 b0 78 c8 66 57 aa 2f 48 e6 83 |.......x.fW./H..| +000000e0 f3 95 60 7e 2d 21 c9 4e c6 47 2d 9f 17 1f 16 83 |..`~-!.N.G-.....| +000000f0 17 74 60 fb 1e 39 d0 21 08 af a8 79 24 91 d5 91 |.t`..9.!...y$...| +00000100 83 29 6e 13 4a 6e a6 ca dc 11 4a b1 c2 79 49 59 |.)n.Jn....J..yIY| +00000110 46 8e ed 14 d3 45 e5 ee a9 31 a2 3a ab b5 8f 76 |F....E...1.:...v| +00000120 e3 54 87 50 f8 65 f3 fe 0c 1b fc 2c e9 c6 97 27 |.T.P.e.....,...'| +00000130 90 cf 55 43 ac 06 4f b9 c2 ce a4 73 87 a8 a0 b4 |..UC..O....s....| +00000140 e5 2c 9f 28 aa a5 ec c1 85 1c 6a cb a6 da 43 28 |.,.(......j...C(| +00000150 5b 93 2e 41 0b 78 28 f8 87 4b d6 46 c0 9b 96 26 |[..A.x(..K.F...&| +00000160 fb d0 52 27 51 51 f2 96 a6 52 1f ac 2b 96 4f 90 |..R'QQ...R..+.O.| +00000170 5b 1b 9c 3a |[..:| +>>> Flow 11 (server to client) +00000000 80 ce 37 c3 ed 9b 6f 7b ea fb 66 b7 bf e3 31 ca |..7...o{..f...1.| +00000010 75 c0 79 26 c7 46 51 9a db 02 bb 88 a5 90 5f ec |u.y&.FQ......._.| +00000020 91 dc d0 be 1d 3f 77 fb 8f cc a6 7f a7 2b b6 50 |.....?w......+.P| +00000030 d6 3a 42 e8 72 bc 08 0b d2 21 1d 7e b7 9f 4d 87 |.:B.r....!.~..M.| +00000040 58 fb fd 1e 7e 3b 0d 49 cf 8a 99 69 84 04 19 d9 |X...~;.I...i....| +00000050 78 c7 d4 0d 47 44 69 32 e5 77 e7 94 92 a8 1d 98 |x...GDi2.w......| +00000060 d2 72 c4 20 5e bb 9d c9 fc 87 c0 b8 33 cf 77 93 |.r. ^.......3.w.| +00000070 9b 6c 1b 55 bf bf 53 03 47 1b 19 37 76 af 65 4e |.l.U..S.G..7v.eN| +00000080 9c 7e 52 9e c4 7f c4 70 34 9e c6 0f a2 c4 bc 76 |.~R....p4......v| +00000090 c0 c9 c5 c5 fb f8 c7 88 04 85 f0 59 92 f1 33 30 |...........Y..30| +000000a0 fa 27 39 c5 de c9 53 a9 ef b1 e2 85 2c a8 1f f7 |.'9...S.....,...| +000000b0 56 a0 7c 60 be 9d 04 7c 10 89 e4 49 bf ec 48 32 |V.|`...|...I..H2| +000000c0 8a 26 27 70 ac f0 7a f0 d4 06 20 47 89 2e 8b 18 |.&'p..z... G....| +000000d0 40 5a e6 16 df 8c 92 35 9b 7e de f6 ca 20 64 5a |@Z.....5.~... dZ| +000000e0 b7 aa 84 f9 1c d5 4b 68 5f a5 50 a2 60 60 f9 df |......Kh_.P.``..| +000000f0 cb 57 c6 c8 09 29 4f f5 7b 48 d2 a5 14 74 23 4c |.W...)O.{H...t#L| +00000100 04 60 04 70 8f 4a fd 16 b0 00 67 d3 08 10 21 83 |.`.p.J....g...!.| +00000110 39 4d 6c eb 12 e5 c5 33 17 58 07 da f9 ab 14 c1 |9Ml....3.X......| +00000120 16 57 3a 77 02 b5 57 d8 80 48 28 17 c0 e0 15 80 |.W:w..W..H(.....| +00000130 4a 12 3e fd ef 3f 45 ad d9 e3 b5 29 46 be 40 fd |J.>..?E....)F.@.| +00000140 01 73 bd 46 2c 48 ef 8a 92 21 85 33 |.s.F,H...!.3| +>>> Flow 12 (client to server) +00000000 79 67 26 72 cf 35 da c3 82 df 67 ae 2f 40 c2 80 |yg&r.5....g./@..| +00000010 67 d4 4b 19 bd b1 ce 0f 79 63 b1 cc 0c ca 4c c1 |g.K.....yc....L.| +00000020 90 f6 83 88 0d 9d 63 d8 1c 6d 2e 65 6e d7 03 4a |......c..m.en..J| +00000030 e8 bf 80 ef 99 17 3f 81 8a 65 b3 c6 55 e7 78 04 |......?..e..U.x.| +00000040 93 64 3c de 74 c9 61 58 f2 01 77 c7 05 b6 23 84 |.d<.t.aX..w...#.| +00000050 99 87 05 c7 37 d4 6f 85 60 cf b3 42 39 11 bd c3 |....7.o.`..B9...| +00000060 c7 a7 3c bf e4 8c 58 05 b3 9f de 42 3c 08 5d 8c |..<...X....B<.].| +00000070 35 75 55 9a 40 8a a2 bc 1f 9d ff 2c 60 97 9b f3 |5uU.@......,`...| +00000080 d2 63 f8 26 56 55 cf be 9b 57 30 22 e1 d5 4d f9 |.c.&VU...W0"..M.| +00000090 19 fd 77 99 dc ec 46 9e 92 bd 0f 66 0e 85 aa 55 |..w...F....f...U| +000000a0 f7 03 aa 92 ad f6 91 7a 09 a7 e5 3a de 3c 6d da |.......z...:.>> Flow 13 (server to client) +00000000 cf 9e bd a8 13 3c 39 72 9b ab 73 84 1b 4b 56 c1 |.....<9r..s..KV.| +00000010 5e 56 d2 33 21 3a 46 31 66 e6 e6 b7 |^V.3!:F1f...| +>>> Flow 14 (client to server) +00000000 7e 3b 3a 3a 13 9d a6 52 0b a3 b7 6a c9 b5 e7 ff |~;::...R...j....| +00000010 68 16 e8 7e d8 cc 32 d6 07 0c 51 8f 26 79 22 49 |h..~..2...Q.&y"I| +00000020 c4 43 03 73 4c 4a dd 9d 95 ff 05 f8 0b f2 b8 66 |.C.sLJ.........f| +00000030 a5 ee 7f b3 |....| +>>> Flow 15 (server to client) +00000000 63 82 c9 37 64 1f 26 13 2e be b7 55 b5 f7 07 f9 |c..7d.&....U....| +00000010 e9 5b 82 ab ae eb be 03 7a 15 28 66 ad f2 a6 32 |.[......z.(f...2| +00000020 f6 10 bb 12 41 d4 02 b5 a7 44 2f 01 |....A....D/.| +>>> Flow 16 (client to server) +00000000 8d 3e b4 b0 50 54 db 61 8c 56 d7 a4 e5 39 4b ff |.>..PT.a.V...9K.| +00000010 39 f4 81 4e 7a 8b 3b e1 41 f4 8e 35 29 1b 9d a2 |9..Nz.;.A..5)...| +00000020 f1 11 83 fb c1 fe 30 75 b5 f4 50 07 75 71 50 fe |......0u..P.uqP.| +00000030 7b 25 09 a8 bb c0 da 17 d8 86 16 41 9f 13 23 43 |{%.........A..#C| +00000040 6f 60 5a 8b 0f 60 67 cb 80 1c 05 5d 7d 0a 29 ec |o`Z..`g....]}.).| +00000050 ef 48 d1 7d 02 7c 4e 33 |.H.}.|N3| +>>> Flow 17 (server to client) +00000000 c3 1f 40 3e b6 39 0a 69 8d f6 b3 9f ea f6 f4 9f |..@>.9.i........| +00000010 ed f8 07 4f 03 dc 06 30 e7 96 74 0d 93 02 e7 93 |...O...0..t.....| +00000020 cb 36 61 3a a9 c0 ec b1 a6 2f 01 ce 52 29 b5 c7 |.6a:...../..R)..| +00000030 f9 85 09 ee f8 1e 4d 08 e3 9e d3 5d 1f 5f 70 f3 |......M....]._p.| +00000040 04 06 96 2d 98 21 aa a0 b6 12 65 3c 5a 35 ab 01 |...-.!....e>> Flow 18 (client to server) +00000000 8a e2 e3 ae f1 09 d1 dd 86 44 b5 00 55 ef df ab |.........D..U...| +00000010 ac d8 68 d9 ac 51 57 7b bb ed 1c 0f 27 ad e9 35 |..h..QW{....'..5| +00000020 81 00 8d c0 35 04 5c a1 06 bd 1c 8e a1 27 8f 8a |....5.\......'..| +00000030 77 6b e1 3c 41 a1 42 36 0d 99 3f bd a4 a5 aa 02 |wk.>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 31 30 2e 30 0d 0a |10.0..| +>>> Flow 3 (server to client) +00000000 00 00 02 6c 05 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...l....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 4b 63 75 72 76 65 32 |EPv..>...Kcurve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 6b 65 78 2d 73 74 72 |bssh.org,kex-str| +00000050 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 |ict-s-v00@openss| +00000060 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d 73 68 61 |h.com...!rsa-sha| +00000070 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 32 2d 35 |2-256,rsa-sha2-5| +00000080 31 32 2c 73 73 68 2d 72 73 61 00 00 00 6c 61 65 |12,ssh-rsa...lae| +00000090 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 |s128-gcm@openssh| +000000a0 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 |.com,aes256-gcm@| +000000b0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 |openssh.com,chac| +000000c0 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 |ha20-poly1305@op| +000000d0 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 |enssh.com,aes128| +000000e0 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c |-ctr,aes192-ctr,| +000000f0 61 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 |aes256-ctr...lae| +00000100 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 |s128-gcm@openssh| +00000110 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 |.com,aes256-gcm@| +00000120 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 |openssh.com,chac| +00000130 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 |ha20-poly1305@op| +00000140 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 |enssh.com,aes128| +00000150 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c |-ctr,aes192-ctr,| +00000160 61 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d |aes256-ctr...nhm| +00000170 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +00000180 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000190 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +000001a0 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000001b0 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +000001c0 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +000001d0 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e |hmac-sha1-96...n| +000001e0 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 |hmac-sha2-256-et| +000001f0 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d |m@openssh.com,hm| +00000200 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 |ac-sha2-512-etm@| +00000210 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000220 2d 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 |-sha2-256,hmac-s| +00000230 68 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 |ha2-512,hmac-sha| +00000240 31 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 |1,hmac-sha1-96..| +00000250 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 |..none....none..| +00000260 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 |............;...| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 c5 d5 30 62 29 26 f3 01 f2 08 |...<....0b)&....| +00000010 8a 6e d9 d5 8e 80 00 00 01 7a 6d 6c 6b 65 6d 37 |.n.......zmlkem7| +00000020 36 38 78 32 35 35 31 39 2d 73 68 61 32 35 36 2c |68x25519-sha256,| +00000030 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 2d |sntrup761x25519-| +00000040 73 68 61 35 31 32 2c 73 6e 74 72 75 70 37 36 31 |sha512,sntrup761| +00000050 78 32 35 35 31 39 2d 73 68 61 35 31 32 40 6f 70 |x25519-sha512@op| +00000060 65 6e 73 73 68 2e 63 6f 6d 2c 63 75 72 76 65 32 |enssh.com,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +000003a0 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 |aes256-gcm@opens| +000003b0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000003c0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +000003d0 32 35 36 2d 63 74 72 00 00 00 6c 63 68 61 63 68 |256-ctr...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |gcm@openssh.com,| +00000410 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e 73 |aes256-gcm@opens| +00000420 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000430 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000440 32 35 36 2d 63 74 72 00 00 00 d5 75 6d 61 63 2d |256-ctr....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 07 c6 6a cc 26 c1 |...,..... ..j.&.| +00000650 98 86 8f 53 1c 84 6b 74 ca a1 20 cc 6e 95 46 85 |...S..kt.. .n.F.| +00000660 4a 31 4a e7 06 31 df f7 8b 49 00 00 00 00 00 00 |J1J..1...I......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 13 cf b6 0f c2 c9 08 d9 7b f6 60 |.... ........{.`| +00000130 d4 53 7f 4b b1 29 37 59 98 3c dd ab b1 51 12 94 |.S.K.)7Y.<...Q..| +00000140 92 eb 56 4c 6f 00 00 01 14 00 00 00 0c 72 73 61 |..VLo........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 64 a3 e2 |-sha2-512....d..| +00000160 1b 13 ca 48 cf 1b ce 82 1f 24 15 74 dd 53 c4 20 |...H.....$.t.S. | +00000170 f3 bb f5 48 45 2c 11 db 63 e2 b2 f6 30 c8 72 b1 |...HE,..c...0.r.| +00000180 42 8a f3 67 3b 1d 9f dc 60 f8 57 d8 9e bf 24 7b |B..g;...`.W...${| +00000190 97 96 cc dd 52 e6 1e f7 d6 ab 83 98 a2 5f 05 fd |....R........_..| +000001a0 15 ae b3 b8 a8 7e d0 b8 3e 49 0a 03 89 69 14 d7 |.....~..>I...i..| +000001b0 58 9f d2 a5 48 3d 65 25 91 e2 13 1b fa 09 e5 f9 |X...H=e%........| +000001c0 c2 6d 2e 6e b7 21 55 90 cd c9 97 29 94 03 c4 d2 |.m.n.!U....)....| +000001d0 b5 0a 36 54 ad 7e de d5 33 e3 04 1e bb 63 c3 ed |..6T.~..3....c..| +000001e0 ce b1 b6 36 f9 8a 75 53 c3 6e 55 4c 78 99 66 55 |...6..uS.nULx.fU| +000001f0 0e eb 1f 41 f6 d9 ca a6 67 3b c9 2a a2 81 26 d6 |...A....g;.*..&.| +00000200 7c 7b fb bb 06 b4 64 1a 44 72 e6 01 3b 51 e4 76 ||{....d.Dr..;Q.v| +00000210 39 66 8e cb a1 5a c8 5c df 94 27 e2 9c 1a fd 97 |9f...Z.\..'.....| +00000220 ef fb c5 c8 15 c1 76 f9 70 ad 33 64 e4 8e df c0 |......v.p.3d....| +00000230 39 b2 12 93 8d d7 59 f3 4e 6e ae bc 4a 9a 7e 8e |9.....Y.Nn..J.~.| +00000240 d6 e5 ba 85 b4 32 2f f6 95 dd c2 79 ca f7 77 74 |.....2/....y..wt| +00000250 ef 12 a7 4e c9 f8 5e b5 4d f2 b4 0c ef e8 a3 63 |...N..^.M......c| +00000260 9c a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc 62 |......W.5...<#.b| +00000270 00 00 00 0c 0a 15 b8 d2 60 16 9a fa 2f 75 ab 91 |........`.../u..| +00000280 46 fe cb a3 45 3f 82 e6 fe 2c d4 e1 e3 0c 8b 21 |F...E?...,.....!| +00000290 72 62 8b bd 5a de b1 65 d3 68 43 56 c3 65 ef d9 |rb..Z..e.hCV.e..| +000002a0 b0 ea 9b 6b 54 1c 04 93 d8 71 5d 4c ff 55 08 84 |...kT....q]L.U..| +000002b0 0f ee 03 cb f7 c1 fd 8f e6 75 26 13 98 b6 c9 63 |.........u&....c| +000002c0 1f 7d 0b 09 d7 14 9d b3 ab a1 32 6f 88 8f 53 2d |.}........2o..S-| +000002d0 fb 0f f8 cf 58 c3 23 78 9f cd a5 81 34 08 24 2f |....X.#x....4.$/| +000002e0 9e 5b 41 f0 81 c5 8d 2f 80 2a d8 6b a5 5b 81 c2 |.[A..../.*.k.[..| +000002f0 4e 2a 71 c6 69 39 94 ba 8c ef 3f ec 13 ba 73 81 |N*q.i9....?...s.| +00000300 9e 23 ca 7c 97 66 4d 06 9c f5 1b d9 30 e4 26 af |.#.|.fM.....0.&.| +00000310 e0 bf 67 25 7a b3 57 02 cd 5d 31 a2 5f 80 22 37 |..g%z.W..]1._."7| +00000320 79 75 87 f7 50 3b 8f 43 cb ec 14 3c 0b d7 6f 0c |yu..P;.C...<..o.| +00000330 3e 95 60 03 f3 fc 36 23 5a 92 63 0d 66 a3 98 61 |>.`...6#Z.c.f..a| +00000340 e5 b2 db b4 bb 1f d6 e7 e7 bd 39 92 c9 66 12 eb |..........9..f..| +00000350 9b 54 3e ba f1 96 bf 39 c6 cd 7a 27 95 c1 b6 7c |.T>....9..z'...|| +00000360 9b e3 f1 a6 ea 93 aa a1 db 3a 3f 32 2f 6d 9e 14 |.........:?2/m..| +00000370 ee 93 3b 89 85 54 87 c7 12 07 66 e4 42 65 ba 28 |..;..T....f.Be.(| +00000380 0b ad 7c d4 |..|.| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 e8 62 17 70 dc 16 ff ad b2 d7 c5 23 45 62 93 83 |.b.p.......#Eb..| +00000020 f8 01 1b 79 df 30 da 0e a9 fd 8b 3c 51 4d b6 cc |...y.0.....>> Flow 7 (server to client) +00000000 10 45 f8 2f ae bb 2c e7 03 ee d8 7e 5a b0 d8 a4 |.E./..,....~Z...| +00000010 91 17 95 56 a1 e3 d3 85 e9 d2 84 84 09 a2 3b d3 |...V..........;.| +00000020 d0 95 a3 1c 05 01 9c e5 b0 91 74 09 |..........t.| +>>> Flow 8 (client to server) +00000000 c3 4f 1f 70 2e b7 7c b2 cf 8a 41 71 87 5a fa ff |.O.p..|...Aq.Z..| +00000010 f1 80 e4 e2 28 05 b8 ff cf 93 ef 9b d3 c8 fe f4 |....(...........| +00000020 19 a7 aa f3 43 82 20 ab a5 f4 84 00 c9 99 33 32 |....C. .......32| +00000030 7e b2 0b 20 b9 75 2b d8 79 ec 48 b0 9e 8d c0 b5 |~.. .u+.y.H.....| +00000040 ff 06 1c b3 |....| +>>> Flow 9 (server to client) +00000000 b7 1a 6c 15 3c 76 f9 e2 f1 4e 22 39 9e af 8c b4 |..l.>> Flow 10 (client to server) +00000000 46 ee 3c 00 23 17 9c ef 31 90 23 82 d7 4e f0 da |F.<.#...1.#..N..| +00000010 ad 91 8f 32 08 a3 db eb 7d 0c 9f f1 00 37 8f 68 |...2....}....7.h| +00000020 1a 0d 8d 04 b0 ab e5 15 bc e9 3c 31 ff 4d 63 52 |..........<1.McR| +00000030 a6 3b e4 f7 2f ed 6c f8 df cd f8 6c 1b 2e 55 37 |.;../.l....l..U7| +00000040 d6 7a 22 20 45 bb cb c3 ba cf fb 45 06 1a 6d 86 |.z" E......E..m.| +00000050 66 f6 d3 b6 60 ab 80 e5 c6 1d 12 2b 10 55 2b cc |f...`......+.U+.| +00000060 59 54 4b b2 f5 71 bd 02 93 0a ed 4a 2f 54 cb 27 |YTK..q.....J/T.'| +00000070 04 e0 b6 6d 2e 9f d1 79 48 e4 75 fb a2 7b 5b 7b |...m...yH.u..{[{| +00000080 59 6a d4 a0 f5 f6 7b b9 60 e8 2e c0 b2 2a bf 2e |Yj....{.`....*..| +00000090 fe 89 c8 71 fa 24 9f 48 be 94 7e 93 cf 1f c0 e5 |...q.$.H..~.....| +000000a0 4c 2d c2 0a f6 95 75 96 a6 54 e5 7a 9b 52 95 4d |L-....u..T.z.R.M| +000000b0 8e 30 a9 1b 0f 07 2d 6f 54 30 3c db 79 47 91 08 |.0....-oT0<.yG..| +000000c0 8e 6b cd fa b2 d8 cc c4 69 07 69 82 48 d9 05 01 |.k......i.i.H...| +000000d0 d8 4d 14 7b 16 6d aa cf 4a da 5e 94 93 5f 81 dd |.M.{.m..J.^.._..| +000000e0 d0 8e 10 e4 fe 94 ed 2e 70 42 2f 6c e5 50 2a 2f |........pB/l.P*/| +000000f0 b6 6d 1f 48 38 93 44 d9 55 46 b5 2b 18 1f 78 89 |.m.H8.D.UF.+..x.| +00000100 32 f1 21 03 cb a8 37 9c e4 dc 7f 34 cd 42 f1 90 |2.!...7....4.B..| +00000110 72 14 d3 c3 25 37 5e b8 a1 bd 39 60 f2 e7 da 39 |r...%7^...9`...9| +00000120 87 5c 37 99 87 64 05 bd c8 45 22 be 79 7c 1e 47 |.\7..d...E".y|.G| +00000130 99 a7 b9 5b ab b0 81 d6 24 3e 85 fe 30 3e b0 3d |...[....$>..0>.=| +00000140 4d 92 eb 95 86 0d 72 2c eb 2c 7d 2a a1 f0 9e ed |M.....r,.,}*....| +00000150 d1 9c 2f 71 3d c4 e0 92 2c 62 ae 4e 32 cd 20 ae |../q=...,b.N2. .| +00000160 e2 6b 91 c2 0f d5 90 6e 80 91 4c eb 40 74 36 1f |.k.....n..L.@t6.| +00000170 50 36 4d f7 |P6M.| +>>> Flow 11 (server to client) +00000000 d5 4c 72 d9 7a c9 22 77 d6 4c 63 74 37 fa 30 ad |.Lr.z."w.Lct7.0.| +00000010 7e 13 45 59 61 84 82 f7 d2 13 3f 44 ac 2d de 41 |~.EYa.....?D.-.A| +00000020 db 9c dd 1b fe 06 aa bc 38 30 1d a4 bb ed 7c 9d |........80....|.| +00000030 4b 6e 79 78 e4 0a 35 5f 68 e9 4f a5 e9 65 99 f3 |Knyx..5_h.O..e..| +00000040 e9 72 59 1d cd 0b ed 44 52 5d f9 dc 76 c9 23 ce |.rY....DR]..v.#.| +00000050 9f 27 21 ff 94 0c dd 60 95 89 ce 71 8d 37 c1 ec |.'!....`...q.7..| +00000060 12 90 99 b3 62 83 18 3a ea d9 c8 73 67 67 c4 64 |....b..:...sgg.d| +00000070 55 f8 3b b9 5b ea 67 5b de 8a e6 00 49 15 9a 64 |U.;.[.g[....I..d| +00000080 2f b6 7c ec 76 71 d0 c2 cc e0 3f 44 46 ed 27 85 |/.|.vq....?DF.'.| +00000090 f1 71 5e 44 94 d0 c0 b4 da 4b ab e5 28 be 62 44 |.q^D.....K..(.bD| +000000a0 3a 36 ef 1d d3 5a a2 ea 9e 5e e0 19 18 5d be 85 |:6...Z...^...]..| +000000b0 26 7c 92 b9 14 38 18 27 35 32 bf f9 18 ce d2 ec |&|...8.'52......| +000000c0 20 1d ac de ea 78 2a 2b 5a 3d a8 e8 95 43 24 ea | ....x*+Z=...C$.| +000000d0 ee eb 24 f1 c1 c3 d0 e4 d9 21 f9 57 17 f9 4d 4c |..$......!.W..ML| +000000e0 03 37 ae dd b8 80 f0 52 77 43 80 e0 6e 79 07 7c |.7.....RwC..ny.|| +000000f0 a9 c6 38 43 a1 89 fd 0d f4 07 84 33 e2 f6 94 61 |..8C.......3...a| +00000100 ff 33 66 05 21 0f 6d 88 4b 41 88 12 9a cc b8 a0 |.3f.!.m.KA......| +00000110 81 4b 7b ed 61 0d a2 6f 05 91 dd ff f8 56 95 73 |.K{.a..o.....V.s| +00000120 6d ec 15 6a ee df cc 7c 65 f0 7d 02 23 06 0f c1 |m..j...|e.}.#...| +00000130 90 6c 76 81 15 9a 22 99 09 78 9f 2c b6 9d 67 9f |.lv..."..x.,..g.| +00000140 45 85 3c a2 dd af c7 f9 f3 0d 05 d3 |E.<.........| +>>> Flow 12 (client to server) +00000000 30 4c 00 77 a3 9a a9 d7 56 a7 37 b1 b5 ed 6d 26 |0L.w....V.7...m&| +00000010 c1 6c e2 cf 5e c8 76 3c f8 84 3f 8b 2b 9d bc 1d |.l..^.v<..?.+...| +00000020 3b 7a 6c 44 e2 64 9b f2 b2 04 09 96 47 27 58 4b |;zlD.d......G'XK| +00000030 18 7b c4 e7 b5 71 07 29 94 34 9b a3 30 4a 4e de |.{...q.).4..0JN.| +00000040 48 83 10 65 25 41 6b 71 2a b8 a1 77 e5 26 9c dd |H..e%Akq*..w.&..| +00000050 d2 5b b7 89 a3 54 1f e2 1e f0 78 19 fe a3 92 db |.[...T....x.....| +00000060 b6 fe 47 3e dd 7c 3a 3d 76 ec 6e 1b 20 9c 02 b1 |..G>.|:=v.n. ...| +00000070 58 85 d0 77 c9 3f 04 68 f3 b5 a1 6c dd 9f 5c 39 |X..w.?.h...l..\9| +00000080 8e 3f 06 9e bd c5 a2 e8 5a 85 b7 de 75 d6 82 81 |.?......Z...u...| +00000090 f2 6f 35 dd b8 e3 de bd a0 b7 2e d6 12 5b b1 0b |.o5..........[..| +000000a0 bb 68 36 ac 1f ad 08 bd f6 0f 27 08 ed 70 5b 5e |.h6.......'..p[^| +000000b0 34 45 8b 00 ef 4f b3 52 53 b0 8d c5 9d 1b c0 fb |4E...O.RS.......| +000000c0 f3 40 70 bb 07 8b e0 d8 11 de 5f 98 b9 36 18 aa |.@p......._..6..| +000000d0 8d 5b 29 45 02 ce 32 04 35 2e f4 21 6a 2d 24 cf |.[)E..2.5..!j-$.| +000000e0 29 a0 3e 1e 14 91 17 09 64 77 23 34 23 3f 5b 37 |).>.....dw#4#?[7| +000000f0 b3 c7 e7 50 23 8d be 32 3d 98 8e 6c d6 96 8b a9 |...P#..2=..l....| +00000100 82 5d 89 e2 56 9a ad 39 04 af 4a 78 20 3e 46 60 |.]..V..9..Jx >F`| +00000110 38 e0 b9 3f 8f 5c 2d b6 82 cf ad 20 89 fd c7 c5 |8..?.\-.... ....| +00000120 e7 54 9a d8 a0 70 31 18 7c 8c 32 99 73 a4 6c ff |.T...p1.|.2.s.l.| +00000130 c0 36 5f 22 1b 01 d3 a6 b0 03 9a 04 0c 0a e3 8d |.6_"............| +00000140 b2 23 28 16 6c 2a c6 8d 53 fa 4c 25 db 0b d9 ab |.#(.l*..S.L%....| +00000150 d1 e6 e1 d3 38 f7 2b 3d 36 03 e2 65 37 04 14 d5 |....8.+=6..e7...| +00000160 66 9f 3b 4f bb e6 8e 64 22 60 f2 ba 8f 15 98 2b |f.;O...d"`.....+| +00000170 09 d6 c0 af aa 26 e5 64 14 0e 61 dd 51 9d 0d ba |.....&.d..a.Q...| +00000180 50 74 51 2d c6 45 5e 25 a3 94 5a b3 68 ce 73 aa |PtQ-.E^%..Z.h.s.| +00000190 e3 11 d1 a4 c2 49 79 1a 1d 24 7c 03 32 ac 91 43 |.....Iy..$|.2..C| +000001a0 1f 40 74 2c 95 c3 90 6d 86 ea d2 ef b5 9e 92 6b |.@t,...m.......k| +000001b0 1e af 4c b4 a7 4f d8 ea 59 27 cb 8c b4 f5 7e 8e |..L..O..Y'....~.| +000001c0 62 7c ae e0 57 20 bc 4b 2c b7 7c 1b 50 a4 3a 14 |b|..W .K,.|.P.:.| +000001d0 3b 9b b3 cd 89 52 3b 72 bb 22 7d 74 00 a9 3f d9 |;....R;r."}t..?.| +000001e0 7c 70 04 f2 24 db 49 e3 80 95 98 85 50 9d 90 8c ||p..$.I.....P...| +000001f0 8c 67 d8 0c 9f 78 32 5b b0 af ab 06 0d 04 1f 19 |.g...x2[........| +00000200 d7 b7 62 3a 2b 49 4f 8e 1b 08 3e f1 0e 6f dd 62 |..b:+IO...>..o.b| +00000210 57 2b c1 fd e1 dc d2 8c 4e 95 d6 0f ab 00 94 a3 |W+......N.......| +00000220 ba 85 08 bf 4c a0 a6 0c 26 dd b0 b2 e5 2c 82 5d |....L...&....,.]| +00000230 53 e0 3b 2e 8e 03 98 c2 d7 f2 67 bc 48 56 bf bb |S.;.......g.HV..| +00000240 9b 62 11 33 38 a1 bb 8d 36 e0 63 5c b8 11 c7 4d |.b.38...6.c\...M| +00000250 00 19 33 73 e8 e2 96 46 e2 ff 44 95 84 05 7f 58 |..3s...F..D....X| +00000260 d1 fb 92 86 a5 65 43 c4 f5 90 a0 f4 00 5b fe 73 |.....eC......[.s| +00000270 86 ec 69 b1 c7 a8 51 d3 3a 6e 4e fa 9c 2c a7 09 |..i...Q.:nN..,..| +00000280 f3 8b 74 39 6d a6 5d d0 43 a2 e6 30 |..t9m.].C..0| +>>> Flow 13 (server to client) +00000000 33 a5 4d 90 84 2c 28 47 86 8c fc 3b 1e 21 e4 54 |3.M..,(G...;.!.T| +00000010 a9 2a 37 82 53 41 fe f2 40 ef b3 c3 |.*7.SA..@...| +>>> Flow 14 (client to server) +00000000 9b c2 b4 83 be 85 e9 65 ef 00 3d 7e d4 4c 8f 1a |.......e..=~.L..| +00000010 d7 3a 45 d7 30 b2 4c c2 fe 3e 44 bd 25 e7 96 fd |.:E.0.L..>D.%...| +00000020 d5 22 6a 21 12 d0 89 b7 8a 97 b3 48 c6 27 04 69 |."j!.......H.'.i| +00000030 0d eb 54 0a |..T.| +>>> Flow 15 (server to client) +00000000 9c 34 68 72 6f 87 4e 6f 08 a5 1e ac 43 31 d3 74 |.4hro.No....C1.t| +00000010 9f 0a 0b e2 c0 3c aa ae 82 35 1f c7 3c 0d 04 c9 |.....<...5..<...| +00000020 67 c9 ec fd 39 e5 15 16 fa ee ca 89 |g...9.......| +>>> Flow 16 (client to server) +00000000 14 7e 97 99 c7 2b 99 94 40 0c 0d 0a a3 2c 69 8a |.~...+..@....,i.| +00000010 59 bd ab ab 60 dd 35 c9 f7 59 02 fc 08 05 0e a7 |Y...`.5..Y......| +00000020 3b de d1 9d 37 29 09 64 1b ed 10 f7 82 7b d6 8c |;...7).d.....{..| +00000030 fc 89 54 ca ca 67 86 c0 6a 60 f8 cf b3 c6 08 fa |..T..g..j`......| +00000040 3d f6 68 d1 c1 1b 5b ea e5 cf d4 24 8f b4 9b e7 |=.h...[....$....| +00000050 b6 95 a9 2e ea 50 38 75 |.....P8u| +>>> Flow 17 (server to client) +00000000 fa cf 4c 38 01 c5 20 b6 3c cd ec b8 9e ae 50 8f |..L8.. .<.....P.| +00000010 bd 5e 77 6a e1 46 ac 25 c8 a3 7c e7 f7 f5 a4 3f |.^wj.F.%..|....?| +00000020 1f f8 4a 68 0e cb e6 a8 3f 9e e7 64 61 3f 42 7e |..Jh....?..da?B~| +00000030 d0 e0 f1 82 15 ab 65 e9 c4 3f 8e 36 7a 84 0c c3 |......e..?.6z...| +00000040 36 90 6d 28 06 89 fa 6a 53 f3 ca 45 8d 52 5c a2 |6.m(...jS..E.R\.| +00000050 50 97 0f 7d e1 61 70 d1 ce bd d8 6f 1c 63 39 13 |P..}.ap....o.c9.| +00000060 10 66 38 a4 8f 0d 90 ff dc e0 57 f5 79 94 3a c8 |.f8.......W.y.:.| +00000070 39 d7 ff 31 8e 62 7f ca 69 8e 37 da |9..1.b..i.7.| +>>> Flow 18 (client to server) +00000000 f8 55 f0 f7 44 40 b9 e2 bb aa e3 09 00 11 f8 19 |.U..D@..........| +00000010 d3 06 9e 95 e5 84 d5 d5 3f 6a d0 89 fe 18 86 3d |........?j.....=| +00000020 a6 02 6e 7f af 0d 37 e4 c1 3e 3c 64 85 13 ea e3 |..n...7..>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 5c 07 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 39 63 75 72 76 65 32 |EPv..>...9curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 62 73 |5519-sha256@libs| +00000030 73 68 2e 6f 72 67 2c 6b 65 78 2d 73 74 72 69 63 |sh.org,kex-stric| +00000040 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e |t-s-v00@openssh.| +00000050 63 6f 6d 00 00 00 21 72 73 61 2d 73 68 61 32 2d |com...!rsa-sha2-| +00000060 32 35 36 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |256,rsa-sha2-512| +00000070 2c 73 73 68 2d 72 73 61 00 00 00 6c 61 65 73 31 |,ssh-rsa...laes1| +00000080 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-gcm@openssh.c| +00000090 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 |om,aes256-gcm@op| +000000a0 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 61 |enssh.com,chacha| +000000b0 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e |20-poly1305@open| +000000c0 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 |ssh.com,aes128-c| +000000d0 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 |tr,aes192-ctr,ae| +000000e0 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 73 31 |s256-ctr...laes1| +000000f0 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 |28-gcm@openssh.c| +00000100 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 |om,aes256-gcm@op| +00000110 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 61 |enssh.com,chacha| +00000120 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e |20-poly1305@open| +00000130 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 |ssh.com,aes128-c| +00000140 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 |tr,aes192-ctr,ae| +00000150 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 63 |s256-ctr...nhmac| +00000160 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000170 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +00000180 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +00000190 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000001a0 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 2d |2-256,hmac-sha2-| +000001b0 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 6d |512,hmac-sha1,hm| +000001c0 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 6d |ac-sha1-96...nhm| +000001d0 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 |ac-sha2-256-etm@| +000001e0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +000001f0 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 |-sha2-512-etm@op| +00000200 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +00000210 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 |ha2-256,hmac-sha| +00000220 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c |2-512,hmac-sha1,| +00000230 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 04 |hmac-sha1-96....| +00000240 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 00 |none....none....| +00000250 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef bc |..........;.....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 db c6 d6 5a 08 0a b4 a2 18 8f |...<.....Z......| +00000010 54 a3 f8 fb cb 62 00 00 01 7a 73 6e 74 72 75 70 |T....b...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 63 3f 48 dc e5 43 |...,..... c?H..C| +00000650 6a cf e3 8f 2d 32 7d 8f 1b 55 07 b9 f2 3e 99 cf |j...-2}..U...>..| +00000660 c6 a1 84 d0 34 3b af 75 5a 49 00 00 00 00 00 00 |....4;.uZI......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 97 16 99 d7 4c 33 e9 17 f8 3d 89 |.... ....L3...=.| +00000130 67 b8 f7 f3 ad 3d 3a b0 a5 f8 ab be c0 36 86 f7 |g....=:......6..| +00000140 d3 59 70 26 00 00 00 01 14 00 00 00 0c 72 73 61 |.Yp&.........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 1a 27 33 |-sha2-512.....'3| +00000160 43 e4 fd 3e 71 d2 c1 dc 2a c3 26 96 2e e3 77 2d |C..>q...*.&...w-| +00000170 4d f7 61 6f ff b2 e4 72 eb 1e f3 c6 c4 75 dd 93 |M.ao...r.....u..| +00000180 57 20 c6 81 9f 69 8c f3 b5 e0 0c fd 4b 51 4c af |W ...i......KQL.| +00000190 c6 fe b3 24 48 10 45 df 6f 2e f6 1f bb e8 32 cd |...$H.E.o.....2.| +000001a0 2a ca 20 9e a7 a5 57 51 63 e2 85 3a d8 0b 8f d8 |*. ...WQc..:....| +000001b0 77 79 da 6f c5 34 c3 0e d6 e2 e8 21 d9 ff d7 64 |wy.o.4.....!...d| +000001c0 7d 1b 83 fe 58 27 93 f5 a4 25 7c f5 47 95 01 36 |}...X'...%|.G..6| +000001d0 5d 64 5b 4c 86 f1 7f cf e9 fb 2d c1 b9 d6 84 ef |]d[L......-.....| +000001e0 4c 43 a3 f7 28 2d 5c 9b 67 20 5a 53 91 ac 79 d7 |LC..(-\.g ZS..y.| +000001f0 92 15 42 d6 37 47 92 69 ed c7 3f e3 46 27 45 71 |..B.7G.i..?.F'Eq| +00000200 81 6d e4 f4 9d a5 59 b4 ab fd 10 4a d7 3c 89 21 |.m....Y....J.<.!| +00000210 24 d8 80 48 55 56 b2 30 10 ef 6f 06 4f c2 b9 1b |$..HUV.0..o.O...| +00000220 80 02 66 57 f1 f3 5e ae c7 a5 fc e2 28 8e db d1 |..fW..^.....(...| +00000230 b3 c3 a6 c8 04 d3 ec 1a 07 42 f8 74 04 61 7f e0 |.........B.t.a..| +00000240 47 52 8e b2 c3 8c 7d 82 ca 0e 41 c0 1e df b3 46 |GR....}...A....F| +00000250 42 08 66 ea 44 8f 7b d8 06 42 be ba 66 63 9c a8 |B.f.D.{..B..fc..| +00000260 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc 62 b8 d2 |....W.5...<#.b..| +00000270 00 00 00 0c 0a 15 60 16 9a fa 2f 75 ab 91 6a 58 |......`.../u..jX| +00000280 3a d6 7b d9 aa 1c 2e 58 16 9a 53 cd 94 52 84 8a |:.{....X..S..R..| +00000290 db e3 db 02 a1 0d 5b ae b3 a1 ab d5 24 be 20 d2 |......[.....$. .| +000002a0 ca 73 e6 bf f8 81 ac 7b cd 70 3f f8 cb a4 6a af |.s.....{.p?...j.| +000002b0 45 9d 4f 98 94 c3 9b be 75 37 9e 9a 3f 6e 6c f9 |E.O.....u7..?nl.| +000002c0 db 6c c2 8d df b6 f8 40 4e 8e 94 a7 a7 55 1b db |.l.....@N....U..| +000002d0 d8 6b 8e b6 11 66 5e 8e f2 1a 03 7e f7 2b c9 ec |.k...f^....~.+..| +000002e0 b2 dc b9 70 ce 09 43 7d 38 90 4d 47 43 9e 01 6e |...p..C}8.MGC..n| +000002f0 67 df 94 b1 e0 b3 e5 2b 53 96 21 89 71 84 e3 ff |g......+S.!.q...| +00000300 19 0a 1a f6 77 cf cc 76 38 3e 1c bc 50 58 55 91 |....w..v8>..PXU.| +00000310 3f 94 5c 7f fc ab 83 65 52 b1 82 1b d6 aa 32 81 |?.\....eR.....2.| +00000320 1c 60 ce d8 d0 74 c1 a3 8a a0 2e 1e 12 32 d1 57 |.`...t.......2.W| +00000330 3d a3 13 c5 a1 80 e0 f8 25 c6 99 58 a3 f5 bc d6 |=.......%..X....| +00000340 ec 37 8b 9b a5 5a ce 11 2b 1b 67 9a ae 25 79 16 |.7...Z..+.g..%y.| +00000350 86 36 82 59 0a 1d a2 a8 29 c7 10 e2 c6 fa ee 84 |.6.Y....).......| +00000360 03 10 d4 cd 2f 11 1f 27 6e f1 39 c5 4e 5f 6e 7f |..../..'n.9.N_n.| +00000370 39 a8 b2 81 fa 28 51 39 0e bd 1c d4 91 b5 2d 62 |9....(Q9......-b| +00000380 b2 fe 73 53 |..sS| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 e0 cb 93 46 0a 39 4c e1 6f 82 cf 66 bc 66 d2 80 |...F.9L.o..f.f..| +00000020 27 aa 9e 90 e0 bd 57 8c b6 63 de f2 cf 45 25 60 |'.....W..c...E%`| +00000030 02 6d 8f 32 69 38 b7 b8 35 2d c2 3d |.m.2i8..5-.=| +>>> Flow 7 (server to client) +00000000 7f d9 d8 c4 54 c3 b3 0a d1 3e 45 c3 14 ae a3 73 |....T....>E....s| +00000010 12 23 9e 0d 5a 06 c0 1c 37 ae 96 eb 67 a3 c6 b7 |.#..Z...7...g...| +00000020 aa 3c 0a f9 34 24 89 4a e2 07 dd 28 |.<..4$.J...(| +>>> Flow 8 (client to server) +00000000 a8 11 c9 f6 8c e5 0f 6c 0e f2 6d 9a 87 19 c8 4f |.......l..m....O| +00000010 84 71 ba 74 a4 ec ba db fe 39 f1 90 9b 8d f7 99 |.q.t.....9......| +00000020 31 50 bb f9 26 2c f9 8a 40 a2 17 e0 d9 44 49 1e |1P..&,..@....DI.| +00000030 c7 97 15 9e 62 b7 9a cd a0 2c ee df 7e 0f c7 80 |....b....,..~...| +00000040 bb 19 9c 3c |...<| +>>> Flow 9 (server to client) +00000000 3f 7c a0 df 3e 1d 5c f7 ab b1 00 14 3b e1 40 01 |?|..>.\.....;.@.| +00000010 dc a7 cd 76 77 53 74 f7 2f 28 86 74 dc bc f0 7d |...vwSt./(.t...}| +00000020 db e8 7d 65 bf 1b d3 cc 85 53 b9 44 |..}e.....S.D| +>>> Flow 10 (client to server) +00000000 b0 49 52 f6 96 ee 66 fa 61 2b d2 e6 3f c3 0e 91 |.IR...f.a+..?...| +00000010 c7 71 07 78 f5 74 ba fd 18 d6 d2 b7 c2 d1 a2 0e |.q.x.t..........| +00000020 f1 d0 f3 bc 5a 93 6e 76 a9 d2 d6 d7 0c dc 55 99 |....Z.nv......U.| +00000030 f4 8c 14 e3 14 a6 b0 16 10 89 9d bc fd 10 7f 9a |................| +00000040 fb e7 b1 dc 42 db 98 9b 43 a0 14 72 83 77 95 14 |....B...C..r.w..| +00000050 e5 8d 82 51 d4 da 00 02 65 ee 25 00 07 71 53 66 |...Q....e.%..qSf| +00000060 55 54 cd 84 a5 ab 6f cf 1f 2f e5 4a 4b 0b ec ca |UT....o../.JK...| +00000070 29 06 a6 54 36 4b 33 48 c5 81 97 24 81 d0 59 28 |)..T6K3H...$..Y(| +00000080 7f b9 a9 8d 41 d3 71 a6 23 79 e6 3c f3 c6 64 fa |....A.q.#y.<..d.| +00000090 23 11 8e d0 94 b5 a0 bb fd ce 70 f2 27 3d 35 b7 |#.........p.'=5.| +000000a0 b6 29 cf 65 56 9a 41 ae 80 b2 3a 61 58 1a 6c 26 |.).eV.A...:aX.l&| +000000b0 39 bb ab 5b 56 cf 02 e3 20 40 de 44 89 3d 57 72 |9..[V... @.D.=Wr| +000000c0 5e c4 52 9a cd 5c 1f ba 57 7d 9e 91 67 bc f5 cf |^.R..\..W}..g...| +000000d0 c0 88 94 cf 5d 54 ea be 3d b4 8a 2b 72 92 24 85 |....]T..=..+r.$.| +000000e0 fa 43 d4 ee f9 f3 5c cc 0a 10 0b 98 5c 27 1d aa |.C....\.....\'..| +000000f0 8e ba d6 3d 82 3d 39 d2 b7 7b 4a 1e 09 47 39 a5 |...=.=9..{J..G9.| +00000100 70 ff 07 3b 85 ef c0 8f c1 91 b7 14 66 54 c2 dc |p..;........fT..| +00000110 ef 14 7b 30 ab 59 93 1f 62 41 cf 5c 1a 47 04 81 |..{0.Y..bA.\.G..| +00000120 eb b4 b1 44 44 ef eb 6b 36 57 4f de 54 6c e4 24 |...DD..k6WO.Tl.$| +00000130 9e 7a 12 a0 20 22 c9 e2 65 ea a7 06 d4 5d 6c 4a |.z.. "..e....]lJ| +00000140 62 e1 80 2e 3b 58 43 28 a7 87 2e ff c4 6c e5 f4 |b...;XC(.....l..| +00000150 1f 99 bc 01 db cd ef 2e 14 39 55 b7 e6 f3 3e 66 |.........9U...>f| +00000160 b2 25 a7 15 a3 09 99 2b eb af d0 77 12 59 91 82 |.%.....+...w.Y..| +00000170 13 f1 dd 9e |....| +>>> Flow 11 (server to client) +00000000 11 56 fb fb ef 43 fc 23 47 e8 40 8e 55 b9 a9 8c |.V...C.#G.@.U...| +00000010 39 ce 59 56 49 e9 3d 9d 7a 32 ae 5c 5e b0 0b f7 |9.YVI.=.z2.\^...| +00000020 f0 19 c0 4f b4 82 0a e3 3f 45 71 83 b0 e2 bc a0 |...O....?Eq.....| +00000030 58 fb a3 6d de 04 e2 db 33 86 2a ef 3d 8b 0d 65 |X..m....3.*.=..e| +00000040 7a 20 19 43 66 98 49 70 17 f8 3e ec a9 6f f6 90 |z .Cf.Ip..>..o..| +00000050 2b 44 2b 93 22 2c 43 88 68 bc b0 ae 30 e8 d6 34 |+D+.",C.h...0..4| +00000060 9d 26 ac 00 54 28 c3 51 ed 9b f6 83 ea c6 00 da |.&..T(.Q........| +00000070 15 f1 46 3a 2d e0 7b 4a ab 98 41 95 8d b7 0b b3 |..F:-.{J..A.....| +00000080 fe 94 a4 d1 c2 6c 0a 88 e0 cc f2 76 6a 5e 24 03 |.....l.....vj^$.| +00000090 a6 4a 83 82 06 70 7c f8 ea b7 23 88 c8 23 03 b2 |.J...p|...#..#..| +000000a0 0e f7 30 93 45 e5 9e 54 57 a2 29 b1 01 0e 4c 42 |..0.E..TW.)...LB| +000000b0 c5 87 9b d4 ec 85 b5 41 3e b6 cf 86 31 5c 6e 74 |.......A>...1\nt| +000000c0 6a 38 07 6f 49 cb d7 5a ab f1 31 44 d1 40 fa b2 |j8.oI..Z..1D.@..| +000000d0 59 0e 4c 21 f9 b3 e6 56 65 9f f4 01 3e 3c a2 6c |Y.L!...Ve...><.l| +000000e0 f3 c0 c8 67 ee 2e b5 45 a3 32 b8 e1 44 73 34 6f |...g...E.2..Ds4o| +000000f0 db 39 ac 7d 61 ca 27 a8 0c 57 84 3b eb 4c 8e 98 |.9.}a.'..W.;.L..| +00000100 fe 49 67 12 d2 c4 23 73 60 7f 43 c3 c5 ea bb 47 |.Ig...#s`.C....G| +00000110 76 b7 ec 71 f8 52 27 b5 2c 60 7a 9e 36 10 30 e4 |v..q.R'.,`z.6.0.| +00000120 18 cb d5 4f 35 f9 42 8b cf 9f 6f 1a ae 4b 37 b7 |...O5.B...o..K7.| +00000130 2a 4d dd c2 5f b2 76 8e 26 5e 2f 1e 64 7a 00 32 |*M.._.v.&^/.dz.2| +00000140 7e a8 e3 b3 0b c1 aa 00 6c 65 56 82 |~.......leV.| +>>> Flow 12 (client to server) +00000000 37 43 5b 1a 4b 8b df b9 ef 86 96 16 a7 d5 3e e7 |7C[.K.........>.| +00000010 91 12 ea a6 9c 42 c5 f2 18 7f a5 0b c1 4e c9 5a |.....B.......N.Z| +00000020 2e 59 9b 3f 25 8a 26 b6 53 8a 3a 2b 59 71 c3 a8 |.Y.?%.&.S.:+Yq..| +00000030 81 cd 60 df 49 ac 67 ac 4f 6e 61 c4 3a 11 7c b1 |..`.I.g.Ona.:.|.| +00000040 dc 8a 43 e5 f0 66 88 df f7 5f 1d a5 56 f1 75 3e |..C..f..._..V.u>| +00000050 5a c1 c6 ef c7 d9 0b ec d5 d8 5c f6 06 eb b4 c9 |Z.........\.....| +00000060 ae b8 f6 6e bc f9 0c 0c e5 e7 3c 4c af c0 f9 30 |...n......>> Flow 13 (server to client) +00000000 7d b5 e0 d7 ce 11 46 82 83 05 80 7c 6e ca 57 ad |}.....F....|n.W.| +00000010 b7 72 f7 9c 06 22 ec d3 58 80 e2 6c |.r..."..X..l| +>>> Flow 14 (client to server) +00000000 28 34 40 c8 c5 25 b1 73 93 b5 93 3d 15 ce ca aa |(4@..%.s...=....| +00000010 8c f3 c6 3a 74 22 94 f2 46 53 e6 92 75 c6 e8 27 |...:t"..FS..u..'| +00000020 26 ec 5a 42 91 e4 96 aa 52 90 44 73 e5 63 a8 6a |&.ZB....R.Ds.c.j| +00000030 b7 ab e9 9e |....| +>>> Flow 15 (server to client) +00000000 81 0d 38 ec 8e b2 08 48 8a b2 35 20 84 5b 8a 47 |..8....H..5 .[.G| +00000010 6c 9c 7c 60 7d b7 22 82 aa 0d 3c 00 48 b1 00 88 |l.|`}."...<.H...| +00000020 1b 30 c9 4a 52 16 9b cd 8c 5d 39 5a |.0.JR....]9Z| +>>> Flow 16 (client to server) +00000000 38 1d bf ca 42 50 9c 02 19 60 f5 27 33 2f 36 a8 |8...BP...`.'3/6.| +00000010 1a 86 b3 91 32 0e 0d dd a7 77 19 da 40 67 2c aa |....2....w..@g,.| +00000020 2a 9d e7 29 1e 96 6e 5d 09 1e 91 2f dc 6b 87 36 |*..)..n].../.k.6| +00000030 c4 b3 d3 44 |...D| +>>> Flow 17 (server to client) +00000000 e4 d6 51 52 ef 4c 4f 54 5f 5d ac c9 c4 80 e7 49 |..QR.LOT_].....I| +00000010 ec 01 b3 58 e5 64 16 f0 d2 c8 50 0c 75 0d d8 d2 |...X.d....P.u...| +00000020 08 30 ed f3 74 63 b6 a5 a7 d3 17 ef 3a 6b 66 ea |.0..tc......:kf.| +00000030 96 91 cc 8e 42 bd 40 e6 a7 8c 9d e8 5c b6 2d 5b |....B.@.....\.-[| +00000040 73 72 de df ae 42 d3 d5 4a 5b 16 d0 db 2a 86 fe |sr...B..J[...*..| +00000050 2e 30 71 b0 05 41 c4 ef 7f bc fc c0 7e 66 c1 23 |.0q..A......~f.#| +00000060 1c 67 35 78 cf 30 d6 c9 94 b3 6f 6e 08 51 ff fd |.g5x.0....on.Q..| +00000070 66 f8 5a 4a 66 2b 6c 3d 8c 0b e8 d5 |f.ZJf+l=....| +>>> Flow 18 (client to server) +00000000 b0 8a 19 1a 46 35 c6 da 97 1b e9 53 96 ce a1 54 |....F5.....S...T| +00000010 90 c4 1d c6 0f ed a7 e0 17 b8 ff 04 9b ad 96 f8 |................| +00000020 55 da b9 15 ed e3 c4 5b ab da 56 f3 af 1d 64 d6 |U......[..V...d.| +00000030 da 96 42 80 36 5b 7e be a3 88 37 c4 b3 b7 2c 02 |..B.6[~...7...,.| +00000040 19 0b f8 4a 5d 8c 12 5d cb 8e 86 65 a9 ca c2 21 |...J]..]...e...!| +00000050 46 5a 68 e6 92 84 bb 21 70 fd b0 66 5c 67 09 a4 |FZh....!p..f\g..| +00000060 81 92 6b 91 c7 3d 77 cb 16 51 01 25 10 2c f8 1f |..k..=w..Q.%.,..| +00000070 1f 86 40 9a 5a 9b bd 49 de bb c5 e2 d5 78 bf fc |..@.Z..I.....x..| +00000080 ba 05 e4 cf |....| diff --git a/ssh/testdata/Server-KEX-diffie-hellman-group14-sha1 b/ssh/testdata/Server-KEX-diffie-hellman-group14-sha1 new file mode 100644 index 0000000000..7bc3e106af --- /dev/null +++ b/ssh/testdata/Server-KEX-diffie-hellman-group14-sha1 @@ -0,0 +1,377 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 5c 08 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 38 64 69 66 66 69 65 |EPv..>...8diffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 34 |-hellman-group14| +00000030 2d 73 68 61 31 2c 6b 65 78 2d 73 74 72 69 63 74 |-sha1,kex-strict| +00000040 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 2e 63 |-s-v00@openssh.c| +00000050 6f 6d 00 00 00 21 72 73 61 2d 73 68 61 32 2d 32 |om...!rsa-sha2-2| +00000060 35 36 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 2c |56,rsa-sha2-512,| +00000070 73 73 68 2d 72 73 61 00 00 00 6c 61 65 73 31 32 |ssh-rsa...laes12| +00000080 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |8-gcm@openssh.co| +00000090 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 |m,aes256-gcm@ope| +000000a0 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 61 32 |nssh.com,chacha2| +000000b0 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +000000c0 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +000000d0 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +000000e0 32 35 36 2d 63 74 72 00 00 00 6c 61 65 73 31 32 |256-ctr...laes12| +000000f0 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |8-gcm@openssh.co| +00000100 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 |m,aes256-gcm@ope| +00000110 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 61 32 |nssh.com,chacha2| +00000120 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 6e 73 |0-poly1305@opens| +00000130 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d 63 74 |sh.com,aes128-ct| +00000140 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 65 73 |r,aes192-ctr,aes| +00000150 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 63 2d |256-ctr...nhmac-| +00000160 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 65 |sha2-256-etm@ope| +00000170 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000180 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e 73 |a2-512-etm@opens| +00000190 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 |sh.com,hmac-sha2| +000001a0 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 |-256,hmac-sha2-5| +000001b0 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 6d 61 |12,hmac-sha1,hma| +000001c0 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 6d 61 |c-sha1-96...nhma| +000001d0 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +000001e0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +000001f0 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +00000200 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +00000210 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +00000220 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +00000230 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 04 6e |mac-sha1-96....n| +00000240 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 00 00 |one....none.....| +00000250 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef bc 88 |.........;......| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 1c 1b 89 35 93 bf b7 bb 14 28 |...<.....5.....(| +00000010 20 45 f3 2c 4f 1e 00 00 01 7a 73 6e 74 72 75 70 | E.,O....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 01 0c 05 1e 00 00 01 01 00 e9 53 49 b6 a3 |............SI..| +00000650 1f dd 76 76 a6 bd 17 c9 31 23 e2 b4 c3 42 a2 91 |..vv....1#...B..| +00000660 53 d7 9f 69 64 2a 9c 13 0c 5f 52 7b 4c 71 0d fd |S..id*..._R{Lq..| +00000670 c5 61 32 e1 3b 40 1f 11 31 0a 90 1b 43 17 35 18 |.a2.;@..1...C.5.| +00000680 20 4c f5 d1 8b 82 d0 bc 00 14 d7 27 3a 34 1a d3 | L.........':4..| +00000690 2a b1 2e d9 f4 4a a8 a1 63 3b 43 75 5f a0 68 68 |*....J..c;Cu_.hh| +000006a0 21 6e bd 05 3c bb 7c 9d f9 ee fd 42 01 03 cf c0 |!n..<.|....B....| +000006b0 36 d9 b9 67 0d e6 16 11 79 df ef 9f 71 f1 97 59 |6..g....y...q..Y| +000006c0 e4 a1 42 ef c4 00 47 66 f8 67 45 ae 2e 2e dd 43 |..B...Gf.gE....C| +000006d0 c4 c4 3f 7c ce 65 e9 42 a7 92 b8 57 be d0 81 46 |..?|.e.B...W...F| +000006e0 14 1d 1d b9 a1 b4 a4 ef ee 54 56 64 d9 c7 6a 75 |.........TVd..ju| +000006f0 64 c1 45 44 be 7a 2f 5c a9 48 63 75 4f 0d c3 64 |d.ED.z/\.HcuO..d| +00000700 20 36 e3 65 d5 a7 e5 30 61 8c 55 a1 a8 7a e7 89 | 6.e...0a.U..z..| +00000710 e6 26 26 1f 1d 17 c1 4d b2 e7 22 f9 6e 68 a7 cd |.&&....M..".nh..| +00000720 11 8c 49 04 a8 5c 28 0c 46 aa 9f 8a 73 96 36 c3 |..I..\(.F...s.6.| +00000730 87 d0 d2 46 b2 18 cb c2 7b 8a 71 13 c1 ee 6d b0 |...F....{.q...m.| +00000740 46 0f 93 df d3 a0 18 1d 74 31 e6 00 00 00 00 00 |F.......t1......| +>>> Flow 5 (server to client) +00000000 00 00 03 4c 12 1f 00 00 01 17 00 00 00 07 73 73 |...L..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 01 01 00 fc 04 01 90 be af 77 49 de a3 |............wI..| +00000130 7c 8e 11 dd 69 52 35 8e 22 88 ae 8b e6 44 3a 0e ||...iR5."....D:.| +00000140 72 1d e3 7f ec f8 64 a6 2f 88 63 3f 67 99 69 8f |r.....d./.c?g.i.| +00000150 d7 26 24 a4 25 98 f9 f3 8e 01 2c 2a e4 ed 30 51 |.&$.%.....,*..0Q| +00000160 ef 09 97 b0 ae 50 2b 00 4d 57 18 d1 88 e8 cf 03 |.....P+.MW......| +00000170 fb 03 34 57 12 66 7a 29 2a 28 a4 1e 99 21 01 07 |..4W.fz)*(...!..| +00000180 89 5b db b2 63 2a d8 ab c1 a5 ce b0 d9 97 30 18 |.[..c*........0.| +00000190 60 7a f8 58 5c 31 d6 6f fe 0c a9 8d 3f 64 f6 ea |`z.X\1.o....?d..| +000001a0 78 42 df 3b 08 66 3c 65 be 3f ba 11 ac 8b bd b3 |xB.;.fPM.I.z`.L......| +000001d0 80 b3 2b 39 c0 09 e6 b8 2b 0f 2a 74 1c c9 13 94 |..+9....+.*t....| +000001e0 ae 93 28 5a e2 21 4a ab 49 6a ff 8c da e9 1c 9a |..(Z.!J.Ij......| +000001f0 a5 07 6d 9a 01 3a c4 ee 7c d4 13 e9 a6 3d f9 a9 |..m..:..|....=..| +00000200 f6 15 bc c7 f0 3f fa fc 62 92 ed 79 d0 59 66 2c |.....?..b..y.Yf,| +00000210 0b c3 fc e8 c2 13 04 d9 c4 94 5d 17 ff 16 d4 82 |..........].....| +00000220 62 d9 96 3a be 91 00 00 01 14 00 00 00 0c 72 73 |b..:..........rs| +00000230 61 2d 73 68 61 32 2d 35 31 32 00 00 01 00 51 63 |a-sha2-512....Qc| +00000240 11 d4 1b 5e 08 b0 69 c4 5c 90 1a 39 25 71 7c 50 |...^..i.\..9%q|P| +00000250 fe 36 7d 81 7d e2 fd e7 88 10 ce 2d 7b 29 ab b1 |.6}.}......-{)..| +00000260 ae f9 07 32 c9 6f 89 9d 06 3a 0a d1 90 2b ec c5 |...2.o...:...+..| +00000270 3f 3a 91 0d 9d ad 0f 70 01 b1 44 60 f9 5e a9 74 |?:.....p..D`.^.t| +00000280 fb f2 0a 68 5e 33 e5 1d 9e 7b e9 dd b2 2f bc d9 |...h^3...{.../..| +00000290 59 8a 61 73 fb 21 1f 02 63 9d 8f a6 69 86 61 94 |Y.as.!..c...i.a.| +000002a0 0e 72 c1 24 b6 dc cb 32 55 ff e2 a1 c4 e3 68 45 |.r.$...2U.....hE| +000002b0 ed 61 a6 ea c9 76 c7 85 bd 43 be 64 91 c7 76 7f |.a...v...C.d..v.| +000002c0 e6 76 2d e0 d2 a2 de 77 1c cd 86 8d 55 13 da 60 |.v-....w....U..`| +000002d0 db 12 79 e0 6e 72 39 f0 cd 91 47 45 bd f8 96 23 |..y.nr9...GE...#| +000002e0 8e 20 14 de c9 0f 55 f5 d0 3f 9e e9 e6 09 dd 04 |. ....U..?......| +000002f0 93 7f 9f 96 a6 c6 1e 8b a7 4c f0 f8 08 c9 02 48 |.........L.....H| +00000300 7a 9b b2 33 93 c5 90 b2 0e 71 f4 bc 1a 54 42 72 |z..3.....q...TBr| +00000310 44 fb b4 5c 44 53 3c c7 9d ac 7f 63 8b 68 ad 2c |D..\DS<....c.h.,| +00000320 8a c8 a8 2a 6e b8 04 2c c4 64 8f f3 6e 03 d7 ca |...*n..,.d..n...| +00000330 4d ff 8f a4 2e 2b 54 57 89 d4 62 5d e2 00 3e a3 |M....+TW..b]..>.| +00000340 ae eb 61 3a 7f 1b 1d e3 3f d7 50 81 f5 92 30 5f |..a:....?.P...0_| +00000350 00 00 00 0c 0a 15 2e 45 26 ed c0 96 31 b1 09 58 |.......E&...1..X| +00000360 1e c8 31 1b fc 43 f0 3c b9 08 cb f2 87 4b f4 2b |..1..C.<.....K.+| +00000370 56 a2 49 47 9e 74 9e 04 76 ef 34 a6 14 68 e5 d5 |V.IG.t..v.4..h..| +00000380 19 20 54 76 ff 6b 4a 2f ed 26 de bc 56 8c 75 e1 |. Tv.kJ/.&..V.u.| +00000390 81 f1 f2 3f a0 01 dd 3a 53 e7 34 b5 99 7c 8b 9d |...?...:S.4..|..| +000003a0 38 ac d9 02 9f 8f a2 ee 99 f3 42 cb 75 f9 9d 56 |8.........B.u..V| +000003b0 04 b0 a0 2d 0b 76 1f 64 5d d1 20 8d 84 33 c6 21 |...-.v.d]. ..3.!| +000003c0 ae ea 4a 72 ec 97 88 c2 ca d7 1e 4d 75 01 c8 81 |..Jr.......Mu...| +000003d0 ab 66 be 36 fc f6 9d 7c e8 1c 73 d6 71 14 4f a6 |.f.6...|..s.q.O.| +000003e0 18 6a d2 2d ed 15 d7 51 f1 3c aa 32 5f 01 08 d4 |.j.-...Q.<.2_...| +000003f0 31 42 14 c1 f5 e7 28 42 de 2d 0a 97 c4 d9 a1 6f |1B....(B.-.....o| +00000400 d0 11 3c cc 35 89 c1 23 40 c0 a1 d5 5e fc 94 40 |..<.5..#@...^..@| +00000410 9a 51 f5 f5 16 8a a9 2b 7d c2 14 bd 5a f3 6f 77 |.Q.....+}...Z.ow| +00000420 d7 9b c0 6a 36 a0 48 29 27 d1 ba 4c 56 ca 39 4c |...j6.H)'..LV.9L| +00000430 ba b9 2b 26 e1 37 e1 34 18 37 24 af b7 c3 85 69 |..+&.7.4.7$....i| +00000440 cb 0f ca fd 35 31 3f 5b ff 91 10 ca 95 bc a0 86 |....51?[........| +00000450 4c 04 1e cb d7 b7 c4 c8 42 82 c8 91 e0 b9 c0 68 |L.......B......h| +00000460 49 d8 41 7e |I.A~| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 57 42 70 d5 6e 04 3c 60 37 29 da 36 1e ac 50 33 |WBp.n.<`7).6..P3| +00000020 d1 7b b0 91 3b a9 de 29 8b 14 63 d5 cd c6 d4 d1 |.{..;..)..c.....| +00000030 1a 08 c9 30 e7 43 e1 b4 1c db c4 f0 |...0.C......| +>>> Flow 7 (server to client) +00000000 46 65 0a ea a9 d3 98 89 ed 18 fa d1 c8 e8 41 4e |Fe............AN| +00000010 ca 2d 76 87 2c 43 d8 60 6e 71 cc 6a fc b8 20 4d |.-v.,C.`nq.j.. M| +00000020 7f 39 95 7e a6 96 27 68 48 0d ab ad |.9.~..'hH...| +>>> Flow 8 (client to server) +00000000 18 8b 65 e3 79 7c a4 c1 d4 d9 d5 31 81 5c 87 fe |..e.y|.....1.\..| +00000010 46 b1 53 cd 7e b0 eb d1 04 53 17 e9 64 89 3a 00 |F.S.~....S..d.:.| +00000020 60 97 a7 d3 1c 6c c4 47 52 ce e5 c9 db 5b 45 c3 |`....l.GR....[E.| +00000030 91 e2 5e 02 4e 36 d5 07 f2 42 65 44 48 57 44 5f |..^.N6...BeDHWD_| +00000040 80 20 db 47 |. .G| +>>> Flow 9 (server to client) +00000000 99 45 c1 21 60 75 a0 5f 49 a0 c7 3c 2c f7 31 0e |.E.!`u._I..<,.1.| +00000010 4c 83 0c a1 0e f2 7f 63 2f 79 4c 1e bd 0c fc 19 |L......c/yL.....| +00000020 b5 60 12 85 17 a5 f5 6d e0 af d9 e1 |.`.....m....| +>>> Flow 10 (client to server) +00000000 62 1a de 2d 3b 5e 79 d3 c4 8f 26 98 5e 9a 85 74 |b..-;^y...&.^..t| +00000010 cf bd 3b 52 e4 86 71 c6 28 44 4d 73 d6 c7 3e 26 |..;R..q.(DMs..>&| +00000020 51 60 9d cf 88 dd 95 27 34 4e e1 5c 99 96 d9 e5 |Q`.....'4N.\....| +00000030 c5 a5 3d b7 1b ad 10 19 46 dd 17 6d 91 41 bd e1 |..=.....F..m.A..| +00000040 bb 42 8b 40 bf de b4 eb 6e 09 3f 10 29 8c 32 40 |.B.@....n.?.).2@| +00000050 00 f3 4a f4 dc b6 18 f4 4c fa 90 dd 8d 88 f6 5e |..J.....L......^| +00000060 23 9f 77 99 76 eb 63 1e b9 5f 76 a4 54 d2 b2 7e |#.w.v.c.._v.T..~| +00000070 08 b6 c0 53 9e 5f 6b 26 a3 61 c1 45 5c db 98 6f |...S._k&.a.E\..o| +00000080 1d de a5 f3 90 af f2 4c f0 e6 02 ad d5 8b 54 a7 |.......L......T.| +00000090 b9 9a 57 e0 71 5c 09 2c 05 7b f7 7a 4b 6b d0 8b |..W.q\.,.{.zKk..| +000000a0 96 8d ef 66 81 0a 3f 1c c5 40 3d 5d 74 29 1a 17 |...f..?..@=]t)..| +000000b0 e5 0d db 01 dc 52 fc 11 30 bd 8b b5 e9 81 a5 fc |.....R..0.......| +000000c0 00 68 ce 46 3d b9 e3 6d 85 05 33 d6 8d 01 44 c1 |.h.F=..m..3...D.| +000000d0 1c cf d8 4c 0b 5b c4 e4 72 1a ec ea 32 13 30 81 |...L.[..r...2.0.| +000000e0 75 a4 52 77 a8 bd f6 86 00 72 e8 b8 62 e0 68 46 |u.Rw.....r..b.hF| +000000f0 4c 68 7c 3a b2 a2 91 60 2d c3 28 21 65 02 8b 80 |Lh|:...`-.(!e...| +00000100 4a 71 35 6c df 96 af a2 7d 01 2b 04 96 c4 f8 22 |Jq5l....}.+...."| +00000110 64 22 60 1c 8c 42 e6 f9 a6 25 49 9b 6e 3b 42 58 |d"`..B...%I.n;BX| +00000120 17 d2 70 ba cb 73 c5 77 05 f7 1a 3e 7a fa 11 ca |..p..s.w...>z...| +00000130 d4 e4 4c fa 9d 39 f7 60 3e db 6d 0f 12 a4 b8 43 |..L..9.`>.m....C| +00000140 a3 f2 ef 3a ea 34 8c 2f bf e2 f9 62 f0 7a e8 c0 |...:.4./...b.z..| +00000150 7b 38 0e 12 71 42 2a d2 ca 7e f0 47 ca 96 5c 7e |{8..qB*..~.G..\~| +00000160 7e 95 e7 26 37 a6 10 81 7d 4d 8f 05 63 c9 99 82 |~..&7...}M..c...| +00000170 91 d3 8c 4e |...N| +>>> Flow 11 (server to client) +00000000 1e d6 a5 8b 1a d1 0f 7a a6 dc 1f 99 fa 46 01 f1 |.......z.....F..| +00000010 d8 05 a8 4a c9 85 42 8c e3 24 bc 03 07 f5 71 58 |...J..B..$....qX| +00000020 32 bb 94 c2 9f 92 91 2a b6 a0 6c 58 a3 90 9b dd |2......*..lX....| +00000030 7e 0b 29 66 df 73 9c d1 52 d1 c7 95 73 7f cb 77 |~.)f.s..R...s..w| +00000040 b7 77 c7 a5 c7 ce 55 e4 da c0 1e 1a 6e 4a 97 cd |.w....U.....nJ..| +00000050 5b a5 20 b3 51 b0 f2 9b 48 4f 10 91 1c 86 00 e7 |[. .Q...HO......| +00000060 66 e1 a4 91 82 a0 43 ab 1e ea b4 f7 7a 3b 85 65 |f.....C.....z;.e| +00000070 af ab 7c 23 2c 72 b4 66 c8 61 fe 5e 59 e4 3b b0 |..|#,r.f.a.^Y.;.| +00000080 19 59 c9 df 15 d3 e6 b8 11 40 bf df 9b 27 24 2a |.Y.......@...'$*| +00000090 2c ca 02 5b f6 54 cc 1e e6 ee 46 78 a8 99 46 4d |,..[.T....Fx..FM| +000000a0 b8 00 08 fd 3c 1a 42 4e ff 4b 62 91 f8 77 a3 5e |....<.BN.Kb..w.^| +000000b0 5a 06 5e f3 cf a0 a6 e1 c9 da 2c a3 60 b5 44 c0 |Z.^.......,.`.D.| +000000c0 75 65 61 4e 65 cd e3 26 65 ca 89 c4 01 5c 58 ea |ueaNe..&e....\X.| +000000d0 cf 96 91 5f b9 b9 98 e5 0e 8b 57 e1 15 68 45 d5 |..._......W..hE.| +000000e0 8b 38 03 10 91 c2 18 bc 10 bd b4 45 35 3f 53 84 |.8.........E5?S.| +000000f0 d4 b3 d9 a7 0d 6b ce 38 72 ac be 18 8f 1d dc e0 |.....k.8r.......| +00000100 61 52 f8 8f 31 e3 68 2a 2f d7 8f 05 e1 2f 95 c9 |aR..1.h*/..../..| +00000110 a6 3b 6b aa 7a 64 1b 3b b7 cd 19 b3 15 34 45 ec |.;k.zd.;.....4E.| +00000120 44 93 17 b0 50 cd 25 d9 fe 9c 40 07 83 59 3d f5 |D...P.%...@..Y=.| +00000130 d0 0c ad 5f 09 0f ef 43 a0 fe ba 60 9e 84 78 44 |..._...C...`..xD| +00000140 6a 34 8a d3 49 8b 95 6a 2e 4a df 84 |j4..I..j.J..| +>>> Flow 12 (client to server) +00000000 0c 5b c4 6a ed 19 3c 2d 81 a7 73 80 5e 08 66 60 |.[.j..<-..s.^.f`| +00000010 f4 dd 10 4a 8d b6 82 6a 3a 9e e4 7e 36 8e 53 25 |...J...j:..~6.S%| +00000020 6d eb 6f 2e ee c6 86 b0 71 62 a3 6c 4d a6 78 3d |m.o.....qb.lM.x=| +00000030 7a ec 3f 6f fc fe 04 cc fb 60 6d 89 ae 2a 10 ef |z.?o.....`m..*..| +00000040 db dc fb d8 e3 ee 6f d6 fd 9c c2 00 50 c4 5c 68 |......o.....P.\h| +00000050 4d 0a ae ed 35 4a 99 61 01 e5 b9 76 d3 86 d9 82 |M...5J.a...v....| +00000060 75 ca 91 ed aa 2d 29 7e e1 1d ba a2 2c 16 c7 a6 |u....-)~....,...| +00000070 16 8f 2f 79 8e eb e8 90 09 a0 0d 2d bc 3d 65 0f |../y.......-.=e.| +00000080 69 0e 3a 85 9a 49 a5 d6 e3 bf 58 f4 f6 e4 ec c9 |i.:..I....X.....| +00000090 1b d9 6e 8d 34 c9 9f 23 71 01 9f 7f 2c 05 e2 26 |..n.4..#q...,..&| +000000a0 f3 32 28 07 6f ba 61 98 f0 eb 77 ef 36 5c 3a c7 |.2(.o.a...w.6\:.| +000000b0 26 ec a8 53 12 2a 64 19 1e d0 fc 30 71 f6 20 7d |&..S.*d....0q. }| +000000c0 8c d5 32 f6 81 8e ea a0 4f fc 79 6e 9e 95 c2 23 |..2.....O.yn...#| +000000d0 eb 3c 9a 6d 3d bf f0 57 93 f1 cd 8a eb e7 fe f5 |.<.m=..W........| +000000e0 0a 97 8e f6 87 73 fd 5d 28 17 f6 94 3e 4c 26 6f |.....s.](...>L&o| +000000f0 7c cc 2b 07 d2 2f 0e 99 4f 9d a9 6c 7b b5 f4 c6 ||.+../..O..l{...| +00000100 45 82 99 db 5d 59 60 4a 95 df 6f ea 73 53 36 74 |E...]Y`J..o.sS6t| +00000110 7d 59 f3 c4 ea 50 c1 b0 f9 38 30 a9 5a f1 f1 1e |}Y...P...80.Z...| +00000120 08 28 15 05 a9 a1 15 e9 a7 9b 51 de 73 77 91 76 |.(........Q.sw.v| +00000130 a5 b6 54 27 73 71 f8 56 f3 85 a1 b2 84 b2 23 7d |..T'sq.V......#}| +00000140 c4 8b d9 0f 78 6c d6 85 70 a7 d2 35 b0 78 47 13 |....xl..p..5.xG.| +00000150 56 23 fe 66 03 6a 5b bd 18 b5 50 a9 c6 50 88 01 |V#.f.j[...P..P..| +00000160 fa a8 40 b1 24 ee f9 ad fc 9b 80 54 84 db 46 67 |..@.$......T..Fg| +00000170 eb a7 3c 52 83 f2 9a f8 4e d1 1e bf 1a cb 54 fb |....P..;.....i..| +00000270 ba 53 be f4 6f b6 d8 9a 9b f8 e9 52 88 07 40 1e |.S..o......R..@.| +00000280 c9 ce 4e d4 29 f0 ab f6 f7 25 e5 61 |..N.)....%.a| +>>> Flow 13 (server to client) +00000000 4f 77 89 d1 cc f7 d3 48 36 c2 86 9b b9 d3 48 0b |Ow.....H6.....H.| +00000010 a5 1e 72 13 da b6 0e 62 20 d7 60 f2 |..r....b .`.| +>>> Flow 14 (client to server) +00000000 61 ad e1 f7 33 da 2f 85 be 85 2b e5 06 e3 02 82 |a...3./...+.....| +00000010 ca 14 06 dd ce 84 b3 2d 3a 76 7d 7d e3 f7 15 f6 |.......-:v}}....| +00000020 f7 98 98 36 c8 d1 0d f2 cb 38 c2 b8 b2 56 d0 37 |...6.....8...V.7| +00000030 db 32 4b 96 |.2K.| +>>> Flow 15 (server to client) +00000000 e7 84 d5 33 9c 46 d1 60 13 f4 1d 6e b2 e7 02 51 |...3.F.`...n...Q| +00000010 d6 77 61 d0 18 f2 d1 56 1c 51 b9 ef 1a 78 a5 59 |.wa....V.Q...x.Y| +00000020 93 bd d1 b7 49 c6 72 48 00 b5 82 90 |....I.rH....| +>>> Flow 16 (client to server) +00000000 34 53 44 4a 49 5e 02 1c 48 e1 76 56 62 bb ed 2d |4SDJI^..H.vVb..-| +00000010 01 89 c3 ca a7 e8 dc 9c c0 70 5a d9 f9 0e ed 31 |.........pZ....1| +00000020 96 e9 66 54 49 c2 b4 6c 89 73 b7 6c 69 c8 10 a3 |..fTI..l.s.li...| +00000030 d8 a8 33 bf 65 1a b8 73 82 12 c6 5a a7 ba e5 a9 |..3.e..s...Z....| +00000040 71 e1 4a 5c e2 7e 35 f0 3b 06 dd c0 5d 5c cb 67 |q.J\.~5.;...]\.g| +00000050 45 ed 31 c6 65 8b 3b 69 |E.1.e.;i| +>>> Flow 17 (server to client) +00000000 01 4d 35 5a bb 52 cf 7e ed 94 35 bd 26 53 e4 74 |.M5Z.R.~..5.&S.t| +00000010 9c c8 42 d1 a6 26 a6 16 d2 b1 5e 0c be 67 79 9a |..B..&....^..gy.| +00000020 e5 aa e7 df f3 13 b8 1e 8d 6a 56 ce 77 36 24 0d |.........jV.w6$.| +00000030 42 ba d5 9e b8 77 de e8 87 3a 20 ff 1e e3 40 72 |B....w...: ...@r| +00000040 c0 33 ec 38 49 1a d2 e3 53 45 7d 43 5c 8f ec e7 |.3.8I...SE}C\...| +00000050 09 d0 51 fe e6 fd be 6a 5a 9d ab 1b 1f 47 45 d1 |..Q....jZ....GE.| +00000060 92 51 f3 60 68 fd e8 12 b6 0b 65 44 01 2b 5d 32 |.Q.`h.....eD.+]2| +00000070 0d 3e 1a bf d0 82 a9 3c 7f 98 b5 b4 |.>.....<....| +>>> Flow 18 (client to server) +00000000 55 9f 3c 18 ea 7f 43 68 c9 d7 6a 41 fc 48 53 11 |U.<...Ch..jA.HS.| +00000010 e6 ef 27 98 88 7f b5 03 45 2f 27 de b0 16 c6 08 |..'.....E/'.....| +00000020 18 db 82 55 19 b0 b1 3b 06 dc ba 34 78 80 85 04 |...U...;...4x...| +00000030 05 f0 b2 63 cd 8a 13 bd 92 73 71 79 d2 30 56 c6 |...c.....sqy.0V.| +00000040 1f 0f 6c 71 bf 3f 8f 2b f6 63 1d 7c 8f 4c c3 20 |..lq.?.+.c.|.L. | +00000050 0e 18 47 b4 43 31 75 59 c1 b4 f7 96 5a 31 ef b2 |..G.C1uY....Z1..| diff --git a/ssh/testdata/Server-KEX-diffie-hellman-group14-sha256 b/ssh/testdata/Server-KEX-diffie-hellman-group14-sha256 new file mode 100644 index 0000000000..863034442f --- /dev/null +++ b/ssh/testdata/Server-KEX-diffie-hellman-group14-sha256 @@ -0,0 +1,377 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 5c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 3a 64 69 66 66 69 65 |EPv..>...:diffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 34 |-hellman-group14| +00000030 2d 73 68 61 32 35 36 2c 6b 65 78 2d 73 74 72 69 |-sha256,kex-stri| +00000040 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000050 2e 63 6f 6d 00 00 00 21 72 73 61 2d 73 68 61 32 |.com...!rsa-sha2| +00000060 2d 32 35 36 2c 72 73 61 2d 73 68 61 32 2d 35 31 |-256,rsa-sha2-51| +00000070 32 2c 73 73 68 2d 72 73 61 00 00 00 6c 61 65 73 |2,ssh-rsa...laes| +00000080 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |128-gcm@openssh.| +00000090 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f |com,aes256-gcm@o| +000000a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 |penssh.com,chach| +000000b0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000000c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +000000d0 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000000e0 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 73 |es256-ctr...laes| +000000f0 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |128-gcm@openssh.| +00000100 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f |com,aes256-gcm@o| +00000110 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 |penssh.com,chach| +00000120 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000130 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000140 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000150 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 |es256-ctr...nhma| +00000160 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +00000170 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000180 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +00000190 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +000001a0 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +000001b0 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +000001c0 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 |mac-sha1-96...nh| +000001d0 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +000001e0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +000001f0 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000210 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000220 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000230 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000240 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000250 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 5e 55 cd 16 86 70 8b 0c e7 15 |...<..^U...p....| +00000010 b3 9b 3b 88 74 e0 00 00 01 7a 73 6e 74 72 75 70 |..;.t....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 01 0c 05 1e 00 00 01 01 00 af 63 d8 65 a8 |............c.e.| +00000650 6a 52 e1 9b ee af eb 13 6c df 73 bd 62 ef 6b 5e |jR......l.s.b.k^| +00000660 b2 49 58 47 54 51 34 43 22 e5 c1 c3 7e 0e 82 ae |.IXGTQ4C"...~...| +00000670 5f d2 67 97 bd b9 5d 70 40 c2 49 31 77 4a 2b 80 |_.g...]p@.I1wJ+.| +00000680 09 c7 ce b2 54 a8 f9 bc a7 ef 4d 8e bc b5 fc e5 |....T.....M.....| +00000690 10 a2 d0 61 a2 63 5d 2d 97 c1 e4 7d 84 79 98 5a |...a.c]-...}.y.Z| +000006a0 4d 55 1f d4 0e 0f f6 a9 9e ad b9 9b 64 85 8f a9 |MU..........d...| +000006b0 12 47 f7 2e a3 67 f3 95 b6 5d b2 10 68 5d 62 f0 |.G...g...]..h]b.| +000006c0 50 47 0c f5 8a 66 5e aa d0 52 17 e0 cf 52 b0 1f |PG...f^..R...R..| +000006d0 55 10 91 6e 89 43 0e a7 af 27 d2 e5 46 9d c7 8c |U..n.C...'..F...| +000006e0 c8 0c b9 c4 a2 b8 b5 a3 6b b7 48 d2 eb 20 f2 df |........k.H.. ..| +000006f0 38 bb 49 a6 94 f4 6b 12 47 10 2b 16 78 ef 15 c8 |8.I...k.G.+.x...| +00000700 18 96 f3 a6 d3 28 53 a0 53 54 54 c4 eb 8b d2 27 |.....(S.STT....'| +00000710 e3 37 1c 18 f8 09 e2 bc e2 70 a4 8e 1d 70 20 90 |.7.......p...p .| +00000720 ef 90 55 16 51 92 dc d8 21 b5 f3 19 54 bc 1e d2 |..U.Q...!...T...| +00000730 37 fd e4 d7 40 d5 e8 56 73 4a 59 1a 2d 83 ca b0 |7...@..VsJY.-...| +00000740 d3 b9 5e 3d 99 d8 26 18 9f 20 d9 00 00 00 00 00 |..^=..&.. ......| +>>> Flow 5 (server to client) +00000000 00 00 03 4c 13 1f 00 00 01 17 00 00 00 07 73 73 |...L..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 01 00 50 78 da cc 44 67 a1 5e fe c0 8a |.....Px..Dg.^...| +00000130 85 c8 e7 5d d2 54 85 e5 c0 70 b3 a3 a1 2c 3a 1f |...].T...p...,:.| +00000140 3c de 26 da a9 72 18 95 77 19 e9 1c 98 14 1c 18 |<.&..r..w.......| +00000150 e5 e1 e3 88 f4 0e 7d 3e 2a d1 28 71 98 85 5a 28 |......}>*.(q..Z(| +00000160 aa fa 63 38 ba bd d0 a0 4d c4 26 2d a9 0d de b6 |..c8....M.&-....| +00000170 30 0f 5a c9 ae 91 ce 96 5f 2e 94 f8 6b 62 6a 84 |0.Z....._...kbj.| +00000180 e5 2a b7 b1 51 d8 7c 90 9f c8 eb 2c fe d8 60 ad |.*..Q.|....,..`.| +00000190 6d 5a 20 57 4a c2 8d d0 f2 54 e0 7d 76 5b 0d 10 |mZ WJ....T.}v[..| +000001a0 4d b8 7c 2b 1a d5 53 f6 a2 5e c1 b5 45 01 97 eb |M.|+..S..^..E...| +000001b0 ce ff 60 a0 58 33 35 87 ce e5 93 53 7a 57 59 af |..`.X35....SzWY.| +000001c0 02 02 34 b5 3a e8 89 90 eb 6a d0 98 66 50 c6 93 |..4.:....j..fP..| +000001d0 37 d0 99 8b fc 6f f9 47 2f 8e f1 bb be 80 8a f3 |7....o.G/.......| +000001e0 c0 09 2b 6f ae 0a 56 c4 a2 3b 1c 51 1a ae d4 aa |..+o..V..;.Q....| +000001f0 62 3f 71 7c d4 cb ef 5c 41 9b 80 3a 75 16 7e 25 |b?q|...\A..:u.~%| +00000200 dd 7b ea a2 9a 03 4c da a5 fc 62 7b 76 53 11 a1 |.{....L...b{vS..| +00000210 39 6b 94 cc 2e b4 8b 2d 66 64 2a e2 51 8f 44 79 |9k.....-fd*.Q.Dy| +00000220 ac 75 8c bf d9 00 00 01 14 00 00 00 0c 72 73 61 |.u...........rsa| +00000230 2d 73 68 61 32 2d 35 31 32 00 00 01 00 44 33 fe |-sha2-512....D3.| +00000240 5e 47 46 28 0e 6d 08 4b 9e 41 45 88 d3 f8 44 70 |^GF(.m.K.AE...Dp| +00000250 71 25 f3 e8 7b 96 0e 6f 10 d9 08 c3 49 d3 35 12 |q%..{..o....I.5.| +00000260 96 9a 2f e8 c2 38 e1 1e a2 ba a2 2a 66 17 f5 68 |../..8.....*f..h| +00000270 61 b9 c8 ed d3 37 7c 73 f6 57 65 e3 58 4d 2d 73 |a....7|s.We.XM-s| +00000280 73 39 4e 00 66 be 3b 86 81 7d 9a b4 49 40 c4 77 |s9N.f.;..}..I@.w| +00000290 63 1d fc 2f ba 3c 36 af 58 89 1f 26 8f 8a 6e f2 |c../.<6.X..&..n.| +000002a0 90 09 00 01 dc 08 ff cc 86 26 0a 1a b0 95 a9 22 |.........&....."| +000002b0 65 66 69 cd 30 2f b9 1e 7c 27 84 5f dc 13 de 4c |efi.0/..|'._...L| +000002c0 d4 4e bd ac 26 5b ef 98 17 25 11 d7 38 64 58 73 |.N..&[...%..8dXs| +000002d0 48 0c 7c 2f 57 91 88 3e 19 4e d0 7f 18 71 5b e9 |H.|/W..>.N...q[.| +000002e0 c6 47 81 ef 89 93 bc 2e 16 cc db 99 08 5b 2d e2 |.G...........[-.| +000002f0 df 52 b0 c3 67 b6 13 1b 44 dd 89 27 a2 17 cf bd |.R..g...D..'....| +00000300 ee b1 3b 5e a9 be 46 8a a0 74 b5 e5 c0 a4 59 46 |..;^..F..t....YF| +00000310 4d 40 85 93 e4 cb 90 4b af da 2a f8 69 55 64 8d |M@.....K..*.iUd.| +00000320 08 4d df c7 d4 e0 4a ea e5 40 3d 42 b4 88 df 5c |.M....J..@=B...\| +00000330 e8 ce 5c 5d 7b 9a 43 84 1a 54 bc 8c e3 0c 59 3e |..\]{.C..T....Y>| +00000340 a3 ae eb 61 3a 7f 1b 1d e3 3f d7 50 81 f5 92 30 |...a:....?.P...0| +00000350 00 00 00 0c 0a 15 5f 2e 45 26 ed c0 96 31 b1 09 |......_.E&...1..| +00000360 2d 8b b0 e8 d7 5f 3b d1 e2 95 5c 56 49 ea fc d5 |-...._;...\VI...| +00000370 92 7f d6 67 3d 83 02 74 c1 af a6 3c b5 a9 be c1 |...g=..t...<....| +00000380 4d 08 da 79 5f 94 06 c0 e0 04 de 2d 11 61 4c ec |M..y_......-.aL.| +00000390 f3 2d b8 c5 7d b7 69 05 49 0b e3 e6 59 66 d7 45 |.-..}.i.I...Yf.E| +000003a0 92 f0 49 00 43 57 cc 7f 87 f1 63 05 34 43 2c 06 |..I.CW....c.4C,.| +000003b0 73 71 d2 86 f5 68 37 af 80 55 73 a8 ea 0a 1e e1 |sq...h7..Us.....| +000003c0 2c 88 a7 6d 66 b9 0b ce 84 21 8a 99 09 10 25 fd |,..mf....!....%.| +000003d0 58 75 cf 1d fd 74 20 31 f7 0c ef 82 06 2b 74 fe |Xu...t 1.....+t.| +000003e0 ce f6 3a 60 2e 90 7a d9 10 e2 da 50 08 23 fd 6b |..:`..z....P.#.k| +000003f0 d2 56 87 f7 70 a2 d1 64 3f 16 1a d6 25 5f ef 92 |.V..p..d?...%_..| +00000400 1a 78 f7 56 97 42 0e 29 a6 3b a7 02 1d 98 a9 7a |.x.V.B.).;.....z| +00000410 89 43 4b 6b 50 df 1c 00 39 c8 bd 31 f8 b8 55 d3 |.CKkP...9..1..U.| +00000420 6a a5 9e de 8e 5c 78 09 22 05 63 12 a8 2c b6 42 |j....\x.".c..,.B| +00000430 b9 1b 1f b8 e1 ee f6 b2 c5 22 2f a0 10 8b 70 79 |........."/...py| +00000440 a9 0b 43 e8 1b 81 30 24 af fa a9 d9 19 83 6b 06 |..C...0$......k.| +00000450 c6 d3 31 05 a6 f4 a3 63 9f 3c 43 9b 48 bf 12 be |..1....c.>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 cd eb 78 bd 32 cc fb 19 b8 a7 52 a9 8a da dc 10 |..x.2.....R.....| +00000020 c4 a9 c3 20 15 2a 78 d0 be 2c c4 9d d1 f2 3c 84 |... .*x..,....<.| +00000030 03 fe ad 6f 6d ee 8a 0e b5 cf a4 1c |...om.......| +>>> Flow 7 (server to client) +00000000 9e a1 f7 90 cf 4f 40 12 ac 39 a8 2d 9f 82 f4 d9 |.....O@..9.-....| +00000010 2f cc 5c c7 92 43 fb 91 04 d8 7f 3c f4 8b 75 12 |/.\..C.....<..u.| +00000020 23 c1 c7 e5 58 56 4c ab f3 6b e7 76 |#...XVL..k.v| +>>> Flow 8 (client to server) +00000000 92 d8 6c 09 b6 f2 c3 5d 53 ff cf b2 75 ff 3b 9f |..l....]S...u.;.| +00000010 e2 fc 73 3a 8a 19 4b b1 7a 6e a5 68 c4 70 47 0c |..s:..K.zn.h.pG.| +00000020 f9 c8 6e 06 27 16 53 ae 73 27 54 02 d2 7e 14 f9 |..n.'.S.s'T..~..| +00000030 dc a7 32 92 33 dd a7 76 06 b7 3e 69 4b d3 d9 4d |..2.3..v..>iK..M| +00000040 58 b8 af 13 |X...| +>>> Flow 9 (server to client) +00000000 96 80 5f 1a 7a bc 0d 10 7e f6 9b d1 f3 9c 0c d4 |.._.z...~.......| +00000010 55 64 5f 80 25 c4 b2 17 f1 bf 94 36 1c 7b ca 01 |Ud_.%......6.{..| +00000020 34 ea 2d 6a 34 6b 16 da fd 4e 22 5d |4.-j4k...N"]| +>>> Flow 10 (client to server) +00000000 5c 05 35 fc c9 91 f3 1c 5f 06 6e 4a 8b d1 41 d0 |\.5....._.nJ..A.| +00000010 9a ed 5d e6 59 bb 45 ac 50 3a 1d 53 e4 5f 56 d5 |..].Y.E.P:.S._V.| +00000020 87 07 0f 82 18 75 cd d7 41 79 2f 92 bc 98 7b 1f |.....u..Ay/...{.| +00000030 b8 2f 3b 56 36 d5 05 52 bb b3 a1 67 f0 69 8c 73 |./;V6..R...g.i.s| +00000040 d2 76 1f fa 25 00 53 20 f6 15 48 13 7c f4 9a 81 |.v..%.S ..H.|...| +00000050 ee 93 2d 8b 92 b3 67 ce 19 ce b4 79 74 42 bd 03 |..-...g....ytB..| +00000060 5d b9 84 ea 19 7e b8 a9 20 16 56 8c a1 9c 61 f1 |]....~.. .V...a.| +00000070 a6 3c 05 b3 00 09 84 61 df e3 81 6f 84 f1 86 6d |.<.....a...o...m| +00000080 12 50 84 36 4f 53 92 24 15 93 e9 05 17 3b 9b e8 |.P.6OS.$.....;..| +00000090 f9 cc c0 bd a2 da 86 04 c4 48 e1 c9 9e 5d 68 04 |.........H...]h.| +000000a0 08 6d 1e 0c e2 b0 e8 a1 d8 50 c8 b3 29 cb ee 26 |.m.......P..)..&| +000000b0 d2 06 22 5b 19 6c 29 d2 68 bd 8a ed 3d 59 b5 8c |.."[.l).h...=Y..| +000000c0 a5 5b 34 7d 1c 38 3d a2 99 6d f0 00 36 f3 b4 d1 |.[4}.8=..m..6...| +000000d0 4f d4 33 51 a7 23 fb de 44 4a dd f4 d1 9c 27 2e |O.3Q.#..DJ....'.| +000000e0 31 3e c8 3c 56 62 c1 a6 17 96 d9 e8 61 37 66 9f |1>.>> Flow 11 (server to client) +00000000 5e 94 3b 46 a8 c3 1a bd e8 50 a9 27 ca c8 3f d4 |^.;F.....P.'..?.| +00000010 a7 2d 72 c4 16 cf 5a 55 95 9a b8 ec 34 a4 15 24 |.-r...ZU....4..$| +00000020 c3 3b 90 e7 5e 2a 43 61 63 7e 5a b9 97 19 11 24 |.;..^*Cac~Z....$| +00000030 b8 20 3b 2a 34 5d d4 18 8e 37 0e 3c d7 79 4b ea |. ;*4]...7.<.yK.| +00000040 42 c2 ba 00 46 70 3f 98 4e ed 1c 4c 92 57 7c b5 |B...Fp?.N..L.W|.| +00000050 fd de a7 04 c7 d0 d8 a9 56 ec 07 9c 60 d7 6f 6f |........V...`.oo| +00000060 3a fb 25 ec 07 f7 b5 a4 e5 36 12 cd 5d 8f bc d0 |:.%......6..]...| +00000070 da 94 5c 2a 98 31 6f 04 76 33 5d 0e 88 d3 d7 87 |..\*.1o.v3].....| +00000080 be 18 b0 cb 14 ee ce f6 87 a9 11 94 96 9c b3 7b |...............{| +00000090 a2 69 ce 4e 61 c0 d9 66 96 79 86 02 03 ad b9 3c |.i.Na..f.y.....<| +000000a0 b7 0d 10 f9 fa ca 45 c0 08 6a 55 9d 3b bf e6 01 |......E..jU.;...| +000000b0 0e dc 15 38 9e eb df cc 96 ce af cb 8b 94 31 70 |...8..........1p| +000000c0 2e 6f 8d 63 36 d3 27 9e c4 0b c0 c2 94 52 d8 a2 |.o.c6.'......R..| +000000d0 86 7a 44 4d 48 d7 fc c4 b2 90 79 e8 46 e3 49 02 |.zDMH.....y.F.I.| +000000e0 e9 99 c7 28 23 3b ca 8e 58 96 a0 35 72 11 95 71 |...(#;..X..5r..q| +000000f0 ba 7b a1 55 cd fa 1e 9b 08 a7 82 6d 99 fd 1e c5 |.{.U.......m....| +00000100 6e c3 db ae c6 c3 bb 60 0e ba f6 ce 39 94 c8 8a |n......`....9...| +00000110 a1 8d 4b 53 a0 ac 02 32 bd dd 13 3e 65 fe 36 ee |..KS...2...>e.6.| +00000120 cd f7 f6 55 f6 63 7a 5d 7e 55 f5 aa 40 44 47 f4 |...U.cz]~U..@DG.| +00000130 27 39 6d e9 cb 8b 18 bd 86 07 bf b7 f3 b2 7b 43 |'9m...........{C| +00000140 30 29 64 ca 38 f9 5d 92 dc 90 e2 8e |0)d.8.].....| +>>> Flow 12 (client to server) +00000000 f6 b7 d6 08 b1 d6 c5 67 d0 ba f1 69 96 9a 52 f6 |.......g...i..R.| +00000010 30 dc 5d 40 4c 49 e5 6a fe a9 da 42 a8 e5 81 57 |0.]@LI.j...B...W| +00000020 db a2 6f 9a 8c 96 bb 27 50 f1 35 53 48 b8 60 b8 |..o....'P.5SH.`.| +00000030 45 86 b4 a6 6d 7c d2 af 4e 6a 0d 5e 19 3a 78 1c |E...m|..Nj.^.:x.| +00000040 4b b0 f5 94 93 af ff 82 61 00 ba 33 60 78 ea 1f |K.......a..3`x..| +00000050 a9 1c cf 2c 1f 6a 2b 27 d7 bd 13 1e 57 8c 6b a9 |...,.j+'....W.k.| +00000060 61 b4 93 3a d9 08 ec 4d 34 7c 5b a1 ee b8 3e c2 |a..:...M4|[...>.| +00000070 4d 49 30 24 e1 59 81 4c 55 4f 8b fd f0 8f c0 79 |MI0$.Y.LUO.....y| +00000080 a3 64 64 0c fc a4 df d9 ae b2 2e 0a 91 25 e4 41 |.dd..........%.A| +00000090 90 89 60 8e 37 da 8d 16 83 e4 e9 44 7b 30 e0 f9 |..`.7......D{0..| +000000a0 60 3d a6 16 a9 aa 8b c7 f1 35 70 db 2c d7 79 de |`=.......5p.,.y.| +000000b0 78 b9 91 6a f8 6e 8b e5 47 a4 f4 b3 d4 1d 45 f4 |x..j.n..G.....E.| +000000c0 17 5b 3b e7 28 1b 7d 62 a7 7d 12 19 73 2c 76 5b |.[;.(.}b.}..s,v[| +000000d0 ec fb 38 ea c7 6e 94 05 1b 7f 45 9d 79 75 62 59 |..8..n....E.yubY| +000000e0 c2 fd cc af 67 21 f9 ba cd 04 1c 7d 65 f7 3e 65 |....g!.....}e.>e| +000000f0 f5 95 63 ad 87 31 aa d9 17 bb 80 3c f4 2f 88 6b |..c..1.....<./.k| +00000100 3b b5 f9 69 e3 7b e8 3f 6a aa 71 85 b3 46 2b 32 |;..i.{.?j.q..F+2| +00000110 9a a7 b7 a9 b7 bc d8 ad 3c cf ee 7b a2 e1 32 6a |........<..{..2j| +00000120 f9 06 06 ef ad 0e b8 f4 42 7d 6f 47 67 a6 83 4b |........B}oGg..K| +00000130 6e b0 ba 9b c2 77 5b 2c 89 90 2e ba 65 2d 4a 8d |n....w[,....e-J.| +00000140 1a 87 83 11 bd a8 da 98 1c 96 71 64 4f e9 10 86 |..........qdO...| +00000150 26 fe c4 39 1e 81 24 0b 8a 7e 61 9d 57 44 75 c9 |&..9..$..~a.WDu.| +00000160 c1 2a 81 77 d4 0d e7 b8 45 37 c3 fc d9 70 47 e4 |.*.w....E7...pG.| +00000170 44 88 35 cb 3b 3e f8 04 9f 15 d7 bb 30 a2 10 0d |D.5.;>......0...| +00000180 cc 37 d1 b0 5e b9 5a f2 a3 97 01 38 53 2a 63 e5 |.7..^.Z....8S*c.| +00000190 a5 ec cc 07 6e 6c 5f de 6c 9b da 51 5f 23 0d f8 |....nl_.l..Q_#..| +000001a0 94 c0 20 56 b7 4e 31 18 19 3d 87 91 f3 69 06 aa |.. V.N1..=...i..| +000001b0 c3 1a af 75 49 18 5b 36 d0 70 23 69 31 d2 60 c2 |...uI.[6.p#i1.`.| +000001c0 99 23 3b a8 8d 55 9c 36 02 57 2b c4 10 bb 80 f2 |.#;..U.6.W+.....| +000001d0 1f a9 27 41 bf af 05 23 50 7a 0e a7 2c d1 eb bd |..'A...#Pz..,...| +000001e0 d9 d0 15 c5 f9 e8 11 d5 e4 fb 44 bd 42 2b ed 31 |..........D.B+.1| +000001f0 bf b7 85 e6 d0 91 61 8f 66 37 b6 a4 69 d5 10 93 |......a.f7..i...| +00000200 63 f2 14 30 92 50 bb 70 ab a1 94 22 a9 76 54 cf |c..0.P.p...".vT.| +00000210 f2 c2 1e 97 d1 83 b3 e2 1d 51 39 41 f3 09 f5 c8 |.........Q9A....| +00000220 cb 55 68 1e f6 fc e9 d3 bb 92 c0 04 b8 2f 2a 28 |.Uh........../*(| +00000230 d6 70 14 c1 55 8b 9d 4d ff 49 42 2b 4b cf f3 4b |.p..U..M.IB+K..K| +00000240 79 f4 7b ac 6c f6 40 56 2e 17 ee b3 8c 7b 66 f9 |y.{.l.@V.....{f.| +00000250 3e b6 d5 45 2d 02 28 36 d0 d4 c8 4e 4d a0 30 fe |>..E-.(6...NM.0.| +00000260 6d 34 7b d8 b9 c0 1f 2c 0c 00 b5 0f 27 eb f6 f5 |m4{....,....'...| +00000270 8d 57 27 94 d0 74 13 d3 65 3d af 0c de 0a 33 30 |.W'..t..e=....30| +00000280 e9 fc 48 18 04 e5 9b 0e ff 04 99 c6 |..H.........| +>>> Flow 13 (server to client) +00000000 33 1f 0e 14 3b 90 85 21 b2 61 9e 03 59 57 6e ff |3...;..!.a..YWn.| +00000010 10 9e eb ed 2a d6 07 43 6b 32 79 a4 |....*..Ck2y.| +>>> Flow 14 (client to server) +00000000 0c 2d b5 85 48 67 bf c9 86 4b 39 31 8a 97 2b bf |.-..Hg...K91..+.| +00000010 9d 76 63 fd 2b 1f c0 1c d7 ce 5a bb 8a ff 1d de |.vc.+.....Z.....| +00000020 34 eb 52 65 9e 7f 6f 2a ac 08 8e 71 9d 9e 96 97 |4.Re..o*...q....| +00000030 a4 14 bd 3c |...<| +>>> Flow 15 (server to client) +00000000 45 f5 10 51 9b 1d d7 a7 c5 eb f6 30 b9 a7 4a 1a |E..Q.......0..J.| +00000010 58 85 c0 e5 17 a0 2d 12 21 3f 32 12 33 29 7c a5 |X.....-.!?2.3)|.| +00000020 17 77 ad f8 29 4c 6c e9 8f 1b b2 87 |.w..)Ll.....| +>>> Flow 16 (client to server) +00000000 2b 98 d6 40 ac 5c 9c e3 5c 0c f4 e2 71 b0 c9 26 |+..@.\..\...q..&| +00000010 d0 1d a8 2c 4a 10 36 80 4b 27 c9 20 a6 63 73 7c |...,J.6.K'. .cs|| +00000020 ac a3 6d f2 a7 f5 01 91 24 2d 45 86 cb 84 73 4c |..m.....$-E...sL| +00000030 1a c3 fc d9 23 bb 74 30 25 60 92 05 1b a8 f8 d1 |....#.t0%`......| +00000040 aa 02 8f d2 4b 56 07 78 46 2e a0 c0 ac fd a0 42 |....KV.xF......B| +00000050 3b 2f ed 7d f3 26 b9 51 |;/.}.&.Q| +>>> Flow 17 (server to client) +00000000 58 d2 f3 75 39 2a 78 69 7d 05 5d 97 59 76 99 7d |X..u9*xi}.].Yv.}| +00000010 9a 64 73 9c 2f f6 0d 20 bb e9 5f b8 5a 26 a1 43 |.ds./.. .._.Z&.C| +00000020 20 17 2c 9c d4 45 c1 4e 3b 75 0c 50 2d 84 4e 20 | .,..E.N;u.P-.N | +00000030 45 5c ad 00 3b f1 9d 57 97 c9 e1 94 65 fb be 3e |E\..;..W....e..>| +00000040 cd 1c fe f5 b2 f1 f5 8b 77 e1 04 e6 db 6e 51 f4 |........w....nQ.| +00000050 a0 50 84 a8 2e d4 3e 22 c5 46 d4 ce 34 55 53 f1 |.P....>".F..4US.| +00000060 8f 24 2d e9 e2 1d 85 9e cb 55 38 65 bc 28 ad 3e |.$-......U8e.(.>| +00000070 ce f0 ac 46 46 5c 4f fe 8f 76 7e 23 |...FF\O..v~#| +>>> Flow 18 (client to server) +00000000 5c fe 55 45 f3 5f 46 a2 36 f7 0c 15 8b 80 d8 7b |\.UE._F.6......{| +00000010 53 b9 92 1e 8d 69 1e 5a ee d9 86 c1 b0 41 01 ce |S....i.Z.....A..| +00000020 f9 38 fe 8e cf 55 ad 4f c6 a1 c7 44 32 45 c6 63 |.8...U.O...D2E.c| +00000030 49 1a 8b 19 bc ca c9 03 2a d1 55 4a 61 38 bc 7e |I.......*.UJa8.~| +00000040 89 5f cf 43 19 d0 12 09 ba 08 21 02 35 75 19 9d |._.C......!.5u..| +00000050 d6 fa 57 c7 71 a0 32 1b 90 ab 9e f9 38 8d 10 9f |..W.q.2.....8...| diff --git a/ssh/testdata/Server-KEX-diffie-hellman-group16-sha512 b/ssh/testdata/Server-KEX-diffie-hellman-group16-sha512 new file mode 100644 index 0000000000..c37ef8cfb8 --- /dev/null +++ b/ssh/testdata/Server-KEX-diffie-hellman-group16-sha512 @@ -0,0 +1,409 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 5c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...\....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 3a 64 69 66 66 69 65 |EPv..>...:diffie| +00000020 2d 68 65 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 |-hellman-group16| +00000030 2d 73 68 61 35 31 32 2c 6b 65 78 2d 73 74 72 69 |-sha512,kex-stri| +00000040 63 74 2d 73 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-s-v00@openssh| +00000050 2e 63 6f 6d 00 00 00 21 72 73 61 2d 73 68 61 32 |.com...!rsa-sha2| +00000060 2d 32 35 36 2c 72 73 61 2d 73 68 61 32 2d 35 31 |-256,rsa-sha2-51| +00000070 32 2c 73 73 68 2d 72 73 61 00 00 00 6c 61 65 73 |2,ssh-rsa...laes| +00000080 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |128-gcm@openssh.| +00000090 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f |com,aes256-gcm@o| +000000a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 |penssh.com,chach| +000000b0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000000c0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +000000d0 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000000e0 65 73 32 35 36 2d 63 74 72 00 00 00 6c 61 65 73 |es256-ctr...laes| +000000f0 31 32 38 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e |128-gcm@openssh.| +00000100 63 6f 6d 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f |com,aes256-gcm@o| +00000110 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 68 61 63 68 |penssh.com,chach| +00000120 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000130 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000140 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000150 65 73 32 35 36 2d 63 74 72 00 00 00 6e 68 6d 61 |es256-ctr...nhma| +00000160 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f |c-sha2-256-etm@o| +00000170 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000180 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 |sha2-512-etm@ope| +00000190 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 |nssh.com,hmac-sh| +000001a0 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 61 32 |a2-256,hmac-sha2| +000001b0 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 2c 68 |-512,hmac-sha1,h| +000001c0 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 6e 68 |mac-sha1-96...nh| +000001d0 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d |mac-sha2-256-etm| +000001e0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 |@openssh.com,hma| +000001f0 63 2d 73 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f |c-sha2-512-etm@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000210 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000220 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000230 2c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |,hmac-sha1-96...| +00000240 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000250 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 b2 21 5c c9 38 f4 f8 56 07 86 |...<...!\.8..V..| +00000010 bf f6 2c 7b 75 6f 00 00 01 7a 73 6e 74 72 75 70 |..,{uo...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 02 0c 05 1e 00 00 02 01 00 ca 77 a8 1a 84 |............w...| +00000650 a6 fd e4 a3 cd 55 49 f9 88 1f a2 d2 6e 25 67 88 |.....UI.....n%g.| +00000660 09 db bc ba 33 aa 14 88 46 14 bb ad 6a 80 92 33 |....3...F...j..3| +00000670 c3 80 10 f6 ee 0f 35 81 b1 20 c4 04 84 ba 71 da |......5.. ....q.| +00000680 db 91 9d 08 bd 44 84 a3 7d 9e 60 27 3a ef 7a c2 |.....D..}.`':.z.| +00000690 6b 9e 62 7b b5 9e 0d 0b 51 ac 23 00 34 3f 1c 0b |k.b{....Q.#.4?..| +000006a0 61 50 8b 12 57 45 bf 75 95 e5 49 91 0f e4 b2 ea |aP..WE.u..I.....| +000006b0 e2 f5 0b 1a d1 c4 c1 c1 b1 1c 64 cc cb a7 67 d8 |..........d...g.| +000006c0 18 1b 35 49 fc 19 11 1b 5a e5 32 df 97 50 48 51 |..5I....Z.2..PHQ| +000006d0 a3 2b 68 e0 ef a7 a9 5d 10 ec 27 cd 9a 60 0f 78 |.+h....]..'..`.x| +000006e0 b7 c2 1c b0 d1 49 f2 7a c7 1f f0 01 52 aa cb 46 |.....I.z....R..F| +000006f0 01 40 d7 09 12 c6 08 ea 88 d4 8e be 61 f0 e7 b6 |.@..........a...| +00000700 1e ec a7 31 17 fa c1 8c 73 aa 56 08 5b f9 7e ae |...1....s.V.[.~.| +00000710 b7 1f 31 8d 20 0f dc 4e 54 24 83 37 86 21 76 d1 |..1. ..NT$.7.!v.| +00000720 70 c7 65 69 e0 3c 19 80 17 26 d0 71 17 36 ac b2 |p.ei.<...&.q.6..| +00000730 25 69 21 ff ef 2c ed a0 d1 42 bc e0 bb db 63 65 |%i!..,...B....ce| +00000740 4c f3 9c 9c 34 f4 4c 73 3c a9 5e 1a ea 64 60 45 |L...4.Ls<.^..d`E| +00000750 55 de 16 e6 82 b7 31 bc cb e9 ad 55 3a 6d 06 51 |U.....1....U:m.Q| +00000760 f7 16 12 32 46 17 d5 7a 68 9f 06 ac 46 30 ca ee |...2F..zh...F0..| +00000770 47 4a dc bd 9a 77 09 b8 67 78 ee 6d f0 7e e9 20 |GJ...w..gx.m.~. | +00000780 be 25 af 1e 2b 90 e7 38 87 bb fa 4f 93 5e 9a 2d |.%..+..8...O.^.-| +00000790 48 fa 60 9a 2d 14 4d f5 02 2f c2 32 35 a0 46 9e |H.`.-.M../.25.F.| +000007a0 62 3b 35 ec 61 48 e8 15 e3 92 84 0c b3 0b e5 f7 |b;5.aH..........| +000007b0 48 51 4c e0 57 e5 03 bd 0a 1b 62 c7 91 b8 9b e9 |HQL.W.....b.....| +000007c0 65 4a a2 fa ce 0f de 95 3a 77 9d 5e b3 c8 d0 1b |eJ......:w.^....| +000007d0 e0 07 30 85 dd 6c 92 07 98 78 3c d2 de 34 7d c8 |..0..l...x<..4}.| +000007e0 2a 12 b1 b3 da c5 30 b2 e9 93 17 b4 ad 54 85 20 |*.....0......T. | +000007f0 f1 f6 ae a8 ba f7 0f 88 a3 c1 ec 2d 66 02 be 9c |...........-f...| +00000800 56 ce 01 8f 55 f1 12 5a e6 34 29 7e 19 c4 82 b2 |V...U..Z.4)~....| +00000810 83 86 a9 5a 43 d0 76 79 93 24 d9 a5 b2 3c f2 3c |...ZC.vy.$...<.<| +00000820 12 be 6d 65 02 95 99 d6 4f f9 bf a4 46 08 42 de |..me....O...F.B.| +00000830 d1 f2 b8 11 aa f3 49 c0 b9 72 d4 27 26 3a ef 8d |......I..r.'&:..| +00000840 97 3b 1e 7e 54 64 c3 8d 51 84 14 00 00 00 00 00 |.;.~Td..Q.......| +>>> Flow 5 (server to client) +00000000 00 00 04 4c 12 1f 00 00 01 17 00 00 00 07 73 73 |...L..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 02 01 00 dc 6e 30 c3 fe 5c ce e6 51 5a |.......n0..\..QZ| +00000130 ea 36 6a a9 c9 81 d4 28 dc 6c 67 7b 6e bf 3e 6d |.6j....(.lg{n.>m| +00000140 36 74 a1 be e3 6c 30 f9 22 70 ee e4 7a 75 c4 15 |6t...l0."p..zu..| +00000150 b6 c3 ae 09 c0 5c bc 97 0d 6c 2a 35 5c a9 1d e4 |.....\...l*5\...| +00000160 03 1a d3 c6 cc 23 e2 37 8e 7c 38 43 46 a8 49 78 |.....#.7.|8CF.Ix| +00000170 02 f4 9e da ea 91 ff 19 a2 87 1b 53 f1 88 9a ae |...........S....| +00000180 45 ac fd 35 ad f7 83 5f de 74 6e 9f 0b f6 b1 91 |E..5..._.tn.....| +00000190 16 e8 a1 b6 6e ed 73 9a 4b ca 18 11 52 be 8d d2 |....n.s.K...R...| +000001a0 ca 42 5c e0 7f f6 64 b5 04 98 30 6c ef 59 f5 f5 |.B\...d...0l.Y..| +000001b0 3f d7 91 47 2b a2 f2 fd 90 82 f4 68 97 8e f1 14 |?..G+......h....| +000001c0 b4 db 4e 3f 18 de f3 c8 07 7e f2 33 75 3b 67 26 |..N?.....~.3u;g&| +000001d0 58 28 e1 56 6a a0 7b 2f 8f de 5f 7f 22 fd 7d 2c |X(.Vj.{/.._.".},| +000001e0 22 11 f0 22 3a 85 f5 15 4b e8 95 16 20 1c 88 6c |"..":...K... ..l| +000001f0 5a c7 02 3a 63 66 19 0f 9e 69 b1 a4 c0 25 56 be |Z..:cf...i...%V.| +00000200 58 a0 ee 88 55 d9 1f 26 7a 55 ff 4a 75 6b ec db |X...U..&zU.Juk..| +00000210 c1 fc 89 58 b8 16 b8 ce 9f 60 a7 f8 cf b8 6a 73 |...X.....`....js| +00000220 66 e7 89 96 c9 7e 31 ee 72 74 bd ac e8 11 90 6c |f....~1.rt.....l| +00000230 31 bd 04 d1 40 34 00 67 2e 1b fe 52 99 06 86 9a |1...@4.g...R....| +00000240 11 cf 5f d4 10 17 20 ec f6 d8 c6 14 9e ae fc 5a |.._... ........Z| +00000250 4b f2 89 d0 6e 06 ca 0c 4e dd c8 31 01 15 60 24 |K...n...N..1..`$| +00000260 81 fb 18 91 a5 37 d5 05 ce 7e 16 0e 1e a2 9f 54 |.....7...~.....T| +00000270 22 f7 16 74 c9 5a 40 79 e0 fe 33 6f be c6 00 ba |"..t.Z@y..3o....| +00000280 03 2a c7 b3 11 32 c3 d0 f5 c5 4a 28 4a 0b 25 53 |.*...2....J(J.%S| +00000290 a1 4c c2 01 44 b9 27 37 29 ed 3a fe a2 e0 50 ff |.L..D.'7).:...P.| +000002a0 c2 55 92 51 98 a1 82 d5 cb 45 39 cb 7f bd 23 37 |.U.Q.....E9...#7| +000002b0 13 88 1f 48 ff 12 1f fe 7e b2 74 29 4c d5 63 41 |...H....~.t)L.cA| +000002c0 b6 e8 dc 05 58 db 27 51 a9 3e 16 84 57 a3 09 61 |....X.'Q.>..W..a| +000002d0 71 f5 14 63 24 c9 d1 51 5d a4 dd ba a5 7b c3 bc |q..c$..Q]....{..| +000002e0 2e 4e 10 fd b6 bd 46 b5 09 6f b5 64 a5 c8 32 23 |.N....F..o.d..2#| +000002f0 37 6b 64 e4 52 69 22 b5 2d 77 c4 3d 35 e1 aa d5 |7kd.Ri".-w.=5...| +00000300 cc 86 33 72 5b d9 ad 4c 24 17 cc 48 c1 17 92 b9 |..3r[..L$..H....| +00000310 46 83 4a c6 93 a8 ec f9 33 cd 9a b0 b1 13 02 27 |F.J.....3......'| +00000320 e1 25 62 71 78 42 00 00 01 14 00 00 00 0c 72 73 |.%bqxB........rs| +00000330 61 2d 73 68 61 32 2d 35 31 32 00 00 01 00 7f c1 |a-sha2-512......| +00000340 b7 8c 49 07 08 dd 37 91 08 23 56 e2 bb 21 fd 04 |..I...7..#V..!..| +00000350 76 d7 72 4e e3 48 0b ae 47 0e cf 44 7e 55 47 e4 |v.rN.H..G..D~UG.| +00000360 fe 95 e7 d8 f2 5b 76 b1 77 38 c6 6f 99 49 bc 88 |.....[v.w8.o.I..| +00000370 ff d9 31 1f 06 50 19 3f b7 7d c0 49 89 b6 84 12 |..1..P.?.}.I....| +00000380 06 14 c5 21 58 c4 40 9c 64 b7 6a e9 1a 4b 9d 37 |...!X.@.d.j..K.7| +00000390 e3 be 9b 01 9e ef eb b5 15 fb c5 eb 05 f1 5d 2a |..............]*| +000003a0 90 60 42 66 87 54 cc 30 a7 2a 15 e7 29 3c 6f b8 |.`Bf.T.0.*..)..g....s.?wj..| +000003e0 9c 7a 99 ef 97 0a 55 4f 2a af 68 e5 a8 bc ca da |.z....UO*.h.....| +000003f0 82 f6 d4 30 cf f1 f1 db f0 55 92 6a 12 08 16 8f |...0.....U.j....| +00000400 1e 3a 34 e9 c1 79 a5 b1 9a c2 02 ec 32 92 e0 a5 |.:4..y......2...| +00000410 aa 9c e5 be 92 f7 3e 0c 71 9b ca 54 72 cb 45 1b |......>.q..Tr.E.| +00000420 60 ad 51 d8 26 d1 b6 42 ab 6b 48 9f 6b 8a de 00 |`.Q.&..B.kH.k...| +00000430 3a 94 13 ab 81 0d 51 bd 42 5b 71 2e d4 2b 2e e0 |:.....Q.B[q..+..| +00000440 97 f0 51 26 6b e6 9d c7 16 fd ee f9 1b 0d 4a b2 |..Q&k.........J.| +00000450 00 00 00 0c 0a 15 de 52 55 50 bf 80 dc 8a 68 4b |.......RUP....hK| +00000460 74 85 13 58 71 09 42 99 7e b2 4a 6a 52 3c d4 da |t..Xq.B.~.JjR<..| +00000470 01 a2 5d a2 8e bd c1 14 e0 8b 34 d3 2b 82 fd 26 |..].......4.+..&| +00000480 3f 73 db 46 b5 71 ad 2b f0 a8 92 a0 a1 5c 03 f0 |?s.F.q.+.....\..| +00000490 26 1c ed 1f d1 64 9a 8b 8a 64 7c 6d 2b f6 ff ef |&....d...d|m+...| +000004a0 52 ed b3 57 2e 92 18 38 69 cc 52 1b 5c 9d 7e 9d |R..W...8i.R.\.~.| +000004b0 5f 88 59 d6 80 a9 34 69 ae d2 69 bf 72 c1 ee 2b |_.Y...4i..i.r..+| +000004c0 b0 e7 4b e7 54 32 a2 37 ba 62 fd 9e 10 e4 50 07 |..K.T2.7.b....P.| +000004d0 65 84 b7 52 35 e1 5e dd 17 6e 32 9c 01 6a 3a 89 |e..R5.^..n2..j:.| +000004e0 42 94 4b 4b c5 78 de c8 30 7d 42 70 2d 2d ec c4 |B.KK.x..0}Bp--..| +000004f0 01 fc 78 c1 a4 51 99 cd e9 97 93 3f 43 d3 01 ce |..x..Q.....?C...| +00000500 1b 03 52 67 ca b3 cf 81 32 7a 28 f5 62 ac 72 52 |..Rg....2z(.b.rR| +00000510 a4 48 4e 7d 0f 5a 6a 55 e5 c0 62 3c ea d2 c9 3c |.HN}.ZjU..b<...<| +00000520 97 44 7b b7 96 4d cf 04 51 83 69 1a 67 95 8c f9 |.D{..M..Q.i.g...| +00000530 88 d7 81 77 6a 60 cf 7b 8c 12 ff 74 2c 4b d2 4e |...wj`.{...t,K.N| +00000540 f8 42 86 d6 0b 76 82 b2 4d 22 0d 16 f0 70 74 6c |.B...v..M"...ptl| +00000550 fc 54 32 a1 7b 5e 2b 8d 40 a0 93 24 d1 61 31 ec |.T2.{^+.@..$.a1.| +00000560 6a 07 65 b4 |j.e.| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 f9 58 80 7a 79 5b 76 62 d3 55 c8 a7 81 31 e4 dd |.X.zy[vb.U...1..| +00000020 ad ae 58 2f 12 91 3b c1 66 cd a3 4e 4f b4 c0 e4 |..X/..;.f..NO...| +00000030 59 20 af 8d 76 63 33 4f e9 f2 ca 61 |Y ..vc3O...a| +>>> Flow 7 (server to client) +00000000 b7 40 82 10 08 e0 e5 f1 92 e1 49 dd 1c 1b ec f6 |.@........I.....| +00000010 c3 e3 c8 a4 b3 7a 30 5d dd 44 03 f0 be b0 8d 7c |.....z0].D.....|| +00000020 af ba ff cc 67 14 63 10 fb 43 78 8f |....g.c..Cx.| +>>> Flow 8 (client to server) +00000000 41 5f 37 17 1a 9d 0e 81 91 bf 5b 36 73 ed 58 fb |A_7.......[6s.X.| +00000010 d1 dc 19 c0 bf 03 ba 92 30 c8 77 5e fa a7 00 48 |........0.w^...H| +00000020 a6 be ed a1 4c 21 84 af 1e 66 96 fd e6 60 b5 b2 |....L!...f...`..| +00000030 43 5f b1 0c 8e 7c fb 65 e8 12 2e cb ec 25 1e 30 |C_...|.e.....%.0| +00000040 13 8b 2a 07 |..*.| +>>> Flow 9 (server to client) +00000000 6b dd a1 1d 57 c1 5d 66 00 d8 7e 6c 34 67 81 d5 |k...W.]f..~l4g..| +00000010 87 f0 0a 51 b2 c8 34 d5 47 50 6d ab bb 5e a7 aa |...Q..4.GPm..^..| +00000020 15 7d 4f 7d 2d 54 21 e1 6a 5a ee 43 |.}O}-T!.jZ.C| +>>> Flow 10 (client to server) +00000000 42 5d 05 3c 8f 55 0c 09 3a 96 22 13 dc b0 e3 62 |B].<.U..:."....b| +00000010 fe 44 c3 47 cf 24 c5 47 04 c1 91 eb 38 fb af 54 |.D.G.$.G....8..T| +00000020 e9 70 f2 ed 32 7b 6c 6d 7c 44 52 f9 8e 66 cf 86 |.p..2{lm|DR..f..| +00000030 43 d9 a9 5b 3d fd 78 e1 e6 b7 b7 b0 2e d7 22 24 |C..[=.x......."$| +00000040 54 93 24 16 d3 65 92 0e bd 12 91 c2 4c 77 4f bb |T.$..e......LwO.| +00000050 13 6c 82 27 88 1d 88 3e d6 13 72 a9 26 42 86 d4 |.l.'...>..r.&B..| +00000060 40 8c 89 a8 25 fa e9 dc 7f 49 ad 93 70 1b 79 07 |@...%....I..p.y.| +00000070 8b 37 5d 16 d7 69 55 b4 6c 55 ea b0 70 11 47 12 |.7]..iU.lU..p.G.| +00000080 9e 77 2f 29 07 f6 c9 e6 ea d0 3c 4d c7 08 5c 35 |.w/)........7..| +000000b0 2a 7a 34 c4 53 d6 22 e9 e0 04 25 56 1b e9 2a 8c |*z4.S."...%V..*.| +000000c0 1f b5 e8 05 27 da 10 f9 f9 d5 86 f9 3d ee 1c 54 |....'.......=..T| +000000d0 3c a6 76 04 96 95 3a e5 19 71 fb fa 5a 87 46 19 |<.v...:..q..Z.F.| +000000e0 ed fd 9c af f1 61 52 82 a4 32 35 b6 46 69 91 04 |.....aR..25.Fi..| +000000f0 43 7b 87 ab 15 50 43 58 45 b7 28 25 23 f4 08 7f |C{...PCXE.(%#...| +00000100 f1 2a 08 c8 db 24 98 f8 61 91 09 19 1d 50 f8 d7 |.*...$..a....P..| +00000110 9f d9 02 b6 22 ab a6 3f 2c e0 d2 33 ad 87 fc 52 |...."..?,..3...R| +00000120 b5 1b fe 6f a9 a9 17 5e 66 c5 af 5e 11 74 95 8e |...o...^f..^.t..| +00000130 53 fd 0f 19 2e ff 9b e9 08 94 48 53 88 3b ae 72 |S.........HS.;.r| +00000140 10 44 00 98 a4 82 cb 0f 13 58 34 c7 5d 81 6e eb |.D.......X4.].n.| +00000150 14 86 00 2e b0 04 3b 50 01 52 5a c0 57 f6 a1 46 |......;P.RZ.W..F| +00000160 75 c9 09 7d 3d b6 45 77 d2 e9 22 05 7f 0c 2f 3d |u..}=.Ew..".../=| +00000170 41 ed 06 c3 |A...| +>>> Flow 11 (server to client) +00000000 a4 58 76 d1 cd c9 70 e3 a4 f7 37 c3 00 44 42 e7 |.Xv...p...7..DB.| +00000010 52 e1 3c 2d b1 cd da 12 33 80 66 e0 30 b0 17 ae |R.<-....3.f.0...| +00000020 12 14 5e 9e 5d 80 78 7e fa 5b b8 0b 9a d0 06 03 |..^.].x~.[......| +00000030 dd 87 55 97 81 8e f4 88 9d 94 c3 da 8f 19 e5 42 |..U............B| +00000040 f3 b4 e4 6f 74 27 53 d8 c9 f2 df 15 c5 21 91 0b |...ot'S......!..| +00000050 a9 20 b6 51 bd 8f 26 0d 1b 2a f1 77 b0 90 a9 61 |. .Q..&..*.w...a| +00000060 28 0f a8 42 8e e6 58 e2 18 5f 0d 75 24 01 5e b5 |(..B..X.._.u$.^.| +00000070 83 12 41 98 50 67 5f 57 b5 cc b2 19 8c 10 82 0d |..A.Pg_W........| +00000080 d0 77 35 fb 21 f1 15 5f b5 9b e6 21 10 5f da 02 |.w5.!.._...!._..| +00000090 3e f2 34 a9 86 ec fb 7f ac e0 c4 5b 70 61 17 49 |>.4........[pa.I| +000000a0 19 2a 99 42 51 7e 8d 9e a3 67 1e f6 3a f8 e4 bb |.*.BQ~...g..:...| +000000b0 f7 90 89 c3 f2 51 51 ea 33 87 39 a7 e5 3a 2d 1a |.....QQ.3.9..:-.| +000000c0 9d 9d 29 5d 15 80 b1 aa d4 66 1d f1 fa a8 5d f4 |..)].....f....].| +000000d0 32 32 ef 72 74 c3 0d 92 bf f9 13 a5 4f 99 d0 28 |22.rt.......O..(| +000000e0 a8 50 1b 82 7c 5d 2d d7 ff 98 20 36 ab 60 7e 9a |.P..|]-... 6.`~.| +000000f0 a3 69 8f c7 dc 35 b9 a7 36 2f ac f6 72 1d 31 8e |.i...5..6/..r.1.| +00000100 11 ee b9 9c ce d2 1e dd f6 c0 38 cb 54 3c 32 a6 |..........8.T<2.| +00000110 cd 43 d7 32 f7 14 13 00 20 02 f4 aa d2 7c a0 e9 |.C.2.... ....|..| +00000120 09 7b 3b a7 ed b5 ca 92 01 1a 3f 5a c1 cd 2d 42 |.{;.......?Z..-B| +00000130 d6 db ee 74 d2 9e 37 80 f4 d0 5b 90 66 79 c4 a3 |...t..7...[.fy..| +00000140 59 67 bc 7d 72 85 8b 44 69 d1 b6 5d |Yg.}r..Di..]| +>>> Flow 12 (client to server) +00000000 2a ce f9 ab c0 63 7b 9f 71 d1 d8 85 77 6d b4 83 |*....c{.q...wm..| +00000010 5a 41 09 96 7a 13 47 dd 48 47 2a c5 85 b4 2f ab |ZA..z.G.HG*.../.| +00000020 13 4e e7 33 ea c9 c3 c1 6d 47 48 e3 2a 14 a9 15 |.N.3....mGH.*...| +00000030 06 36 d4 d6 dd 6a 52 8a 74 4f 80 57 b6 63 6c b0 |.6...jR.tO.W.cl.| +00000040 4f ea f5 df 8b 48 04 6c 8d 87 36 c0 34 2d 19 1a |O....H.l..6.4-..| +00000050 98 e0 39 1f d5 83 a7 67 8f a3 e2 51 71 41 86 44 |..9....g...QqA.D| +00000060 22 bb 1d 93 63 62 63 55 08 19 a7 0e f1 27 31 b8 |"...cbcU.....'1.| +00000070 4b ef 00 61 5b 88 48 45 40 e0 10 83 65 3e 2f e3 |K..a[.HE@...e>/.| +00000080 5c 44 1f 65 c1 8b 8d 79 84 91 cb 75 3c 23 80 1b |\D.e...y...u<#..| +00000090 78 f2 0d 75 55 06 1b 39 11 17 5d 1c db c0 82 a2 |x..uU..9..].....| +000000a0 2e db 47 f1 a7 53 51 04 06 40 65 aa 01 f4 5b d6 |..G..SQ..@e...[.| +000000b0 57 1d dd ba f4 cd ac e2 3d fd 17 31 6e 2e 58 ef |W.......=..1n.X.| +000000c0 3a be ff fa ee 8b 14 0f 84 26 32 ff 08 5a ac 42 |:........&2..Z.B| +000000d0 ae b5 77 4d 97 f6 ce e3 92 f4 53 91 95 c5 eb 21 |..wM......S....!| +000000e0 27 45 ae e9 37 92 b9 7f a2 77 55 21 3c eb 69 9e |'E..7....wU!<.i.| +000000f0 a1 f9 6a c2 41 66 79 9b 99 e6 a0 10 cb 19 21 55 |..j.Afy.......!U| +00000100 e2 53 04 d0 32 bd 26 78 b8 61 80 4a 80 1b c1 fd |.S..2.&x.a.J....| +00000110 6f 44 1d 65 35 b8 29 5d de ae de ca 5c de 02 b7 |oD.e5.)]....\...| +00000120 6a da 86 34 ba f3 0e ab 53 8e 4e b0 70 f7 b3 4e |j..4....S.N.p..N| +00000130 1e ca 88 7b d6 f4 ce 36 21 52 b0 0c e8 f2 f2 63 |...{...6!R.....c| +00000140 af f6 66 ec 77 d5 e3 83 30 92 3a e7 63 ce c8 93 |..f.w...0.:.c...| +00000150 77 71 40 8e d1 a9 8d 0d 68 50 f2 f7 de c5 79 c9 |wq@.....hP....y.| +00000160 55 7d fd 71 26 af f6 ba bc bd 6f db db 92 e0 25 |U}.q&.....o....%| +00000170 f0 84 ef 2a f7 84 43 b2 c7 74 47 7e 48 a4 51 70 |...*..C..tG~H.Qp| +00000180 c4 03 0a e0 25 36 b8 b9 39 77 49 a2 76 b8 a7 ed |....%6..9wI.v...| +00000190 b2 24 cf 1d db 43 40 0a c7 ec 5e 1e e7 76 2b dc |.$...C@...^..v+.| +000001a0 0e fc eb a1 5d 55 5d 76 68 54 ec 30 08 2a 2d 62 |....]U]vhT.0.*-b| +000001b0 0a 8d 76 cf eb ae 61 b6 6a 51 23 50 9e 9f a9 93 |..v...a.jQ#P....| +000001c0 53 78 c2 b3 86 6b 2b 68 dd 31 cc e5 43 46 fb 9e |Sx...k+h.1..CF..| +000001d0 77 12 4f 6a 1c 22 89 d5 de 95 7a 21 43 d2 35 ab |w.Oj."....z!C.5.| +000001e0 db d8 41 85 2c e8 3f 5e 01 3f 5c 44 b0 a0 4c e1 |..A.,.?^.?\D..L.| +000001f0 30 dc bd 6f b2 68 58 c0 c4 34 21 0b 8b b1 53 7f |0..o.hX..4!...S.| +00000200 30 0d 35 24 f2 87 5d 20 9d 3b d2 24 e0 91 7e 30 |0.5$..] .;.$..~0| +00000210 91 a8 a7 81 7b 14 1f 3f 05 2c ad 2a ef 4b f3 6c |....{..?.,.*.K.l| +00000220 c6 29 8a 9b a5 4a b0 6d 53 00 30 c2 48 05 20 c3 |.)...J.mS.0.H. .| +00000230 16 5d 04 54 b9 99 23 2c dc b9 01 73 f1 66 20 d6 |.].T..#,...s.f .| +00000240 ef f1 2c ac c9 c8 f1 d7 7e 51 1e c4 b6 7e 61 a1 |..,.....~Q...~a.| +00000250 28 4b a9 18 a1 35 25 38 93 17 f6 fd 44 e6 ad 71 |(K...5%8....D..q| +00000260 b6 a5 07 d7 3f 27 dd b4 e8 d8 ef cf 47 c9 19 cd |....?'......G...| +00000270 f6 15 bb ab 21 4f ea c0 f8 4a 8e ab 8e 4d f8 54 |....!O...J...M.T| +00000280 d6 3f c0 10 3b 2e 49 73 7f cd 12 00 |.?..;.Is....| +>>> Flow 13 (server to client) +00000000 9f 40 bb b6 29 c0 90 55 61 9d 50 43 6f 2a a2 cc |.@..)..Ua.PCo*..| +00000010 c5 68 c2 1b b1 85 3d 70 dc d1 fb b9 |.h....=p....| +>>> Flow 14 (client to server) +00000000 9b 82 ed ef 37 0f 69 c7 08 b4 9c cb 65 a1 b5 18 |....7.i.....e...| +00000010 d3 16 ea e3 02 54 23 65 d3 13 c4 7f 2e 22 50 6d |.....T#e....."Pm| +00000020 e3 75 b0 b6 79 00 2b 72 b8 11 53 20 96 e8 d6 87 |.u..y.+r..S ....| +00000030 52 59 8c c0 |RY..| +>>> Flow 15 (server to client) +00000000 03 89 66 d2 c7 04 00 3a f6 2e cb 25 39 4f 3f b3 |..f....:...%9O?.| +00000010 7c f7 31 1e 8c f6 7d 46 4c 8f a8 f5 b2 3b e3 51 ||.1...}FL....;.Q| +00000020 ec bc 48 58 a5 d3 ad b9 fd 51 36 dc |..HX.....Q6.| +>>> Flow 16 (client to server) +00000000 f9 f6 ca 18 9a b1 b3 72 18 c7 69 e5 27 c3 ce 96 |.......r..i.'...| +00000010 15 11 4a 58 b3 35 c3 b4 fd 11 ff 0b cd e2 9d 10 |..JX.5..........| +00000020 7e 5e 2c eb 54 27 59 96 93 d9 07 1f c8 bc 59 44 |~^,.T'Y.......YD| +00000030 0d c9 6a b1 bc f1 ae 31 2a 12 5f 80 ca e4 ef 25 |..j....1*._....%| +00000040 f4 bb 1a bf 5b 7c d7 2e 2f f9 ce 4a 24 96 8f 39 |....[|../..J$..9| +00000050 32 2a 74 0f da 61 b9 7b |2*t..a.{| +>>> Flow 17 (server to client) +00000000 c7 62 3b b2 ab 7f b2 e5 5d c9 a1 97 5e 65 a7 f9 |.b;.....]...^e..| +00000010 19 b8 61 68 48 85 92 9c 7c bd 85 c5 c6 ca 98 c7 |..ahH...|.......| +00000020 6a db 2b 9b 4a db 15 4a 22 aa 47 b6 6b 97 06 fe |j.+.J..J".G.k...| +00000030 a4 fd 96 74 af e0 c5 ae 53 08 45 0b a1 1f ca 48 |...t....S.E....H| +00000040 a5 70 ee fa 35 19 e3 fb 89 b3 18 e1 07 08 77 95 |.p..5.........w.| +00000050 ec 0d bd bc 5d dd f4 9e 31 78 df 97 c0 84 24 32 |....]...1x....$2| +00000060 a4 53 ad 90 1f 66 e4 e4 99 af 0a da b0 62 bb 39 |.S...f.......b.9| +00000070 b4 68 9a 35 67 38 43 68 af e9 54 0c |.h.5g8Ch..T.| +>>> Flow 18 (client to server) +00000000 62 ce ad 5e 1e 2d 74 12 f7 25 6b d8 14 8e dc 95 |b..^.-t..%k.....| +00000010 5b 04 b2 ba 6e 07 70 c7 42 d6 94 b7 7d 6a 5c aa |[...n.p.B...}j\.| +00000020 09 2b 06 80 1d f6 c4 53 15 98 2a 8b 2b b9 5e f5 |.+.....S..*.+.^.| +00000030 de ed da 23 08 08 6b d2 3e 86 09 ac 1d d0 a7 44 |...#..k.>......D| +00000040 15 de 86 a4 3b ef b7 9a d2 47 2d 7a e1 29 f5 5d |....;....G-z.).]| +00000050 6e 65 43 75 cf 12 7e d2 70 b2 d5 f6 1c ad ae 84 |neCu..~.p.......| diff --git a/ssh/testdata/Server-MAC-hmac-sha1 b/ssh/testdata/Server-MAC-hmac-sha1 new file mode 100644 index 0000000000..912910c2cd --- /dev/null +++ b/ssh/testdata/Server-MAC-hmac-sha1 @@ -0,0 +1,345 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 0c 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000120 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +00000130 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +00000140 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000150 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +00000160 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +00000170 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000180 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000190 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +000001a0 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +000001b0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000001c0 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +000001d0 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +000001e0 09 68 6d 61 63 2d 73 68 61 31 00 00 00 09 68 6d |.hmac-sha1....hm| +000001f0 61 63 2d 73 68 61 31 00 00 00 04 6e 6f 6e 65 00 |ac-sha1....none.| +00000200 00 00 04 6e 6f 6e 65 00 00 00 00 00 00 00 00 00 |...none.........| +00000210 00 00 00 00 d7 3b 80 93 f6 ef bc 88 eb 1a 6e ac |.....;........n.| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 79 9b 01 db 43 eb 2e 58 19 de |...<..y...C..X..| +00000010 df 03 5c 65 63 e4 00 00 01 7a 73 6e 74 72 75 70 |..\ec....zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 48 b5 68 59 ae 37 |...,..... H.hY.7| +00000650 cf 2e 5d b1 5b 75 7d 54 72 ba d8 5a 00 73 08 22 |..].[u}Tr..Z.s."| +00000660 24 fe c0 99 4a f5 99 5a 34 71 00 00 00 00 00 00 |$...J..Z4q......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 97 2a 27 9c 51 e0 85 78 c9 af 5e |.... .*'.Q..x..^| +00000130 e1 c2 f1 3c 5f 32 ec 81 86 b9 5c 99 da 16 77 49 |...<_2....\...wI| +00000140 8e f4 bb b0 19 00 00 01 14 00 00 00 0c 72 73 61 |.............rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 45 8b 1f |-sha2-512....E..| +00000160 e0 1e b5 77 16 15 8c 88 f3 36 86 4c c5 67 fb d4 |...w.....6.L.g..| +00000170 91 f4 61 db ef bf 66 a0 b7 a0 bb dc a2 8d 8a b5 |..a...f.........| +00000180 c1 a6 46 69 b4 ed 61 72 0f 4a 28 b4 e6 d4 e6 7e |..Fi..ar.J(....~| +00000190 70 95 99 89 f1 2e 96 df 91 ad ff fe b2 ed f3 b2 |p...............| +000001a0 d4 89 e9 85 ce b2 38 06 34 be 0d bd 3d c2 89 55 |......8.4...=..U| +000001b0 3b 25 c3 5e 91 b9 74 00 7b 31 f7 e2 e1 20 86 87 |;%.^..t.{1... ..| +000001c0 e7 6c 6c b0 8b 84 ac 37 91 a4 a8 94 61 dd a5 ef |.ll....7....a...| +000001d0 a8 5a 5f 40 63 ba 1b f8 24 17 65 f2 05 64 b1 53 |.Z_@c...$.e..d.S| +000001e0 ad b0 c0 f7 0d 4f c7 d1 43 05 59 36 1f a5 6a 2a |.....O..C.Y6..j*| +000001f0 a8 40 29 01 6e 19 4e e9 93 57 70 f3 4b e6 1d 10 |.@).n.N..Wp.K...| +00000200 66 19 fe 89 83 af f4 11 1c e9 eb f7 38 8f 64 88 |f...........8.d.| +00000210 ba f2 64 f4 68 de c9 22 5f 80 e8 ea d4 3e 6e 63 |..d.h.."_....>nc| +00000220 35 d2 70 f5 46 a5 d1 f4 86 b9 bb cd c2 c3 a3 e2 |5.p.F...........| +00000230 5c 8a 1f 0b 54 61 6d 1d c4 dc 67 7a 58 00 ef fb |\...Tam...gzX...| +00000240 9e d4 6b ba 60 03 b4 c9 67 cb aa bd 93 be 7f 22 |..k.`...g......"| +00000250 53 29 10 aa 97 f6 84 0d 9b 36 20 f0 e6 f9 ae 57 |S).......6 ....W| +00000260 e2 35 b8 cc 87 3c 23 dc 62 b8 d2 60 16 9a fa 2f |.5...<#.b..`.../| +00000270 00 00 00 0c 0a 15 75 ab 91 6a 58 d9 74 91 88 35 |......u..jX.t..5| +00000280 a6 f0 ae d8 cf 8b b0 92 a8 a0 8c 75 57 54 83 0d |...........uWT..| +00000290 09 47 2d 50 e9 19 c9 85 62 c2 92 99 ce af 6e 0d |.G-P....b.....n.| +000002a0 7a 35 29 1f a3 7a d8 b5 b4 cc 8f 4c 68 ed cd 07 |z5)..z.....Lh...| +000002b0 3b cf 4c bc 89 18 04 11 31 1e 52 92 9b f9 a6 64 |;.L.....1.R....d| +000002c0 84 15 6b 05 ce 06 90 93 7e d3 61 91 83 82 44 5d |..k.....~.a...D]| +000002d0 69 8a b0 5f cb b2 21 f1 b6 22 fe 4a b5 7f 1a 88 |i.._..!..".J....| +000002e0 ea 26 71 fc 2f a5 d3 07 cf ac 64 73 f8 ea cc 14 |.&q./.....ds....| +000002f0 7c 81 86 f5 60 7c 7f d1 90 73 82 f7 4f e4 25 49 ||...`|...s..O.%I| +00000300 57 c9 fe e5 4a bf 0b 88 0c 88 42 7b b5 08 6f ba |W...J.....B{..o.| +00000310 70 b7 f9 2d 9c e7 c6 7e c1 bc a1 0d 5f 18 f0 6f |p..-...~...._..o| +00000320 e5 79 3a 11 fe 28 ec 00 fc 8d 19 48 35 cd e4 01 |.y:..(.....H5...| +00000330 bf 46 08 f4 97 ec 34 06 cb be e4 31 3e ba b8 1b |.F....4....1>...| +00000340 a4 2b 34 09 2c a2 5d 3e 1b a7 5c d7 9c 23 3c f4 |.+4.,.]>..\..#<.| +00000350 95 f2 1c 93 33 4e 7a a8 7b 90 39 f3 38 fd 11 a4 |....3Nz.{.9.8...| +00000360 18 d9 8f f3 4a 93 b2 35 d5 38 0e 31 24 1b 36 ea |....J..5.8.1$.6.| +00000370 6d 1f 4e 08 e3 2d a7 df 23 00 b9 fb 10 f3 cb 43 |m.N..-..#......C| +00000380 2b 3e 85 93 |+>..| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 c4 c7 b2 a7 21 c7 5c 4e 06 d2 31 53 cf c3 c7 ee |....!.\N..1S....| +00000020 a9 9d ba fc 57 50 31 7d 1d 03 f4 76 1d fa 8f 50 |....WP1}...v...P| +00000030 a9 5e cb 03 d2 dd a7 dc 4d 3b b4 93 |.^......M;..| +>>> Flow 7 (server to client) +00000000 f0 e0 7a 59 a6 c7 7f 16 a2 83 93 24 03 04 aa 6d |..zY.......$...m| +00000010 1b af d5 1f 60 0a ef d5 e6 42 17 6f 2e 73 da f2 |....`....B.o.s..| +00000020 2c cd de 63 99 6e c4 0e 6b dd fd 98 |,..c.n..k...| +>>> Flow 8 (client to server) +00000000 64 cc a6 67 d4 02 cd dd f4 b4 f2 af 17 5d 8c 1f |d..g.........]..| +00000010 bf 1a b0 df c1 3f d0 6b c3 41 a4 50 c0 e9 e3 22 |.....?.k.A.P..."| +00000020 05 20 af 5e 94 8e 6a b1 d2 ba 1e 94 6e 2a 61 02 |. .^..j.....n*a.| +00000030 08 12 ad 77 13 c4 f4 e0 28 cf 81 02 fa 13 e4 3e |...w....(......>| +00000040 a2 4b 53 92 |.KS.| +>>> Flow 9 (server to client) +00000000 73 22 1c 34 be 53 5a 08 a6 0c 16 a0 65 78 28 40 |s".4.SZ.....ex(@| +00000010 24 db 9f f7 26 b9 df 0e 78 21 61 d5 90 cc 88 90 |$...&...x!a.....| +00000020 19 88 f5 0c ab 20 41 a1 16 75 a9 0f |..... A..u..| +>>> Flow 10 (client to server) +00000000 30 02 87 6c c1 23 c1 94 67 22 23 d7 52 2b d0 27 |0..l.#..g"#.R+.'| +00000010 28 56 1e 8e 9f 32 fd c7 37 87 fd 89 9e e9 62 9c |(V...2..7.....b.| +00000020 e5 5a eb 6d 12 d7 7b 82 a3 aa f8 60 2c 5a 2c 63 |.Z.m..{....`,Z,c| +00000030 f1 3c db 9f c4 6a 24 5b 93 2c 19 d7 0c 90 fe 93 |.<...j$[.,......| +00000040 dd e5 c5 71 ed 75 96 ca df 7f 57 72 34 25 56 16 |...q.u....Wr4%V.| +00000050 c2 f7 d6 dd 4b aa 41 e1 fb 3b 50 37 eb c5 98 42 |....K.A..;P7...B| +00000060 a6 df d4 3a d7 80 ee 36 e6 58 6f f9 cb b5 91 d1 |...:...6.Xo.....| +00000070 df 13 ae 60 88 34 6f 72 38 84 ba 26 d3 1f 8d b7 |...`.4or8..&....| +00000080 df cb 12 01 4c 99 f6 2c 0c 4b 3b 94 a1 0e 92 fd |....L..,.K;.....| +00000090 1d 99 53 2f 63 9d e9 e6 a4 6d 86 ff 63 97 23 5f |..S/c....m..c.#_| +000000a0 ec b1 15 ca 83 bc 3f e8 89 eb 9e 9d f0 3f 6e 82 |......?......?n.| +000000b0 d7 a4 95 9b 8e 8a 07 0b 70 66 f0 86 8e e8 d2 4a |........pf.....J| +000000c0 a3 e3 fd 37 0a 8f 19 dd 07 e4 3f a7 7d 1e b1 e0 |...7......?.}...| +000000d0 c3 d3 7d 96 84 e5 87 14 77 ba 45 4b 0b 92 7d 71 |..}.....w.EK..}q| +000000e0 71 ef 5e 42 91 4a db 62 ed 76 07 4f 25 8d 08 0c |q.^B.J.b.v.O%...| +000000f0 bf 5b 98 2a 18 41 d7 ac 64 8d 93 05 a5 97 80 d7 |.[.*.A..d.......| +00000100 0d a4 3b 3f 75 5b bb ea 1b bd 02 78 7e b6 0a 00 |..;?u[.....x~...| +00000110 94 d5 6e 51 5f af e2 a8 80 2c 77 b1 1e 9a b9 88 |..nQ_....,w.....| +00000120 aa 59 9b 92 b8 8e 72 4c c4 59 75 6d 17 10 04 23 |.Y....rL.Yum...#| +00000130 65 6d 27 88 56 7d e1 d8 11 7e 56 d3 fb 91 7c 5f |em'.V}...~V...|_| +00000140 bf 57 42 bf b5 e4 11 d4 0c 39 4a 37 5d 5a a9 9b |.WB......9J7]Z..| +00000150 53 cb 24 f9 ba 05 f5 1d 50 b4 69 e8 f0 ec ee fc |S.$.....P.i.....| +00000160 2a c4 67 a5 e7 d2 68 2e cb 99 f5 4c 34 c1 5a f6 |*.g...h....L4.Z.| +00000170 5e 96 d8 5a |^..Z| +>>> Flow 11 (server to client) +00000000 f7 0c 2b 5b df 03 cd 5e c7 46 01 75 ef 38 1e 5f |..+[...^.F.u.8._| +00000010 94 31 e9 39 80 9b 40 32 c5 3d e0 56 12 41 9f 48 |.1.9..@2.=.V.A.H| +00000020 25 2a 9a 71 15 c5 2a 5b 7d f7 89 88 85 71 97 d0 |%*.q..*[}....q..| +00000030 2f 3e d9 cf 30 86 6d 84 d7 32 e5 05 0f d2 a0 22 |/>..0.m..2....."| +00000040 85 1d 7f 1a be 90 97 53 16 2a 51 ee 85 8b fb 9f |.......S.*Q.....| +00000050 bf b0 75 97 36 6a 77 8d 3e e0 02 45 f8 62 74 c7 |..u.6jw.>..E.bt.| +00000060 7c 3f 62 d0 0b c2 9e 3a 0f 11 c9 35 bd 92 13 68 ||?b....:...5...h| +00000070 df 66 0a ec 78 80 7a 5b 0c 1a c0 e6 7c 61 76 11 |.f..x.z[....|av.| +00000080 be 5b b4 b6 64 9e 9a f8 77 44 5c 2c 47 73 5f dc |.[..d...wD\,Gs_.| +00000090 5f 3f af 72 69 ee 64 bf 43 c6 5d f3 2e 1e b1 01 |_?.ri.d.C.].....| +000000a0 2e a8 04 dd f9 99 7b a7 de 20 7a 92 03 8c 0a a2 |......{.. z.....| +000000b0 c2 5c fa bf 57 81 a1 59 ce 6f 3f d0 73 21 7b 64 |.\..W..Y.o?.s!{d| +000000c0 1e b4 e9 9c b0 ce f8 20 7c 8f 6c 0e e4 2c 8e 38 |....... |.l..,.8| +000000d0 5e 29 80 c2 0a 21 ec 82 af bf 1c 5d 81 07 36 44 |^)...!.....]..6D| +000000e0 c0 7b 32 4c 65 57 be 11 b4 a4 73 ca 2f dc b9 92 |.{2LeW....s./...| +000000f0 d0 cb 5b 3f d2 d9 0e be 59 41 f2 a3 77 44 55 4d |..[?....YA..wDUM| +00000100 35 c2 19 84 5a 34 0d 25 08 24 5b f5 29 6c b7 c9 |5...Z4.%.$[.)l..| +00000110 88 1f 3c f7 73 c0 74 50 90 d3 60 70 3d db 25 32 |..<.s.tP..`p=.%2| +00000120 8c 56 30 c7 75 7c 4a 85 d4 43 71 1e e7 71 42 51 |.V0.u|J..Cq..qBQ| +00000130 60 e4 ab d5 eb e4 34 a0 b6 19 49 af fe bc 17 78 |`.....4...I....x| +00000140 47 6e 0a 31 70 30 d1 f0 27 45 65 a2 |Gn.1p0..'Ee.| +>>> Flow 12 (client to server) +00000000 1f db 9f 0f 27 33 ed 23 e5 ab 1c 89 31 ee fa 99 |....'3.#....1...| +00000010 20 52 3f 9d 1a 27 78 f3 f7 b8 c4 5d 65 b2 bc f3 | R?..'x....]e...| +00000020 1d 1e c0 e6 98 a6 63 9b 6d 3a e2 16 fb 54 f4 c9 |......c.m:...T..| +00000030 94 09 e4 03 42 dc bd a3 36 ac 7c 52 9b 3b 3d d0 |....B...6.|R.;=.| +00000040 fd 8c 89 20 60 26 01 52 09 47 f1 a3 9c f9 34 7f |... `&.R.G....4.| +00000050 ef c8 49 c6 ca b8 27 81 9f ba 3e 88 bb b1 4c 56 |..I...'...>...LV| +00000060 45 07 54 d4 48 99 41 6f 7d 3c c7 2a 6e f0 3d c8 |E.T.H.Ao}<.*n.=.| +00000070 6f 81 14 a0 48 5e 5a 0b fc c0 9b 0a ff f7 7a c6 |o...H^Z.......z.| +00000080 27 41 cd ca bd 4c 56 70 27 11 fd 09 f5 10 50 92 |'A...LVp'.....P.| +00000090 fc 90 98 f2 99 97 cb b4 b6 c5 e9 56 63 02 2d 43 |...........Vc.-C| +000000a0 69 16 43 65 99 61 e7 ee 1d 3f 50 64 09 2c 11 37 |i.Ce.a...?Pd.,.7| +000000b0 ec 91 71 0c 75 54 09 95 c9 0f 6c 54 4a 4a 7a a1 |..q.uT....lTJJz.| +000000c0 b6 95 6e bc 00 51 21 29 be fc cc c5 63 03 1b 11 |..n..Q!)....c...| +000000d0 f3 a7 61 4e 90 92 b2 3c fe 21 be 27 14 b9 3f 1d |..aN...<.!.'..?.| +000000e0 b5 1d c6 f2 e9 13 5a 89 0c 4b ba 40 3f 64 7d b4 |......Z..K.@?d}.| +000000f0 2a 88 cd 16 91 88 77 b6 13 9e 4c 52 ed 2e 8a 8f |*.....w...LR....| +00000100 95 70 1a c9 30 c2 5e 25 3a d4 eb a8 91 5f 77 4e |.p..0.^%:...._wN| +00000110 30 0f ca e5 dc d3 9d 65 40 5d 3e 37 44 30 7a bf |0......e@]>7D0z.| +00000120 ed c3 e5 50 fb 12 20 c9 aa b7 e9 95 aa a7 d3 3b |...P.. ........;| +00000130 6f b0 3e 4d 20 43 65 e8 aa f9 96 80 05 3b c5 95 |o.>M Ce......;..| +00000140 35 0e fc b7 55 96 dd 1b 48 82 df bc 51 4a c9 c6 |5...U...H...QJ..| +00000150 19 e1 37 30 94 7c 30 33 2e 22 12 60 d8 97 c3 e3 |..70.|03.".`....| +00000160 7d 39 8c fb 4b 0b 6c b1 80 d1 bf 7a b3 ea a2 c0 |}9..K.l....z....| +00000170 9c 36 c0 70 bd 7f 03 c9 3e f9 f2 6a dd 43 34 1b |.6.p....>..j.C4.| +00000180 31 a3 77 b5 c3 6c 1d 61 6e b4 4d bf cd ca 7b ca |1.w..l.an.M...{.| +00000190 5b b1 e3 2a c1 00 39 f9 ed b5 1b 54 cf ac 90 2a |[..*..9....T...*| +000001a0 99 44 d9 bc e6 52 b6 34 4e 8e 8a cf c9 5a 83 3b |.D...R.4N....Z.;| +000001b0 4e 2b be b1 e1 2c db 46 1d 8d ab b0 3c 64 fe e3 |N+...,.F.......`Tw.......| +000001d0 75 35 ed cf a9 51 f6 35 aa 76 6a 0c 7d 3b 51 63 |u5...Q.5.vj.};Qc| +000001e0 8d f5 e9 d7 13 c5 24 85 3c 96 0a ca f8 64 5b a3 |......$.<....d[.| +000001f0 2f 05 5c 3f f5 0b 75 30 a2 53 8e 67 e4 a7 55 1f |/.\?..u0.S.g..U.| +00000200 a7 d5 4c a6 f4 94 0a ce 0a ee 3b 55 6f 6d 97 a9 |..L.......;Uom..| +00000210 c8 33 c4 20 b1 f4 e2 dc 20 94 db dc 36 7c ae c7 |.3. .... ...6|..| +00000220 48 c5 79 d1 e8 78 b6 ec 55 b7 5f 40 11 5b d9 8f |H.y..x..U._@.[..| +00000230 65 51 98 d8 65 47 ba b3 d2 36 b7 6d 91 62 dc 23 |eQ..eG...6.m.b.#| +00000240 f3 33 b0 d9 b3 27 8d f4 db 3b 06 0c af 34 6c a7 |.3...'...;...4l.| +00000250 30 ea 74 b8 2f b8 b9 c2 a2 de 5b 5e a2 8d 08 11 |0.t./.....[^....| +00000260 78 9b 06 ed 51 c3 2d 97 ff 2c 4b 9c 6a c7 4b 20 |x...Q.-..,K.j.K | +00000270 f1 d0 00 69 b8 e3 5e 14 ce 09 b5 03 5d ae 80 29 |...i..^.....]..)| +00000280 c1 1f 01 5c c9 81 ac e8 3f 74 cc 45 |...\....?t.E| +>>> Flow 13 (server to client) +00000000 b0 e3 f6 ce b6 c8 d3 ce bb 6f 3d a7 5e fa 38 cf |.........o=.^.8.| +00000010 2f 9d eb 57 99 06 2a 3a 26 af a8 da |/..W..*:&...| +>>> Flow 14 (client to server) +00000000 e0 0b be df 17 02 5a 6d 8e 02 91 da dc 45 fb a4 |......Zm.....E..| +00000010 52 ed 1d a5 3d 01 87 67 e2 3b 48 d1 c6 2e 87 e4 |R...=..g.;H.....| +00000020 d2 97 59 95 cc 4b 25 41 0d d2 4e 5e d0 07 59 c6 |..Y..K%A..N^..Y.| +00000030 b3 1a ff 85 |....| +>>> Flow 15 (server to client) +00000000 fc 3b c7 88 5f 90 c0 91 cb 40 21 53 f3 ff 9c 8a |.;.._....@!S....| +00000010 33 05 9e b5 2e f7 ab fe f2 42 73 f4 cf aa af 6c |3........Bs....l| +00000020 30 68 6b fe a9 24 a1 85 a8 c7 4a 12 |0hk..$....J.| +>>> Flow 16 (client to server) +00000000 80 77 73 8c 4c b6 da 9f d4 4b a5 6f 5e 8e 3a b9 |.ws.L....K.o^.:.| +00000010 3e 52 66 65 23 55 30 32 8e 54 97 6f 0e ef c1 9d |>Rfe#U02.T.o....| +00000020 5d 16 c5 0e 41 5b ad 2c 0e 49 e6 83 15 12 23 c0 |]...A[.,.I....#.| +00000030 c8 f8 98 f5 9c 57 60 08 6e 3b 12 80 d5 b9 f3 73 |.....W`.n;.....s| +00000040 f9 21 e2 48 95 f6 48 c4 a9 86 4c 93 c4 34 6d d9 |.!.H..H...L..4m.| +00000050 2e 3d ca 8e ac 4d c9 f2 |.=...M..| +>>> Flow 17 (server to client) +00000000 51 9d 2c ee fc fc ec fc f6 02 06 eb 95 ef a7 48 |Q.,............H| +00000010 31 94 e9 65 f8 40 df 1a a0 a8 93 cf 67 6d 4a a7 |1..e.@......gmJ.| +00000020 a3 b1 c9 5b ee bf 56 bc a0 33 80 32 a4 a1 4f 43 |...[..V..3.2..OC| +00000030 ea 3e 33 d6 1d 8d 05 d5 20 f9 3f 62 39 77 89 78 |.>3..... .?b9w.x| +00000040 0b f1 6a 49 67 a4 a5 f4 25 f4 ae 12 f0 24 c8 63 |..jIg...%....$.c| +00000050 35 34 93 49 f6 1a 00 e1 4f 61 6b 1c 02 38 f9 2a |54.I....Oak..8.*| +00000060 45 40 f1 2e a8 3d b6 1b 01 c8 44 bf 55 ba 5e da |E@...=....D.U.^.| +00000070 be 76 ed b9 e8 cc 2e ef c0 aa d6 5b |.v.........[| +>>> Flow 18 (client to server) +00000000 a8 6f 01 3b 92 64 6e 2b 47 3e 2a f4 b4 65 78 43 |.o.;.dn+G>*..exC| +00000010 b3 60 9b d6 43 36 22 4b 4c 16 52 4a 36 5d 3a 21 |.`..C6"KL.RJ6]:!| +00000020 ed 5b 6d 81 5e fa df 81 f9 e2 c9 01 54 94 a7 fa |.[m.^.......T...| +00000030 c8 3b 96 26 d3 d7 73 23 da 3e 68 a9 17 f6 21 09 |.;.&..s#.>h...!.| +00000040 f8 51 1a cc 5a 73 14 dd 14 ef bf 7b c5 75 df 27 |.Q..Zs.....{.u.'| +00000050 16 ea b9 c5 35 98 0d 94 d2 5b 3a e8 2a f6 83 a8 |....5....[:.*...| diff --git a/ssh/testdata/Server-MAC-hmac-sha1-96 b/ssh/testdata/Server-MAC-hmac-sha1-96 new file mode 100644 index 0000000000..e03329c2a5 --- /dev/null +++ b/ssh/testdata/Server-MAC-hmac-sha1-96 @@ -0,0 +1,345 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 06 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000120 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +00000130 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +00000140 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000150 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +00000160 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +00000170 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000180 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000190 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +000001a0 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +000001b0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000001c0 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +000001d0 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +000001e0 0c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |.hmac-sha1-96...| +000001f0 0c 68 6d 61 63 2d 73 68 61 31 2d 39 36 00 00 00 |.hmac-sha1-96...| +00000200 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 00 00 |.none....none...| +00000210 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 f6 ef |...........;....| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 8a fa 00 55 12 d3 8f d0 12 b7 |...<.....U......| +00000010 0c c3 24 d5 9c 5e 00 00 01 7a 73 6e 74 72 75 70 |..$..^...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 18 1e f9 ea 31 64 |...,..... ....1d| +00000650 9c e2 a3 43 bc 69 89 6e 6b 8a ef 27 15 a7 de 57 |...C.i.nk..'...W| +00000660 e2 a0 76 62 3f cb 54 9e a5 19 00 00 00 00 00 00 |..vb?.T.........| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 ee a0 9c c6 be 90 37 5d 28 ba ea |.... ......7](..| +00000130 a8 41 a5 72 c8 5e 4d 2d 23 c4 f9 26 88 44 60 fc |.A.r.^M-#..&.D`.| +00000140 30 d9 da 91 6a 00 00 01 14 00 00 00 0c 72 73 61 |0...j........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 8e b3 a9 |-sha2-512.......| +00000160 21 08 56 42 50 ff 33 ec 4e a0 51 70 f3 e7 8f 9b |!.VBP.3.N.Qp....| +00000170 e3 79 ee e9 33 1d c8 af 96 dc ec cc f0 5f 65 92 |.y..3........_e.| +00000180 7d 01 0a af ab 17 77 90 d5 a8 46 04 c6 ec 37 b6 |}.....w...F...7.| +00000190 64 f1 bc 66 f6 7d 43 c4 7b d3 f7 89 b7 22 2a a3 |d..f.}C.{...."*.| +000001a0 9d ab fb d6 06 f0 2a a7 7d 90 46 21 47 81 d9 e4 |......*.}.F!G...| +000001b0 5c 95 f3 02 30 92 0a c8 90 68 88 51 6b c0 6a 64 |\...0....h.Qk.jd| +000001c0 14 d6 98 6c 9b 22 35 16 24 b0 88 08 8d 18 93 03 |...l."5.$.......| +000001d0 27 9f 85 63 8e 08 de 39 de ed f6 b7 4f a6 b4 4c |'..c...9....O..L| +000001e0 fd c7 55 22 91 16 29 7a b7 19 3d 33 89 03 94 74 |..U"..)z..=3...t| +000001f0 85 88 59 73 1f 90 05 af 16 21 05 ca c7 81 49 5e |..Ys.....!....I^| +00000200 e9 ba 93 1b 86 9d d1 f8 31 84 86 97 cc d7 c6 10 |........1.......| +00000210 1b c9 46 8c 12 c7 80 c8 0b ab dd d2 3f dd e1 37 |..F.........?..7| +00000220 49 e8 2f 12 28 d4 c9 68 c2 a5 97 45 ca fe 81 3e |I./.(..h...E...>| +00000230 ea 94 8e 5b 3e 39 ca f6 68 56 08 8c 9b 30 fa f3 |...[>9..hV...0..| +00000240 db ec 68 c5 38 3a 84 5f 39 d4 3d d7 3f 08 ed f2 |..h.8:._9.=.?...| +00000250 b0 b5 29 27 b1 05 d8 92 9d 49 97 64 c8 a3 63 9c |..)'.....I.d..c.| +00000260 a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc 62 b8 |.....W.5...<#.b.| +00000270 00 00 00 0c 0a 15 d2 60 16 9a fa 2f 75 ab 91 6a |.......`.../u..j| +00000280 39 bc 03 11 9f 7f b0 62 48 f4 12 27 e9 ad ec d7 |9......bH..'....| +00000290 49 7e 9a 53 0c fc c8 48 c3 ce f3 d1 c6 37 69 8e |I~.S...H.....7i.| +000002a0 c1 fd 89 fe 43 85 b6 08 47 f0 df 7b 38 04 fe 50 |....C...G..{8..P| +000002b0 ff e7 8e ff 98 86 38 0c 8a 7d d7 a5 d3 28 2a 8f |......8..}...(*.| +000002c0 fc 2f 0b b4 2a 21 5e 35 25 2f 51 53 e0 7c 0a 71 |./..*!^5%/QS.|.q| +000002d0 a6 5a 47 e0 f4 57 cb f0 4b 41 59 e3 fe 4d 4d 35 |.ZG..W..KAY..MM5| +000002e0 b8 0a 20 a4 ba 70 0a 56 6c 98 76 1a 54 73 c7 0d |.. ..p.Vl.v.Ts..| +000002f0 af c6 69 7f 58 3b 1b a3 24 07 29 97 78 84 41 c4 |..i.X;..$.).x.A.| +00000300 53 e5 c7 b8 b0 f4 c2 cb 91 aa 96 b2 5a 65 bf c0 |S...........Ze..| +00000310 66 7e d6 e7 1e 4b 1b 90 41 91 8f 4e c9 98 7d 48 |f~...K..A..N..}H| +00000320 e4 bd 9b 70 aa c4 f4 36 db 64 b2 b1 dc 85 f8 73 |...p...6.d.....s| +00000330 06 7e bf 84 ab 46 26 de 22 e1 89 7d 4e 80 fc 03 |.~...F&."..}N...| +00000340 3d 6f e9 13 b0 cc 88 c2 43 0c 9a ac ec 03 97 56 |=o......C......V| +00000350 f3 53 a7 1e 3a 23 d2 8f e6 50 ee 29 a3 ff a5 e3 |.S..:#...P.)....| +00000360 9c 9c d3 eb 65 44 e5 a3 8b d1 f2 65 fb 65 e2 67 |....eD.....e.e.g| +00000370 9a b1 85 79 2c 56 7d 0d 5b b2 b1 83 0a a5 44 0e |...y,V}.[.....D.| +00000380 79 68 16 4b |yh.K| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 92 f3 05 18 a5 00 14 29 fd 9b 5b 1c ff bd 66 fd |.......)..[...f.| +00000020 13 cb 01 0d 63 64 04 7f 48 ea 10 79 d7 3c d7 6a |....cd..H..y.<.j| +00000030 03 fd c5 dd b0 67 06 d4 ea be 8e f0 |.....g......| +>>> Flow 7 (server to client) +00000000 eb d9 a3 a1 cb e7 50 f6 2f 8d dd 48 0b 1a a3 12 |......P./..H....| +00000010 12 eb 07 05 e2 5d fb fb ee 7a 64 3e 4d 9c 23 f2 |.....]...zd>M.#.| +00000020 40 4c c0 0e 90 f7 7f 27 4a 53 47 36 |@L.....'JSG6| +>>> Flow 8 (client to server) +00000000 4b 2e 91 bf f0 85 a5 84 8c 62 1d f3 f8 3a b4 a2 |K........b...:..| +00000010 61 c9 1e c4 88 cf 8a c0 c2 51 dd c7 ea c7 db 0e |a........Q......| +00000020 c1 46 3e 18 4f 31 5e 70 4e 8d 79 16 f6 0a d7 85 |.F>.O1^pN.y.....| +00000030 cb 37 66 7f 1d 3a 3f c6 56 a3 87 37 a1 96 59 56 |.7f..:?.V..7..YV| +00000040 fe be 46 2a |..F*| +>>> Flow 9 (server to client) +00000000 84 05 61 5f 4d 4b 65 c4 28 f5 53 0e 07 12 fe 5c |..a_MKe.(.S....\| +00000010 dd 58 a5 e1 c4 55 df 16 a3 16 a4 b9 78 b5 2c e8 |.X...U......x.,.| +00000020 a0 4a b9 10 be 94 a2 45 e4 6b b1 ab |.J.....E.k..| +>>> Flow 10 (client to server) +00000000 fd 95 6d 1c 91 9c 99 7f 97 ad 97 47 90 88 54 ce |..m........G..T.| +00000010 3c f1 3d 53 4b 1f 7b 98 a7 6f d2 69 73 64 2f 75 |<.=SK.{..o.isd/u| +00000020 27 e2 fd 18 89 5d 94 7d d1 a4 8a b0 eb 86 fe 57 |'....].}.......W| +00000030 5c 81 b0 5b 7c f6 b9 62 1d 78 91 5f 0f f4 1c 5a |\..[|..b.x._...Z| +00000040 86 e0 67 c5 b2 5b e9 2f 92 f1 7b 2a 1d df 86 00 |..g..[./..{*....| +00000050 0c 28 c8 a0 de fb be b6 1e 2d 5c 9f c8 24 1f ad |.(.......-\..$..| +00000060 c2 48 40 26 69 2e 39 f0 06 11 32 81 09 ca c8 84 |.H@&i.9...2.....| +00000070 47 d5 62 68 4a 2e 10 1a e6 bf 5f 08 cb f3 1a 58 |G.bhJ....._....X| +00000080 fa 5b c6 b3 3d 00 05 ae 67 c9 c6 91 dc 2e 8c ec |.[..=...g.......| +00000090 dd 88 d4 37 93 01 f6 c7 0d 2a ad 69 32 b8 2e 23 |...7.....*.i2..#| +000000a0 f1 2b a6 3d 8f 0f a0 5a 3b c6 31 77 eb f0 d1 95 |.+.=...Z;.1w....| +000000b0 54 8a 7f 5e d3 a6 05 a9 fc 0e 04 58 46 38 0a 41 |T..^.......XF8.A| +000000c0 97 60 41 ef 2c 65 91 bc 18 bf 83 99 14 91 fb b7 |.`A.,e..........| +000000d0 4e 1a ba 9f 9d ef 26 f1 36 40 1a 03 c6 fb d4 e0 |N.....&.6@......| +000000e0 a1 de 10 af f4 c5 e2 a2 81 ef 5f 27 11 6e 4f 91 |.........._'.nO.| +000000f0 3d 58 a4 c5 88 c9 f2 e8 72 87 77 4c 9e 7a e3 10 |=X......r.wL.z..| +00000100 44 e2 00 20 22 d5 3e 1e bd 91 2a 35 ab b7 7c d5 |D.. ".>...*5..|.| +00000110 47 39 0e b9 8e 3f 7f 81 cc a8 f2 40 5d a8 45 db |G9...?.....@].E.| +00000120 37 81 43 2e 79 fd e8 6a 48 42 a5 8a 4b df 02 45 |7.C.y..jHB..K..E| +00000130 4f 8e e5 87 c6 21 56 39 ba 32 81 05 38 eb ee 37 |O....!V9.2..8..7| +00000140 f2 b1 82 6f 3c 52 6f 06 ff ec 1d 81 10 51 d7 35 |...o>> Flow 11 (server to client) +00000000 8e 11 f4 60 fc 93 73 4c 07 db 0f 3e 59 c7 3f 33 |...`..sL...>Y.?3| +00000010 3b c8 2a a1 32 ab 63 90 c0 56 04 fc 0c 2f 90 fa |;.*.2.c..V.../..| +00000020 51 24 41 07 fe 6b f6 b9 6e 0b 6f 9d d5 0e 31 4d |Q$A..k..n.o...1M| +00000030 8e 99 85 fd ed c0 95 fd c9 15 40 a3 f7 d0 be ce |..........@.....| +00000040 3d c2 54 1a 47 82 d4 f8 60 db ac 2d e0 a2 8f 7c |=.T.G...`..-...|| +00000050 dc 43 78 c9 35 6e 4a ab fd b5 74 a8 72 01 8b ff |.Cx.5nJ...t.r...| +00000060 87 94 a6 c5 ed 71 d1 23 80 4c b9 b0 90 e7 d1 3c |.....q.#.L.....<| +00000070 6c 0c 74 1f 10 e5 0c 10 9a b2 aa e0 85 65 fa df |l.t..........e..| +00000080 0d b7 cb e0 55 dc 94 71 fa 4c 6e a0 e1 c7 10 89 |....U..q.Ln.....| +00000090 f9 80 fa 46 40 b4 03 13 c4 af 86 1a 70 6e 7e 3f |...F@.......pn~?| +000000a0 3d bb 18 b5 d4 2f 8b 50 3c 27 55 9e 47 b1 b3 d5 |=..../.P<'U.G...| +000000b0 20 b6 79 e3 35 3f 3c 3a 41 c8 16 9c ab 72 b3 4e | .y.5?<:A....r.N| +000000c0 3f d3 7b 87 91 a3 09 c4 39 ad 05 10 6b 68 6b ad |?.{.....9...khk.| +000000d0 25 d2 e8 b1 52 a8 b2 c3 46 47 12 92 ac ea 04 28 |%...R...FG.....(| +000000e0 f2 6a 89 93 10 6b a5 df b7 8f 7c 24 f8 4c e4 2f |.j...k....|$.L./| +000000f0 34 91 58 ed ab fb 13 7d 24 36 0a 30 ba 1b 69 b7 |4.X....}$6.0..i.| +00000100 dd 9c a2 e1 c2 48 08 93 8b 89 81 32 b7 56 6b cb |.....H.....2.Vk.| +00000110 51 59 1a 3b a4 c9 03 83 9f 71 8f ff 3a f6 dc 29 |QY.;.....q..:..)| +00000120 84 7e df 48 0a 52 bf 17 ca df 1d 69 9b ac 02 82 |.~.H.R.....i....| +00000130 16 64 7e b2 33 59 45 4b 1b 2f 13 76 7f e7 7a 3c |.d~.3YEK./.v..z<| +00000140 8b ae b9 66 04 b1 92 56 bc bc 82 8a |...f...V....| +>>> Flow 12 (client to server) +00000000 a0 48 46 fd 3c 4b 43 c2 0a 17 b4 e3 cb 1a 1e 3d |.HF.>> Flow 13 (server to client) +00000000 77 78 dc 59 56 5c c3 37 7b 22 b6 61 c0 48 16 20 |wx.YV\.7{".a.H. | +00000010 65 d4 48 08 fb 90 a4 84 17 d0 a8 1a |e.H.........| +>>> Flow 14 (client to server) +00000000 4e bf b9 99 b6 65 87 1e 58 8a 75 2c 5f cd 10 56 |N....e..X.u,_..V| +00000010 ee 9d f7 e3 6a 91 70 06 f6 ff b9 23 e5 63 24 e7 |....j.p....#.c$.| +00000020 6b a5 8d 63 63 d3 ce b3 39 8b fd a2 03 f6 75 40 |k..cc...9.....u@| +00000030 6d b2 09 d5 |m...| +>>> Flow 15 (server to client) +00000000 29 7c fb 31 ce 0f 8d 41 54 4d 4a 07 e6 cc 5d 1f |)|.1...ATMJ...].| +00000010 4b a5 d6 15 77 6c 6c 3d 50 5e 3b 1e 5e be b9 41 |K...wll=P^;.^..A| +00000020 02 16 de 69 be d3 7b f4 9d 2a 3f a2 |...i..{..*?.| +>>> Flow 16 (client to server) +00000000 4a 25 48 57 d5 e0 03 ee 95 e3 ad cf 00 af d7 40 |J%HW...........@| +00000010 04 37 28 3a 8f 9e 2e 5c 89 c8 7e 36 64 5c ed 90 |.7(:...\..~6d\..| +00000020 fa 0f 75 7c ac 0d c8 c7 b8 ab 8b 03 65 0e cc 39 |..u|........e..9| +00000030 63 38 fd c1 81 e0 db a0 44 e7 15 68 33 6c 78 c2 |c8......D..h3lx.| +00000040 ff 71 98 b8 59 bd ca c1 c6 a3 86 12 53 6a 4c 9a |.q..Y.......SjL.| +00000050 f6 7c 8a ca c4 5d 82 a7 |.|...]..| +>>> Flow 17 (server to client) +00000000 ba 24 e6 32 c6 b8 e1 03 7c b5 e3 0a f8 11 4d 83 |.$.2....|.....M.| +00000010 bb 93 c6 39 ef d3 b4 e4 d1 05 7e 5f 9b 93 a9 49 |...9......~_...I| +00000020 d5 9f 5e 3d 04 b8 09 ae 7e 50 ae 39 e2 98 fa 49 |..^=....~P.9...I| +00000030 04 80 54 b3 28 69 00 0c 1b 2e c7 55 e8 75 03 1d |..T.(i.....U.u..| +00000040 95 2c 62 e0 96 cb 0b 19 0e 94 ec 5a e0 84 6c d7 |.,b........Z..l.| +00000050 6e 4f d7 9f d7 88 96 54 31 60 1d 00 d3 03 9d 16 |nO.....T1`......| +00000060 21 6e f2 67 40 47 ab 07 b8 69 2f 9e 4c 7b ee 53 |!n.g@G...i/.L{.S| +00000070 72 7e 36 cf 81 b3 84 67 ac a0 7a a3 |r~6....g..z.| +>>> Flow 18 (client to server) +00000000 16 17 00 5a 57 bf 9b 6c 4e ed 63 73 b8 43 7d 36 |...ZW..lN.cs.C}6| +00000010 d7 79 a0 ed 18 d9 fb 98 6d 90 c1 ca 02 92 4b 98 |.y......m.....K.| +00000020 bc 2a e5 6d fb 36 15 6d f9 88 31 0e 15 6d 5a bb |.*.m.6.m..1..mZ.| +00000030 fb 09 ff 5d f3 c7 8c f4 63 d7 8a d0 b1 9a 87 05 |...]....c.......| +00000040 76 10 01 9d c8 db c6 3e 4a f4 40 ad b7 2f ed b1 |v......>J.@../..| +00000050 83 df 54 7e 79 90 22 90 9a 46 96 15 e3 65 ef 67 |..T~y."..F...e.g| diff --git a/ssh/testdata/Server-MAC-hmac-sha2-256 b/ssh/testdata/Server-MAC-hmac-sha2-256 new file mode 100644 index 0000000000..a873db67ef --- /dev/null +++ b/ssh/testdata/Server-MAC-hmac-sha2-256 @@ -0,0 +1,346 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 04 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000120 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +00000130 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +00000140 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000150 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +00000160 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +00000170 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000180 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000190 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +000001a0 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +000001b0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000001c0 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +000001d0 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +000001e0 0d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 00 00 |.hmac-sha2-256..| +000001f0 00 0d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 00 |..hmac-sha2-256.| +00000200 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 |...none....none.| +00000210 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 |.............;..| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 8e bc e5 c0 82 58 4e ba ef b4 |...<.......XN...| +00000010 b7 fa 4c 6f 93 67 00 00 01 7a 73 6e 74 72 75 70 |..Lo.g...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 8d f1 9c b3 83 0a |...,..... ......| +00000650 d4 c8 3a 70 c4 2c 35 57 0a a3 d2 71 c4 c7 45 52 |..:p.,5W...q..ER| +00000660 e1 f4 54 87 bd 75 4a 67 6e 38 00 00 00 00 00 00 |..T..uJgn8......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 13 87 32 34 3e 68 e6 9b 9a cb 23 |.... ..24>h....#| +00000130 22 06 11 e8 24 71 e5 d7 96 79 83 48 59 1a 95 f2 |"...$q...y.HY...| +00000140 b0 86 1c 76 54 00 00 01 14 00 00 00 0c 72 73 61 |...vT........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 8d 7f de |-sha2-512.......| +00000160 5c 87 dd be 55 88 26 02 c5 10 b3 cc 48 82 ef f5 |\...U.&.....H...| +00000170 b9 f6 0a 16 39 cd c2 a7 c2 e5 a4 53 d8 b9 3f a9 |....9......S..?.| +00000180 aa 5d 3b 89 61 a8 07 3a 97 d3 1b 28 ce 04 38 a0 |.];.a..:...(..8.| +00000190 2a fb 49 ad 5e 83 10 ef 61 c7 1a 52 28 e4 74 19 |*.I.^...a..R(.t.| +000001a0 fb 94 82 ba 78 6d 3e ca 34 49 ca 52 08 81 df 7a |....xm>.4I.R...z| +000001b0 48 6b 38 2f d2 76 bb 2a 0a 8c fa 5f b7 9e e0 81 |Hk8/.v.*..._....| +000001c0 07 4c 4e d9 04 2a ac 28 f4 c8 82 b4 82 77 11 f4 |.LN..*.(.....w..| +000001d0 4d 8b e9 55 56 82 ce c5 9a 4b 99 fd b0 13 e8 2a |M..UV....K.....*| +000001e0 b5 42 99 cf a4 6b 48 79 f2 b8 4b 1b 06 41 0e e4 |.B...kHy..K..A..| +000001f0 ed 5b 64 86 d9 5b 69 cb 90 eb 7f 5b 24 93 75 60 |.[d..[i....[$.u`| +00000200 a9 ea ff 25 43 8c 3f 70 93 8e e2 ac 6a 81 e8 04 |...%C.?p....j...| +00000210 bd 49 22 24 8e 1f 6f 64 90 83 d2 fd e3 e4 03 98 |.I"$..od........| +00000220 b5 23 32 da cc a9 10 2b 11 0b 1b 50 e8 8f 7b 34 |.#2....+...P..{4| +00000230 b7 cf fd 94 f9 37 9e e3 97 12 c7 90 a7 34 d5 22 |.....7.......4."| +00000240 be 9b 0e 27 4e b5 26 b3 20 39 47 95 7e ce 9e 40 |...'N.&. 9G.~..@| +00000250 35 b3 36 41 cf c9 45 99 a6 aa ec cd b0 58 e8 a3 |5.6A..E......X..| +00000260 63 9c a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc |c......W.5...<#.| +00000270 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000280 fb 03 1a c0 0e 6e d0 da 3a 83 a2 e8 7e 12 48 5b |.....n..:...~.H[| +00000290 f2 7e 4f cd a8 11 85 69 11 b6 27 25 82 95 f5 4c |.~O....i..'%...L| +000002a0 b9 83 41 18 58 60 69 b8 6c 07 72 e4 8f 4b b6 02 |..A.X`i.l.r..K..| +000002b0 da 39 b4 e3 9f 05 c6 33 09 de 37 2a f6 94 58 ff |.9.....3..7*..X.| +000002c0 2c 1e 2e a2 90 ac a1 f4 ed ad 25 7e 04 29 4d 67 |,.........%~.)Mg| +000002d0 dd 91 b9 57 b2 a5 c0 36 99 5c 70 29 bb aa 80 25 |...W...6.\p)...%| +000002e0 5e ff 23 ad f5 72 9c 97 57 15 b3 49 6f d6 06 54 |^.#..r..W..Io..T| +000002f0 27 7f 2a d2 ed 66 d9 f2 28 7a 62 b7 97 ed bc d1 |'.*..f..(zb.....| +00000300 41 38 bd 8e 8c 67 c8 8d 22 b5 18 22 ae 95 50 33 |A8...g..".."..P3| +00000310 95 a2 18 c2 17 11 7f 14 3a c3 da fb 5a 79 36 b9 |........:...Zy6.| +00000320 d0 30 fe 3e fa 83 7c 42 60 51 e3 88 d1 b2 85 f1 |.0.>..|B`Q......| +00000330 20 52 70 bc 36 08 42 60 1f 5b 7f ea 95 6c 5d d0 | Rp.6.B`.[...l].| +00000340 99 1d 30 25 88 a4 1d 85 f7 9c 4d 7b 8e e1 dc c6 |..0%......M{....| +00000350 f1 f6 79 f8 86 fa 91 a3 b0 51 ff 2b b2 07 30 b0 |..y......Q.+..0.| +00000360 0b c1 19 cf 4c 6e b0 60 2c c2 25 77 2a f4 3a eb |....Ln.`,.%w*.:.| +00000370 8d 4b 10 72 f5 47 f0 5b 70 08 05 c7 05 48 a2 13 |.K.r.G.[p....H..| +00000380 8b 14 82 83 |....| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 71 8c 1d 65 cf 82 68 c6 11 c0 fb 18 4d 75 39 38 |q..e..h.....Mu98| +00000020 f7 92 38 39 e3 03 ec 57 35 17 01 65 47 fe 7c 43 |..89...W5..eG.|C| +00000030 34 02 8e 74 ea a8 6c 7f e8 91 d8 64 |4..t..l....d| +>>> Flow 7 (server to client) +00000000 5b 6e 70 49 00 67 34 68 9a d1 55 34 e5 53 e2 4d |[npI.g4h..U4.S.M| +00000010 6c fa 58 c1 cb c1 4e 97 9c ea 23 ac b0 d6 9b df |l.X...N...#.....| +00000020 24 95 3c 9d 8f 5a 85 55 56 96 b2 1c |$.<..Z.UV...| +>>> Flow 8 (client to server) +00000000 95 c7 61 84 bf 3b 6d 74 25 78 36 4e 40 33 6f 5b |..a..;mt%x6N@3o[| +00000010 f5 19 c5 61 d5 fe d6 58 d0 4c eb 13 b1 d5 bd 8f |...a...X.L......| +00000020 1c 2c 35 28 bc d5 af 85 d4 7c 0f 13 a3 cc 45 ec |.,5(.....|....E.| +00000030 11 33 25 75 c4 eb 85 27 7c b0 f8 86 84 99 84 27 |.3%u...'|......'| +00000040 4f 97 94 1e |O...| +>>> Flow 9 (server to client) +00000000 22 0f 3f ee 33 fe ee ad e0 07 33 11 38 b5 65 d7 |".?.3.....3.8.e.| +00000010 ab af 0d 65 61 e6 8f 55 27 c4 cd 9b 22 90 49 68 |...ea..U'...".Ih| +00000020 13 1e d8 26 b3 ea 12 3b e2 f1 22 88 |...&...;..".| +>>> Flow 10 (client to server) +00000000 cb 20 a6 3a 32 7d ad ef fd 63 27 ca 6c 1d 81 81 |. .:2}...c'.l...| +00000010 ad 5e 39 eb 54 42 d7 8d ed 09 f7 84 5d 20 b0 a2 |.^9.TB......] ..| +00000020 64 3a 66 1d ad dc dc 9d 7f 43 62 56 08 b2 f5 5c |d:f......CbV...\| +00000030 6c fa 46 4f 06 76 5c 60 fc 0b fd 8c da db e2 9e |l.FO.v\`........| +00000040 5e 3d 60 3d c9 44 7c 56 cb 44 66 6b e4 2d ed 41 |^=`=.D|V.Dfk.-.A| +00000050 8c c0 4a 7e 43 ca 88 3c 04 7a 55 93 0e 3d 98 d7 |..J~C..<.zU..=..| +00000060 60 ac 2a c1 a6 c5 2a 11 a7 e1 2c 71 3c 41 97 45 |`.*...*...,q>> Flow 11 (server to client) +00000000 e2 34 47 af 73 fd 83 1a ea f4 48 dd 78 3a 3f 5d |.4G.s.....H.x:?]| +00000010 85 ff d6 99 ad 92 6a 4b da e7 46 aa a4 54 47 2e |......jK..F..TG.| +00000020 40 13 12 9a 22 fa f0 1a e7 e0 3d 98 b6 62 43 ed |@...".....=..bC.| +00000030 1f 38 81 19 58 d0 64 29 a1 87 79 9a 1b 35 2a c6 |.8..X.d)..y..5*.| +00000040 f9 a4 13 7d e4 5d b5 4b 93 01 91 3f ea ad 7c 53 |...}.].K...?..|S| +00000050 90 2a 07 85 93 3c 56 a9 ef 62 2e 71 f1 6d 71 64 |.*...>> Flow 12 (client to server) +00000000 ba f3 4a b3 67 fe 0d a8 93 21 a3 14 fe cd e4 04 |..J.g....!......| +00000010 bd b9 fa 41 bd 43 df 0c f7 7c 93 66 2c 23 3e e4 |...A.C...|.f,#>.| +00000020 a9 c0 64 d9 03 17 39 be 5d 54 d6 a2 cb 65 1a 93 |..d...9.]T...e..| +00000030 40 c1 90 76 13 01 2d e8 7c f9 62 8e 49 3c 83 d7 |@..v..-.|.b.I<..| +00000040 55 69 ab 0d 60 f4 6c f1 4c be 11 f5 e9 47 b5 d9 |Ui..`.l.L....G..| +00000050 43 45 59 cd ac e0 81 ae 04 1c 36 40 ef 10 01 fe |CEY.......6@....| +00000060 83 79 73 57 cc 3f 55 62 a8 97 c7 51 d1 16 1f 6d |.ysW.?Ub...Q...m| +00000070 ea 03 2c 0c 42 69 56 da b1 95 84 c9 7f b6 19 00 |..,.BiV.........| +00000080 94 c2 39 a5 fd f6 a9 cc 3b ef 4d ac 9a bf 6c 51 |..9.....;.M...lQ| +00000090 ef 64 78 54 5e 86 85 11 38 48 68 5c b3 27 4e 5e |.dxT^...8Hh\.'N^| +000000a0 5d fd 1a 76 20 bb 8a f3 c5 88 a2 a3 2e 36 b2 67 |]..v ........6.g| +000000b0 5e b7 36 66 1f d7 42 dc 04 df cf 5e e6 34 9c 14 |^.6f..B....^.4..| +000000c0 59 6e aa e2 2a 70 32 fa 61 d8 04 06 01 e0 be 37 |Yn..*p2.a......7| +000000d0 6b 5f ee f8 53 85 05 aa 89 90 ba 91 6e c5 80 fa |k_..S.......n...| +000000e0 fa b6 ce 14 90 1c 5c a6 11 03 f7 64 0c 75 ec 27 |......\....d.u.'| +000000f0 fc a6 b5 c1 0b c4 16 06 05 23 9d 1b 60 c8 84 26 |.........#..`..&| +00000100 f2 cf e4 b4 4f dc 52 6d 01 f8 ea d7 4a 7a 1c b5 |....O.Rm....Jz..| +00000110 86 cb c9 55 22 aa 50 7d 38 fe af 88 aa 19 77 8f |...U".P}8.....w.| +00000120 e5 c3 0c 80 93 c5 56 6d 18 4e c5 f4 44 db 5c 51 |......Vm.N..D.\Q| +00000130 49 1d 38 cd 45 b4 bb 5e 24 71 64 53 2d cd cd be |I.8.E..^$qdS-...| +00000140 9f 0a 68 41 1d 8c da 36 92 71 c2 82 94 3e b7 29 |..hA...6.q...>.)| +00000150 da 39 77 2d 3c 9e 38 17 db 67 5d 2b 54 13 09 60 |.9w-<.8..g]+T..`| +00000160 01 eb dc f8 53 67 51 c4 e4 f2 dc 08 4f d2 a2 2e |....SgQ.....O...| +00000170 06 7a dd 6b 2a eb b8 23 ad 9f 0e f1 7d 18 df 6a |.z.k*..#....}..j| +00000180 a8 63 c4 77 7a 9a 79 9c 94 9d 8d 2d e2 5a bc 32 |.c.wz.y....-.Z.2| +00000190 5b bb a1 13 12 0e 80 de c4 f6 79 81 6d b9 5d 99 |[.........y.m.].| +000001a0 d8 92 c0 32 28 d4 f5 16 84 6e 55 82 15 fa 68 4c |...2(....nU...hL| +000001b0 c9 6f 75 27 02 6a 79 d7 27 3b cf a0 d8 1d 76 7f |.ou'.jy.';....v.| +000001c0 de f9 40 d9 e3 3c 9f 4e bd ac c2 09 1a 16 6f ee |..@..<.N......o.| +000001d0 04 2e 26 fa 29 82 3d f3 9b e9 86 10 15 28 f6 30 |..&.).=......(.0| +000001e0 0e 81 bd 77 09 d0 b2 dc 30 22 73 be 03 e2 77 42 |...w....0"s...wB| +000001f0 42 45 5a 85 20 44 a8 6a 5f 1f 33 3c 64 f7 e2 f6 |BEZ. D.j_.3>> Flow 13 (server to client) +00000000 8b 0b 95 f5 97 f7 e5 0c 98 46 a8 5c 4b 08 3a 6c |.........F.\K.:l| +00000010 8e 97 08 e0 a0 b6 6c 4e d8 d5 7e dd |......lN..~.| +>>> Flow 14 (client to server) +00000000 d2 73 df 2e 57 65 d9 82 c7 c4 f8 12 db c9 64 55 |.s..We........dU| +00000010 b7 46 96 2c 7d 6f e3 7f 21 24 91 0c f3 bf 7b 7d |.F.,}o..!$....{}| +00000020 cf 0c dd 70 b0 fa 16 3d 7a cf 45 6c f1 3c 58 b5 |...p...=z.El.>> Flow 15 (server to client) +00000000 38 4b 2d a5 ff 3f 02 3f 13 ce be 88 43 a7 c9 6b |8K-..?.?....C..k| +00000010 26 60 59 23 73 ae 1f 5e a0 58 f5 cf 09 fa 20 53 |&`Y#s..^.X.... S| +00000020 dc 61 b2 93 19 cf b4 b0 a6 ea 26 47 |.a........&G| +>>> Flow 16 (client to server) +00000000 61 cc 24 3c f2 3b ba 66 92 09 a6 a7 31 d4 6e 24 |a.$<.;.f....1.n$| +00000010 43 a7 2e 04 c9 13 d4 81 7b 73 62 83 ff ba 79 ad |C.......{sb...y.| +00000020 a3 20 4f 01 49 24 b3 a9 29 33 be 66 8a ce be 61 |. O.I$..)3.f...a| +00000030 cc 45 a5 97 |.E..| +>>> Flow 17 (server to client) +00000000 7c 3f ea 45 56 22 4b 15 f5 e4 0b 4c 57 f8 f7 29 ||?.EV"K....LW..)| +00000010 4a 99 ff 62 85 3c 99 8f 17 c9 42 89 6a 4a 73 df |J..b.<....B.jJs.| +00000020 4a f9 57 07 65 a2 8e dd a3 ec d8 93 f9 51 c0 a7 |J.W.e........Q..| +00000030 a6 c0 7b 13 63 56 f9 f6 fa 02 35 3e 11 37 4c 8d |..{.cV....5>.7L.| +00000040 55 6a 2d 2a af 9c 37 e4 be 23 de 13 a3 9d 46 13 |Uj-*..7..#....F.| +00000050 a4 ec f3 57 9f cc b1 03 33 dc 27 af 53 4e cf a2 |...W....3.'.SN..| +00000060 36 f2 2d 8c a3 0b 89 80 24 04 bb bf b8 ef ed 08 |6.-.....$.......| +00000070 e4 40 bd ec be 71 f9 67 9a 57 2d af |.@...q.g.W-.| +>>> Flow 18 (client to server) +00000000 2e 33 5b 8a ed 22 b1 92 80 63 a2 e6 45 4f d6 08 |.3[.."...c..EO..| +00000010 06 cf b3 6f 9d 8e 00 38 d8 94 f1 91 de 09 c6 39 |...o...8.......9| +00000020 c2 a2 c9 48 d6 0e b5 93 80 e5 74 5c c1 59 b0 4a |...H......t\.Y.J| +00000030 9b 36 64 3f dc dd b9 17 f2 05 c2 8f ff ae bc f9 |.6d?............| +00000040 b6 0a cc 66 48 31 fc a0 35 4a d6 37 16 c6 75 7c |...fH1..5J.7..u|| +00000050 f4 4f cd 74 95 4e 99 39 81 ae a3 6b b6 c2 39 b9 |.O.t.N.9...k..9.| +00000060 67 5c 5d d9 ae 7a f1 93 4f df 19 81 25 38 5b a4 |g\]..z..O...%8[.| +00000070 10 98 71 bf 6c 9d cb fb 64 0b b5 af 64 72 e4 e4 |..q.l...d...dr..| +00000080 3f e1 35 b1 |?.5.| diff --git a/ssh/testdata/Server-MAC-hmac-sha2-256-etm@openssh.com b/ssh/testdata/Server-MAC-hmac-sha2-256-etm@openssh.com new file mode 100644 index 0000000000..a54c44c303 --- /dev/null +++ b/ssh/testdata/Server-MAC-hmac-sha2-256-etm@openssh.com @@ -0,0 +1,347 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 3c 04 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...<....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000120 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +00000130 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +00000140 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000150 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +00000160 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +00000170 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000180 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000190 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +000001a0 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +000001b0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000001c0 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +000001d0 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +000001e0 1d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d 65 |.hmac-sha2-256-e| +000001f0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 |tm@openssh.com..| +00000200 00 1d 68 6d 61 63 2d 73 68 61 32 2d 32 35 36 2d |..hmac-sha2-256-| +00000210 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |etm@openssh.com.| +00000220 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 |...none....none.| +00000230 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 |.............;..| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 20 57 dc a8 4f 0e f1 4b 11 58 |...<.. W..O..K.X| +00000010 6b ee 95 3f dc 68 00 00 01 7a 73 6e 74 72 75 70 |k..?.h...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 91 ca 5d c7 1b 4e |...,..... ..]..N| +00000650 d8 97 21 7e 4f 6b f1 0b 04 46 aa b8 88 ee 1b 53 |..!~Ok...F.....S| +00000660 c8 5b c5 d3 4a a4 ba 22 4a 15 00 00 00 00 00 00 |.[..J.."J.......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 13 87 32 34 3e 68 e6 9b 9a cb 23 |.... ..24>h....#| +00000130 22 06 11 e8 24 71 e5 d7 96 79 83 48 59 1a 95 f2 |"...$q...y.HY...| +00000140 b0 86 1c 76 54 00 00 01 14 00 00 00 0c 72 73 61 |...vT........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 09 70 aa |-sha2-512.....p.| +00000160 81 87 fb bd 69 2f 6f a1 a2 ca 57 91 6d 0b 31 6a |....i/o...W.m.1j| +00000170 e1 1d c3 70 c5 c8 c5 9e 02 3c f3 f6 4d c7 c3 67 |...p.....<..M..g| +00000180 64 71 4e 03 1f 6e 53 8b 68 cc 9b 72 77 a1 f7 65 |dqN..nS.h..rw..e| +00000190 f2 8c cc a2 1b 33 9f 13 74 6e 7d 97 e8 2b 5e 43 |.....3..tn}..+^C| +000001a0 76 be 56 a0 8c 01 79 e2 b2 b0 b7 3f 64 4c 43 7d |v.V...y....?dLC}| +000001b0 54 1b 24 c0 98 43 a5 7a ab 48 77 6a 90 0e 9a 2c |T.$..C.z.Hwj...,| +000001c0 c0 3c 1f 30 b5 c8 cc 5c 96 05 16 87 13 f0 31 58 |.<.0...\......1X| +000001d0 a0 b1 d2 4c 26 0c 34 7e 19 fc 5e 5e 29 bb d8 6e |...L&.4~..^^)..n| +000001e0 4e c5 56 24 7c f0 fa 2f 5f 9b 0f 0f 54 bc 44 7e |N.V$|../_...T.D~| +000001f0 85 d3 f9 f1 54 a1 91 e1 38 a4 8a dd 57 c2 de 70 |....T...8...W..p| +00000200 80 0c 5f 74 3d c7 4f 1c 30 1f 2b 9f 93 c1 2e 16 |.._t=.O.0.+.....| +00000210 7c 73 09 79 f2 11 57 70 c5 1f 48 9e 00 34 47 2e ||s.y..Wp..H..4G.| +00000220 75 7c 82 b9 91 44 e6 55 5c 5a 9e 04 41 18 31 ab |u|...D.U\Z..A.1.| +00000230 5a f4 bb 15 75 8e fd 05 2e 91 5a e2 1b a0 1b 49 |Z...u.....Z....I| +00000240 94 3b 1e f9 49 8c 50 fd 59 56 d6 9f 42 90 a0 49 |.;..I.P.YV..B..I| +00000250 de 4f 7f d3 22 24 fe 98 23 3d 2c 40 24 58 e8 a3 |.O.."$..#=,@$X..| +00000260 63 9c a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc |c......W.5...<#.| +00000270 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000280 b4 e6 ce eb 6f f0 b1 d4 65 b8 53 a3 57 09 88 92 |....o...e.S.W...| +00000290 0d 37 11 02 fa 93 9d af 83 e4 8c f8 0f ca 38 54 |.7............8T| +000002a0 ab c7 79 d7 dc 51 46 ba 26 24 e2 d1 ad b5 b6 96 |..y..QF.&$......| +000002b0 a1 18 24 9c 14 c4 80 be 99 38 2f a0 0f 05 e9 8a |..$......8/.....| +000002c0 9a 63 f2 8c 8a ba 81 00 4d fb f2 0d 82 94 5b 8f |.c......M.....[.| +000002d0 fd 36 ad 7f 75 df 62 ea c5 d8 8b 72 13 bb e5 7f |.6..u.b....r....| +000002e0 a8 4e 74 50 57 cf 32 3f 76 2f 85 84 85 85 00 7a |.NtPW.2?v/.....z| +000002f0 77 34 40 3e 20 0e ac b5 59 26 18 96 fa a2 cf b0 |w4@> ...Y&......| +00000300 b6 a4 f1 34 8e 70 27 6f c9 72 1b 8c 8e d2 76 45 |...4.p'o.r....vE| +00000310 cf 72 3e c9 96 3f fd c1 60 55 03 a9 c2 46 c1 9c |.r>..?..`U...F..| +00000320 fa a1 d6 b7 e2 3f f3 65 ea 74 77 10 39 ff 58 b4 |.....?.e.tw.9.X.| +00000330 d9 c8 69 b9 40 05 9b 4e 3b 36 e3 13 33 6c 32 17 |..i.@..N;6..3l2.| +00000340 1d 90 2f 44 50 48 e7 d0 7b 72 8b 54 1b 2a 9e b5 |../DPH..{r.T.*..| +00000350 10 7a eb a3 d6 7b f2 a9 31 f3 e2 4b 9a 28 b1 7c |.z...{..1..K.(.|| +00000360 bb fe 40 ba 10 d6 b8 d7 20 5a d3 5b 39 bd 51 35 |..@..... Z.[9.Q5| +00000370 24 18 b8 4c c5 4b 01 9f dd bb 8c 93 6a cc 79 b8 |$..L.K......j.y.| +00000380 d5 cc 5c cb |..\.| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 9e 58 da 8f cd 5b 40 98 56 a0 bc 31 4a 6c aa 14 |.X...[@.V..1Jl..| +00000020 a2 42 c9 55 0e 07 b4 51 4b 92 54 7b 57 97 c6 11 |.B.U...QK.T{W...| +00000030 a4 bd 6f 4b 5c ba 77 a0 13 a3 a0 a3 |..oK\.w.....| +>>> Flow 7 (server to client) +00000000 db 66 28 c9 3d 2a ea f5 b4 3c c2 b7 08 db 34 9a |.f(.=*...<....4.| +00000010 a2 c0 4e 92 88 83 a6 bc 88 c7 39 23 b1 37 f0 d2 |..N.......9#.7..| +00000020 ec 88 3d b3 47 9a 26 e9 e1 55 86 99 |..=.G.&..U..| +>>> Flow 8 (client to server) +00000000 05 36 32 93 77 a1 67 52 d5 80 af a1 ad 5d f7 ef |.62.w.gR.....]..| +00000010 ec b1 25 c1 a8 7f 2a 0f a4 7c a8 85 dc 92 d9 cb |..%...*..|......| +00000020 63 f3 cc 8b 59 da 61 7a 0f f3 06 3a ea 65 19 c2 |c...Y.az...:.e..| +00000030 aa f8 23 68 16 4b 48 e3 c8 77 78 77 1d 89 a0 6a |..#h.KH..wxw...j| +00000040 bc f5 f5 d4 |....| +>>> Flow 9 (server to client) +00000000 31 4a 14 e8 87 89 ff b1 db 4a 96 ac 30 42 5f 00 |1J.......J..0B_.| +00000010 64 63 73 2b 1e 2d ad 63 e9 28 70 0d dd c2 77 a4 |dcs+.-.c.(p...w.| +00000020 47 52 f5 ee 13 c1 71 76 6f b7 54 00 |GR....qvo.T.| +>>> Flow 10 (client to server) +00000000 47 7f 42 8d 64 67 c0 a9 64 31 99 e9 b6 96 ff 2c |G.B.dg..d1.....,| +00000010 ad cf 4e 60 f2 8a 76 33 f1 cf 58 09 41 f9 6a ac |..N`..v3..X.A.j.| +00000020 bb b2 41 e6 b5 12 51 ad 56 f2 76 b3 b8 a6 90 38 |..A...Q.V.v....8| +00000030 c8 34 4e e2 7b a6 4c 79 24 6a 02 8f 5f 0c 8a a4 |.4N.{.Ly$j.._...| +00000040 da 85 de c3 07 d9 cd 58 db a4 4d 28 b6 14 f1 16 |.......X..M(....| +00000050 f9 34 6c ec 97 6f 9f c7 f1 f3 9d 64 8c 8b 89 1b |.4l..o.....d....| +00000060 d1 37 50 46 22 27 c5 9e c4 a1 8c 84 12 dc bf 0b |.7PF"'..........| +00000070 12 5e db bf 0f fe b6 08 0a 44 a3 2d bd 54 d7 5b |.^.......D.-.T.[| +00000080 e0 ba 5d ee 03 fa 6e e1 27 03 80 a0 c5 92 19 37 |..]...n.'......7| +00000090 4c 56 74 0f 04 67 71 9a b0 a4 6e 22 ad 3e 1c bc |LVt..gq...n".>..| +000000a0 58 58 2b 9a d6 41 9b a5 d0 fe 88 66 5e a5 33 37 |XX+..A.....f^.37| +000000b0 35 69 79 44 e1 ed ee 32 34 bb 2a d9 0d 19 d0 b2 |5iyD...24.*.....| +000000c0 6b bd 6f 78 0f c9 64 54 be c2 d3 28 bc 86 2a 89 |k.ox..dT...(..*.| +000000d0 76 49 ae 04 1d a8 17 c9 b5 82 60 f3 c7 c6 4a 72 |vI........`...Jr| +000000e0 2d a1 23 74 c0 9f 51 c8 d0 dd 57 84 90 7d 23 18 |-.#t..Q...W..}#.| +000000f0 a4 a9 71 7b f4 c5 45 c6 7a fd b8 f3 cc 44 29 aa |..q{..E.z....D).| +00000100 71 44 ec 01 0c 55 3c 3a bd a3 56 f0 69 83 7b 0a |qD...U<:..V.i.{.| +00000110 70 f5 9d 17 32 2e 1e 84 2c 03 36 ab 7d c6 31 a2 |p...2...,.6.}.1.| +00000120 06 17 38 f0 30 d2 35 8f 4f 74 09 f8 a1 25 a1 85 |..8.0.5.Ot...%..| +00000130 e4 9d 96 04 c1 04 84 b2 65 13 76 99 ec 72 4d a8 |........e.v..rM.| +00000140 c5 7c b9 a5 83 92 59 82 71 7c fb 61 b3 37 3b c8 |.|....Y.q|.a.7;.| +00000150 09 96 02 fd 93 23 1a 98 11 ef 3b 37 87 13 04 11 |.....#....;7....| +00000160 8e 5b 97 25 26 a9 1d 1a 36 43 93 31 e9 26 fa 35 |.[.%&...6C.1.&.5| +00000170 91 dc 42 73 |..Bs| +>>> Flow 11 (server to client) +00000000 f1 37 1b c7 fc 88 df 2e 6a f4 b8 de d9 fc fc 0b |.7......j.......| +00000010 05 95 d2 3d 3d 5b 85 ba 70 a9 75 67 e5 b9 86 95 |...==[..p.ug....| +00000020 1e 2f 26 a8 70 65 c7 5d d8 65 25 c7 a0 95 de a7 |./&.pe.].e%.....| +00000030 0d 6b 22 71 dd e7 5c 9f 06 7e 93 80 f1 f4 fb bf |.k"q..\..~......| +00000040 3c e5 94 78 ba 3b fd fd d1 87 29 92 a0 a8 6c b5 |<..x.;....)...l.| +00000050 f5 e2 42 1c 54 3c 89 fc 5f 9d b1 6e 6d 42 d7 77 |..B.T<.._..nmB.w| +00000060 f7 a4 64 bc c6 2e de 02 76 83 98 6a 3a 2a 83 44 |..d.....v..j:*.D| +00000070 8d 37 ab 52 bb eb 13 fb 8a ef 62 59 c5 6a ac 9f |.7.R......bY.j..| +00000080 d1 05 7a 82 6f 43 c5 9f 1b 3e c7 dc 0d 59 32 57 |..z.oC...>...Y2W| +00000090 f5 e2 25 17 a7 3a 57 2f e5 c1 06 18 87 e2 bc f9 |..%..:W/........| +000000a0 9a f2 cf 56 8c 54 fb b4 89 44 0e 9d 92 c2 d7 9f |...V.T...D......| +000000b0 75 a0 e8 22 ec e4 15 7a 96 6c 14 36 5e 13 02 ff |u.."...z.l.6^...| +000000c0 6a 1e 94 19 ab 98 c2 1d 18 77 65 bb 43 50 71 1d |j........we.CPq.| +000000d0 20 86 e3 e9 7a c5 12 9d a0 a5 8f 47 bc 47 33 64 | ...z......G.G3d| +000000e0 15 c0 48 cf 1a 8a b1 d0 a8 17 a1 53 ba bf 16 ac |..H........S....| +000000f0 70 3d 51 c3 2d 33 3c 41 8f 3e fb aa 16 c0 92 25 |p=Q.-3.....%| +00000100 fc 01 57 4d fc bb e5 f1 7e f0 7a f6 06 c4 ea 91 |..WM....~.z.....| +00000110 c3 63 da 6a f0 62 78 dd 27 cd cf 1d 94 c8 99 87 |.c.j.bx.'.......| +00000120 db 28 7b c3 6b a8 05 88 f2 92 51 98 be be e6 62 |.({.k.....Q....b| +00000130 14 60 8d 67 e7 d5 d2 5f 0d 51 ee 8a 4b 9d 93 31 |.`.g..._.Q..K..1| +00000140 55 c2 04 89 47 ba e3 ca 30 c1 ed ec |U...G...0...| +>>> Flow 12 (client to server) +00000000 db de f3 e0 89 10 e2 9d e2 7e 17 70 19 92 ac a0 |.........~.p....| +00000010 c9 55 e8 2c 8c cd 8d a7 57 09 dc 03 cb 60 46 5e |.U.,....W....`F^| +00000020 73 14 53 bb 07 1b dd 2d 08 42 d9 9e a6 f0 80 71 |s.S....-.B.....q| +00000030 a6 53 7b 23 40 7e 8e 8a ed 41 4c 5b 20 c0 86 d5 |.S{#@~...AL[ ...| +00000040 46 6b 9d f2 94 13 65 37 46 7e bc 64 93 e0 74 53 |Fk....e7F~.d..tS| +00000050 58 af 96 86 41 2d ca 7c c2 38 5c a1 ef 6b b9 9a |X...A-.|.8\..k..| +00000060 82 89 e7 c7 d2 27 dc ea c2 c5 97 7b b3 e7 72 12 |.....'.....{..r.| +00000070 9a 9b 35 f5 ad 3f 50 8f e0 26 64 72 59 c4 78 da |..5..?P..&drY.x.| +00000080 07 d8 19 43 ce d2 d9 bc 71 4e 70 0e 7e d5 70 27 |...C....qNp.~.p'| +00000090 1f 28 af f5 5f c5 db ce a6 c5 66 f6 f5 b3 f1 ff |.(.._.....f.....| +000000a0 d9 e8 61 46 b4 24 c0 49 c9 f7 6b aa 2a 64 61 32 |..aF.$.I..k.*da2| +000000b0 43 ce 47 1a df 37 49 f0 c4 64 87 8a d2 8a a7 b9 |C.G..7I..d......| +000000c0 68 58 5c 14 14 fa 54 a9 f1 fe fc 5a 21 49 9c e9 |hX\...T....Z!I..| +000000d0 69 43 d5 7e ee 8a 15 05 88 c5 d1 23 12 d0 69 3e |iC.~.......#..i>| +000000e0 20 d9 a9 bc 75 26 4f 65 b6 17 ba b2 6a 81 55 93 | ...u&Oe....j.U.| +000000f0 8a e3 95 8f 65 6f 9e 62 c1 25 69 1c 47 a6 c4 a0 |....eo.b.%i.G...| +00000100 52 af e3 cd 56 38 fb b3 6d 2a f0 a4 ab b2 e6 2f |R...V8..m*...../| +00000110 5b b3 6e 5f f5 42 e6 a1 8b 6f c1 19 62 cd 58 dd |[.n_.B...o..b.X.| +00000120 e8 8e c3 7d 42 b5 a5 ba 90 28 4d 8d 55 e3 98 e5 |...}B....(M.U...| +00000130 6f ce c8 5f f9 28 c5 02 82 c6 26 08 35 19 34 01 |o.._.(....&.5.4.| +00000140 07 1d ee 3e 2a b0 a7 f4 41 ad 8e a5 9a 4b d2 4c |...>*...A....K.L| +00000150 c4 da b9 ec 23 ba c1 a2 7c a8 5f 87 d2 c4 f8 52 |....#...|._....R| +00000160 eb 3c 1b 0f 20 bf 89 3f 40 17 13 a1 0b 5c 9e 74 |.<.. ..?@....\.t| +00000170 03 5b 5f 06 49 a4 2d 98 d2 6b 52 0a 5a 4c 36 9b |.[_.I.-..kR.ZL6.| +00000180 7f cf a3 85 29 69 82 fa 8a d5 d7 c3 b8 12 0d e5 |....)i..........| +00000190 2b 42 09 6b 38 41 6d ab 74 d5 9f d1 2c 86 0b 72 |+B.k8Am.t...,..r| +000001a0 d4 96 9f 97 8f fc 07 59 58 61 5e b7 c9 42 d3 3a |.......YXa^..B.:| +000001b0 46 91 53 07 76 d7 5a 01 9f f2 72 fc 12 e1 73 71 |F.S.v.Z...r...sq| +000001c0 f7 8f 63 94 c3 9a 1a fd c3 2c 48 db 42 99 40 4a |..c......,H.B.@J| +000001d0 fe 55 12 aa 0a f0 70 d5 c0 13 fa ed c9 1a d1 42 |.U....p........B| +000001e0 98 02 72 33 95 2c 2f 9a 50 a0 7f 1f 46 15 01 08 |..r3.,/.P...F...| +000001f0 9f ac 14 40 08 ae a0 e4 86 a1 6d fd ce 6f e0 38 |...@......m..o.8| +00000200 4e 3e ff 9e a3 0a d7 3f 5f b9 e5 43 fc 51 11 38 |N>.....?_..C.Q.8| +00000210 c9 27 8a 50 ab a8 ec 0d c7 75 8a 48 17 3e 19 18 |.'.P.....u.H.>..| +00000220 e6 8a f6 0e 0c aa 40 00 d4 55 0b 1f 5a b7 7d 59 |......@..U..Z.}Y| +00000230 88 73 30 f0 ca ce 19 4f 76 22 8e 6d ff 41 75 f2 |.s0....Ov".m.Au.| +00000240 f1 13 6b ab 57 cf 3d 10 09 ae e2 1e 6b 45 26 f1 |..k.W.=.....kE&.| +00000250 1b 84 fa b1 95 ff 28 e3 4f 19 62 78 dd f9 e4 8e |......(.O.bx....| +00000260 f7 99 38 74 53 2d 64 c8 70 d5 1e 33 9a e8 9d 16 |..8tS-d.p..3....| +00000270 fe ed 9b a9 81 51 bb 60 ac 50 1d d9 61 b3 7f 54 |.....Q.`.P..a..T| +00000280 98 72 2e fe a5 4d 2e 4e 83 34 0a e3 |.r...M.N.4..| +>>> Flow 13 (server to client) +00000000 7e b8 83 f9 b9 db ee 2a 85 5a c3 98 fe e2 f3 b0 |~......*.Z......| +00000010 dd a7 15 5d 29 33 8e db f8 f0 0c e8 |...])3......| +>>> Flow 14 (client to server) +00000000 29 bf a2 22 ea b2 d2 e1 c6 21 d4 ad 36 52 d1 11 |)..".....!..6R..| +00000010 cd 0b ca d2 0f 05 5a 99 11 43 89 69 18 9e e8 75 |......Z..C.i...u| +00000020 6d bb 32 51 8d 62 d6 6c 69 4e 74 ea 4b 99 ee 55 |m.2Q.b.liNt.K..U| +00000030 7f 59 26 91 |.Y&.| +>>> Flow 15 (server to client) +00000000 b9 8b 8b d1 c8 dc 15 bd 01 8c bc 8d 90 4f fe 9c |.............O..| +00000010 32 19 e4 2b 42 23 1a 25 ce 97 ea ca 7b 74 1e 81 |2..+B#.%....{t..| +00000020 d6 ea 2f b2 b2 08 4a 95 ee 08 6e 43 |../...J...nC| +>>> Flow 16 (client to server) +00000000 ed f2 52 5e 31 e3 ba 26 c6 07 2a 79 9c c9 c0 12 |..R^1..&..*y....| +00000010 75 c4 14 9d 51 dd 6e 13 2c a8 6e 36 ef fa 27 5f |u...Q.n.,.n6..'_| +00000020 ff 00 bb eb d8 8c 0c 03 0d 4e f8 00 4b 55 5a 80 |.........N..KUZ.| +00000030 d4 bc 8d 41 23 b1 ca dc 30 1e 47 87 00 ff 4f 81 |...A#...0.G...O.| +00000040 f4 4c d3 f3 db c6 2d 18 48 e5 b5 00 04 cf 9a 45 |.L....-.H......E| +00000050 1d 0b 1b a4 4d da a8 38 |....M..8| +>>> Flow 17 (server to client) +00000000 09 bf b0 d2 a7 8a c4 99 3d 92 0a bb 29 13 ca 31 |........=...)..1| +00000010 12 95 f8 68 4e b9 bc 24 16 b0 cd 3e 75 3c 46 2e |...hN..$...>u>> Flow 18 (client to server) +00000000 17 d3 94 6b 35 fd 98 28 8a 5a 87 29 2d 9f fd 47 |...k5..(.Z.)-..G| +00000010 b9 86 cd e7 25 c3 53 64 32 10 38 a3 29 1b 99 ad |....%.Sd2.8.)...| +00000020 e3 ae 62 b1 fb 76 6a 29 ce c1 e6 a1 3a 97 6c 3b |..b..vj)....:.l;| +00000030 4f c3 c2 fb 5b b1 42 97 c3 0e 4b ca 1d 93 2a 45 |O...[.B...K...*E| +00000040 dc e1 69 da e9 9a dc 53 ae d8 d4 64 f4 d6 e6 be |..i....S...d....| +00000050 42 01 29 49 ed a9 da ba 29 96 e6 80 20 8a e9 b0 |B.)I....)... ...| diff --git a/ssh/testdata/Server-MAC-hmac-sha2-512 b/ssh/testdata/Server-MAC-hmac-sha2-512 new file mode 100644 index 0000000000..ebd17b9d95 --- /dev/null +++ b/ssh/testdata/Server-MAC-hmac-sha2-512 @@ -0,0 +1,345 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 1c 04 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |........+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000120 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +00000130 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +00000140 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000150 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +00000160 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +00000170 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000180 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000190 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +000001a0 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +000001b0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000001c0 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +000001d0 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +000001e0 0d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 00 00 |.hmac-sha2-512..| +000001f0 00 0d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 00 |..hmac-sha2-512.| +00000200 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 |...none....none.| +00000210 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 |.............;..| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 57 42 a4 7e 22 44 b5 74 1c 61 |...<..WB.~"D.t.a| +00000010 f5 0b fe 4e 81 46 00 00 01 7a 73 6e 74 72 75 70 |...N.F...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 73 73 68 2d 65 64 32 35 |.com....ssh-ed25| +000001a0 35 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |519-cert-v01@ope| +000001b0 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +000001c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000001d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000001e0 6d 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |m,ecdsa-sha2-nis| +000001f0 74 70 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f |tp384-cert-v01@o| +00000200 70 65 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 |penssh.com,ecdsa| +00000210 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 |-sha2-nistp521-c| +00000220 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000230 63 6f 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 |com,sk-ssh-ed255| +00000240 31 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |19-cert-v01@open| +00000250 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 |ssh.com,sk-ecdsa| +00000260 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 |-sha2-nistp256-c| +00000270 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e |ert-v01@openssh.| +00000280 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 35 31 32 |com,rsa-sha2-512| +00000290 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002a0 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 61 32 2d 32 |h.com,rsa-sha2-2| +000002b0 35 36 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e |56-cert-v01@open| +000002c0 73 73 68 2e 63 6f 6d 2c 73 73 68 2d 65 64 32 35 |ssh.com,ssh-ed25| +000002d0 35 31 39 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e |519,ecdsa-sha2-n| +000002e0 69 73 74 70 32 35 36 2c 65 63 64 73 61 2d 73 68 |istp256,ecdsa-sh| +000002f0 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 63 64 73 |a2-nistp384,ecds| +00000300 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31 2c |a-sha2-nistp521,| +00000310 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 40 6f |sk-ssh-ed25519@o| +00000320 70 65 6e 73 73 68 2e 63 6f 6d 2c 73 6b 2d 65 63 |penssh.com,sk-ec| +00000330 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000340 36 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 |6@openssh.com,rs| +00000350 61 2d 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 |a-sha2-512,rsa-s| +00000360 68 61 32 2d 32 35 36 00 00 00 6c 63 68 61 63 68 |ha2-256...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 cb 46 8c 61 32 2c |...,..... .F.a2,| +00000650 80 c4 21 11 55 6c ba 2c b6 a0 90 79 b2 bb 5e b5 |..!.Ul.,...y..^.| +00000660 0e 1c 7f 0d 26 81 75 d2 8d 63 00 00 00 00 00 00 |....&.u..c......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 13 87 32 34 3e 68 e6 9b 9a cb 23 |.... ..24>h....#| +00000130 22 06 11 e8 24 71 e5 d7 96 79 83 48 59 1a 95 f2 |"...$q...y.HY...| +00000140 b0 86 1c 76 54 00 00 01 14 00 00 00 0c 72 73 61 |...vT........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 2d 75 7a |-sha2-512....-uz| +00000160 64 02 52 3d d1 14 c2 00 94 c3 a4 a9 da fd d6 af |d.R=............| +00000170 ee e8 51 d6 58 1a 12 1e 64 bb f2 d4 45 22 85 44 |..Q.X...d...E".D| +00000180 2e fa f9 99 97 35 02 d3 6f 0d 14 86 6b 9a bd 11 |.....5..o...k...| +00000190 b9 d7 51 cd 8b 96 7e 9d 06 0e 8b 22 58 57 a7 04 |..Q...~...."XW..| +000001a0 44 0f 5c 82 de 9f 2c 8d 28 a2 63 70 b8 45 0a 74 |D.\...,.(.cp.E.t| +000001b0 6f c8 72 d5 9d 72 31 62 21 4d 09 ae 86 c2 7a 0c |o.r..r1b!M....z.| +000001c0 28 b8 95 94 18 d4 02 84 99 e5 9f e3 0a 6d 3e 92 |(............m>.| +000001d0 1e da f6 5e 69 89 6e 33 70 eb eb bb 03 b9 a1 96 |...^i.n3p.......| +000001e0 7c 7e 3b f1 52 ba a1 33 32 e1 43 f8 2e fa 53 ad ||~;.R..32.C...S.| +000001f0 a7 c3 ac 58 55 0d f2 c0 3a 5b 6a 01 78 9f 8f 0d |...XU...:[j.x...| +00000200 c2 50 90 6d 8f e5 cc 61 f5 7a 5f 10 68 aa b6 6b |.P.m...a.z_.h..k| +00000210 9c 9d 67 8e b9 f8 97 5b 7e 05 ff f9 95 c1 03 49 |..g....[~......I| +00000220 c4 0e 29 70 63 1f c6 cc 6a 30 6e 4a 76 9f 37 01 |..)pc...j0nJv.7.| +00000230 80 13 e5 ea b1 34 bf 25 3f f9 3c ff a5 f8 c8 e5 |.....4.%?.<.....| +00000240 57 56 52 b4 80 1a b0 ab 52 08 69 d4 84 d3 6b f0 |WVR.....R.i...k.| +00000250 be ac 4f 7d a4 ff 8f 7c 01 6a 0d 7f 14 58 e8 a3 |..O}...|.j...X..| +00000260 63 9c a8 a1 e3 f9 ae 57 e2 35 b8 cc 87 3c 23 dc |c......W.5...<#.| +00000270 00 00 00 0c 0a 15 62 b8 d2 60 16 9a fa 2f 75 ab |......b..`.../u.| +00000280 63 57 b2 31 9a 10 9b 6f 28 1d 4c cc d9 34 23 8a |cW.1...o(.L..4#.| +00000290 89 9a af 3c 68 1f 45 33 1e 51 af 8a f2 ca 79 d4 |....(..d.+._.| +00000370 01 09 90 b2 95 88 ac a9 68 e7 a4 25 45 aa c8 55 |........h..%E..U| +00000380 62 e7 cc 3d |b..=| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 e1 8f 6c 6a 80 c5 c0 5d db 78 b0 34 ed 0e 47 1f |..lj...].x.4..G.| +00000020 c3 67 2c 71 93 27 30 91 e5 52 e3 64 09 21 fa d3 |.g,q.'0..R.d.!..| +00000030 9d a1 25 c8 d3 ee 77 ba f0 f5 b6 d0 |..%...w.....| +>>> Flow 7 (server to client) +00000000 cc ea 42 96 a2 6c fc a8 22 4a 0f 4f f9 ba 87 39 |..B..l.."J.O...9| +00000010 0e 08 63 a6 e6 9c 1e 31 e9 b4 79 d5 6f 7f 0b ec |..c....1..y.o...| +00000020 36 b1 17 f5 93 f2 ce ed 4a 07 b6 f7 |6.......J...| +>>> Flow 8 (client to server) +00000000 64 4a f8 ef b7 16 b6 e8 df 08 b6 76 c2 30 4b 68 |dJ.........v.0Kh| +00000010 e7 aa 65 ac b8 33 06 79 a9 73 13 65 33 80 1e e0 |..e..3.y.s.e3...| +00000020 53 32 61 6a 45 d6 ef 3b 13 d6 45 b3 5a 08 4c 6d |S2ajE..;..E.Z.Lm| +00000030 a7 d9 c7 a3 98 4b 87 b2 1c 4e 17 db 4b 44 da fd |.....K...N..KD..| +00000040 cf 89 89 b3 |....| +>>> Flow 9 (server to client) +00000000 ad f3 82 36 ce 2e 6a dd 37 d1 78 4a f2 12 15 33 |...6..j.7.xJ...3| +00000010 b2 7d 9c 17 9a 62 ff 46 6f ac 9b 49 bf 89 c4 c4 |.}...b.Fo..I....| +00000020 e5 89 1e 2f 43 93 92 f0 74 9b 06 ad |.../C...t...| +>>> Flow 10 (client to server) +00000000 a1 ee a5 44 83 3b 5f 5d 83 cb 78 73 08 0a 54 a8 |...D.;_]..xs..T.| +00000010 12 ee b4 e4 85 6b 7c 89 99 34 a3 52 9a 3b 3c ec |.....k|..4.R.;<.| +00000020 5a e5 0c be b2 ce b0 1d 6f c6 6c 27 38 ff 8d de |Z.......o.l'8...| +00000030 80 bd c6 2d 7c 1d bf 4f 7f b5 0e d9 f6 8c 81 29 |...-|..O.......)| +00000040 18 32 f9 e3 47 3c 1f e4 76 21 c8 72 41 13 3c 07 |.2..G<..v!.rA.<.| +00000050 73 85 fd 9a ff a2 19 b9 55 82 1d 7c 3a f3 8d be |s.......U..|:...| +00000060 a7 53 d6 40 cf f7 c6 32 e1 7e 6c 1e e9 fe b1 62 |.S.@...2.~l....b| +00000070 d4 9e 67 3a 52 d0 97 7f 31 de 15 0f 21 9c f9 55 |..g:R...1...!..U| +00000080 ae dd 3d f8 4b ee 1e 99 20 ee 5b 61 cd 92 13 36 |..=.K... .[a...6| +00000090 41 ea b3 7a 06 a4 bb e5 16 05 d0 15 98 37 dc 62 |A..z.........7.b| +000000a0 ce cf 74 06 d6 dc 64 63 e4 bc 5d 34 45 ea b0 6b |..t...dc..]4E..k| +000000b0 35 bd 44 56 08 ac 29 27 1c a0 d1 1f 00 ee 09 b1 |5.DV..)'........| +000000c0 10 dd ec 95 cf 6b ca cc b3 1b 6b 51 d5 97 44 e3 |.....k....kQ..D.| +000000d0 0d 56 47 67 c1 9f 66 3c 5f 29 9b 9e 6a b8 db 70 |.VGg..f<_)..j..p| +000000e0 61 aa e2 3b 6c 41 2c fa a3 1e 7d f9 dd b2 b6 4e |a..;lA,...}....N| +000000f0 13 7a 61 71 9d 29 2d 1b a9 37 26 e1 cb 67 8d 20 |.zaq.)-..7&..g. | +00000100 4a 48 44 33 bb 9e 49 40 e4 58 b1 37 1c 1b 3d e3 |JHD3..I@.X.7..=.| +00000110 ab 85 9e d2 f6 95 44 f0 23 13 4a b6 88 b9 8f d5 |......D.#.J.....| +00000120 7f 64 46 48 e9 64 2b 2e 25 c7 de 79 62 7d 21 c4 |.dFH.d+.%..yb}!.| +00000130 e4 a6 41 bd ca 37 67 2d 4b 34 43 36 3e 36 fd c3 |..A..7g-K4C6>6..| +00000140 32 e8 47 fd 93 e1 7a c2 7d d3 96 34 b4 c5 17 50 |2.G...z.}..4...P| +00000150 e1 49 b5 8b 5f 44 f4 01 b9 1b f9 41 07 01 ed ce |.I.._D.....A....| +00000160 b2 42 d2 31 53 64 6d 9e 73 cb f1 8f 3d 30 0d 42 |.B.1Sdm.s...=0.B| +00000170 2f 39 e6 72 |/9.r| +>>> Flow 11 (server to client) +00000000 48 f8 b8 00 62 ee 8b 15 7b 87 d1 de 0f 64 b8 2c |H...b...{....d.,| +00000010 ef 87 8e 0b ec 1e 65 32 26 2b c3 5b d5 f8 f5 f8 |......e2&+.[....| +00000020 91 d7 5a 74 0c 39 31 86 e4 21 80 69 06 23 1e 3b |..Zt.91..!.i.#.;| +00000030 17 37 8b 03 4e 18 e2 aa 7d 56 16 3c c6 ab ea 05 |.7..N...}V.<....| +00000040 16 db d1 6a 7a 56 04 4f 14 39 28 f4 69 05 06 3f |...jzV.O.9(.i..?| +00000050 a9 dc ca 88 4e c2 fa d3 fa f4 6a 28 59 49 33 0d |....N.....j(YI3.| +00000060 2d 3b fa 62 b5 e6 5e fe 8f 11 7d 11 ea 32 cd e5 |-;.b..^...}..2..| +00000070 0a 23 a5 d5 8c 1c fa 0b f7 8f 33 1d d0 3d 82 21 |.#........3..=.!| +00000080 f2 28 a3 9c 98 36 2b 39 f1 99 63 48 a6 a1 48 4d |.(...6+9..cH..HM| +00000090 0f 21 70 06 f9 5f 4d ae 30 42 a8 4c 66 55 9b e0 |.!p.._M.0B.LfU..| +000000a0 38 f4 0f 78 f5 24 2e 60 81 fc e6 50 98 0f 08 a8 |8..x.$.`...P....| +000000b0 d8 64 89 ad 6f 34 c4 20 54 6a 33 1a 74 18 a2 29 |.d..o4. Tj3.t..)| +000000c0 55 be 0e 9e 5e cb 05 ef a1 f1 c7 e2 4f a4 bb b6 |U...^.......O...| +000000d0 e6 74 d9 b1 78 fe 03 2a 63 84 54 0d df 27 90 52 |.t..x..*c.T..'.R| +000000e0 03 53 21 ef 75 5f 78 bb a3 0e 2f 04 44 84 46 fb |.S!.u_x.../.D.F.| +000000f0 d2 66 1e 06 73 9b 26 6c 37 62 76 eb e8 d0 f8 09 |.f..s.&l7bv.....| +00000100 89 3b 6f 96 5e de ce e9 24 9b 20 cd 02 d9 9e 60 |.;o.^...$. ....`| +00000110 8c 32 ac 86 73 62 a2 26 6a 6f bf 86 9d 11 a6 a5 |.2..sb.&jo......| +00000120 50 89 2d 8b 9a 23 0b fb 8b 8b 32 9c 30 ae a3 6f |P.-..#....2.0..o| +00000130 3c 24 c1 f3 e6 50 e0 01 a8 48 0d 68 3c de a7 00 |<$...P...H.h<...| +00000140 c3 e7 a3 4f 18 93 98 8d e1 9e 44 94 |...O......D.| +>>> Flow 12 (client to server) +00000000 e2 1c 2f 57 87 99 c1 77 04 89 d7 5d 84 72 a9 a5 |../W...w...].r..| +00000010 2e 69 4a 86 fb 76 f7 15 f2 20 f0 a9 cf e7 fd ca |.iJ..v... ......| +00000020 ae 7e f4 c5 91 b7 b7 ed aa e0 f4 22 8a 3b a8 59 |.~.........".;.Y| +00000030 2e 6f 4f ca e7 ba d8 04 62 b0 27 c9 e2 9e f4 13 |.oO.....b.'.....| +00000040 b2 2c 2a e6 8a 89 58 e1 16 9f d4 60 bb 1f 99 8e |.,*...X....`....| +00000050 45 70 2a 0c b9 4a e1 d5 c1 7a 98 34 5d 7d d0 ae |Ep*..J...z.4]}..| +00000060 59 f7 1f a4 9f 47 7c 1b c5 58 af a1 3e fc 28 5a |Y....G|..X..>.(Z| +00000070 33 d4 cc 30 6f 44 4a 1e 74 24 8e a7 de 1f 9a e1 |3..0oDJ.t$......| +00000080 c9 e2 ad 0e ac b2 04 a2 55 b5 02 50 1c 37 9d a7 |........U..P.7..| +00000090 cc 1d 17 f4 6a 1f ba 28 2b f2 63 62 ee 42 61 74 |....j..(+.cb.Bat| +000000a0 32 f5 55 50 51 4e da 50 84 16 0f a5 84 02 e7 91 |2.UPQN.P........| +000000b0 6b fe a4 40 1f b0 e6 48 89 93 48 8d 78 ad bf 14 |k..@...H..H.x...| +000000c0 00 27 50 24 53 4b de b3 94 74 37 0e b5 2d 87 5b |.'P$SK...t7..-.[| +000000d0 4a e4 f1 77 e9 46 11 30 77 3e 8f 3c bf 21 ca 6b |J..w.F.0w>.<.!.k| +000000e0 a9 1f 7d 9e eb ca 0e 3b d6 f5 28 92 c8 bf 91 29 |..}....;..(....)| +000000f0 54 57 e6 8a 56 24 a1 8e 10 27 74 8d bd 24 ae 55 |TW..V$...'t..$.U| +00000100 f6 c5 47 e8 4a 4a 7a 17 f3 5f 39 b1 2d 9e b3 91 |..G.JJz.._9.-...| +00000110 58 b2 d3 13 e4 8c 02 72 57 f2 b3 9f 7f d7 c8 52 |X......rW......R| +00000120 a2 42 78 ad 62 26 37 4e c5 16 ff 99 6c 79 4c 36 |.Bx.b&7N....lyL6| +00000130 20 63 2d d8 35 0b 15 e7 ab bb 0c 85 52 38 3d 65 | c-.5.......R8=e| +00000140 81 63 5b 60 d5 cb eb 6e f9 e5 3a 41 96 d4 88 19 |.c[`...n..:A....| +00000150 8a b5 e3 e5 9f d4 49 87 7a 8b 5b 5b e4 45 bd 20 |......I.z.[[.E. | +00000160 a3 64 90 81 b3 dd b2 55 70 27 63 8a 39 1d 43 f6 |.d.....Up'c.9.C.| +00000170 55 05 7d bf 43 90 d9 f4 dc 78 a7 4f f5 d3 21 bc |U.}.C....x.O..!.| +00000180 13 3b 1c 9e cc 53 02 d6 7a 7a eb 1c d1 61 75 a5 |.;...S..zz...au.| +00000190 bc 86 45 16 f3 d5 0c 0f 25 63 69 ab a4 08 ec 39 |..E.....%ci....9| +000001a0 08 a1 0e a9 c2 52 45 30 fc 11 db e6 31 c4 24 8c |.....RE0....1.$.| +000001b0 26 47 70 d4 59 f3 51 74 07 35 88 f0 c1 af 6c ba |&Gp.Y.Qt.5....l.| +000001c0 ba be fe bb e5 fa e4 f5 a0 64 f9 49 05 a7 39 7a |.........d.I..9z| +000001d0 39 05 00 d4 04 f8 c0 87 e3 32 ad 0d 3c fc 28 3d |9........2..<.(=| +000001e0 23 6d e9 cf d6 28 b7 99 67 8b 71 10 32 c8 20 c5 |#m...(..g.q.2. .| +000001f0 7e 49 9a ba df 16 47 ed f8 de 3b f3 91 2d 33 62 |~I....G...;..-3b| +00000200 0f 51 9c 34 27 4b fb 9d 19 aa 8d f4 9e ab ce 84 |.Q.4'K..........| +00000210 e8 68 bb 68 55 01 69 cd f9 5f aa 73 e2 10 a9 a9 |.h.hU.i.._.s....| +00000220 82 0d 7e 33 3e 07 92 75 64 f9 4d af 8f 50 22 a9 |..~3>..ud.M..P".| +00000230 c5 ba 47 67 a5 36 90 8a c2 d5 72 99 6f e6 df 54 |..Gg.6....r.o..T| +00000240 59 4f dd af 89 e1 d1 aa 0b cb cc 53 2d 3c 07 25 |YO.........S-<.%| +00000250 46 7f 9e dd 16 c9 68 70 7c b5 7e 1a 02 ca ec 6c |F.....hp|.~....l| +00000260 66 a2 89 4e a9 24 f9 6a 26 32 81 be 2e a0 5e 04 |f..N.$.j&2....^.| +00000270 64 c6 bc a1 5e 06 ef a1 da 5a 69 6d a0 54 54 cb |d...^....Zim.TT.| +00000280 cd 0b cd 14 f0 84 16 b1 65 54 8b a8 |........eT..| +>>> Flow 13 (server to client) +00000000 08 d1 60 08 6b 7b 0a ba 7f ba 0a 20 41 a5 f7 17 |..`.k{..... A...| +00000010 a5 5d 25 cd 5a dd da 80 95 63 89 4e |.]%.Z....c.N| +>>> Flow 14 (client to server) +00000000 0b e9 d0 4f d5 94 cf 71 cb 3f 39 e4 b1 b4 35 33 |...O...q.?9...53| +00000010 46 bc 2d 23 bc e1 f9 26 e5 81 bc 3e 3c 42 9b ff |F.-#...&...>>> Flow 15 (server to client) +00000000 bf 5f 18 99 c2 62 69 0a cf 86 9a 7a 9b e0 0b 03 |._...bi....z....| +00000010 3b 81 27 d3 ea eb 23 ab c6 a3 86 af 74 0b 92 a9 |;.'...#.....t...| +00000020 8f f4 94 5a ae 60 e4 0b 80 10 44 55 |...Z.`....DU| +>>> Flow 16 (client to server) +00000000 aa 07 b9 da 29 6f f0 99 1f bc 07 76 cf ae f5 a8 |....)o.....v....| +00000010 52 85 7d bf 68 07 e6 d6 61 94 e8 7a a6 21 fc c3 |R.}.h...a..z.!..| +00000020 d3 a1 bc 06 18 30 4b 1e 6b a1 7b 2a e3 4f f6 87 |.....0K.k.{*.O..| +00000030 aa 3e 75 36 99 f3 09 a1 5d 95 ae 6b b8 19 d7 4f |.>u6....]..k...O| +00000040 f5 04 9e 95 05 59 d8 ad 6f 9a b8 1e 9e a7 d9 94 |.....Y..o.......| +00000050 bc fb e1 37 37 53 58 74 |...77SXt| +>>> Flow 17 (server to client) +00000000 d6 02 85 58 5a 38 40 e5 64 01 ec 93 ac 67 8c ed |...XZ8@.d....g..| +00000010 9c 3b 88 74 7e 23 11 2e ea cd 28 ef c2 de 9a b6 |.;.t~#....(.....| +00000020 79 1a 5e 11 38 54 2c 8c e8 97 6b fc 09 dc 6c d6 |y.^.8T,...k...l.| +00000030 a2 88 bf 49 51 f3 94 29 7d aa d7 67 82 db 92 8f |...IQ..)}..g....| +00000040 98 3a 86 a0 d4 d6 3a a6 34 2d 93 1a d3 e4 f4 c7 |.:....:.4-......| +00000050 6d 8d 9e da bf 24 97 54 8e 22 84 c1 67 4a ad 37 |m....$.T."..gJ.7| +00000060 00 dd 3c 16 2a 07 a6 57 35 d2 99 01 42 36 f3 02 |..<.*..W5...B6..| +00000070 4c 5d 83 14 2b cd 03 92 6e 63 e8 19 |L]..+...nc..| +>>> Flow 18 (client to server) +00000000 8a f2 f5 38 00 d5 a5 b6 cf d6 0d 48 47 55 78 c9 |...8.......HGUx.| +00000010 ee b0 8b f2 7d 0b 44 61 62 7d cd b5 51 f6 af b5 |....}.Dab}..Q...| +00000020 da 3c e6 d8 3f a7 d5 c4 12 43 08 b4 4f c1 ba fb |.<..?....C..O...| +00000030 5a 57 7a d6 ba 29 b2 1c 31 ca b4 b3 bc c7 23 de |ZWz..)..1.....#.| +00000040 d5 9d e6 2e b9 25 20 17 6e e6 13 fd a3 86 14 91 |.....% .n.......| +00000050 e1 0b 44 dc 1b 1d ca b7 f1 b3 fd 35 90 3b c3 52 |..D........5.;.R| diff --git a/ssh/testdata/Server-MAC-hmac-sha2-512-etm@openssh.com b/ssh/testdata/Server-MAC-hmac-sha2-512-etm@openssh.com new file mode 100644 index 0000000000..54d9ddac83 --- /dev/null +++ b/ssh/testdata/Server-MAC-hmac-sha2-512-etm@openssh.com @@ -0,0 +1,347 @@ +>>> Flow 1 (server to client) +00000000 53 53 48 2d 32 2e 30 2d 47 6f 0d 0a |SSH-2.0-Go..| +>>> Flow 2 (client to server) +00000000 53 53 48 2d 32 2e 30 2d 4f 70 65 6e 53 53 48 5f |SSH-2.0-OpenSSH_| +00000010 39 2e 39 0d 0a |9.9..| +>>> Flow 3 (server to client) +00000000 00 00 02 3c 04 14 7f 9c 2b a4 e8 8f 82 7d 61 60 |...<....+....}a`| +00000010 45 50 76 05 85 3e 00 00 00 be 63 75 72 76 65 32 |EPv..>....curve2| +00000020 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000030 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000040 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +00000050 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +00000060 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +00000070 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +00000080 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +00000090 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 2c |-group14-sha256,| +000000a0 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d 67 |diffie-hellman-g| +000000b0 72 6f 75 70 31 34 2d 73 68 61 31 2c 6b 65 78 2d |roup14-sha1,kex-| +000000c0 73 74 72 69 63 74 2d 73 2d 76 30 30 40 6f 70 65 |strict-s-v00@ope| +000000d0 6e 73 73 68 2e 63 6f 6d 00 00 00 21 72 73 61 2d |nssh.com...!rsa-| +000000e0 73 68 61 32 2d 32 35 36 2c 72 73 61 2d 73 68 61 |sha2-256,rsa-sha| +000000f0 32 2d 35 31 32 2c 73 73 68 2d 72 73 61 00 00 00 |2-512,ssh-rsa...| +00000100 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000110 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000120 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +00000130 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +00000140 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +00000150 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +00000160 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +00000170 6c 61 65 73 31 32 38 2d 67 63 6d 40 6f 70 65 6e |laes128-gcm@open| +00000180 73 73 68 2e 63 6f 6d 2c 61 65 73 32 35 36 2d 67 |ssh.com,aes256-g| +00000190 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 63 |cm@openssh.com,c| +000001a0 68 61 63 68 61 32 30 2d 70 6f 6c 79 31 33 30 35 |hacha20-poly1305| +000001b0 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 |@openssh.com,aes| +000001c0 31 32 38 2d 63 74 72 2c 61 65 73 31 39 32 2d 63 |128-ctr,aes192-c| +000001d0 74 72 2c 61 65 73 32 35 36 2d 63 74 72 00 00 00 |tr,aes256-ctr...| +000001e0 1d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d 65 |.hmac-sha2-512-e| +000001f0 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 |tm@openssh.com..| +00000200 00 1d 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2d |..hmac-sha2-512-| +00000210 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 |etm@openssh.com.| +00000220 00 00 04 6e 6f 6e 65 00 00 00 04 6e 6f 6e 65 00 |...none....none.| +00000230 00 00 00 00 00 00 00 00 00 00 00 00 d7 3b 80 93 |.............;..| +>>> Flow 4 (client to server) +00000000 00 00 06 3c 08 14 31 a4 c9 a7 34 6f d5 a1 b8 5a |...<..1...4o...Z| +00000010 4c 78 77 d7 08 21 00 00 01 7a 73 6e 74 72 75 70 |Lxw..!...zsntrup| +00000020 37 36 31 78 32 35 35 31 39 2d 73 68 61 35 31 32 |761x25519-sha512| +00000030 2c 73 6e 74 72 75 70 37 36 31 78 32 35 35 31 39 |,sntrup761x25519| +00000040 2d 73 68 61 35 31 32 40 6f 70 65 6e 73 73 68 2e |-sha512@openssh.| +00000050 63 6f 6d 2c 6d 6c 6b 65 6d 37 36 38 78 32 35 35 |com,mlkem768x255| +00000060 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 65 32 |19-sha256,curve2| +00000070 35 35 31 39 2d 73 68 61 32 35 36 2c 63 75 72 76 |5519-sha256,curv| +00000080 65 32 35 35 31 39 2d 73 68 61 32 35 36 40 6c 69 |e25519-sha256@li| +00000090 62 73 73 68 2e 6f 72 67 2c 65 63 64 68 2d 73 68 |bssh.org,ecdh-sh| +000000a0 61 32 2d 6e 69 73 74 70 32 35 36 2c 65 63 64 68 |a2-nistp256,ecdh| +000000b0 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34 2c 65 |-sha2-nistp384,e| +000000c0 63 64 68 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 |cdh-sha2-nistp52| +000000d0 31 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e |1,diffie-hellman| +000000e0 2d 67 72 6f 75 70 2d 65 78 63 68 61 6e 67 65 2d |-group-exchange-| +000000f0 73 68 61 32 35 36 2c 64 69 66 66 69 65 2d 68 65 |sha256,diffie-he| +00000100 6c 6c 6d 61 6e 2d 67 72 6f 75 70 31 36 2d 73 68 |llman-group16-sh| +00000110 61 35 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c |a512,diffie-hell| +00000120 6d 61 6e 2d 67 72 6f 75 70 31 38 2d 73 68 61 35 |man-group18-sha5| +00000130 31 32 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 |12,diffie-hellma| +00000140 6e 2d 67 72 6f 75 70 31 34 2d 73 68 61 32 35 36 |n-group14-sha256| +00000150 2c 64 69 66 66 69 65 2d 68 65 6c 6c 6d 61 6e 2d |,diffie-hellman-| +00000160 67 72 6f 75 70 31 34 2d 73 68 61 31 2c 65 78 74 |group14-sha1,ext| +00000170 2d 69 6e 66 6f 2d 63 2c 6b 65 78 2d 73 74 72 69 |-info-c,kex-stri| +00000180 63 74 2d 63 2d 76 30 30 40 6f 70 65 6e 73 73 68 |ct-c-v00@openssh| +00000190 2e 63 6f 6d 00 00 01 cf 72 73 61 2d 73 68 61 32 |.com....rsa-sha2| +000001a0 2d 35 31 32 2d 63 65 72 74 2d 76 30 31 40 6f 70 |-512-cert-v01@op| +000001b0 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d 73 68 |enssh.com,rsa-sh| +000001c0 61 32 2d 32 35 36 2d 63 65 72 74 2d 76 30 31 40 |a2-256-cert-v01@| +000001d0 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 72 73 61 2d |openssh.com,rsa-| +000001e0 73 68 61 32 2d 35 31 32 2c 72 73 61 2d 73 68 61 |sha2-512,rsa-sha| +000001f0 32 2d 32 35 36 2c 73 73 68 2d 65 64 32 35 35 31 |2-256,ssh-ed2551| +00000200 39 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 |9-cert-v01@opens| +00000210 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 68 61 |sh.com,ecdsa-sha| +00000220 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 74 2d |2-nistp256-cert-| +00000230 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c |v01@openssh.com,| +00000240 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 |ecdsa-sha2-nistp| +00000250 33 38 34 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 |384-cert-v01@ope| +00000260 6e 73 73 68 2e 63 6f 6d 2c 65 63 64 73 61 2d 73 |nssh.com,ecdsa-s| +00000270 68 61 32 2d 6e 69 73 74 70 35 32 31 2d 63 65 72 |ha2-nistp521-cer| +00000280 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +00000290 6d 2c 73 6b 2d 73 73 68 2d 65 64 32 35 35 31 39 |m,sk-ssh-ed25519| +000002a0 2d 63 65 72 74 2d 76 30 31 40 6f 70 65 6e 73 73 |-cert-v01@openss| +000002b0 68 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 |h.com,sk-ecdsa-s| +000002c0 68 61 32 2d 6e 69 73 74 70 32 35 36 2d 63 65 72 |ha2-nistp256-cer| +000002d0 74 2d 76 30 31 40 6f 70 65 6e 73 73 68 2e 63 6f |t-v01@openssh.co| +000002e0 6d 2c 73 73 68 2d 65 64 32 35 35 31 39 2c 65 63 |m,ssh-ed25519,ec| +000002f0 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 |dsa-sha2-nistp25| +00000300 36 2c 65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 |6,ecdsa-sha2-nis| +00000310 74 70 33 38 34 2c 65 63 64 73 61 2d 73 68 61 32 |tp384,ecdsa-sha2| +00000320 2d 6e 69 73 74 70 35 32 31 2c 73 6b 2d 73 73 68 |-nistp521,sk-ssh| +00000330 2d 65 64 32 35 35 31 39 40 6f 70 65 6e 73 73 68 |-ed25519@openssh| +00000340 2e 63 6f 6d 2c 73 6b 2d 65 63 64 73 61 2d 73 68 |.com,sk-ecdsa-sh| +00000350 61 32 2d 6e 69 73 74 70 32 35 36 40 6f 70 65 6e |a2-nistp256@open| +00000360 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +00000370 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +00000380 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000390 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +000003a0 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +000003b0 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +000003c0 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +000003d0 73 73 68 2e 63 6f 6d 00 00 00 6c 63 68 61 63 68 |ssh.com...lchach| +000003e0 61 32 30 2d 70 6f 6c 79 31 33 30 35 40 6f 70 65 |a20-poly1305@ope| +000003f0 6e 73 73 68 2e 63 6f 6d 2c 61 65 73 31 32 38 2d |nssh.com,aes128-| +00000400 63 74 72 2c 61 65 73 31 39 32 2d 63 74 72 2c 61 |ctr,aes192-ctr,a| +00000410 65 73 32 35 36 2d 63 74 72 2c 61 65 73 31 32 38 |es256-ctr,aes128| +00000420 2d 67 63 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-gcm@openssh.com| +00000430 2c 61 65 73 32 35 36 2d 67 63 6d 40 6f 70 65 6e |,aes256-gcm@open| +00000440 73 73 68 2e 63 6f 6d 00 00 00 d5 75 6d 61 63 2d |ssh.com....umac-| +00000450 36 34 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |64-etm@openssh.c| +00000460 6f 6d 2c 75 6d 61 63 2d 31 32 38 2d 65 74 6d 40 |om,umac-128-etm@| +00000470 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 |openssh.com,hmac| +00000480 2d 73 68 61 32 2d 32 35 36 2d 65 74 6d 40 6f 70 |-sha2-256-etm@op| +00000490 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 |enssh.com,hmac-s| +000004a0 68 61 32 2d 35 31 32 2d 65 74 6d 40 6f 70 65 6e |ha2-512-etm@open| +000004b0 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 |ssh.com,hmac-sha| +000004c0 31 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f |1-etm@openssh.co| +000004d0 6d 2c 75 6d 61 63 2d 36 34 40 6f 70 65 6e 73 73 |m,umac-64@openss| +000004e0 68 2e 63 6f 6d 2c 75 6d 61 63 2d 31 32 38 40 6f |h.com,umac-128@o| +000004f0 70 65 6e 73 73 68 2e 63 6f 6d 2c 68 6d 61 63 2d |penssh.com,hmac-| +00000500 73 68 61 32 2d 32 35 36 2c 68 6d 61 63 2d 73 68 |sha2-256,hmac-sh| +00000510 61 32 2d 35 31 32 2c 68 6d 61 63 2d 73 68 61 31 |a2-512,hmac-sha1| +00000520 00 00 00 d5 75 6d 61 63 2d 36 34 2d 65 74 6d 40 |....umac-64-etm@| +00000530 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 |openssh.com,umac| +00000540 2d 31 32 38 2d 65 74 6d 40 6f 70 65 6e 73 73 68 |-128-etm@openssh| +00000550 2e 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 |.com,hmac-sha2-2| +00000560 35 36 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 |56-etm@openssh.c| +00000570 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 |om,hmac-sha2-512| +00000580 2d 65 74 6d 40 6f 70 65 6e 73 73 68 2e 63 6f 6d |-etm@openssh.com| +00000590 2c 68 6d 61 63 2d 73 68 61 31 2d 65 74 6d 40 6f |,hmac-sha1-etm@o| +000005a0 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 6d 61 63 2d |penssh.com,umac-| +000005b0 36 34 40 6f 70 65 6e 73 73 68 2e 63 6f 6d 2c 75 |64@openssh.com,u| +000005c0 6d 61 63 2d 31 32 38 40 6f 70 65 6e 73 73 68 2e |mac-128@openssh.| +000005d0 63 6f 6d 2c 68 6d 61 63 2d 73 68 61 32 2d 32 35 |com,hmac-sha2-25| +000005e0 36 2c 68 6d 61 63 2d 73 68 61 32 2d 35 31 32 2c |6,hmac-sha2-512,| +000005f0 68 6d 61 63 2d 73 68 61 31 00 00 00 15 6e 6f 6e |hmac-sha1....non| +00000600 65 2c 7a 6c 69 62 40 6f 70 65 6e 73 73 68 2e 63 |e,zlib@openssh.c| +00000610 6f 6d 00 00 00 15 6e 6f 6e 65 2c 7a 6c 69 62 40 |om....none,zlib@| +00000620 6f 70 65 6e 73 73 68 2e 63 6f 6d 00 00 00 00 00 |openssh.com.....| +00000630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000640 00 00 00 2c 06 1e 00 00 00 20 cd 90 6a 64 8c 1f |...,..... ..jd..| +00000650 43 77 95 01 4a 87 01 10 ae c4 fc d3 88 4e 63 b5 |Cw..J........Nc.| +00000660 a1 c1 0a 21 2e c6 8e 7b 78 6b 00 00 00 00 00 00 |...!...{xk......| +>>> Flow 5 (server to client) +00000000 00 00 02 6c 13 1f 00 00 01 17 00 00 00 07 73 73 |...l..........ss| +00000010 68 2d 72 73 61 00 00 00 03 01 00 01 00 00 01 01 |h-rsa...........| +00000020 00 9e ea 33 28 cb 5c 42 42 08 99 91 92 7b 82 2e |...3(.\BB....{..| +00000030 8d 2e 3e 2e 46 ac f6 39 a5 06 2b f3 89 61 94 df |..>.F..9..+..a..| +00000040 06 a2 be 4a 54 bd 8b 29 80 96 e1 ee f4 af 9c 73 |...JT..).......s| +00000050 8f b4 ab 1c 74 82 7e dd 45 32 56 20 d4 a0 ce f7 |....t.~.E2V ....| +00000060 1a e9 ac 98 7b df 79 10 a8 03 d6 11 39 92 b8 7d |....{.y.....9..}| +00000070 04 7d 1b 46 b5 c1 fa 11 aa ca c9 5c 64 e8 0b 34 |.}.F.......\d..4| +00000080 ef af f2 36 28 8c 29 50 6d 1b 44 4f 6b 52 fb 16 |...6(.)Pm.DOkR..| +00000090 f8 93 7d c6 0a e2 f9 c2 09 5a db bf 74 66 03 90 |..}......Z..tf..| +000000a0 82 ce e1 b9 05 23 1b 44 bc 73 55 be 11 8b 7a 7c |.....#.D.sU...z|| +000000b0 8e 1c 58 4f c3 78 40 67 bf db 2a af 24 bc ac e6 |..XO.x@g..*.$...| +000000c0 f4 3d b3 3a 59 47 7b 5c 16 9d c3 24 85 59 84 14 |.=.:YG{\...$.Y..| +000000d0 5f 47 a2 e7 a1 8d b7 5d 99 e2 00 03 10 69 45 41 |_G.....].....iEA| +000000e0 5f ce 9d 5d 0f be 74 dc 00 c1 94 97 4a df 4e 83 |_..]..t.....J.N.| +000000f0 e0 27 88 e0 a2 05 8a a1 35 56 b9 9f 70 c8 0f f1 |.'......5V..p...| +00000100 fb 62 d1 2d 1b e0 9b 66 bd eb d8 a0 f7 7e ff 00 |.b.-...f.....~..| +00000110 7d 22 d1 6a be 17 3a 9f 2b b1 17 43 df 58 7f 92 |}".j..:.+..C.X..| +00000120 bf 00 00 00 20 13 87 32 34 3e 68 e6 9b 9a cb 23 |.... ..24>h....#| +00000130 22 06 11 e8 24 71 e5 d7 96 79 83 48 59 1a 95 f2 |"...$q...y.HY...| +00000140 b0 86 1c 76 54 00 00 01 14 00 00 00 0c 72 73 61 |...vT........rsa| +00000150 2d 73 68 61 32 2d 35 31 32 00 00 01 00 92 b4 90 |-sha2-512.......| +00000160 76 2e 99 3e 6c e0 ec bc 90 03 b9 b4 ea ce 52 56 |v..>l.........RV| +00000170 e7 c3 e4 1d 17 dd 23 c3 aa f9 6a 67 b6 b1 29 15 |......#...jg..).| +00000180 78 d3 8a 83 2d e6 21 fe ec 45 49 f5 cc d4 8c cf |x...-.!..EI.....| +00000190 b6 a9 3d 7d 18 29 53 e5 c1 e9 0d c0 48 b6 b4 1e |..=}.)S.....H...| +000001a0 8e 31 49 71 dc d3 7d 25 85 1f 46 df 4f 74 af a7 |.1Iq..}%..F.Ot..| +000001b0 46 82 83 24 1d 81 13 05 51 84 8c 59 94 93 7c 50 |F..$....Q..Y..|P| +000001c0 84 3d f1 21 39 36 32 d5 fb 13 93 fb 68 e1 91 85 |.=.!962.....h...| +000001d0 0a 74 de 55 9a 68 72 63 2b f3 00 f4 6a d9 8b 7a |.t.U.hrc+...j..z| +000001e0 71 04 2e 07 b9 04 91 f2 31 7e e1 e3 cf fb 9d 87 |q.......1~......| +000001f0 12 55 63 eb d5 26 f7 02 30 7a 71 13 ff 04 e9 2b |.Uc..&..0zq....+| +00000200 38 e1 2a 0c de 9d 9c fc 88 1a 65 06 d0 f2 b8 f5 |8.*.......e.....| +00000210 87 3c 6c 92 a6 97 db 2a 0e dd e2 f3 f9 d4 ba b4 |.......| +000002f0 af 3f 83 10 5b db 43 27 0c 0d 0a 5e 15 f2 21 41 |.?..[.C'...^..!A| +00000300 a5 81 82 3a 88 7d 47 9a 1b b9 be 50 5a c3 57 e8 |...:.}G....PZ.W.| +00000310 dd d9 41 2a 87 5b 6b 2d 36 67 45 d9 3c 8f ba 07 |..A*.[k-6gE.<...| +00000320 99 8f bc 5e 63 1a 71 c4 77 e2 db 87 fa 6b 30 2c |...^c.q.w....k0,| +00000330 86 98 a9 5d df fc 6f 93 e9 b4 d4 ab 85 de 47 19 |...]..o.......G.| +00000340 ed 7f 8b 3c ef ed 65 2f fe 7d fc fa d9 a6 c8 6f |...<..e/.}.....o| +00000350 2a d3 02 a3 06 0b bd b4 5f 48 65 f2 45 f1 51 f0 |*......._He.E.Q.| +00000360 7a 34 e5 53 f6 cd b0 13 45 b0 0b bb 92 34 8f da |z4.S....E....4..| +00000370 bf 6c f3 4a 3f 9c 10 06 28 d3 a6 ab 68 7c 8f 46 |.l.J?...(...h|.F| +00000380 1d b8 6d e2 |..m.| +>>> Flow 6 (client to server) +00000000 00 00 00 0c 0a 15 00 00 00 00 00 00 00 00 00 00 |................| +00000010 a0 19 63 f7 40 b0 95 0f 71 71 4b 8a 26 ac 70 da |..c.@...qqK.&.p.| +00000020 f7 6f ec 54 7f fb 39 fd f0 70 b2 6e 3a 65 9e 8c |.o.T..9..p.n:e..| +00000030 04 b8 92 90 0f 7f 30 16 a0 c4 74 2a |......0...t*| +>>> Flow 7 (server to client) +00000000 fd a2 3a 15 d1 c6 24 ad 32 87 f7 d4 30 ca 0f 53 |..:...$.2...0..S| +00000010 5f a2 31 d8 55 18 6e 3e 5e 98 67 d8 f9 88 0a b6 |_.1.U.n>^.g.....| +00000020 c8 af e9 ac d3 6c ec c0 79 fa 91 f5 |.....l..y...| +>>> Flow 8 (client to server) +00000000 40 64 0c b2 cb cf 0e 75 5b 42 f7 9f c5 c6 f2 6c |@d.....u[B.....l| +00000010 8a 55 6c ca d7 d3 fa e1 85 e7 62 e9 7f 7d 71 63 |.Ul.......b..}qc| +00000020 37 8f 97 67 30 bf 63 4f e0 18 95 42 71 c6 2b 5c |7..g0.cO...Bq.+\| +00000030 01 e1 99 ff 6d 54 55 7a be ef c1 16 c9 de b3 89 |....mTUz........| +00000040 44 ec d4 e5 |D...| +>>> Flow 9 (server to client) +00000000 ac 75 be 5d 0f 91 c8 47 f5 7f ed 3b 7a 39 b2 36 |.u.]...G...;z9.6| +00000010 ac 8b 20 22 d7 7a d4 7e 93 0e 0d 76 3a 7e 9c dc |.. ".z.~...v:~..| +00000020 89 24 9e 24 16 98 d4 3a c8 d9 1e 78 |.$.$...:...x| +>>> Flow 10 (client to server) +00000000 c9 01 19 c8 2a fe 81 b7 5f 02 81 d8 32 d4 41 38 |....*..._...2.A8| +00000010 f4 ae 8e 9d 83 8e f8 72 60 d0 99 e9 72 bc d7 90 |.......r`...r...| +00000020 ff 30 7b bf 0b f5 ca 12 fa 32 22 c6 10 4c db 0c |.0{......2"..L..| +00000030 f2 a7 0e cc c2 37 48 f7 91 b6 94 3e f4 7d 65 d2 |.....7H....>.}e.| +00000040 1c fe 2c d8 88 d7 ee be dd ff d2 59 d5 d1 d2 c3 |..,........Y....| +00000050 10 23 f7 16 86 eb bd 3a cf cc 77 d0 16 53 a2 10 |.#.....:..w..S..| +00000060 ab 00 56 43 f5 b6 68 04 c5 62 bd 35 f0 74 b7 2e |..VC..h..b.5.t..| +00000070 cb 24 2a 42 89 2a 85 33 b8 16 bb bc a8 66 59 01 |.$*B.*.3.....fY.| +00000080 ae 84 05 d1 1d 82 37 20 a5 20 ad 1d 54 7d 51 99 |......7 . ..T}Q.| +00000090 d2 34 ab 3a 17 da 2e ca 8d 6f 80 20 45 9a 61 67 |.4.:.....o. E.ag| +000000a0 c3 9f c0 52 7b a4 af 66 97 a5 42 34 f2 d7 08 f9 |...R{..f..B4....| +000000b0 b4 a9 df 6c 17 62 b5 bf b7 71 73 d0 f4 46 64 f2 |...l.b...qs..Fd.| +000000c0 8d fd 62 f9 6a 5a 7a e6 26 b6 20 09 38 7c ac 45 |..b.jZz.&. .8|.E| +000000d0 23 9e 1f 02 e2 94 55 b5 fc 69 41 db a7 d8 d4 39 |#.....U..iA....9| +000000e0 05 c6 39 79 d8 8f 3d 23 a4 e0 9d ec a8 3d 7b 9b |..9y..=#.....={.| +000000f0 b2 3e d5 ee 0d ce 66 14 63 bd 96 b8 f8 8b cd df |.>....f.c.......| +00000100 ee e1 71 b3 70 cb fc 37 85 e8 ad 00 4f 03 a5 3a |..q.p..7....O..:| +00000110 64 1d 2b db fe ed c2 20 94 ab cf 2f 9a 40 a9 d1 |d.+.... .../.@..| +00000120 90 f1 c7 fa c8 93 35 26 08 c5 54 40 1c c2 47 2b |......5&..T@..G+| +00000130 20 06 b0 ca 06 4b bd 39 73 5b 16 9d be 6b 0e 7b | ....K.9s[...k.{| +00000140 09 72 2d dd 5b 70 43 03 03 c8 30 1b 9d ea a2 0f |.r-.[pC...0.....| +00000150 83 9b 29 bb da 56 36 e2 4c 92 3e 29 d7 37 78 3f |..)..V6.L.>).7x?| +00000160 39 c3 7b a0 36 40 4f 68 d3 e9 da fa 3b 49 35 70 |9.{.6@Oh....;I5p| +00000170 d5 94 f6 24 |...$| +>>> Flow 11 (server to client) +00000000 a4 0e 4e 0b aa 02 40 13 98 d9 8a 70 7c 6c e3 9d |..N...@....p|l..| +00000010 b7 00 02 83 23 38 0b f8 80 e0 5d 91 ff 56 b6 ad |....#8....]..V..| +00000020 c7 4f 8d 9d 8e 99 97 99 77 8f 13 ab c1 7b 6d 9c |.O......w....{m.| +00000030 6a cb ff a6 dc e8 b2 26 e3 8e f1 62 45 5a 80 09 |j......&...bEZ..| +00000040 90 03 d4 5a 1e a8 9d f2 93 d4 87 9e dc 0a f2 f0 |...Z............| +00000050 e5 ad 9d d4 84 9c 9b ed bb 2e 1c a1 5e 7e dc 8b |............^~..| +00000060 da 1a 67 4b cf 61 b6 f4 a3 3f b8 6e 76 b1 bc 40 |..gK.a...?.nv..@| +00000070 04 36 69 7f f8 f0 4f c0 0b 23 66 70 36 27 4d 5d |.6i...O..#fp6'M]| +00000080 b8 81 69 5d c2 ec 5e 4b 92 6e d0 44 f7 d9 c2 ac |..i]..^K.n.D....| +00000090 9d 39 23 31 f6 af 9d 52 a5 f9 f1 93 e8 1e c6 e2 |.9#1...R........| +000000a0 b0 22 64 11 f7 35 e7 0b 24 fc bf 3f 8e 0e d7 38 |."d..5..$..?...8| +000000b0 2b f6 ca c5 53 8c cd d6 bb aa 20 f9 20 f0 35 63 |+...S..... . .5c| +000000c0 5b 77 ff f3 5c 10 34 bd ee 5d 3f 75 cf 38 bd df |[w..\.4..]?u.8..| +000000d0 21 3c 40 21 70 22 6d 6a 17 a0 69 cb a0 6c 5f ce |!<@!p"mj..i..l_.| +000000e0 b3 2a 6d a1 63 92 7f 8d 79 e8 f1 88 a0 4c ac 30 |.*m.c...y....L.0| +000000f0 d4 c8 bc 54 cb 39 81 28 51 b9 cc 16 f6 4f 02 e9 |...T.9.(Q....O..| +00000100 c7 37 19 7c f8 a4 4c ed 40 63 42 5c c4 b2 25 ba |.7.|..L.@cB\..%.| +00000110 c0 64 bf 2a 35 6a ed 35 dc fe 36 91 c3 99 85 fe |.d.*5j.5..6.....| +00000120 a8 4d 67 16 1b 13 4a 05 e3 e7 2b 55 25 72 94 ed |.Mg...J...+U%r..| +00000130 b7 48 4e 05 6a 6a 47 51 de fd fd 74 fe dd c8 49 |.HN.jjGQ...t...I| +00000140 18 10 54 69 e9 a0 f9 89 27 1a cb c2 |..Ti....'...| +>>> Flow 12 (client to server) +00000000 b1 32 2d d6 1e f3 be 4f aa fe 2d b2 29 d3 90 88 |.2-....O..-.)...| +00000010 4b 7e 33 44 c2 5f 80 96 11 d9 e1 06 97 6c f0 6a |K~3D._.......l.j| +00000020 74 68 43 83 3b 96 87 69 9a ad 96 08 14 38 a4 09 |thC.;..i.....8..| +00000030 ca 1e 22 05 c7 e1 ac 20 ac 73 8c 0c 54 1c e5 1f |..".... .s..T...| +00000040 94 73 ae 71 49 cd 62 ed f7 39 6f 91 d5 83 25 90 |.s.qI.b..9o...%.| +00000050 85 a8 ad ae 51 3d 81 ff 37 04 d6 c4 ea ae d4 b0 |....Q=..7.......| +00000060 26 34 c9 b4 45 c1 ea 9f ae 70 57 28 58 25 db 7c |&4..E....pW(X%.|| +00000070 57 40 8f 71 6e 7c ac 99 9a ae cf 3a 64 f6 c9 f4 |W@.qn|.....:d...| +00000080 ca a2 75 3a 29 94 33 23 59 ec 95 83 b1 f0 d5 f2 |..u:).3#Y.......| +00000090 4d fa 77 fe 3e 18 cf 9a bd 44 51 a4 5f 0b d1 dd |M.w.>....DQ._...| +000000a0 f5 3d 06 be 13 71 47 e4 24 5d e6 bb 81 1c 93 fb |.=...qG.$]......| +000000b0 ab 98 a6 f3 77 9d f9 72 46 93 fa 45 ac c3 00 0e |....w..rF..E....| +000000c0 76 b4 0a 23 ec 23 c2 08 2f 7e 26 18 6f da 15 d1 |v..#.#../~&.o...| +000000d0 48 3b 78 03 4f d3 ed d7 9f 30 6b 69 55 24 5a 82 |H;x.O....0kiU$Z.| +000000e0 92 df ba de c1 ee 35 d7 7a 15 c4 e7 80 3e 22 d4 |......5.z....>".| +000000f0 d9 cf 59 a1 e8 05 81 81 05 99 44 8d 13 28 3c 22 |..Y.......D..(<"| +00000100 64 82 c4 23 9c a3 27 a1 8a 7e 37 ca 7f a6 b5 fc |d..#..'..~7.....| +00000110 9e 78 e9 9c c4 23 53 f4 85 24 e1 92 65 2d 02 1a |.x...#S..$..e-..| +00000120 98 c0 31 dd b0 31 8d 80 91 dd e9 ab f8 a3 76 84 |..1..1........v.| +00000130 be e9 79 d6 0f c9 9f df 2e 23 00 2a 6e ed 96 43 |..y......#.*n..C| +00000140 bd 4f 5d e0 9d 07 4d 8d f1 71 1c 2e 33 fa 1a e9 |.O]...M..q..3...| +00000150 64 a3 62 05 12 37 a5 e5 41 81 f4 05 7e 3c df 4c |d.b..7..A...~<.L| +00000160 32 c7 7c d9 f6 7e 01 57 59 9e 00 f8 da c1 16 0d |2.|..~.WY.......| +00000170 0c e0 37 e7 f4 26 22 10 50 12 a9 e3 fc 79 c5 3e |..7..&".P....y.>| +00000180 66 5a ab d0 f6 a7 ee c6 21 ba 3c ec aa f7 84 42 |fZ......!.<....B| +00000190 04 5c 50 4c d3 7e 04 0e b9 0b 87 17 c3 50 16 a9 |.\PL.~.......P..| +000001a0 6d e6 c7 cc 68 99 8c 64 dc a1 57 95 31 fc 6e da |m...h..d..W.1.n.| +000001b0 d1 45 15 82 6e 66 ed 7b 8a db e6 11 8f 2d 4f 7f |.E..nf.{.....-O.| +000001c0 ab 3a 66 be 34 ae cb 74 59 e2 c0 cf 9b 31 9f 7e |.:f.4..tY....1.~| +000001d0 50 36 0e 32 29 7c 60 b4 23 28 7c 36 ea dc fc fd |P6.2)|`.#(|6....| +000001e0 5f 2a cb 9f 86 d9 45 16 b0 77 6f 1d 8e 48 81 18 |_*....E..wo..H..| +000001f0 f7 64 6b b1 84 89 a3 3f ea 16 49 dc 33 64 3c ed |.dk....?..I.3d<.| +00000200 09 66 58 1a 35 9b 5f 71 b4 f6 3f 38 e8 e9 ae 6c |.fX.5._q..?8...l| +00000210 2e 39 b6 5c 7e 02 38 2f 80 6b bc 85 4c c1 33 7f |.9.\~.8/.k..L.3.| +00000220 8c 15 d5 d4 6a e9 3e 78 61 66 93 b5 e2 f4 a8 5b |....j.>xaf.....[| +00000230 0f d7 8c f9 12 f1 f8 83 ac de f5 c1 b8 bf 2d ba |..............-.| +00000240 f8 51 d6 ee bb 31 2f e4 61 4f b5 4e 17 4c 5c 4f |.Q...1/.aO.N.L\O| +00000250 f2 15 4d de cc 55 7d 84 62 0c bf c2 e4 3f c5 e2 |..M..U}.b....?..| +00000260 f2 4a 08 c1 61 5d 4d b3 1e d0 9e a3 20 37 41 25 |.J..a]M..... 7A%| +00000270 7e 56 39 7d b2 57 a2 ed a8 32 00 bb 9e b4 8c ad |~V9}.W...2......| +00000280 6b cd 27 08 14 bf 1c df 96 ff b9 f7 |k.'.........| +>>> Flow 13 (server to client) +00000000 5b b9 6f 2a 65 3b 61 a2 87 c2 78 40 34 a5 20 e6 |[.o*e;a...x@4. .| +00000010 5c ee 2b b1 fc 5a 9a cb 87 44 b4 98 |\.+..Z...D..| +>>> Flow 14 (client to server) +00000000 6e ae d2 f2 5a a0 7e 13 ff ca 7a f2 2a 0f 78 a3 |n...Z.~...z.*.x.| +00000010 09 61 7a 55 05 c8 1f 1f 42 7b 75 fb 7f 70 c8 45 |.azU....B{u..p.E| +00000020 20 8c e0 0b c8 cd 8e 9d f8 05 77 f6 60 a2 f5 2e | .........w.`...| +00000030 6d f9 3a b2 |m.:.| +>>> Flow 15 (server to client) +00000000 07 ff 37 34 9c 06 b2 63 1f de 5c 29 07 ee 70 ec |..74...c..\)..p.| +00000010 0d 59 fa 57 a0 4e 4e 7e c3 65 52 69 5c b5 75 ff |.Y.W.NN~.eRi\.u.| +00000020 35 76 3f 3e ff 5a c1 82 f9 b4 a5 29 |5v?>.Z.....)| +>>> Flow 16 (client to server) +00000000 55 dc 28 42 22 3b ab 1e a6 76 a3 27 c2 56 96 c6 |U.(B";...v.'.V..| +00000010 f8 98 36 ab a0 90 c8 e2 07 ab 32 3c 89 06 96 8c |..6.......2<....| +00000020 d2 02 1a 26 94 aa 96 f0 44 a4 62 e7 92 9b 48 32 |...&....D.b...H2| +00000030 2a e7 d6 75 e0 48 b8 68 21 c2 c0 e6 b2 6c f3 bc |*..u.H.h!....l..| +00000040 9a 16 f0 ea 00 81 00 e2 bc de 54 60 59 03 7a c9 |..........T`Y.z.| +00000050 24 f7 86 9d 69 fe fe 7b |$...i..{| +>>> Flow 17 (server to client) +00000000 19 ee 4d f5 42 38 a4 13 c3 03 06 a4 7e 4f 41 e9 |..M.B8......~OA.| +00000010 74 12 76 7b ca 4c e6 59 0d e8 c5 2e 23 ef c1 47 |t.v{.L.Y....#..G| +00000020 19 1a 6a 75 3f dc f2 52 ed 31 88 46 15 f8 4c 96 |..ju?..R.1.F..L.| +00000030 25 de 02 d3 18 dc ea cd bc 23 13 4d c9 c9 7e 28 |%........#.M..~(| +00000040 17 61 2e aa 6b 75 f9 8c 2d 98 ef bb 7e de 1e db |.a..ku..-...~...| +00000050 60 ba 76 c3 ca 8b 5f fe 66 e5 70 b5 c3 62 19 28 |`.v..._.f.p..b.(| +00000060 b0 ca 4b 83 cf 92 d3 81 0d e4 64 ec bf 62 85 d6 |..K.......d..b..| +00000070 95 fe 09 ed bc 5e ab fe cc 46 a0 3f |.....^...F.?| +>>> Flow 18 (client to server) +00000000 9d ca e3 b5 62 10 95 49 4f 01 77 0f 99 df 28 b9 |....b..IO.w...(.| +00000010 4a d7 5c b4 cd f9 bb 66 49 7d b7 03 12 72 83 48 |J.\....fI}...r.H| +00000020 d5 3e 28 18 31 ef b9 a9 b4 8e 46 58 6e 4a f5 f9 |.>(.1.....FXnJ..| +00000030 d8 12 f5 5b 4b 37 58 b5 2e 9b 5e d4 3f b2 7a 64 |...[K7X...^.?.zd| +00000040 7c 0e 84 3f 36 3b 3f fe 46 d5 03 56 30 6e 0c a2 ||..?6;?.F..V0n..| +00000050 fb d9 e6 e0 34 16 1e 20 89 14 40 18 fd 21 89 a5 |....4.. ..@..!..| diff --git a/ssh/testdata/doc.go b/ssh/testdata/doc.go index fcae47ca68..ae7bd8b89e 100644 --- a/ssh/testdata/doc.go +++ b/ssh/testdata/doc.go @@ -5,4 +5,4 @@ // This package contains test data shared between the various subpackages of // the golang.org/x/crypto/ssh package. Under no circumstance should // this data be used for production code. -package testdata // import "golang.org/x/crypto/ssh/testdata" +package testdata diff --git a/ssh/testdata/keys.go b/ssh/testdata/keys.go index bfae85fed8..6e48841b67 100644 --- a/ssh/testdata/keys.go +++ b/ssh/testdata/keys.go @@ -46,19 +46,31 @@ FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ== -----END EC PRIVATE KEY----- `), "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2 -a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8 -Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB -AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R -38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT -Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq -2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9 -6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR -fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu -X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa -NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM -z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 -KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= +MIIEpQIBAAKCAQEAnuozKMtcQkIImZGSe4IujS4+Lkas9jmlBivziWGU3waivkpU +vYspgJbh7vSvnHOPtKscdIJ+3UUyViDUoM73GumsmHvfeRCoA9YROZK4fQR9G0a1 +wfoRqsrJXGToCzTvr/I2KIwpUG0bRE9rUvsW+JN9xgri+cIJWtu/dGYDkILO4bkF +IxtEvHNVvhGLenyOHFhPw3hAZ7/bKq8kvKzm9D2zOllHe1wWncMkhVmEFF9Houeh +jbddmeIAAxBpRUFfzp1dD7503ADBlJdK306D4CeI4KIFiqE1VrmfcMgP8fti0S0b +4JtmvevYoPd+/wB9ItFqvhc6nyuxF0PfWH+SvwIDAQABAoIBAQCCcpNeSFjKVvRC +Q1nwIrPd1njaec+fK0CIqWl3e2++B+9trwySrvp5gOGjyp2hGsd7Mf7gsQI81oF0 +a+y+uEXlhK3WWdDey0pwI7ft/7+LeDTOQCQRQBpijaXvPzGviVu7nWLRtARx7a41 +S9A4xL5dfI0BFYyuIpaVS8+EV/1TEJIbceZ5q5RBlARA1rc+nBvjygNzYdRq9Rao +yyehvnXZ7pQrATnwofPolbZNseW2Q9sRMmtm1E60XJJ433P7nFbxXtsMAYgxWSQc +V/92iRPYeD7sN/b7qulLEgC6e8el2gLGIB9aQyG7B6KFqloqvx/ymYs07+bWIQCU +6i9y7LABAoGBANKB2Rs0lF5c+gpEE3w0AWoxGyL04TZECtl2hQ/b2jc2n8hLqLhv +zNIKN+xzEP6j0ijXajjEMLiQH10qQ6+Plv8C7o8GJC1V/Oj4u4kbPqfVV1kSxuWm +FBjz6+c8VPbEBgXq5lCMEgC2Ii8XVRoyd3iSSOh+LIMBu/Br3JEsjJq/AoGBAMFC +CvODTiThrZo8v765dRSHrLOvB4jZOPrEKLWECLaQDQpuhgzZhyWm9zFfxGB+LWE9 +R9pU6ZCFPtPfd4cRZ9cezrp+lgdrqjcUX/2ZLLMk21WXFuRaw/4KTlKNsMY6lbAK +qVkUFWIZWaCQ8bdVCP48polipRNmN9mAHsIhIwgBAoGBAM6yn1qeS11I0GAKLlPT +wNvjsfCmIQmm0DxtqwRCbUevxD7pQ5cueCB51iW/ap2OgEqIEo4A3pIrOhDB8kpN +pQdrepFHh3hYqYicy5A6B1DHJAibbl+Krss9n5KjZA4VtpBS8al/kCHQtUomD/M0 +QKlMgnh/g/dzWXYegyqtYraDAoGAGbeBH5B8iJnjcR/eYDHrq5S2XZ7QANzvISeT +RzxPsIOQyK+WdQVJX7BNOqvExRZlUYhHFH2yKwIgLy+Qh0/Aora9ycFok4o3N2cl +suh8M0aXTVdyu2Z8qESU0ZV7TZWkL63rhSgQBGLdM2m2ULAnJzXI74VJ9D/o9K+A +6FJiiAECgYEAujJ/hKxVKEUvxwloGSDhKCUH86+7UOkb/EM2zZFrlPYAz1VcCwr3 +K14r8BtmLFXuLXOlACpoH0Wf4uia+t6n8m9JK3mvpJ7fempAsptP3AdZMQFe7xUm +SXEGQBYxcyS5Q+ncwWZuPgby5wJ9D4Fd6TQH+wwG52sFugt/fGxbPug= -----END RSA PRIVATE KEY----- `), "pkcs8": []byte(`-----BEGIN PRIVATE KEY----- @@ -113,6 +125,37 @@ pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID +-----END OPENSSH PRIVATE KEY-----`), + "p256-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSN5Ld/DFy8LJK0yrWg+Ryhq4/ifHry +QyCQeT4UXSB+UGdRct7kWA0hARbTaSCh+8U/Gs5O+IkDNoTKVsgxKUMQAAAAsO3C7nPtwu +5zAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI3kt38MXLwskrTK +taD5HKGrj+J8evJDIJB5PhRdIH5QZ1Fy3uRYDSEBFtNpIKH7xT8azk74iQM2hMpWyDEpQx +AAAAAhAIHB48R+goZaiXndfYTrwk4BT1+MeLPC2/dwe0J5d1QDAAAAE21hcmlhbm9AZW5k +b3IubG9jYWwBAgME +-----END OPENSSH PRIVATE KEY-----`), + "p384-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS +1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTZb2VzEPs2NN/i1qHddKTVfwoIq3Tf +PeQ/kcWBvuCVJfIygvpm9MeusawEPuLSEXwiNDew+YHZ9xHIvFjCmZsLuEOzuh9t9KotwM +57H+7N+RDFzhM2j8hAaOuT5XDLKfUAAADgn/Sny5/0p8sAAAATZWNkc2Etc2hhMi1uaXN0 +cDM4NAAAAAhuaXN0cDM4NAAAAGEE2W9lcxD7NjTf4tah3XSk1X8KCKt03z3kP5HFgb7glS +XyMoL6ZvTHrrGsBD7i0hF8IjQ3sPmB2fcRyLxYwpmbC7hDs7ofbfSqLcDOex/uzfkQxc4T +No/IQGjrk+Vwyyn1AAAAMQDg0hwGKB/9Eq+e2FeTspi8QHW5xTD6prqsHDFx4cKk0ccgFV +61dhFhD/8SEbYlHzEAAAATbWFyaWFub0BlbmRvci5sb2NhbAECAwQ= +-----END OPENSSH PRIVATE KEY-----`), + "p521-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS +1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBKzI3QSp1a2e1zMulZl1uFF1Y2Dnv +LSIwEu837hOV1epYEgNveAhGNm57TuBqYtnZeVfd2pzaz7CKX6N4B33N1XABQ5Ngji7lF2 +dUbmhNqJoMh43ioIsQNBaBenhmRpYP6f5k8P/7JZMIsLhkJk2hykb8maSZ+B3PYwPMNBdS +vP+0sHQAAAEYIsr2CCLK9ggAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ +AAAIUEASsyN0EqdWtntczLpWZdbhRdWNg57y0iMBLvN+4TldXqWBIDb3gIRjZue07gamLZ +2XlX3dqc2s+wil+jeAd9zdVwAUOTYI4u5RdnVG5oTaiaDIeN4qCLEDQWgXp4ZkaWD+n+ZP +D/+yWTCLC4ZCZNocpG/Jmkmfgdz2MDzDQXUrz/tLB0AAAAQgEdeH+im6iRcP/juTAoeSHo +ExLtWhgL4JYqRwcOnzCKuLOPjEY/HSOuc+HRrbN9rbjsq+PcPHYe1NnkzXk0IW8hxQAAAB +NtYXJpYW5vQGVuZG9yLmxvY2FsAQIDBAUGBw== -----END OPENSSH PRIVATE KEY-----`), "user": []byte(`-----BEGIN EC PRIVATE KEY----- MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 @@ -159,14 +202,25 @@ var SSHCertificates = map[string][]byte{ // // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub": // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub - "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com + "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgWcP1x+t9PQTxkt/fRa8v5HXz0FFW/fwN3mpR5jdGo3UAAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzUQAAAAAd8sPtQAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEPAAAAB3NzaC1yc2EAAAEAs8/78EsftS/0+6CfUAtRhmgpOPZVH8XJc2o4Qx/lQCBg/uB2sucGGx/5BuFUwAjhMNQ1UejJ6+AbNgZNlH7LIssGxpcW+eKQXLfd9KwWNPCU3DqZGiMBsYESNtVLjKAMuvJmxKFFu4rceyya+GZfsQFJR7G++XK0cQQ4rgDSnQo3pxQnHwguFWeHtwjdOj0helYER4XDKjKQlo0SxI1nVo7n1jkl8QghdxX6HKia6MP7MqstgNujTvrCEUJ6L3YflD/SJ00Y3ySD9+5hqvfqrDh4c4rRuc4+k0e3fYZwyWO2NNtKHRBOZAgW8zzfR3G99YdTw8N8+2oXeAdvB9k0tA== host.example.com +`), + "rsa-sha2-256": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg4+hKHVPKv183MU/Q7XD/mzDBFSc2YY3eraltxLMGJo0AAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzYAAAAAAd8sP4wAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTI1NgAAAQA/ByIegNZYJRRl413S/8LxGvTZnbxsPwaluoJ/54niGZV9P28THz7d9jXfSHPjalhH93jNPfTYXvI4opnDC37ua1Nu8KKfk40IWXnnDdZLWraUxEidIzhmfVtz8kGdGoFQ8H0EzubL7zKNOTlfSfOoDlmQVOuxT/+eh2mEp4ri0/+8J1mLfLBr8tREX0/iaNjK+RKdcyTMicKursAYMCDdu8vlaphxea+ocyHM9izSX/l33t44V13ueTqIOh2Zbl2UE2k+jk+0dc1CmV0SEoiWiIyt8TRM4yQry1vPlQLsrf28sYM/QMwnhCVhyZO3vs5F25aQWrB9d51VEzBW9/fd host.example.com +`), + "rsa-sha2-512": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgylCoUX+0nYXGG9k/KEepcgEd22921eUwSQsYuQXKOswAAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzbwAAAAAd8sQBAAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTUxMgAAAQADOjYUNxzwYZ9O3zjjZSKhX7Ix/vUBq8lIltBRckbKJtcjn2/qqtaeZK2ijkbMlnPFCJ59U+Z6m4DMU6gxYF8R9/WJrANlWYNQ4+52fXjE/FPDdJkwB/kPWABt+ffEiM1HfzP4/zXgTtOJ0GogEzTYoMSrhAlpdKACUaC9nCQ7gjmO+owGkrB3ZbyQS4gltqQZjiBNqF0P/vxmXP+0Kx66/ei8JNYUpEPCXT4ZhLZmsVptaYD1gpvc2i5T5LnjRrsvf4Q6EKR+gwJEjlwnylhH5+h+ZU/KXydkw1hhEVP+ZiIBkVo9nN78Qb/VMJum4Fdoltuyh/9k2lMDeyDuRVh7 host.example.com +`), + // Assumes "ca" key above in file named "ca", sign a user cert for "rsa.pub" + // using "testcertificate" as principal: + // + // ssh-keygen -s ca -I username -n testcertificate rsa.pub + "rsa-user-testcertificate": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgEKR9xnhXkbi/pgP669VjBH6XVTYR0yx1wunCtOIjzjUAAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAABAAAACHVzZXJuYW1lAAAAEwAAAA90ZXN0Y2VydGlmaWNhdGUAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTUxMgAAAQCKVn2S7FJYhXTRVbcz1Di1HLz1g5Yae5WBhd0Tg471XkNw7ylcCK23Wnrzj1GxrW0oWCCGHROtUnxQXei1xNWt8HONN+eeafrJSZJR6ald3Yd4OveXlHNT6mEDPgqRj4B56OPoY33LzpaFlQZlZ6U9KXySshNaCTjVp3ojTj6uPNxcuOnG9O5emEPC2eaM4QYsz4cqHNJ9SWWEu+HIQgpx5SM12qcrq/KhN6WJhG3edL1YAsxkf1/THEcfi6wvsHi+DKewJ5hZ876//japjHBKA9SB7gsCrLx3m+0XI8TkWUZTZJHETJHHVjJN8xjRvMv5gWKLvRsz7ScmnN1+ckL6 rsa.pub `), } var PEMEncryptedKeys = []struct { - Name string - EncryptionKey string - PEMBytes []byte + Name string + EncryptionKey string + IncludesPublicKey bool + PEMBytes []byte }{ 0: { Name: "rsa-encrypted", @@ -224,4 +278,55 @@ IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8= -----END DSA PRIVATE KEY----- `), }, + + 2: { + Name: "ed25519-encrypted", + EncryptionKey: "password", + IncludesPublicKey: true, + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKj29BlC +ocEWuVhQ94/RjoAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIw1gSurPTDwZidA +2AIjQZgoQi3IFn9jBtFdP10/Jj7DAAAAoFGkQbB2teSU7ikUsnc7ct2aH3pitM359lNVUh +7DQbJWMjbQFbrBYyDJP+ALj1/RZmP2yoIf7/wr99q53/pm28Xp1gGP5V2RGRJYCA6kgFIH +xdB6KEw1Ce7Bz8JaDIeagAGd3xtQTH3cuuleVxCZZnk9NspsPxigADKCls/RUiK7F+z3Qf +Lvs9+PH8nIuhFMYZgo3liqZbVS5z4Fqhyzyq4= +-----END OPENSSH PRIVATE KEY----- +`), + }, + + 3: { + Name: "ed25519-encrypted-cbc", + EncryptionKey: "password", + IncludesPublicKey: true, + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABDzGKF3uX +G1gXALZKFd6Ir4AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDne4/teO42zTDdj +NwxUMNpbfmp/dxgU4ZNkC3ydgcugAAAAoJ3J/oA7+iqVOz0CIUUk9ufdP1VP4jDf2um+0s +Sgs7x6Gpyjq67Ps7wLRdSmxr/G5b+Z8dRGFYS/wUCQEe3whwuImvLyPwWjXLzkAyMzc01f +ywBGSrHnvP82ppenc2HuTI+E05Xc02i6JVyI1ShiekQL5twoqtR6pEBZnD17UonIx7cRzZ +gbDGyT3bXMQtagvCwoW+/oMTKXiZP5jCJpEO8= +-----END OPENSSH PRIVATE KEY----- +`), + }, +} + +// SKData contains a list of PubKeys backed by U2F/FIDO2 Security Keys and their test data. +var SKData = []struct { + Name string + PubKey []byte + HexData []byte + HexSignature []byte +}{ + { + Name: "sk-ecdsa-sha2-nistp256@openssh.com", + PubKey: []byte("sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGRNqlFgED/pf4zXz8IzqA6CALNwYcwgd4MQDmIS1GOtn1SySFObiuyJaOlpqkV5FeEifhxfIC2ejKKtNyO4CysAAAAEc3NoOg== user@host"), + HexData: []byte("00000020A4DE1F50DE0EF3F66DCD156C78F5C93B07EEE89D5B5A6531656E835FA1C87B323200000006736B696E6E650000000E7373682D636F6E6E656374696F6E000000097075626C69636B65790100000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D0000007F00000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D000000086E697374703235360000004104644DAA5160103FE97F8CD7CFC233A80E8200B37061CC207783100E6212D463AD9F54B248539B8AEC8968E969AA457915E1227E1C5F202D9E8CA2AD3723B80B2B000000047373683A"), + HexSignature: []byte("0000007800000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D000000490000002016CC1A3070E180621CB206C2C6313D1CC5F094DB844A61D06001E243C608875F0000002100E4BD45D6B9DAA11489AEA8D76C222AA3FD6D50FBFFDA8049526D5D61F63B2C5601000000F9"), + }, + { + Name: "sk-ssh-ed25519@openssh.com", + PubKey: []byte("sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJjzc2a20RjCvN/0ibH6UpGuN9F9hDvD7x182bOesNhHAAAABHNzaDo= user@host"), + HexData: []byte("000000204CFE6EA65CCB99B69348339165C7F38E359D95807A377EEE8E603C71DC3316FA3200000006736B696E6E650000000E7373682D636F6E6E656374696F6E000000097075626C69636B6579010000001A736B2D7373682D65643235353139406F70656E7373682E636F6D0000004A0000001A736B2D7373682D65643235353139406F70656E7373682E636F6D0000002098F37366B6D118C2BCDFF489B1FA5291AE37D17D843BC3EF1D7CD9B39EB0D847000000047373683A"), + HexSignature: []byte("000000670000001A736B2D7373682D65643235353139406F70656E7373682E636F6D000000404BF5CA0CAA553099306518732317B3FE4BA6C75365BC0CB02019FBE65A1647016CBD7A682C26928DF234C378ADDBC5077B47F72381144840BF00FB2DA2FB6A0A010000009E"), + }, } diff --git a/ssh/transport.go b/ssh/transport.go index 49ddc2e7de..fa3dd6a429 100644 --- a/ssh/transport.go +++ b/ssh/transport.go @@ -8,6 +8,7 @@ import ( "bufio" "bytes" "errors" + "fmt" "io" "log" ) @@ -16,12 +17,6 @@ import ( // wire. No message decoding is done, to minimize the impact on timing. const debugTransport = false -const ( - gcmCipherID = "aes128-gcm@openssh.com" - aes128cbcID = "aes128-cbc" - tripledescbcID = "3des-cbc" -) - // packetConn represents a transport that implements packet based // operations. type packetConn interface { @@ -48,6 +43,9 @@ type transport struct { rand io.Reader isClient bool io.Closer + + strictMode bool + initialKEXDone bool } // packetCipher represents a combination of SSH encryption/MAC @@ -73,17 +71,29 @@ type connectionState struct { pendingKeyChange chan packetCipher } +func (t *transport) setStrictMode() error { + if t.reader.seqNum != 1 { + return errors.New("ssh: sequence number != 1 when strict KEX mode requested") + } + t.strictMode = true + return nil +} + +func (t *transport) setInitialKEXDone() { + t.initialKEXDone = true +} + // prepareKeyChange sets up key material for a keychange. The key changes in // both directions are triggered by reading and writing a msgNewKey packet // respectively. -func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { - ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) +func (t *transport) prepareKeyChange(algs *NegotiatedAlgorithms, kexResult *kexResult) error { + ciph, err := newPacketCipher(t.reader.dir, algs.Read, kexResult) if err != nil { return err } t.reader.pendingKeyChange <- ciph - ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) + ciph, err = newPacketCipher(t.writer.dir, algs.Write, kexResult) if err != nil { return err } @@ -111,11 +121,12 @@ func (t *transport) printPacket(p []byte, write bool) { // Read and decrypt next packet. func (t *transport) readPacket() (p []byte, err error) { for { - p, err = t.reader.readPacket(t.bufReader) + p, err = t.reader.readPacket(t.bufReader, t.strictMode) if err != nil { break } - if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { + // in strict mode we pass through DEBUG and IGNORE packets only during the initial KEX + if len(p) == 0 || (t.strictMode && !t.initialKEXDone) || (p[0] != msgIgnore && p[0] != msgDebug) { break } } @@ -126,7 +137,7 @@ func (t *transport) readPacket() (p []byte, err error) { return p, err } -func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { +func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool) ([]byte, error) { packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) s.seqNum++ if err == nil && len(packet) == 0 { @@ -139,6 +150,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { select { case cipher := <-s.pendingKeyChange: s.packetCipher = cipher + if strictMode { + s.seqNum = 0 + } default: return nil, errors.New("ssh: got bogus newkeys message") } @@ -169,10 +183,10 @@ func (t *transport) writePacket(packet []byte) error { if debugTransport { t.printPacket(packet, true) } - return t.writer.writePacket(t.bufWriter, t.rand, packet) + return t.writer.writePacket(t.bufWriter, t.rand, packet, t.strictMode) } -func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { +func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte, strictMode bool) error { changeKeys := len(packet) > 0 && packet[0] == msgNewKeys err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) @@ -187,6 +201,9 @@ func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet [] select { case cipher := <-s.pendingKeyChange: s.packetCipher = cipher + if strictMode { + s.seqNum = 0 + } default: panic("ssh: no key material for msgNewKeys") } @@ -236,17 +253,24 @@ var ( // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as // described in RFC 4253, section 6.4. direction should either be serverKeys // (to setup server->client keys) or clientKeys (for client->server keys). -func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { +func newPacketCipher(d direction, algs DirectionAlgorithms, kex *kexResult) (packetCipher, error) { cipherMode := cipherModes[algs.Cipher] - macMode := macModes[algs.MAC] + if cipherMode == nil { + return nil, fmt.Errorf("ssh: unsupported cipher %v", algs.Cipher) + } iv := make([]byte, cipherMode.ivSize) key := make([]byte, cipherMode.keySize) - macKey := make([]byte, macMode.keySize) generateKeyMaterial(iv, d.ivTag, kex) generateKeyMaterial(key, d.keyTag, kex) - generateKeyMaterial(macKey, d.macKeyTag, kex) + + var macKey []byte + if !aeadCiphers[algs.Cipher] { + macMode := macModes[algs.MAC] + macKey = make([]byte, macMode.keySize) + generateKeyMaterial(macKey, d.macKeyTag, kex) + } return cipherModes[algs.Cipher].create(key, iv, macKey, algs) } diff --git a/twofish/twofish.go b/twofish/twofish.go index 1197d75132..6d0a3028d3 100644 --- a/twofish/twofish.go +++ b/twofish/twofish.go @@ -9,7 +9,7 @@ // implementation. Instead, use AES (from crypto/aes, if necessary in an AEAD // mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from // golang.org/x/crypto/chacha20poly1305). -package twofish // import "golang.org/x/crypto/twofish" +package twofish // Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH] @@ -18,7 +18,10 @@ package twofish // import "golang.org/x/crypto/twofish" // LibTomCrypt is free for all purposes under the public domain. // It was heavily inspired by the go blowfish package. -import "strconv" +import ( + "math/bits" + "strconv" +) // BlockSize is the constant block size of Twofish. const BlockSize = 16 @@ -76,12 +79,12 @@ func NewCipher(key []byte) (*Cipher, error) { tmp[j] = 2*i + 1 } B := h(tmp[:], key, 1) - B = rol(B, 8) + B = bits.RotateLeft32(B, 8) c.k[2*i] = A + B // K[2i+1] = (A + 2B) <<< 9 - c.k[2*i+1] = rol(2*B+A, 9) + c.k[2*i+1] = bits.RotateLeft32(2*B+A, 9) } // Calculate sboxes @@ -129,16 +132,6 @@ func load32l(src []byte) uint32 { return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24 } -// rol returns x after a left circular rotation of y bits. -func rol(x, y uint32) uint32 { - return (x << (y & 31)) | (x >> (32 - (y & 31))) -} - -// ror returns x after a right circular rotation of y bits. -func ror(x, y uint32) uint32 { - return (x >> (y & 31)) | (x << (32 - (y & 31))) -} - // The RS matrix. See [TWOFISH] 4.3 var rs = [4][8]byte{ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E}, @@ -282,13 +275,13 @@ func (c *Cipher) Encrypt(dst, src []byte) { k := c.k[8+i*4 : 12+i*4] t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 - ic = ror(ic^(t1+k[0]), 1) - id = rol(id, 1) ^ (t2 + t1 + k[1]) + ic = bits.RotateLeft32(ic^(t1+k[0]), -1) + id = bits.RotateLeft32(id, 1) ^ (t2 + t1 + k[1]) t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 - ia = ror(ia^(t1+k[2]), 1) - ib = rol(ib, 1) ^ (t2 + t1 + k[3]) + ia = bits.RotateLeft32(ia^(t1+k[2]), -1) + ib = bits.RotateLeft32(ib, 1) ^ (t2 + t1 + k[3]) } // Output with "undo last swap" @@ -326,13 +319,13 @@ func (c *Cipher) Decrypt(dst, src []byte) { k := c.k[4+i*4 : 8+i*4] t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 - ia = rol(ia, 1) ^ (t1 + k[2]) - ib = ror(ib^(t2+t1+k[3]), 1) + ia = bits.RotateLeft32(ia, 1) ^ (t1 + k[2]) + ib = bits.RotateLeft32(ib^(t2+t1+k[3]), -1) t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 - ic = rol(ic, 1) ^ (t1 + k[0]) - id = ror(id^(t2+t1+k[1]), 1) + ic = bits.RotateLeft32(ic, 1) ^ (t1 + k[0]) + id = bits.RotateLeft32(id^(t2+t1+k[1]), -1) } // Undo pre-whitening diff --git a/x509roots/fallback/bundle/bundle.der b/x509roots/fallback/bundle/bundle.der new file mode 100644 index 0000000000..7c75ce5e07 Binary files /dev/null and b/x509roots/fallback/bundle/bundle.der differ diff --git a/x509roots/fallback/bundle/bundle.go b/x509roots/fallback/bundle/bundle.go new file mode 100644 index 0000000000..8b8f20a470 --- /dev/null +++ b/x509roots/fallback/bundle/bundle.go @@ -0,0 +1,897 @@ +// Code generated by gen_fallback_bundle.go; DO NOT EDIT. + +package bundle + +var unparsedCertificates = []unparsedCertificate{ + { + cn: "CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS,OU=Ceres,O=FNMT-RCM,C=ES,2.5.4.97=#130f56415445532d51323832363030344a", + sha256Hash: "554153b13d2cf9ddb753bfbe1a4e0ae08d0aa4187058fe60a2b862b2e4b87bcb", + certStartOff: 0, + certLength: 626, + }, + { + cn: "CN=ACCVRAIZ1,OU=PKIACCV,O=ACCV,C=ES", + sha256Hash: "9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113", + certStartOff: 626, + certLength: 2007, + }, + { + cn: "CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT", + sha256Hash: "55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066", + certStartOff: 2633, + certLength: 1471, + }, + { + cn: "CN=AffirmTrust Commercial,O=AffirmTrust,C=US", + sha256Hash: "0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7", + certStartOff: 4104, + certLength: 848, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=AffirmTrust Networking,O=AffirmTrust,C=US", + sha256Hash: "0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b", + certStartOff: 4952, + certLength: 848, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US", + sha256Hash: "bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423", + certStartOff: 5800, + certLength: 514, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=AffirmTrust Premium,O=AffirmTrust,C=US", + sha256Hash: "70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a", + certStartOff: 6314, + certLength: 1354, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Amazon Root CA 1,O=Amazon,C=US", + sha256Hash: "8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e", + certStartOff: 7668, + certLength: 837, + }, + { + cn: "CN=Amazon Root CA 2,O=Amazon,C=US", + sha256Hash: "1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4", + certStartOff: 8505, + certLength: 1349, + }, + { + cn: "CN=Amazon Root CA 3,O=Amazon,C=US", + sha256Hash: "18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4", + certStartOff: 9854, + certLength: 442, + }, + { + cn: "CN=Amazon Root CA 4,O=Amazon,C=US", + sha256Hash: "e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092", + certStartOff: 10296, + certLength: 502, + }, + { + cn: "CN=Atos TrustedRoot 2011,O=Atos,C=DE", + sha256Hash: "f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474", + certStartOff: 10798, + certLength: 891, + }, + { + cn: "CN=Atos TrustedRoot Root CA ECC TLS 2021,O=Atos,C=DE", + sha256Hash: "b2fae53e14ccd7ab9212064701ae279c1d8988facb775fa8a008914e663988a8", + certStartOff: 11689, + certLength: 537, + }, + { + cn: "CN=Atos TrustedRoot Root CA RSA TLS 2021,O=Atos,C=DE", + sha256Hash: "81a9088ea59fb364c548a6f85559099b6f0405efbf18e5324ec9f457ba00112f", + certStartOff: 12226, + certLength: 1384, + }, + { + cn: "CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES", + sha256Hash: "57de0583efd2b26e0361da99da9df4648def7ee8441c3b728afa9bcde0f9b26a", + certStartOff: 13610, + certLength: 1560, + }, + { + cn: "CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN", + sha256Hash: "f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae", + certStartOff: 15170, + certLength: 1400, + }, + { + cn: "CN=BJCA Global Root CA2,O=BEIJING CERTIFICATE AUTHORITY,C=CN", + sha256Hash: "574df6931e278039667b720afdc1600fc27eb66dd3092979fb73856487212882", + certStartOff: 16570, + certLength: 553, + }, + { + cn: "CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO", + sha256Hash: "9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48", + certStartOff: 17123, + certLength: 1373, + }, + { + cn: "CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO", + sha256Hash: "edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d", + certStartOff: 18496, + certLength: 1373, + }, + { + cn: "CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK", + sha256Hash: "e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703", + certStartOff: 19869, + certLength: 1389, + }, + { + cn: "CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN", + sha256Hash: "5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd", + certStartOff: 21258, + certLength: 1425, + }, + { + cn: "CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66", + certStartOff: 22683, + certLength: 1057, + }, + { + cn: "CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7", + certStartOff: 23740, + certLength: 653, + }, + { + cn: "CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB", + sha256Hash: "52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234", + certStartOff: 24393, + certLength: 1500, + }, + { + cn: "CN=Certainly Root E1,O=Certainly,C=US", + sha256Hash: "b4585f22e4ac756a4e8612a1361c5d9d031a93fd84febb778fa3068b0fc42dc2", + certStartOff: 25893, + certLength: 507, + }, + { + cn: "CN=Certainly Root R1,O=Certainly,C=US", + sha256Hash: "77b82cd8644c4305f7acc5cb156b45675004033d51c60c6202a8e0c33467d3a0", + certStartOff: 26400, + certLength: 1355, + }, + { + cn: "CN=Certigna Root CA,OU=0002 48146308100036,O=Dhimyotis,C=FR", + sha256Hash: "d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168", + certStartOff: 27755, + certLength: 1631, + }, + { + cn: "CN=Certigna,O=Dhimyotis,C=FR", + sha256Hash: "e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d", + certStartOff: 29386, + certLength: 940, + }, + { + cn: "CN=Certum EC-384 CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL", + sha256Hash: "6b328085625318aa50d173c98d8bda09d57e27413d114cf787a0f5d06c030cf6", + certStartOff: 30326, + certLength: 617, + }, + { + cn: "CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL", + sha256Hash: "b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804", + certStartOff: 30943, + certLength: 1494, + }, + { + cn: "CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL", + sha256Hash: "5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e", + certStartOff: 32437, + certLength: 959, + }, + { + cn: "CN=Certum Trusted Root CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL", + sha256Hash: "fe7696573855773e37a95e7ad4d9cc96c30157c15d31765ba9b15704e1ae78fd", + certStartOff: 33396, + certLength: 1476, + }, + { + cn: "CN=CommScope Public Trust ECC Root-01,O=CommScope,C=US", + sha256Hash: "11437cda7bb45e41365f45b39a38986b0de00def348e0c7bb0873633800bc38b", + certStartOff: 34872, + certLength: 545, + }, + { + cn: "CN=CommScope Public Trust ECC Root-02,O=CommScope,C=US", + sha256Hash: "2ffb7f813bbbb3c89ab4e8162d0f16d71509a830cc9d73c262e5140875d1ad4a", + certStartOff: 35417, + certLength: 544, + }, + { + cn: "CN=CommScope Public Trust RSA Root-01,O=CommScope,C=US", + sha256Hash: "02bdf96e2a45dd9bf18fc7e1dbdf21a0379ba3c9c2610344cfd8d606fec1ed81", + certStartOff: 35961, + certLength: 1392, + }, + { + cn: "CN=CommScope Public Trust RSA Root-02,O=CommScope,C=US", + sha256Hash: "ffe943d793424b4f7c440c1c3d648d5363f34b82dc87aa7a9f118fc5dee101f1", + certStartOff: 37353, + certLength: 1392, + }, + { + cn: "CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE", + sha256Hash: "e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044", + certStartOff: 38745, + certLength: 735, + }, + { + cn: "CN=D-TRUST BR Root CA 2 2023,O=D-Trust GmbH,C=DE", + sha256Hash: "0552e6f83fdf65e8fa9670e666df28a4e21340b510cbe52566f97c4fb94b2bd1", + certStartOff: 39480, + certLength: 1453, + }, + { + cn: "CN=D-TRUST EV Root CA 1 2020,O=D-Trust GmbH,C=DE", + sha256Hash: "08170d1aa36453901a2f959245e347db0c8d37abaabc56b81aa100dc958970db", + certStartOff: 40933, + certLength: 735, + }, + { + cn: "CN=D-TRUST EV Root CA 2 2023,O=D-Trust GmbH,C=DE", + sha256Hash: "8e8221b2e7d4007836a1672f0dcc299c33bc07d316f132fa1a206d587150f1ce", + certStartOff: 41668, + certLength: 1453, + }, + { + cn: "CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE", + sha256Hash: "49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1", + certStartOff: 43121, + certLength: 1079, + }, + { + cn: "CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE", + sha256Hash: "eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881", + certStartOff: 44200, + certLength: 1095, + }, + { + cn: "CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c", + certStartOff: 45295, + certLength: 955, + }, + { + cn: "CN=DigiCert Assured ID Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185", + certStartOff: 46250, + certLength: 922, + }, + { + cn: "CN=DigiCert Assured ID Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2", + certStartOff: 47172, + certLength: 586, + }, + { + cn: "CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161", + certStartOff: 47758, + certLength: 947, + }, + { + cn: "CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f", + certStartOff: 48705, + certLength: 914, + }, + { + cn: "CN=DigiCert Global Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0", + certStartOff: 49619, + certLength: 579, + }, + { + cn: "CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf", + certStartOff: 50198, + certLength: 969, + }, + { + cn: "CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\\, Inc.,C=US", + sha256Hash: "018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05", + certStartOff: 51167, + certLength: 541, + }, + { + cn: "CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\\, Inc.,C=US", + sha256Hash: "371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75", + certStartOff: 51708, + certLength: 1386, + }, + { + cn: "CN=DigiCert Trusted Root G4,OU=www.digicert.com,O=DigiCert Inc,C=US", + sha256Hash: "552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988", + certStartOff: 53094, + certLength: 1428, + }, + { + cn: "CN=Entrust Root Certification Authority - EC1,OU=See www.entrust.net/legal-terms+OU=(c) 2012 Entrust\\, Inc. - for authorized use only,O=Entrust\\, Inc.,C=US", + sha256Hash: "02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5", + certStartOff: 54522, + certLength: 765, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Entrust Root Certification Authority - G2,OU=See www.entrust.net/legal-terms+OU=(c) 2009 Entrust\\, Inc. - for authorized use only,O=Entrust\\, Inc.,C=US", + sha256Hash: "43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339", + certStartOff: 55287, + certLength: 1090, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=Entrust Root Certification Authority,OU=www.entrust.net/CPS is incorporated by reference+OU=(c) 2006 Entrust\\, Inc.,O=Entrust\\, Inc.,C=US", + sha256Hash: "73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c", + certStartOff: 56377, + certLength: 1173, + distrustAfter: "2024-11-30T23:59:59Z", + }, + { + cn: "CN=FIRMAPROFESIONAL CA ROOT-A WEB,O=Firmaprofesional SA,C=ES,2.5.4.97=#130f56415445532d413632363334303638", + sha256Hash: "bef256daf26e9c69bdec1602359798f3caf71821a03e018257c53c65617f3d4a", + certStartOff: 57550, + certLength: 638, + }, + { + cn: "CN=GDCA TrustAUTH R5 ROOT,O=GUANG DONG CERTIFICATE AUTHORITY CO.\\,LTD.,C=CN", + sha256Hash: "bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893", + certStartOff: 58188, + certLength: 1420, + }, + { + cn: "CN=GLOBALTRUST 2020,O=e-commerce monitoring GmbH,C=AT", + sha256Hash: "9a296a5182d1d451a2e37f439b74daafa267523329f90f9a0d2007c334e23c9a", + certStartOff: 59608, + certLength: 1414, + distrustAfter: "2024-06-30T00:00:00Z", + }, + { + cn: "CN=GTS Root R1,O=Google Trust Services LLC,C=US", + sha256Hash: "d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf", + certStartOff: 61022, + certLength: 1371, + }, + { + cn: "CN=GTS Root R2,O=Google Trust Services LLC,C=US", + sha256Hash: "8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8", + certStartOff: 62393, + certLength: 1371, + }, + { + cn: "CN=GTS Root R3,O=Google Trust Services LLC,C=US", + sha256Hash: "34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48", + certStartOff: 63764, + certLength: 525, + }, + { + cn: "CN=GTS Root R4,O=Google Trust Services LLC,C=US", + sha256Hash: "349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d", + certStartOff: 64289, + certLength: 525, + }, + { + cn: "CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE", + sha256Hash: "cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058", + certStartOff: 64814, + certLength: 527, + }, + { + cn: "CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE", + sha256Hash: "4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9", + certStartOff: 65341, + certLength: 1374, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign ECC Root CA - R4,O=GlobalSign", + sha256Hash: "b085d70b964f191a73e4af0d54ae7a0e07aafdaf9b71dd0862138ab7325a24a2", + certStartOff: 66715, + certLength: 480, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign ECC Root CA - R5,O=GlobalSign", + sha256Hash: "179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924", + certStartOff: 67195, + certLength: 546, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign Root CA - R3,O=GlobalSign", + sha256Hash: "cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b", + certStartOff: 67741, + certLength: 867, + }, + { + cn: "CN=GlobalSign,OU=GlobalSign Root CA - R6,O=GlobalSign", + sha256Hash: "2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69", + certStartOff: 68608, + certLength: 1415, + }, + { + cn: "CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\\, Inc.,L=Scottsdale,ST=Arizona,C=US", + sha256Hash: "45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda", + certStartOff: 70023, + certLength: 969, + }, + { + cn: "CN=HARICA TLS ECC Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR", + sha256Hash: "3f99cc474acfce4dfed58794665e478d1547739f2e780f1bb4ca9b133097d401", + certStartOff: 70992, + certLength: 600, + }, + { + cn: "CN=HARICA TLS RSA Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR", + sha256Hash: "d95d0e8eda79525bf9beb11b14d2100d3294985f0c62d9fabd9cd999eccb7b1d", + certStartOff: 71592, + certLength: 1448, + }, + { + cn: "CN=Hellenic Academic and Research Institutions ECC RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR", + sha256Hash: "44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833", + certStartOff: 73040, + certLength: 711, + }, + { + cn: "CN=Hellenic Academic and Research Institutions RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR", + sha256Hash: "a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36", + certStartOff: 73751, + certLength: 1551, + }, + { + cn: "CN=HiPKI Root CA - G1,O=Chunghwa Telecom Co.\\, Ltd.,C=TW", + sha256Hash: "f015ce3cc239bfef064be9f1d2c417e1a0264a0a94be1f0c8d121864eb6949cc", + certStartOff: 75302, + certLength: 1390, + }, + { + cn: "CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK", + sha256Hash: "5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6", + certStartOff: 76692, + certLength: 1491, + }, + { + cn: "CN=ISRG Root X1,O=Internet Security Research Group,C=US", + sha256Hash: "96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6", + certStartOff: 78183, + certLength: 1391, + }, + { + cn: "CN=ISRG Root X2,O=Internet Security Research Group,C=US", + sha256Hash: "69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470", + certStartOff: 79574, + certLength: 543, + }, + { + cn: "CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US", + sha256Hash: "5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae", + certStartOff: 80117, + certLength: 1380, + }, + { + cn: "CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US", + sha256Hash: "30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f", + certStartOff: 81497, + certLength: 1386, + }, + { + cn: "CN=Izenpe.com,O=IZENPE S.A.,C=ES", + sha256Hash: "2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f", + certStartOff: 82883, + certLength: 1525, + }, + { + cn: "CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU,1.2.840.113549.1.9.1=#0c10696e666f40652d737a69676e6f2e6875", + sha256Hash: "3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378", + certStartOff: 84408, + certLength: 1038, + }, + { + cn: "CN=Microsoft ECC Root Certificate Authority 2017,O=Microsoft Corporation,C=US", + sha256Hash: "358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02", + certStartOff: 85446, + certLength: 605, + }, + { + cn: "CN=Microsoft RSA Root Certificate Authority 2017,O=Microsoft Corporation,C=US", + sha256Hash: "c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0", + certStartOff: 86051, + certLength: 1452, + }, + { + cn: "CN=NAVER Global Root Certification Authority,O=NAVER BUSINESS PLATFORM Corp.,C=KR", + sha256Hash: "88f438dcf8ffd1fa8f429115ffe5f82ae1e06e0c70c375faad717b34a49e7265", + certStartOff: 87503, + certLength: 1446, + }, + { + cn: "CN=NetLock Arany (Class Gold) Főtanúsítvány,OU=Tanúsítványkiadók (Certification Services),O=NetLock Kft.,L=Budapest,C=HU", + sha256Hash: "6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98", + certStartOff: 88949, + certLength: 1049, + }, + { + cn: "CN=OISTE Server Root ECC G1,O=OISTE Foundation,C=CH", + sha256Hash: "eec997c0c30f216f7e3b8b307d2bae42412d753fc8219dafd1520b2572850f49", + certStartOff: 89998, + certLength: 569, + }, + { + cn: "CN=OISTE Server Root RSA G1,O=OISTE Foundation,C=CH", + sha256Hash: "9ae36232a5189ffddb353dfd26520c015395d22777dac59db57b98c089a651e6", + certStartOff: 90567, + certLength: 1415, + }, + { + cn: "CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH", + sha256Hash: "6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6", + certStartOff: 91982, + certLength: 953, + }, + { + cn: "CN=OISTE WISeKey Global Root GC CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH", + sha256Hash: "8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d", + certStartOff: 92935, + certLength: 621, + }, + { + cn: "CN=QuoVadis Root CA 1 G3,O=QuoVadis Limited,C=BM", + sha256Hash: "8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74", + certStartOff: 93556, + certLength: 1380, + }, + { + cn: "CN=QuoVadis Root CA 2 G3,O=QuoVadis Limited,C=BM", + sha256Hash: "8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840", + certStartOff: 94936, + certLength: 1380, + }, + { + cn: "CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM", + sha256Hash: "85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86", + certStartOff: 96316, + certLength: 1467, + }, + { + cn: "CN=QuoVadis Root CA 3 G3,O=QuoVadis Limited,C=BM", + sha256Hash: "88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46", + certStartOff: 97783, + certLength: 1380, + }, + { + cn: "CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM", + sha256Hash: "18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35", + certStartOff: 99163, + certLength: 1697, + }, + { + cn: "CN=SSL.com EV Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8", + certStartOff: 100860, + certLength: 664, + }, + { + cn: "CN=SSL.com EV Root Certification Authority RSA R2,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c", + certStartOff: 101524, + certLength: 1519, + }, + { + cn: "CN=SSL.com Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65", + certStartOff: 103043, + certLength: 657, + }, + { + cn: "CN=SSL.com Root Certification Authority RSA,O=SSL Corporation,L=Houston,ST=Texas,C=US", + sha256Hash: "85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69", + certStartOff: 103700, + certLength: 1505, + }, + { + cn: "CN=SSL.com TLS ECC Root CA 2022,O=SSL Corporation,C=US", + sha256Hash: "c32ffd9f46f936d16c3673990959434b9ad60aafbb9e7cf33654f144cc1ba143", + certStartOff: 105205, + certLength: 574, + }, + { + cn: "CN=SSL.com TLS RSA Root CA 2022,O=SSL Corporation,C=US", + sha256Hash: "8faf7d2e2cb4709bb8e0b33666bf75a5dd45b5de480f8ea8d4bfe6bebc17f2ed", + certStartOff: 105779, + certLength: 1421, + }, + { + cn: "CN=SZAFIR ROOT CA2,O=Krajowa Izba Rozliczeniowa S.A.,C=PL", + sha256Hash: "a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe", + certStartOff: 107200, + certLength: 886, + }, + { + cn: "CN=Sectigo Public Server Authentication Root E46,O=Sectigo Limited,C=GB", + sha256Hash: "c90f26f0fb1b4018b22227519b5ca2b53e2ca5b3be5cf18efe1bef47380c5383", + certStartOff: 108086, + certLength: 574, + }, + { + cn: "CN=Sectigo Public Server Authentication Root R46,O=Sectigo Limited,C=GB", + sha256Hash: "7bb647a62aeeac88bf257aa522d01ffea395e0ab45c73f93f65654ec38f25a06", + certStartOff: 108660, + certLength: 1422, + }, + { + cn: "CN=Secure Global CA,O=SecureTrust Corporation,C=US", + sha256Hash: "4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69", + certStartOff: 110082, + certLength: 960, + }, + { + cn: "CN=SecureSign Root CA12,O=Cybertrust Japan Co.\\, Ltd.,C=JP", + sha256Hash: "3f034bb5704d44b2d08545a02057de93ebf3905fce721acbc730c06ddaee904e", + certStartOff: 111042, + certLength: 886, + }, + { + cn: "CN=SecureSign Root CA14,O=Cybertrust Japan Co.\\, Ltd.,C=JP", + sha256Hash: "4b009c1034494f9ab56bba3ba1d62731fc4d20d8955adcec10a925607261e338", + certStartOff: 111928, + certLength: 1398, + }, + { + cn: "CN=SecureSign Root CA15,O=Cybertrust Japan Co.\\, Ltd.,C=JP", + sha256Hash: "e778f0f095fe843729cd1a0082179e5314a9c291442805e1fb1d8fb6b8886c3a", + certStartOff: 113326, + certLength: 551, + }, + { + cn: "CN=SecureTrust CA,O=SecureTrust Corporation,C=US", + sha256Hash: "f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73", + certStartOff: 113877, + certLength: 956, + }, + { + cn: "CN=Security Communication ECC RootCA1,O=SECOM Trust Systems CO.\\,LTD.,C=JP", + sha256Hash: "e74fbda55bd564c473a36b441aa799c8a68e077440e8288b9fa1e50e4bbaca11", + certStartOff: 114833, + certLength: 572, + }, + { + cn: "CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\\, Inc.,L=Scottsdale,ST=Arizona,C=US", + sha256Hash: "2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5", + certStartOff: 115405, + certLength: 993, + }, + { + cn: "CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\\, Inc.,L=Scottsdale,ST=Arizona,C=US", + sha256Hash: "568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5", + certStartOff: 116398, + certLength: 1011, + }, + { + cn: "CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH", + sha256Hash: "62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95", + certStartOff: 117409, + certLength: 1470, + }, + { + cn: "CN=SwissSign RSA TLS Root CA 2022 - 1,O=SwissSign AG,C=CH", + sha256Hash: "193144f431e0fddb740717d4de926a571133884b4360d30e272913cbe660ce41", + certStartOff: 118879, + certLength: 1431, + }, + { + cn: "CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE", + sha256Hash: "91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552", + certStartOff: 120310, + certLength: 967, + }, + { + cn: "CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE", + sha256Hash: "fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd", + certStartOff: 121277, + certLength: 967, + }, + { + cn: "CN=TWCA CYBER Root CA,OU=Root CA,O=TAIWAN-CA,C=TW", + sha256Hash: "3f63bb2814be174ec8b6439cf08d6d56f0b7c405883a5648a334424d6b3ec558", + certStartOff: 122244, + certLength: 1425, + }, + { + cn: "CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW", + sha256Hash: "59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b", + certStartOff: 123669, + certLength: 1349, + }, + { + cn: "CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW", + sha256Hash: "bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44", + certStartOff: 125018, + certLength: 895, + }, + { + cn: "CN=Telekom Security TLS ECC Root 2020,O=Deutsche Telekom Security GmbH,C=DE", + sha256Hash: "578af4ded0853f4e5998db4aeaf9cbea8d945f60b620a38d1a3c13b2bc7ba8e1", + certStartOff: 125913, + certLength: 582, + }, + { + cn: "CN=Telekom Security TLS RSA Root 2023,O=Deutsche Telekom Security GmbH,C=DE", + sha256Hash: "efc65cadbb59adb6efe84da22311b35624b71b3b1ea0da8b6655174ec8978646", + certStartOff: 126495, + certLength: 1463, + }, + { + cn: "CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI", + sha256Hash: "242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c", + certStartOff: 127958, + certLength: 1400, + }, + { + cn: "CN=TeliaSonera Root CA v1,O=TeliaSonera", + sha256Hash: "dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389", + certStartOff: 129358, + certLength: 1340, + }, + { + cn: "CN=TrustAsia Global Root CA G3,O=TrustAsia Technologies\\, Inc.,C=CN", + sha256Hash: "e0d3226aeb1163c2e48ff9be3b50b4c6431be7bb1eacc5c36b5d5ec509039a08", + certStartOff: 130698, + certLength: 1449, + }, + { + cn: "CN=TrustAsia Global Root CA G4,O=TrustAsia Technologies\\, Inc.,C=CN", + sha256Hash: "be4b56cb5056c0136a526df444508daa36a0b54f42e4ac38f72af470e479654c", + certStartOff: 132147, + certLength: 601, + }, + { + cn: "CN=TrustAsia TLS ECC Root CA,O=TrustAsia Technologies\\, Inc.,C=CN", + sha256Hash: "c0076b9ef0531fb1a656d67c4ebe97cd5dbaa41ef44598acc2489878c92d8711", + certStartOff: 132748, + certLength: 565, + }, + { + cn: "CN=TrustAsia TLS RSA Root CA,O=TrustAsia Technologies\\, Inc.,C=CN", + sha256Hash: "06c08d7dafd876971eb1124fe67f847ec0c7a158d3ea53cbe940e2ea9791f4c3", + certStartOff: 133313, + certLength: 1412, + }, + { + cn: "CN=Trustwave Global Certification Authority,O=Trustwave Holdings\\, Inc.,L=Chicago,ST=Illinois,C=US", + sha256Hash: "97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8", + certStartOff: 134725, + certLength: 1502, + }, + { + cn: "CN=Trustwave Global ECC P256 Certification Authority,O=Trustwave Holdings\\, Inc.,L=Chicago,ST=Illinois,C=US", + sha256Hash: "945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4", + certStartOff: 136227, + certLength: 612, + }, + { + cn: "CN=Trustwave Global ECC P384 Certification Authority,O=Trustwave Holdings\\, Inc.,L=Chicago,ST=Illinois,C=US", + sha256Hash: "55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097", + certStartOff: 136839, + certLength: 673, + }, + { + cn: "CN=TunTrust Root CA,O=Agence Nationale de Certification Electronique,C=TN", + sha256Hash: "2e44102ab58cb85419451c8e19d9acf3662cafbc614b6a53960a30f7d0e2eb41", + certStartOff: 137512, + certLength: 1463, + }, + { + cn: "CN=UCA Extended Validation Root,O=UniTrust,C=CN", + sha256Hash: "d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24", + certStartOff: 138975, + certLength: 1374, + }, + { + cn: "CN=UCA Global G2 Root,O=UniTrust,C=CN", + sha256Hash: "9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c", + certStartOff: 140349, + certLength: 1354, + }, + { + cn: "CN=USERTrust ECC Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US", + sha256Hash: "4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a", + certStartOff: 141703, + certLength: 659, + }, + { + cn: "CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US", + sha256Hash: "e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2", + certStartOff: 142362, + certLength: 1506, + }, + { + cn: "CN=e-Szigno Root CA 2017,O=Microsec Ltd.,L=Budapest,C=HU,2.5.4.97=#130e56415448552d3233353834343937", + sha256Hash: "beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99", + certStartOff: 143868, + certLength: 580, + }, + { + cn: "CN=emSign ECC Root CA - C3,OU=emSign PKI,O=eMudhra Inc,C=US", + sha256Hash: "bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3", + certStartOff: 144448, + certLength: 559, + }, + { + cn: "CN=emSign ECC Root CA - G3,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN", + sha256Hash: "86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b", + certStartOff: 145007, + certLength: 594, + }, + { + cn: "CN=emSign Root CA - C1,OU=emSign PKI,O=eMudhra Inc,C=US", + sha256Hash: "125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f", + certStartOff: 145601, + certLength: 887, + }, + { + cn: "CN=emSign Root CA - G1,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN", + sha256Hash: "40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367", + certStartOff: 146488, + certLength: 920, + }, + { + cn: "CN=vTrus ECC Root CA,O=iTrusChina Co.\\,Ltd.,C=CN", + sha256Hash: "30fbba2c32238e2a98547af97931e550428b9b3f1c8eeb6633dcfa86c5b27dd3", + certStartOff: 147408, + certLength: 531, + }, + { + cn: "CN=vTrus Root CA,O=iTrusChina Co.\\,Ltd.,C=CN", + sha256Hash: "8a71de6559336f426c26e53880d00d88a18da4c6a91f0dcb6194e206c5c96387", + certStartOff: 147939, + certLength: 1370, + }, + { + cn: "OU=AC RAIZ FNMT-RCM,O=FNMT-RCM,C=ES", + sha256Hash: "ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa", + certStartOff: 149309, + certLength: 1415, + }, + { + cn: "OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\\,LTD.,C=JP", + sha256Hash: "513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6", + certStartOff: 150724, + certLength: 891, + }, + { + cn: "OU=certSIGN ROOT CA G2,O=CERTSIGN SA,C=RO", + sha256Hash: "657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305", + certStartOff: 151615, + certLength: 1355, + }, + { + cn: "OU=certSIGN ROOT CA,O=certSIGN,C=RO", + sha256Hash: "eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb", + certStartOff: 152970, + certLength: 828, + }, + { + cn: "OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\\, Ltd.,C=TW", + sha256Hash: "c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5", + certStartOff: 153798, + certLength: 1460, + distrustAfter: "2025-04-15T23:59:59Z", + }, + { + cn: "SERIALNUMBER=G63287510,CN=ANF Secure Server Root CA,OU=ANF CA Raiz,O=ANF Autoridad de Certificacion,C=ES", + sha256Hash: "fb8fec759169b9106b1e511644c618c51304373f6c0643088d8beffd1b997599", + certStartOff: 155258, + certLength: 1523, + }, +} diff --git a/x509roots/fallback/bundle/bundle_test.go b/x509roots/fallback/bundle/bundle_test.go new file mode 100644 index 0000000000..3eafe153af --- /dev/null +++ b/x509roots/fallback/bundle/bundle_test.go @@ -0,0 +1,32 @@ +// Copyright 2025 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 bundle + +import ( + "crypto/sha256" + "crypto/x509" + "encoding/hex" + "testing" +) + +func TestBundle(t *testing.T) { + for i, unparsed := range unparsedCertificates { + cert, err := x509.ParseCertificate(rawCerts[unparsed.certStartOff : unparsed.certStartOff+unparsed.certLength]) + if err != nil { + t.Errorf("ParseCertificate(unparsedCertificates[%v]) unexpected error: %v", i, err) + continue + } + + if unparsed.cn != cert.Subject.String() { + t.Errorf("unparsedCertificates[%v].cn = %q; want = %q", i, unparsed.cn, cert.Subject.String()) + } + + sum := sha256.Sum256(cert.Raw) + sumHex := hex.EncodeToString(sum[:]) + if sumHex != unparsed.sha256Hash { + t.Errorf("unparsedCertificates[%v].sha256Hash = %q; want = %q", i, unparsed.sha256Hash, sumHex) + } + } +} diff --git a/x509roots/fallback/bundle/roots.go b/x509roots/fallback/bundle/roots.go new file mode 100644 index 0000000000..38a1b3d671 --- /dev/null +++ b/x509roots/fallback/bundle/roots.go @@ -0,0 +1,73 @@ +// Copyright 2025 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 bundle contains the bundle of root certificates parsed from the NSS +// trust store, using x509roots/nss. +package bundle + +import ( + "crypto/x509" + _ "embed" + "fmt" + "iter" + "time" +) + +//go:embed bundle.der +var rawCerts []byte + +// Root represents a root certificate parsed from the NSS trust store. +type Root struct { + // Certificate is the DER-encoded certificate (read-only; do not modify!). + Certificate []byte + + // Constraint is nil if the root is unconstrained. If Constraint is non-nil, + // the certificate has additional constraints that cannot be encoded in + // X.509, and when building a certificate chain anchored with this root the + // chain should be passed to this function to check its validity. If using a + // [crypto/x509.CertPool] the root should be added using + // [crypto/x509.CertPool.AddCertWithConstraint]. + Constraint func([]*x509.Certificate) error +} + +// Roots returns the bundle of root certificates from the NSS trust store. The +// [Root.Certificate] slice must be treated as read-only and should not be +// modified. +func Roots() iter.Seq[Root] { + return func(yield func(Root) bool) { + for _, unparsed := range unparsedCertificates { + root := Root{ + Certificate: rawCerts[unparsed.certStartOff : unparsed.certStartOff+unparsed.certLength], + } + // parse possible constraints, this should check all fields of unparsedCertificate. + if unparsed.distrustAfter != "" { + distrustAfter, err := time.Parse(time.RFC3339, unparsed.distrustAfter) + if err != nil { + panic(fmt.Sprintf("failed to parse distrustAfter %q: %s", unparsed.distrustAfter, err)) + } + root.Constraint = func(chain []*x509.Certificate) error { + for _, c := range chain { + if c.NotBefore.After(distrustAfter) { + return fmt.Errorf("certificate issued after distrust-after date %q", distrustAfter) + } + } + return nil + } + } + if !yield(root) { + return + } + } + } +} + +type unparsedCertificate struct { + cn string + sha256Hash string + certStartOff int + certLength int + + // possible constraints + distrustAfter string +} diff --git a/x509roots/fallback/bundle/roots_test.go b/x509roots/fallback/bundle/roots_test.go new file mode 100644 index 0000000000..04ba9db299 --- /dev/null +++ b/x509roots/fallback/bundle/roots_test.go @@ -0,0 +1,18 @@ +// Copyright 2025 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 bundle + +import ( + "crypto/x509" + "testing" +) + +func TestRootsCanBeParsed(t *testing.T) { + for root := range Roots() { + if _, err := x509.ParseCertificate(root.Certificate); err != nil { + t.Fatalf("Could not parse root certificate: %v", err) + } + } +} diff --git a/x509roots/fallback/fallback.go b/x509roots/fallback/fallback.go new file mode 100644 index 0000000000..79e18704a8 --- /dev/null +++ b/x509roots/fallback/fallback.go @@ -0,0 +1,45 @@ +// Copyright 2023 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 fallback embeds a set of fallback X.509 trusted roots in the +// application by automatically invoking [x509.SetFallbackRoots]. This allows +// the application to work correctly even if the operating system does not +// provide a verifier or system roots pool. +// +// To use it, import the package like +// +// import _ "golang.org/x/crypto/x509roots/fallback" +// +// It's recommended that only binaries, and not libraries, import this package. +// +// This package must be kept up to date for security and compatibility reasons. +// Use govulncheck to be notified of when new versions of the package are +// available. +package fallback + +import ( + "crypto/x509" + + "golang.org/x/crypto/x509roots/fallback/bundle" +) + +func init() { + x509.SetFallbackRoots(newFallbackCertPool()) +} + +func newFallbackCertPool() *x509.CertPool { + p := x509.NewCertPool() + for c := range bundle.Roots() { + cert, err := x509.ParseCertificate(c.Certificate) + if err != nil { + panic(err) + } + if c.Constraint == nil { + p.AddCert(cert) + } else { + p.AddCertWithConstraint(cert, c.Constraint) + } + } + return p +} diff --git a/x509roots/fallback/fallback_test.go b/x509roots/fallback/fallback_test.go new file mode 100644 index 0000000000..e380046180 --- /dev/null +++ b/x509roots/fallback/fallback_test.go @@ -0,0 +1,11 @@ +package fallback + +import "testing" + +// BenchmarkInitTime benchmarks the time it takes to parse all certificates +// in this bundle, it corresponds to the init time of this package. +func BenchmarkInitTime(b *testing.B) { + for range b.N { + newFallbackCertPool() + } +} diff --git a/x509roots/fallback/go.mod b/x509roots/fallback/go.mod new file mode 100644 index 0000000000..5d4b07eee5 --- /dev/null +++ b/x509roots/fallback/go.mod @@ -0,0 +1,3 @@ +module golang.org/x/crypto/x509roots/fallback + +go 1.24.0 diff --git a/x509roots/gen_fallback_bundle.go b/x509roots/gen_fallback_bundle.go new file mode 100644 index 0000000000..810996cbac --- /dev/null +++ b/x509roots/gen_fallback_bundle.go @@ -0,0 +1,143 @@ +// Copyright 2023 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. + +//go:build generate + +//go:generate go run gen_fallback_bundle.go + +package main + +import ( + "bytes" + "crypto/sha256" + "flag" + "fmt" + "go/format" + "io" + "log" + "mime" + "net/http" + "os" + "sort" + "time" + + "golang.org/x/crypto/x509roots/nss" +) + +const tmpl = `// Code generated by gen_fallback_bundle.go; DO NOT EDIT. + +package bundle + +var unparsedCertificates = []unparsedCertificate{ +` + +var ( + certDataURL = flag.String("certdata-url", "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt", "URL to the raw certdata.txt file to parse (certdata-path overrides this, if provided)") + certDataPath = flag.String("certdata-path", "", "Path to the NSS certdata.txt file to parse (this overrides certdata-url, if provided)") + output = flag.String("output", "fallback/bundle/bundle.go", "Path to file to write output to") + derOutput = flag.String("deroutput", "fallback/bundle/bundle.der", "Path to file to write output to (DER certificate bundle)") +) + +func main() { + flag.Parse() + + var certdata io.Reader + + if *certDataPath != "" { + f, err := os.Open(*certDataPath) + if err != nil { + log.Fatalf("unable to open %q: %s", *certDataPath, err) + } + defer f.Close() + certdata = f + } else { + resp, err := http.Get(*certDataURL) + if err != nil { + log.Fatalf("failed to request %q: %s", *certDataURL, err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(io.LimitReader(resp.Body, 4<<10)) + log.Fatalf("got non-200 OK status code: %v body: %q", resp.Status, body) + } else if ct, want := resp.Header.Get("Content-Type"), `text/plain; charset="UTF-8"`; ct != want { + if mediaType, _, err := mime.ParseMediaType(ct); err != nil { + log.Fatalf("bad Content-Type header %q: %v", ct, err) + } else if mediaType != "text/plain" { + log.Fatalf("got media type %q, want %q", mediaType, "text/plain") + } + } + certdata = resp.Body + } + + certs, err := nss.Parse(certdata) + if err != nil { + log.Fatalf("failed to parse %q: %s", *certDataPath, err) + } + + if len(certs) == 0 { + log.Fatal("certdata.txt appears to contain zero roots") + } + + sort.Slice(certs, func(i, j int) bool { + // Sort based on the stringified subject (which may not be unique), and + // break any ties by just sorting on the raw DER (which will be unique, + // but is expensive). This should produce a stable sorting, which should + // be mostly readable by a human looking for a specific root or set of + // roots. + subjI, subjJ := certs[i].X509.Subject.String(), certs[j].X509.Subject.String() + if subjI == subjJ { + return string(certs[i].X509.Raw) < string(certs[j].X509.Raw) + } + return subjI < subjJ + }) + + rawCertsData := new(bytes.Buffer) + goSrcOut := new(bytes.Buffer) + goSrcOut.WriteString(tmpl) + for _, c := range certs { + var constraints []string + var skip bool + for _, constraint := range c.Constraints { + switch t := constraint.(type) { + case nss.DistrustAfter: + constraints = append(constraints, fmt.Sprintf("distrustAfter: \"%s\",", time.Time(t).Format(time.RFC3339))) + default: + // If we encounter any constraints we don't support, skip the certificate. + skip = true + break + } + } + if skip { + continue + } + + off := rawCertsData.Len() + rawCertsData.Write(c.X509.Raw) + + fmt.Fprintf(goSrcOut, "{\ncn: %q,\nsha256Hash: \"%x\",\ncertStartOff: %v,\ncertLength: %v,\n", + c.X509.Subject.String(), + sha256.Sum256(c.X509.Raw), + off, + len(c.X509.Raw), + ) + for _, constraint := range constraints { + fmt.Fprintln(goSrcOut, constraint) + } + fmt.Fprintln(goSrcOut, "},") + } + fmt.Fprintln(goSrcOut, "}") + + formatted, err := format.Source(goSrcOut.Bytes()) + if err != nil { + log.Fatalf("failed to format source: %s", err) + } + + if err := os.WriteFile(*output, formatted, 0644); err != nil { + log.Fatalf("failed to write to %q: %s", *output, err) + } + + if err := os.WriteFile(*derOutput, rawCertsData.Bytes(), 0644); err != nil { + log.Fatalf("failed to write to %q: %s", *output, err) + } +} diff --git a/x509roots/nss/parser.go b/x509roots/nss/parser.go new file mode 100644 index 0000000000..5c9f36a651 --- /dev/null +++ b/x509roots/nss/parser.go @@ -0,0 +1,276 @@ +// Copyright 2023 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 nss provides functionality for parsing NSS certdata.txt +// formatted certificate lists and extracting serverAuth roots. Most +// users should not use this package themselves, and should instead +// rely on the golang.org/x/crypto/x509roots/fallback package which +// calls x509.SetFallbackRoots on a pre-parsed set of roots. +package nss + +import ( + "bufio" + "bytes" + "crypto/sha1" + "crypto/x509" + "errors" + "fmt" + "io" + "strconv" + "strings" + "time" +) + +// Constraint is a constraint to be applied to a certificate or +// certificate chain. +type Constraint interface { + Kind() Kind +} + +// Kind is the constraint kind, using the NSS enumeration. +type Kind int + +const ( + CKA_NSS_SERVER_DISTRUST_AFTER Kind = iota +) + +// DistrustAfter is a Constraint that indicates a certificate has a +// CKA_NSS_SERVER_DISTRUST_AFTER constraint. This constraint defines a date +// after which any certificate issued which is rooted by the constrained +// certificate should be distrusted. +type DistrustAfter time.Time + +func (DistrustAfter) Kind() Kind { + return CKA_NSS_SERVER_DISTRUST_AFTER +} + +// A Certificate represents a single trusted serverAuth certificate in the NSS +// certdata.txt list and any constraints that should be applied to chains +// rooted by it. +type Certificate struct { + // Certificate is the parsed certificate + X509 *x509.Certificate + // Constraints contains a list of additional constraints that should be + // applied to any certificates that chain to Certificate. If there are + // any unknown constraints in the slice, Certificate should not be + // trusted. + Constraints []Constraint +} + +func parseMulitLineOctal(s *bufio.Scanner) ([]byte, error) { + buf := bytes.NewBuffer(nil) + for s.Scan() { + if s.Text() == "END" { + break + } + b, err := strconv.Unquote(fmt.Sprintf("\"%s\"", s.Text())) + if err != nil { + return nil, err + } + buf.Write([]byte(b)) + } + return buf.Bytes(), nil +} + +type certObj struct { + c *x509.Certificate + DistrustAfter *time.Time +} + +func parseCertClass(s *bufio.Scanner) ([sha1.Size]byte, *certObj, error) { + var h [sha1.Size]byte + co := &certObj{} + for s.Scan() { + l := s.Text() + if l == "" { + // assume an empty newline indicates the end of a block + break + } + if strings.HasPrefix(l, "CKA_VALUE") { + b, err := parseMulitLineOctal(s) + if err != nil { + return h, nil, err + } + co.c, err = x509.ParseCertificate(b) + if err != nil { + return h, nil, err + } + h = sha1.Sum(b) + } else if strings.HasPrefix(l, "CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE") { + // we don't want it + return h, nil, nil + } else if l == "CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL" { + dateStr, err := parseMulitLineOctal(s) + if err != nil { + return h, nil, err + } + t, err := time.Parse("060102150405Z0700", string(dateStr)) + if err != nil { + return h, nil, err + } + co.DistrustAfter = &t + } + } + if co.c == nil { + return h, nil, errors.New("malformed CKO_CERTIFICATE object") + } + return h, co, nil +} + +type trustObj struct { + trusted bool +} + +func parseTrustClass(s *bufio.Scanner) ([sha1.Size]byte, *trustObj, error) { + var h [sha1.Size]byte + to := &trustObj{trusted: false} // default to untrusted + + for s.Scan() { + l := s.Text() + if l == "" { + // assume an empty newline indicates the end of a block + break + } + if l == "CKA_CERT_SHA1_HASH MULTILINE_OCTAL" { + hash, err := parseMulitLineOctal(s) + if err != nil { + return h, nil, err + } + copy(h[:], hash) + } else if l == "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR" { + // we only care about server auth + to.trusted = true + } + } + + return h, to, nil +} + +// manualExclusions contains a map of SHA1 fingerprints of roots that we manually exclude +// from the bundle for various reasons. +var manualExclusions = map[string]bool{ + // TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 + // We exclude this root because mozilla manually constrains this root to + // issue names under .tr, but this information is only encoded in the CCADB + // IncludedCACertificateReport, in a field the format of which is + // undocumented, and is only used for this particular certificate. Rather + // than adding special parsing for this, we skip it. When code constraint + // support is available, we may also want to simply add a manual constraint, + // rather than a manual exclusion. + "3143649becce27eced3a3f0b8f0de4e891ddeeca": true, +} + +// Parse parses a NSS certdata.txt formatted file, returning only +// trusted serverAuth roots, as well as any additional constraints. This parser +// is very opinionated, only returning roots that are currently trusted for +// serverAuth. As such roots returned by this package should only be used for +// making trust decisions about serverAuth certificates, as the trust status for +// other uses is not considered. Using the roots returned by this package for +// trust decisions should be done carefully. +// +// Some roots returned by the parser may include additional constraints +// (currently only DistrustAfter) which need to be considered when verifying +// certificates which chain to them. +// +// Parse is not intended to be a general purpose parser for certdata.txt. +func Parse(r io.Reader) ([]*Certificate, error) { + // certdata.txt is a rather strange format. It is essentially a list of + // textual PKCS#11 objects, delimited by empty lines. There are two main + // types of objects, certificates (CKO_CERTIFICATE) and trust definitions + // (CKO_NSS_TRUST). These objects appear to alternate, but this ordering is + // not defined anywhere, and should probably not be relied on. A single root + // certificate requires both the certificate object and the trust definition + // object in order to be properly understood. + // + // The list contains not just serverAuth certificates, so we need to be + // careful to only extract certificates which have the serverAuth trust bit + // set. Similarly there are a number of trust related bool fields that + // appear to _always_ be CKA_TRUE, but it seems unsafe to assume this is the + // case, so we should always double check. + // + // Since we only really care about a couple of fields, this parser throws + // away a lot of information, essentially just consuming CKA_CLASS objects + // and looking for the individual fields we care about. We could write a + // significantly more complex parser, which handles the entire format, but + // it feels like that would be over engineered for the little information + // that we really care about. + + scanner := bufio.NewScanner(r) + + type nssEntry struct { + cert *certObj + trust *trustObj + } + entries := map[[sha1.Size]byte]*nssEntry{} + + for scanner.Scan() { + // scan until we hit CKA_CLASS + if !strings.HasPrefix(scanner.Text(), "CKA_CLASS") { + continue + } + + f := strings.Fields(scanner.Text()) + if len(f) != 3 { + return nil, errors.New("malformed CKA_CLASS") + } + switch f[2] { + case "CKO_CERTIFICATE": + h, co, err := parseCertClass(scanner) + if err != nil { + return nil, err + } + if co != nil { + e, ok := entries[h] + if !ok { + e = &nssEntry{} + entries[h] = e + } + e.cert = co + } + + case "CKO_NSS_TRUST": + h, to, err := parseTrustClass(scanner) + if err != nil { + return nil, err + } + if to != nil { + e, ok := entries[h] + if !ok { + e = &nssEntry{} + entries[h] = e + } + e.trust = to + } + } + } + if err := scanner.Err(); err != nil { + return nil, err + } + + var certs []*Certificate + for h, e := range entries { + if e.cert == nil && e.trust != nil { + // We may skip some certificates which are distrusted due to mozilla + // policy (CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE), which means + // we might get entries that appear to have a trust object, but no + // certificate. We can just continue on here. + continue + } else if e.cert != nil && e.trust == nil { + return nil, fmt.Errorf("missing trust object for certificate with SHA1 hash: %x", h) + } + if !e.trust.trusted { + continue + } + if manualExclusions[fmt.Sprintf("%x", h)] { + continue + } + nssCert := &Certificate{X509: e.cert.c} + if e.cert.DistrustAfter != nil { + nssCert.Constraints = append(nssCert.Constraints, DistrustAfter(*e.cert.DistrustAfter)) + } + certs = append(certs, nssCert) + } + + return certs, nil +} diff --git a/x509roots/nss/parser_test.go b/x509roots/nss/parser_test.go new file mode 100644 index 0000000000..581b02cf06 --- /dev/null +++ b/x509roots/nss/parser_test.go @@ -0,0 +1,1216 @@ +// Copyright 2023 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 nss + +import ( + "crypto/x509" + "encoding/pem" + "reflect" + "sort" + "strings" + "testing" + "time" +) + +func mustParse(b []byte) *x509.Certificate { + block, _ := pem.Decode(b) + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + panic(err) + } + return cert +} + +var testComodo = mustParse([]byte(`-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE-----`)) + +var testTrustcor = mustParse([]byte(`-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE-----`)) + +func TestParseCertData(t *testing.T) { + trustcorDistrust, err := time.Parse("060102150405Z0700", "221130000000Z") + if err != nil { + t.Fatalf("failed to parse distrust time: %s", err) + } + + for _, tc := range []struct { + name string + data string + output []*Certificate + err string + }{ + { + name: "valid certs", + data: validCertdata, + output: []*Certificate{ + &Certificate{X509: testComodo}, + &Certificate{X509: testTrustcor, Constraints: []Constraint{DistrustAfter(trustcorDistrust)}}, + }, + }, + { + name: "cert obj, no trust obj", + data: certNoTrust, + err: "missing trust object for certificate with SHA1 hash: d1eb23a46d17d68fd92564c2f1f1601764d8e349", + }, + { + name: "trust obj, no cert obj", + data: trustNoCert, + }, + { + name: "missing certificate der", + data: missingCertificateOctal, + err: "malformed CKO_CERTIFICATE object", + }, + { + name: "untrusted cert (cert)", + data: untrustedCertCert, + }, + { + name: "untrusted cert (trust)", + data: untrustedCertTrust, + }, + { + name: "malformed class", + data: malformedClass, + err: "malformed CKA_CLASS", + }, + { + name: "malformed cert octal", + data: malformedOctalCert, + err: "invalid syntax", + }, + { + name: "malformed hash octal", + data: malformedOctalhash, + err: "invalid syntax", + }, + { + name: "malformed distrust octal", + data: malformedOctalDistrust, + err: "invalid syntax", + }, + } { + t.Run(tc.name, func(t *testing.T) { + r := strings.NewReader(tc.data) + nc, err := Parse(r) + if err != nil { + if tc.err == "" { + t.Fatalf("unexpected error: %s", err) + } else if tc.err != err.Error() { + t.Fatalf("unexpected error: want %q, got %q", tc.err, err) + } + } else if tc.err != "" { + t.Fatal("expected error, got nil") + } + + if len(tc.output) != len(nc) { + t.Fatalf("unexpected number of parsed certs: want %d, got %d", len(tc.output), len(nc)) + } + + // sort so we can check equality + sort.Slice(nc, func(i, j int) bool { + return nc[i].X509.Subject.String() < nc[j].X509.Subject.String() + }) + + if !reflect.DeepEqual(tc.output, nc) { + t.Fatal("unexpected results") + } + }) + } +} + +const validCertdata = `# +# Certificate "Comodo AAA Services root" +# +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 +\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 +\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 +\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 +\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 +\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 +\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 +\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 +\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 +\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 +\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 +\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 +\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 +\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 +\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 +\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 +\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 +\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 +\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 +\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 +\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 +\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 +\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 +\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 +\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 +\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 +\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 +\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 +\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 +\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 +\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 +\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 +\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 +\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 +\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 +\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 +\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 +\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 +\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 +\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 +\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 +\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 +\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 +\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 +\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 +\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 +\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 +\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 +\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 +\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 +\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 +\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 +\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 +\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 +\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 +\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 +\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 +\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 +\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 +\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 +\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 +\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 +\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 +\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 +\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 +\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 +\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 +\225\351\066\226\230\156 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "Comodo AAA Services root" +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 +\144\330\343\111 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 +END +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "TrustCor RootCert CA-2" +# +# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA +# Serial Number:25:a1:df:ca:33:cb:59:02 +# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA +# Not Valid Before: Thu Feb 04 12:32:23 2016 +# Not Valid After : Sun Dec 31 17:26:39 2034 +# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 +# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustCor RootCert CA-2" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 +\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 +\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 +\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 +\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 +\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 +\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 +\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 +\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 +\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 +\162\164\040\103\101\055\062 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 +\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 +\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 +\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 +\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 +\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 +\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 +\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 +\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 +\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 +\162\164\040\103\101\055\062 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\010\045\241\337\312\063\313\131\002 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\006\057\060\202\004\027\240\003\002\001\002\002\010\045 +\241\337\312\063\313\131\002\060\015\006\011\052\206\110\206\367 +\015\001\001\013\005\000\060\201\244\061\013\060\011\006\003\125 +\004\006\023\002\120\101\061\017\060\015\006\003\125\004\010\014 +\006\120\141\156\141\155\141\061\024\060\022\006\003\125\004\007 +\014\013\120\141\156\141\155\141\040\103\151\164\171\061\044\060 +\042\006\003\125\004\012\014\033\124\162\165\163\164\103\157\162 +\040\123\171\163\164\145\155\163\040\123\056\040\144\145\040\122 +\056\114\056\061\047\060\045\006\003\125\004\013\014\036\124\162 +\165\163\164\103\157\162\040\103\145\162\164\151\146\151\143\141 +\164\145\040\101\165\164\150\157\162\151\164\171\061\037\060\035 +\006\003\125\004\003\014\026\124\162\165\163\164\103\157\162\040 +\122\157\157\164\103\145\162\164\040\103\101\055\062\060\036\027 +\015\061\066\060\062\060\064\061\062\063\062\062\063\132\027\015 +\063\064\061\062\063\061\061\067\062\066\063\071\132\060\201\244 +\061\013\060\011\006\003\125\004\006\023\002\120\101\061\017\060 +\015\006\003\125\004\010\014\006\120\141\156\141\155\141\061\024 +\060\022\006\003\125\004\007\014\013\120\141\156\141\155\141\040 +\103\151\164\171\061\044\060\042\006\003\125\004\012\014\033\124 +\162\165\163\164\103\157\162\040\123\171\163\164\145\155\163\040 +\123\056\040\144\145\040\122\056\114\056\061\047\060\045\006\003 +\125\004\013\014\036\124\162\165\163\164\103\157\162\040\103\145 +\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157\162 +\151\164\171\061\037\060\035\006\003\125\004\003\014\026\124\162 +\165\163\164\103\157\162\040\122\157\157\164\103\145\162\164\040 +\103\101\055\062\060\202\002\042\060\015\006\011\052\206\110\206 +\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 +\002\202\002\001\000\247\040\156\302\052\242\142\044\225\220\166 +\310\070\176\200\322\253\301\233\145\005\224\364\301\012\020\325 +\002\254\355\237\223\307\207\310\260\047\053\102\014\075\012\076 +\101\132\236\165\335\215\312\340\233\354\150\062\244\151\222\150 +\214\013\201\016\126\240\076\032\335\054\045\024\202\057\227\323 +\144\106\364\124\251\334\072\124\055\061\053\231\202\362\331\052 +\327\357\161\000\270\061\244\276\172\044\007\303\102\040\362\212 +\324\222\004\033\145\126\114\154\324\373\266\141\132\107\043\264 +\330\151\264\267\072\320\164\074\014\165\241\214\116\166\241\351 +\333\052\245\073\372\316\260\377\176\152\050\375\047\034\310\261 +\351\051\361\127\156\144\264\320\301\025\155\016\276\056\016\106 +\310\136\364\121\376\357\016\143\072\073\161\272\317\157\131\312 +\014\343\233\135\111\270\114\342\127\261\230\212\102\127\234\166 +\357\357\275\321\150\250\322\364\011\273\167\065\276\045\202\010 +\304\026\054\104\040\126\251\104\021\167\357\135\264\035\252\136 +\153\076\213\062\366\007\057\127\004\222\312\365\376\235\302\351 +\350\263\216\114\113\002\061\331\344\074\110\202\047\367\030\202 +\166\110\072\161\261\023\241\071\325\056\305\064\302\035\142\205 +\337\003\376\115\364\257\075\337\134\133\215\372\160\341\245\176 +\047\307\206\056\152\217\022\306\204\136\103\121\120\234\031\233 +\170\346\374\366\355\107\176\173\075\146\357\023\023\210\137\074 +\241\143\373\371\254\207\065\237\363\202\236\244\077\012\234\061 +\151\213\231\244\210\112\216\156\146\115\357\026\304\017\171\050 +\041\140\015\205\026\175\327\124\070\361\222\126\375\265\063\114 +\203\334\327\020\237\113\375\306\370\102\275\272\174\163\002\340 +\377\175\315\133\341\324\254\141\173\127\325\112\173\133\324\205 +\130\047\135\277\370\053\140\254\240\046\256\024\041\047\306\167 +\232\063\200\074\136\106\077\367\303\261\243\206\063\306\350\136 +\015\271\065\054\252\106\301\205\002\165\200\240\353\044\373\025 +\252\344\147\177\156\167\077\364\004\212\057\174\173\343\027\141 +\360\335\011\251\040\310\276\011\244\320\176\104\303\262\060\112 +\070\252\251\354\030\232\007\202\053\333\270\234\030\255\332\340 +\106\027\254\317\135\002\003\001\000\001\243\143\060\141\060\035 +\006\003\125\035\016\004\026\004\024\331\376\041\100\156\224\236 +\274\233\075\234\175\230\040\031\345\214\060\142\262\060\037\006 +\003\125\035\043\004\030\060\026\200\024\331\376\041\100\156\224 +\236\274\233\075\234\175\230\040\031\345\214\060\142\262\060\017 +\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 +\016\006\003\125\035\017\001\001\377\004\004\003\002\001\206\060 +\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 +\002\001\000\236\105\236\014\073\266\357\341\072\310\174\321\000 +\075\317\342\352\006\265\262\072\273\006\113\150\172\320\043\227 +\164\247\054\360\010\330\171\132\327\132\204\212\330\022\232\033 +\331\175\134\115\160\305\245\371\253\345\243\211\211\335\001\372 +\354\335\371\351\222\227\333\260\106\102\363\323\142\252\225\376 +\061\147\024\151\130\220\012\252\013\356\067\043\307\120\121\264 +\365\176\236\343\173\367\344\314\102\062\055\111\014\313\377\111 +\014\233\036\064\375\156\156\226\212\171\003\266\157\333\011\313 +\375\137\145\024\067\341\070\365\363\141\026\130\344\265\155\015 +\013\004\033\077\120\055\177\263\307\172\032\026\200\140\370\212 +\037\351\033\052\306\371\272\001\032\151\277\322\130\307\124\127 +\010\217\341\071\140\167\113\254\131\204\032\210\361\335\313\117 +\170\327\347\341\063\055\374\356\101\372\040\260\276\313\367\070 +\224\300\341\320\205\017\273\355\054\163\253\355\376\222\166\032 +\144\177\133\015\063\011\007\063\173\006\077\021\244\134\160\074 +\205\300\317\343\220\250\203\167\372\333\346\305\214\150\147\020 +\147\245\122\055\360\304\231\217\177\277\321\153\342\265\107\326 +\331\320\205\231\115\224\233\017\113\215\356\000\132\107\035\021 +\003\254\101\030\257\207\267\157\014\072\217\312\317\334\003\301 +\242\011\310\345\375\200\136\310\140\102\001\033\032\123\132\273 +\067\246\267\274\272\204\351\036\154\032\324\144\332\324\103\376 +\223\213\113\362\054\171\026\020\324\223\013\210\217\241\330\206 +\024\106\221\107\233\050\044\357\127\122\116\134\102\234\252\367 +\111\354\047\350\100\036\263\246\211\042\162\234\365\015\063\264 +\130\243\060\073\335\324\152\124\223\276\032\115\363\223\224\367 +\374\204\013\077\204\040\134\064\003\104\305\332\255\274\012\301 +\002\317\036\345\224\331\363\216\133\330\114\360\235\354\141\027 +\273\024\062\124\014\002\051\223\036\222\206\366\177\357\347\222 +\005\016\131\335\231\010\056\056\372\234\000\122\323\305\146\051 +\344\247\227\104\244\016\050\201\023\065\305\366\157\144\346\101 +\304\325\057\314\064\105\045\317\101\000\226\075\112\056\302\226 +\230\117\116\112\234\227\267\333\037\222\062\310\377\017\121\156 +\326\354\011 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +# For Server Distrust After: Wed Nov 30 00:00:00 2022 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\062\061\061\063\060\060\060\060\060\060\060\132 +END +# For Email Distrust After: Wed Nov 30 00:00:00 2022 +CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL +\062\062\061\061\063\060\060\060\060\060\060\060\132 +END + + +# Trust for "TrustCor RootCert CA-2" +# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA +# Serial Number:25:a1:df:ca:33:cb:59:02 +# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA +# Not Valid Before: Thu Feb 04 12:32:23 2016 +# Not Valid After : Sun Dec 31 17:26:39 2034 +# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 +# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustCor RootCert CA-2" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\270\276\155\313\126\361\125\271\143\324\022\312\116\006\064\307 +\224\262\034\300 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\242\341\370\030\013\272\105\325\307\101\052\273\067\122\105\144 +END +CKA_ISSUER MULTILINE_OCTAL +\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 +\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 +\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 +\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 +\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 +\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 +\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 +\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 +\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 +\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 +\162\164\040\103\101\055\062 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\010\045\241\337\312\063\313\131\002 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +` + +const trustNoCert = `CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 +\144\330\343\111 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 +END +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` + +const certNoTrust = `CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 +\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 +\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 +\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 +\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 +\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 +\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 +\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 +\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 +\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 +\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 +\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 +\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 +\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 +\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 +\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 +\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 +\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 +\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 +\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 +\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 +\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 +\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 +\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 +\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 +\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 +\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 +\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 +\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 +\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 +\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 +\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 +\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 +\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 +\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 +\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 +\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 +\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 +\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 +\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 +\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 +\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 +\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 +\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 +\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 +\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 +\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 +\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 +\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 +\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 +\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 +\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 +\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 +\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 +\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 +\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 +\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 +\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 +\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 +\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 +\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 +\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 +\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 +\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 +\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 +\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 +\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 +\225\351\066\226\230\156 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE` + +const missingCertificateOctal = `CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE` + +const untrustedCertCert = `# +# Certificate "Comodo AAA Services root" +# +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 +\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 +\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 +\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 +\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 +\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 +\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 +\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 +\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 +\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 +\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 +\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 +\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 +\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 +\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 +\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 +\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 +\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 +\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 +\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 +\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 +\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 +\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 +\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 +\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 +\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 +\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 +\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 +\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 +\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 +\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 +\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 +\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 +\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 +\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 +\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 +\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 +\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 +\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 +\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 +\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 +\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 +\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 +\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 +\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 +\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 +\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 +\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 +\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 +\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 +\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 +\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 +\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 +\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 +\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 +\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 +\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 +\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 +\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 +\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 +\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 +\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 +\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 +\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 +\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 +\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 +\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 +\225\351\066\226\230\156 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "Comodo AAA Services root" +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 +\144\330\343\111 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 +END +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` + +const untrustedCertTrust = `# +# Certificate "Comodo AAA Services root" +# +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 +\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 +\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 +\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 +\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 +\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 +\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 +\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 +\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 +\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 +\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 +\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 +\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 +\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 +\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 +\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 +\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 +\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 +\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 +\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 +\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 +\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 +\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 +\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 +\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 +\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 +\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 +\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 +\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 +\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 +\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 +\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 +\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 +\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 +\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 +\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 +\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 +\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 +\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 +\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 +\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 +\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 +\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 +\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 +\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 +\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 +\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 +\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 +\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 +\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 +\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 +\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 +\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 +\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 +\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 +\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 +\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 +\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 +\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 +\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 +\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 +\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 +\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 +\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 +\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 +\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 +\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 +\225\351\066\226\230\156 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "Comodo AAA Services root" +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 +\144\330\343\111 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 +END +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_TRUST_SERVER_AUTH CK_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` + +const malformedClass = `CKA_CLASS` + +const malformedOctalCert = `# +# Certificate "Comodo AAA Services root" +# +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_VALUE MULTILINE_OCTAL +hello\xxxxxxx +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE` + +const malformedOctalhash = `# Trust for "Comodo AAA Services root" +# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Serial Number: 1 (0x1) +# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB +# Not Valid Before: Thu Jan 01 00:00:00 2004 +# Not Valid After : Sun Dec 31 23:59:59 2028 +# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 +# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Comodo AAA Services root" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\xxxxx +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 +END +CKA_ISSUER MULTILINE_OCTAL +\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 +\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 +\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 +\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 +\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 +\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 +\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 +\143\141\164\145\040\123\145\162\166\151\143\145\163 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\001\001 +END +CKA_TRUST_SERVER_AUTH CK_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` + +const malformedOctalDistrust = `# +# Certificate "TrustCor RootCert CA-2" +# +# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA +# Serial Number:25:a1:df:ca:33:cb:59:02 +# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA +# Not Valid Before: Thu Feb 04 12:32:23 2016 +# Not Valid After : Sun Dec 31 17:26:39 2034 +# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 +# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustCor RootCert CA-2" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 +\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 +\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 +\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 +\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 +\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 +\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 +\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 +\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 +\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 +\162\164\040\103\101\055\062 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 +\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 +\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 +\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 +\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 +\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 +\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 +\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 +\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 +\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 +\162\164\040\103\101\055\062 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\010\045\241\337\312\063\313\131\002 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\006\057\060\202\004\027\240\003\002\001\002\002\010\045 +\241\337\312\063\313\131\002\060\015\006\011\052\206\110\206\367 +\015\001\001\013\005\000\060\201\244\061\013\060\011\006\003\125 +\004\006\023\002\120\101\061\017\060\015\006\003\125\004\010\014 +\006\120\141\156\141\155\141\061\024\060\022\006\003\125\004\007 +\014\013\120\141\156\141\155\141\040\103\151\164\171\061\044\060 +\042\006\003\125\004\012\014\033\124\162\165\163\164\103\157\162 +\040\123\171\163\164\145\155\163\040\123\056\040\144\145\040\122 +\056\114\056\061\047\060\045\006\003\125\004\013\014\036\124\162 +\165\163\164\103\157\162\040\103\145\162\164\151\146\151\143\141 +\164\145\040\101\165\164\150\157\162\151\164\171\061\037\060\035 +\006\003\125\004\003\014\026\124\162\165\163\164\103\157\162\040 +\122\157\157\164\103\145\162\164\040\103\101\055\062\060\036\027 +\015\061\066\060\062\060\064\061\062\063\062\062\063\132\027\015 +\063\064\061\062\063\061\061\067\062\066\063\071\132\060\201\244 +\061\013\060\011\006\003\125\004\006\023\002\120\101\061\017\060 +\015\006\003\125\004\010\014\006\120\141\156\141\155\141\061\024 +\060\022\006\003\125\004\007\014\013\120\141\156\141\155\141\040 +\103\151\164\171\061\044\060\042\006\003\125\004\012\014\033\124 +\162\165\163\164\103\157\162\040\123\171\163\164\145\155\163\040 +\123\056\040\144\145\040\122\056\114\056\061\047\060\045\006\003 +\125\004\013\014\036\124\162\165\163\164\103\157\162\040\103\145 +\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157\162 +\151\164\171\061\037\060\035\006\003\125\004\003\014\026\124\162 +\165\163\164\103\157\162\040\122\157\157\164\103\145\162\164\040 +\103\101\055\062\060\202\002\042\060\015\006\011\052\206\110\206 +\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 +\002\202\002\001\000\247\040\156\302\052\242\142\044\225\220\166 +\310\070\176\200\322\253\301\233\145\005\224\364\301\012\020\325 +\002\254\355\237\223\307\207\310\260\047\053\102\014\075\012\076 +\101\132\236\165\335\215\312\340\233\354\150\062\244\151\222\150 +\214\013\201\016\126\240\076\032\335\054\045\024\202\057\227\323 +\144\106\364\124\251\334\072\124\055\061\053\231\202\362\331\052 +\327\357\161\000\270\061\244\276\172\044\007\303\102\040\362\212 +\324\222\004\033\145\126\114\154\324\373\266\141\132\107\043\264 +\330\151\264\267\072\320\164\074\014\165\241\214\116\166\241\351 +\333\052\245\073\372\316\260\377\176\152\050\375\047\034\310\261 +\351\051\361\127\156\144\264\320\301\025\155\016\276\056\016\106 +\310\136\364\121\376\357\016\143\072\073\161\272\317\157\131\312 +\014\343\233\135\111\270\114\342\127\261\230\212\102\127\234\166 +\357\357\275\321\150\250\322\364\011\273\167\065\276\045\202\010 +\304\026\054\104\040\126\251\104\021\167\357\135\264\035\252\136 +\153\076\213\062\366\007\057\127\004\222\312\365\376\235\302\351 +\350\263\216\114\113\002\061\331\344\074\110\202\047\367\030\202 +\166\110\072\161\261\023\241\071\325\056\305\064\302\035\142\205 +\337\003\376\115\364\257\075\337\134\133\215\372\160\341\245\176 +\047\307\206\056\152\217\022\306\204\136\103\121\120\234\031\233 +\170\346\374\366\355\107\176\173\075\146\357\023\023\210\137\074 +\241\143\373\371\254\207\065\237\363\202\236\244\077\012\234\061 +\151\213\231\244\210\112\216\156\146\115\357\026\304\017\171\050 +\041\140\015\205\026\175\327\124\070\361\222\126\375\265\063\114 +\203\334\327\020\237\113\375\306\370\102\275\272\174\163\002\340 +\377\175\315\133\341\324\254\141\173\127\325\112\173\133\324\205 +\130\047\135\277\370\053\140\254\240\046\256\024\041\047\306\167 +\232\063\200\074\136\106\077\367\303\261\243\206\063\306\350\136 +\015\271\065\054\252\106\301\205\002\165\200\240\353\044\373\025 +\252\344\147\177\156\167\077\364\004\212\057\174\173\343\027\141 +\360\335\011\251\040\310\276\011\244\320\176\104\303\262\060\112 +\070\252\251\354\030\232\007\202\053\333\270\234\030\255\332\340 +\106\027\254\317\135\002\003\001\000\001\243\143\060\141\060\035 +\006\003\125\035\016\004\026\004\024\331\376\041\100\156\224\236 +\274\233\075\234\175\230\040\031\345\214\060\142\262\060\037\006 +\003\125\035\043\004\030\060\026\200\024\331\376\041\100\156\224 +\236\274\233\075\234\175\230\040\031\345\214\060\142\262\060\017 +\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 +\016\006\003\125\035\017\001\001\377\004\004\003\002\001\206\060 +\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 +\002\001\000\236\105\236\014\073\266\357\341\072\310\174\321\000 +\075\317\342\352\006\265\262\072\273\006\113\150\172\320\043\227 +\164\247\054\360\010\330\171\132\327\132\204\212\330\022\232\033 +\331\175\134\115\160\305\245\371\253\345\243\211\211\335\001\372 +\354\335\371\351\222\227\333\260\106\102\363\323\142\252\225\376 +\061\147\024\151\130\220\012\252\013\356\067\043\307\120\121\264 +\365\176\236\343\173\367\344\314\102\062\055\111\014\313\377\111 +\014\233\036\064\375\156\156\226\212\171\003\266\157\333\011\313 +\375\137\145\024\067\341\070\365\363\141\026\130\344\265\155\015 +\013\004\033\077\120\055\177\263\307\172\032\026\200\140\370\212 +\037\351\033\052\306\371\272\001\032\151\277\322\130\307\124\127 +\010\217\341\071\140\167\113\254\131\204\032\210\361\335\313\117 +\170\327\347\341\063\055\374\356\101\372\040\260\276\313\367\070 +\224\300\341\320\205\017\273\355\054\163\253\355\376\222\166\032 +\144\177\133\015\063\011\007\063\173\006\077\021\244\134\160\074 +\205\300\317\343\220\250\203\167\372\333\346\305\214\150\147\020 +\147\245\122\055\360\304\231\217\177\277\321\153\342\265\107\326 +\331\320\205\231\115\224\233\017\113\215\356\000\132\107\035\021 +\003\254\101\030\257\207\267\157\014\072\217\312\317\334\003\301 +\242\011\310\345\375\200\136\310\140\102\001\033\032\123\132\273 +\067\246\267\274\272\204\351\036\154\032\324\144\332\324\103\376 +\223\213\113\362\054\171\026\020\324\223\013\210\217\241\330\206 +\024\106\221\107\233\050\044\357\127\122\116\134\102\234\252\367 +\111\354\047\350\100\036\263\246\211\042\162\234\365\015\063\264 +\130\243\060\073\335\324\152\124\223\276\032\115\363\223\224\367 +\374\204\013\077\204\040\134\064\003\104\305\332\255\274\012\301 +\002\317\036\345\224\331\363\216\133\330\114\360\235\354\141\027 +\273\024\062\124\014\002\051\223\036\222\206\366\177\357\347\222 +\005\016\131\335\231\010\056\056\372\234\000\122\323\305\146\051 +\344\247\227\104\244\016\050\201\023\065\305\366\157\144\346\101 +\304\325\057\314\064\105\045\317\101\000\226\075\112\056\302\226 +\230\117\116\112\234\227\267\333\037\222\062\310\377\017\121\156 +\326\354\011 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +# For Server Distrust After: Wed Nov 30 00:00:00 2022 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\xxxxxxxx +END +# For Email Distrust After: Wed Nov 30 00:00:00 2022 +CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL +\062\062\061\061\063\060\060\060\060\060\060\060\132 +END` diff --git a/xtea/cipher.go b/xtea/cipher.go index a4c2fd02b3..7b4f8aaa6b 100644 --- a/xtea/cipher.go +++ b/xtea/cipher.go @@ -12,7 +12,7 @@ // Deprecated: any new system should use AES (from crypto/aes, if necessary in // an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from // golang.org/x/crypto/chacha20poly1305). -package xtea // import "golang.org/x/crypto/xtea" +package xtea // For details, see http://www.cix.co.uk/~klockstone/xtea.pdf diff --git a/xts/xts.go b/xts/xts.go index b51308e95e..6a73020207 100644 --- a/xts/xts.go +++ b/xts/xts.go @@ -21,7 +21,11 @@ // // Note that XTS is usually not appropriate for any use besides disk encryption. // Most users should use an AEAD mode like GCM (from crypto/cipher.NewGCM) instead. -package xts // import "golang.org/x/crypto/xts" +// +// The xts package is [frozen] and is not accepting new features. +// +// [frozen]: https://go.dev/wiki/Frozen +package xts import ( "crypto/cipher" @@ -29,7 +33,7 @@ import ( "errors" "sync" - "golang.org/x/crypto/internal/subtle" + "golang.org/x/crypto/internal/alias" ) // Cipher contains an expanded key structure. It is safe for concurrent use if @@ -75,7 +79,7 @@ func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { if len(plaintext)%blockSize != 0 { panic("xts: plaintext is not a multiple of the block size") } - if subtle.InexactOverlap(ciphertext[:len(plaintext)], plaintext) { + if alias.InexactOverlap(ciphertext[:len(plaintext)], plaintext) { panic("xts: invalid buffer overlap") } @@ -114,7 +118,7 @@ func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { if len(ciphertext)%blockSize != 0 { panic("xts: ciphertext is not a multiple of the block size") } - if subtle.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) { + if alias.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) { panic("xts: invalid buffer overlap") }