This commit is contained in:
MXi4oyu 2019-05-17 19:29:43 +08:00
commit 809362e16e
900 changed files with 185840 additions and 65920 deletions

View File

@ -128,11 +128,15 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
return *c.dir, nil
}
<<<<<<< HEAD
dirURL := c.DirectoryURL
if dirURL == "" {
dirURL = LetsEncryptURL
}
res, err := c.get(ctx, dirURL, wantStatus(http.StatusOK))
=======
res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK))
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if err != nil {
return Directory{}, err
}
@ -165,6 +169,13 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
return *c.dir, nil
}
func (c *Client) directoryURL() string {
if c.DirectoryURL != "" {
return c.DirectoryURL
}
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.
@ -323,6 +334,20 @@ func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
// a valid authorization (Authorization.Status is StatusValid). If so, the caller
// need not fulfill any challenge and can proceed to requesting a certificate.
func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
return c.authorize(ctx, "dns", domain)
}
// AuthorizeIP is the same as Authorize but requests IP address authorization.
// Clients which successfully obtain such authorization may request to issue
// a certificate for IP addresses.
//
// See the ACME spec extension for more details about IP address identifiers:
// https://tools.ietf.org/html/draft-ietf-acme-ip.
func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) {
return c.authorize(ctx, "ip", ipaddr)
}
func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) {
if _, err := c.Discover(ctx); err != nil {
return nil, err
}
@ -336,7 +361,7 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
Identifier authzID `json:"identifier"`
}{
Resource: "new-authz",
Identifier: authzID{Type: "dns", Value: domain},
Identifier: authzID{Type: typ, Value: val},
}
res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
if err != nil {
@ -697,12 +722,18 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
}
// popNonce returns a nonce value previously stored with c.addNonce
// or fetches a fresh one from the given URL.
// or fetches a fresh one from a URL by issuing a HEAD request.
// It first tries c.directoryURL() and then the provided url if the former fails.
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
c.noncesMu.Lock()
defer c.noncesMu.Unlock()
if len(c.nonces) == 0 {
return c.fetchNonce(ctx, url)
dirURL := c.directoryURL()
v, err := c.fetchNonce(ctx, dirURL)
if err != nil && url != dirURL {
v, err = c.fetchNonce(ctx, url)
}
return v, err
}
var nonce string
for nonce = range c.nonces {

View File

@ -75,6 +75,10 @@ func TestDiscover(t *testing.T) {
)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
<<<<<<< HEAD
=======
w.Header().Set("Replay-Nonce", "testnonce")
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
fmt.Fprintf(w, `{
"new-reg": %q,
"new-authz": %q,
@ -100,6 +104,9 @@ func TestDiscover(t *testing.T) {
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) {
@ -147,7 +154,11 @@ func TestRegister(t *testing.T) {
return false
}
c := Client{Key: testKeyEC, dir: &Directory{RegURL: ts.URL}}
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 {
@ -288,6 +299,7 @@ func TestGetReg(t *testing.T) {
}
func TestAuthorize(t *testing.T) {
<<<<<<< HEAD
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.Header().Set("Replay-Nonce", "test-nonce")
@ -296,73 +308,117 @@ func TestAuthorize(t *testing.T) {
if r.Method != "POST" {
t.Errorf("r.Method = %q; want POST", r.Method)
}
var j struct {
Resource string
Identifier struct {
Type string
Value string
}
}
decodeJWSRequest(t, &j, r)
// Test request
if j.Resource != "new-authz" {
t.Errorf("j.Resource = %q; want new-authz", j.Resource)
}
if j.Identifier.Type != "dns" {
t.Errorf("j.Identifier.Type = %q; want dns", j.Identifier.Type)
}
if j.Identifier.Value != "example.com" {
t.Errorf("j.Identifier.Value = %q; want example.com", j.Identifier.Value)
}
w.Header().Set("Location", "https://ca.tld/acme/auth/1")
w.WriteHeader(http.StatusCreated)
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"
=======
tt := []struct{ typ, value string }{
{"dns", "example.com"},
{"ip", "1.2.3.4"},
}
for _, test := range tt {
t.Run(test.typ, func(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
}
],
"combinations":[[0],[1]]}`)
}))
defer ts.Close()
if r.Method != "POST" {
t.Errorf("r.Method = %q; want POST", r.Method)
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
cl := Client{Key: testKeyEC, dir: &Directory{AuthzURL: ts.URL}}
auth, err := cl.Authorize(context.Background(), "example.com")
if err != nil {
t.Fatal(err)
}
var j struct {
Resource string
Identifier struct {
Type string
Value string
}
}
decodeJWSRequest(t, &j, r)
if auth.URI != "https://ca.tld/acme/auth/1" {
t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI)
}
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)
}
// Test request
if j.Resource != "new-authz" {
t.Errorf("j.Resource = %q; want new-authz", j.Resource)
}
if j.Identifier.Type != test.typ {
t.Errorf("j.Identifier.Type = %q; want %q", j.Identifier.Type, test.typ)
}
if j.Identifier.Value != test.value {
t.Errorf("j.Identifier.Value = %q; want %q", j.Identifier.Value, test.value)
}
if n := len(auth.Challenges); n != 2 {
t.Fatalf("len(auth.Challenges) = %d; want 2", n)
}
w.Header().Set("Location", "https://ca.tld/acme/auth/1")
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, `{
"identifier": {"type":%q,"value":%q},
"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]]
}`, test.typ, test.value)
}))
defer ts.Close()
var (
auth *Authorization
err error
)
cl := Client{
Key: testKeyEC,
DirectoryURL: ts.URL,
dir: &Directory{AuthzURL: ts.URL},
}
switch test.typ {
case "dns":
auth, err = cl.Authorize(context.Background(), test.value)
case "ip":
auth, err = cl.AuthorizeIP(context.Background(), test.value)
default:
t.Fatalf("unknown identifier type: %q", test.typ)
}
if err != nil {
t.Fatal(err)
}
if auth.URI != "https://ca.tld/acme/auth/1" {
t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI)
}
if auth.Status != "pending" {
t.Errorf("Status = %q; want pending", auth.Status)
}
if auth.Identifier.Type != test.typ {
t.Errorf("Identifier.Type = %q; want %q", auth.Identifier.Type, test.typ)
}
if auth.Identifier.Value != test.value {
t.Errorf("Identifier.Value = %q; want %q", auth.Identifier.Value, test.value)
}
if n := len(auth.Challenges); n != 2 {
t.Fatalf("len(auth.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)
}
<<<<<<< HEAD
c := auth.Challenges[0]
if c.Type != "http-01" {
t.Errorf("c.Type = %q; want http-01", c.Type)
@ -384,10 +440,25 @@ func TestAuthorize(t *testing.T) {
if c.Token != "token2" {
t.Errorf("c.Token = %q; want token2", 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 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)
combs := [][]int{{0}, {1}}
if !reflect.DeepEqual(auth.Combinations, combs) {
t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
})
}
}
@ -401,7 +472,11 @@ func TestAuthorizeValid(t *testing.T) {
w.Write([]byte(`{"status":"valid"}`))
}))
defer ts.Close()
client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
client := Client{
Key: testKey,
DirectoryURL: ts.URL,
dir: &Directory{AuthzURL: ts.URL},
}
_, err := client.Authorize(context.Background(), "example.com")
if err != nil {
t.Errorf("err = %v", err)
@ -501,6 +576,7 @@ func TestWaitAuthorization(t *testing.T) {
}
if authz == nil {
t.Fatal("authz is nil")
<<<<<<< HEAD
}
})
t.Run("invalid status", func(t *testing.T) {
@ -524,6 +600,31 @@ func TestWaitAuthorization(t *testing.T) {
t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code)
}
})
=======
}
})
t.Run("invalid status", func(t *testing.T) {
_, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"status":"invalid"}`)
})
if _, ok := err.(*AuthorizationError); !ok {
t.Errorf("err is %v (%T); want non-nil *AuthorizationError", err, err)
}
})
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) {
w.WriteHeader(code)
})
res, ok := err.(*Error)
if !ok {
t.Fatalf("err is %v (%T); want a non-nil *Error", err, err)
}
if res.StatusCode != code {
t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code)
}
})
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
for _, code := range []int{http.StatusTooManyRequests, http.StatusInternalServerError} {
t.Run(fmt.Sprintf("retriable %d error", code), func(t *testing.T) {
var count int
@ -1016,6 +1117,53 @@ func TestNonce_fetchError(t *testing.T) {
}
}
func TestNonce_popWhenEmpty(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "HEAD" {
t.Errorf("r.Method = %q; want HEAD", r.Method)
}
switch r.URL.Path {
case "/dir-with-nonce":
w.Header().Set("Replay-Nonce", "dirnonce")
case "/new-nonce":
w.Header().Set("Replay-Nonce", "newnonce")
case "/dir-no-nonce", "/empty":
// No nonce in the header.
default:
t.Errorf("Unknown URL: %s", r.URL)
}
}))
defer ts.Close()
ctx := context.Background()
tt := []struct {
dirURL, popURL, nonce string
wantOK bool
}{
{ts.URL + "/dir-with-nonce", ts.URL + "/new-nonce", "dirnonce", true},
{ts.URL + "/dir-no-nonce", ts.URL + "/new-nonce", "newnonce", true},
{ts.URL + "/dir-no-nonce", ts.URL + "/empty", "", false},
}
for _, test := range tt {
t.Run(fmt.Sprintf("nonce:%s wantOK:%v", test.nonce, test.wantOK), func(t *testing.T) {
c := Client{DirectoryURL: test.dirURL}
v, err := c.popNonce(ctx, test.popURL)
if !test.wantOK {
if err == nil {
t.Fatalf("c.popNonce(%q) returned nil error", test.popURL)
}
return
}
if err != nil {
t.Fatalf("c.popNonce(%q): %v", test.popURL, err)
}
if v != test.nonce {
t.Errorf("c.popNonce(%q) = %q; want %q", test.popURL, v, test.nonce)
}
})
}
}
func TestNonce_postJWS(t *testing.T) {
var count int
seen := make(map[string]bool)
@ -1049,7 +1197,11 @@ func TestNonce_postJWS(t *testing.T) {
}))
defer ts.Close()
client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
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)
}

View File

@ -32,6 +32,7 @@ import (
"time"
"golang.org/x/crypto/acme"
"golang.org/x/net/idna"
)
// createCertRetryAfter is how much time to wait before removing a failed state
@ -62,10 +63,16 @@ type HostPolicy func(ctx context.Context, host string) error
// HostWhitelist returns a policy where only the specified host names are allowed.
// Only exact matches are currently supported. Subdomains, regexp or wildcard
// will not match.
//
// Note that all hosts will be converted to Punycode via idna.Lookup.ToASCII so that
// Manager.GetCertificate can handle the Unicode IDN and mixedcase hosts correctly.
// Invalid hosts will be silently ignored.
func HostWhitelist(hosts ...string) HostPolicy {
whitelist := make(map[string]bool, len(hosts))
for _, h := range hosts {
whitelist[h] = true
if h, err := idna.Lookup.ToASCII(h); err == nil {
whitelist[h] = true
}
}
return func(_ context.Context, host string) error {
if !whitelist[host] {
@ -243,7 +250,21 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
if !strings.Contains(strings.Trim(name, "."), ".") {
return nil, errors.New("acme/autocert: server name component count invalid")
}
<<<<<<< HEAD
if strings.ContainsAny(name, `+/\`) {
=======
// Note that this conversion is necessary because some server names in the handshakes
// started by some clients (such as cURL) are not converted to Punycode, which will
// prevent us from obtaining certificates for them. In addition, we should also treat
// example.com and EXAMPLE.COM as equivalent and return the same certificate for them.
// Fortunately, this conversion also helped us deal with this kind of mixedcase problems.
//
// Due to the "σςΣ" problem (see https://unicode.org/faq/idn.html#22), we can't use
// idna.Punycode.ToASCII (or just idna.ToASCII) here.
name, err := idna.Lookup.ToASCII(name)
if err != nil {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return nil, errors.New("acme/autocert: server name contains invalid character")
}
@ -801,6 +822,7 @@ func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certi
defer m.tokensMu.Unlock()
if m.certTokens == nil {
m.certTokens = make(map[string]*tls.Certificate)
<<<<<<< HEAD
}
m.certTokens[name] = cert
m.cachePut(ctx, certKey{domain: name, isToken: true}, cert)
@ -832,6 +854,39 @@ func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, erro
return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath))
}
=======
}
m.certTokens[name] = cert
m.cachePut(ctx, certKey{domain: name, isToken: true}, cert)
}
// 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()
delete(m.certTokens, name)
if m.Cache != nil {
ck := certKey{domain: name, isToken: true}
m.Cache.Delete(context.Background(), ck.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()
if v, ok := m.httpTokens[tokenPath]; ok {
return v, nil
}
if m.Cache == nil {
return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath)
}
return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath))
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// putHTTPToken stores an http-01 token value using tokenPath as key
// in both in-memory map and the optional Cache.
//

View File

@ -206,6 +206,31 @@ func TestGetCertificate_trailingDot(t *testing.T) {
man := &Manager{Prompt: AcceptTOS}
defer man.stopRenew()
hello := clientHelloInfo("example.org.", true)
<<<<<<< HEAD
=======
testGetCertificate(t, man, "example.org", hello)
}
func TestGetCertificate_unicodeIDN(t *testing.T) {
man := &Manager{Prompt: AcceptTOS}
defer man.stopRenew()
hello := clientHelloInfo("σσσ.com", true)
testGetCertificate(t, man, "xn--4xaaa.com", hello)
hello = clientHelloInfo("σςΣ.com", true)
testGetCertificate(t, man, "xn--4xaaa.com", hello)
}
func TestGetCertificate_mixedcase(t *testing.T) {
man := &Manager{Prompt: AcceptTOS}
defer man.stopRenew()
hello := clientHelloInfo("example.org", true)
testGetCertificate(t, man, "example.org", hello)
hello = clientHelloInfo("EXAMPLE.ORG", true)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
testGetCertificate(t, man, "example.org", hello)
}
@ -858,11 +883,19 @@ func TestCache(t *testing.T) {
cert, err := dummyCert(ecdsaKey.Public(), exampleDomain)
if err != nil {
t.Fatal(err)
<<<<<<< HEAD
}
ecdsaCert := &tls.Certificate{
Certificate: [][]byte{cert},
PrivateKey: ecdsaKey,
}
=======
}
ecdsaCert := &tls.Certificate{
Certificate: [][]byte{cert},
PrivateKey: ecdsaKey,
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
rsaKey, err := rsa.GenerateKey(rand.Reader, 512)
if err != nil {
@ -882,6 +915,7 @@ func TestCache(t *testing.T) {
ctx := context.Background()
if err := man.cachePut(ctx, exampleCertKey, ecdsaCert); err != nil {
<<<<<<< HEAD
t.Fatalf("man.cachePut: %v", err)
}
if err := man.cachePut(ctx, exampleCertKeyRSA, rsaCert); err != nil {
@ -900,19 +934,40 @@ func TestCache(t *testing.T) {
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
=======
t.Fatalf("man.cachePut: %v", err)
}
if err := man.cachePut(ctx, exampleCertKeyRSA, rsaCert); err != nil {
t.Fatalf("man.cachePut: %v", err)
}
res, err := man.cacheGet(ctx, exampleCertKey)
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
if res == nil || !bytes.Equal(res.Certificate[0], ecdsaCert.Certificate[0]) {
t.Errorf("man.cacheGet = %+v; want %+v", res, ecdsaCert)
}
res, err = man.cacheGet(ctx, exampleCertKeyRSA)
if err != nil {
t.Fatalf("man.cacheGet: %v", err)
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if res == nil || !bytes.Equal(res.Certificate[0], rsaCert.Certificate[0]) {
t.Errorf("man.cacheGet = %+v; want %+v", res, rsaCert)
}
}
func TestHostWhitelist(t *testing.T) {
policy := HostWhitelist("example.com", "example.org", "*.example.net")
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},
{"one.example.com", false},
{"two.example.org", false},
{"three.example.net", false},

View File

@ -106,7 +106,15 @@ func TestPostWithRetries(t *testing.T) {
}))
defer ts.Close()
<<<<<<< HEAD
client := &Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
=======
client := &Client{
Key: testKey,
DirectoryURL: ts.URL,
dir: &Directory{AuthzURL: ts.URL},
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// This call will fail with badNonce, causing a retry
if _, err := client.Authorize(context.Background(), "example.com"); err != nil {
t.Errorf("client.Authorize 1: %v", err)

View File

@ -75,19 +75,23 @@ func Sum256(data []byte) [Size256]byte {
}
// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil
// key turns the hash into a MAC. The key must between zero and 64 bytes long.
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil
// key turns the hash into a MAC. The key must between zero and 64 bytes long.
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil
// key turns the hash into a MAC. The key must between zero and 64 bytes long.
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length.
<<<<<<< HEAD
// A non-nil key turns the hash into a MAC. The key must between zero and 64 bytes long.
=======
// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long.
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// The hash size can be a value between 1 and 64 but it is highly recommended to use
// values equal or greater than:
// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).

View File

@ -4,7 +4,10 @@
package blake2b
import "encoding/binary"
import (
"encoding/binary"
"math/bits"
)
// the precomputed values for BLAKE2b
// there are 12 16-byte arrays - one for each round
@ -51,118 +54,118 @@ func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
v0 += m[s[0]]
v0 += v4
v12 ^= v0
v12 = v12<<(64-32) | v12>>32
v12 = bits.RotateLeft64(v12, -32)
v8 += v12
v4 ^= v8
v4 = v4<<(64-24) | v4>>24
v4 = bits.RotateLeft64(v4, -24)
v1 += m[s[1]]
v1 += v5
v13 ^= v1
v13 = v13<<(64-32) | v13>>32
v13 = bits.RotateLeft64(v13, -32)
v9 += v13
v5 ^= v9
v5 = v5<<(64-24) | v5>>24
v5 = bits.RotateLeft64(v5, -24)
v2 += m[s[2]]
v2 += v6
v14 ^= v2
v14 = v14<<(64-32) | v14>>32
v14 = bits.RotateLeft64(v14, -32)
v10 += v14
v6 ^= v10
v6 = v6<<(64-24) | v6>>24
v6 = bits.RotateLeft64(v6, -24)
v3 += m[s[3]]
v3 += v7
v15 ^= v3
v15 = v15<<(64-32) | v15>>32
v15 = bits.RotateLeft64(v15, -32)
v11 += v15
v7 ^= v11
v7 = v7<<(64-24) | v7>>24
v7 = bits.RotateLeft64(v7, -24)
v0 += m[s[4]]
v0 += v4
v12 ^= v0
v12 = v12<<(64-16) | v12>>16
v12 = bits.RotateLeft64(v12, -16)
v8 += v12
v4 ^= v8
v4 = v4<<(64-63) | v4>>63
v4 = bits.RotateLeft64(v4, -63)
v1 += m[s[5]]
v1 += v5
v13 ^= v1
v13 = v13<<(64-16) | v13>>16
v13 = bits.RotateLeft64(v13, -16)
v9 += v13
v5 ^= v9
v5 = v5<<(64-63) | v5>>63
v5 = bits.RotateLeft64(v5, -63)
v2 += m[s[6]]
v2 += v6
v14 ^= v2
v14 = v14<<(64-16) | v14>>16
v14 = bits.RotateLeft64(v14, -16)
v10 += v14
v6 ^= v10
v6 = v6<<(64-63) | v6>>63
v6 = bits.RotateLeft64(v6, -63)
v3 += m[s[7]]
v3 += v7
v15 ^= v3
v15 = v15<<(64-16) | v15>>16
v15 = bits.RotateLeft64(v15, -16)
v11 += v15
v7 ^= v11
v7 = v7<<(64-63) | v7>>63
v7 = bits.RotateLeft64(v7, -63)
v0 += m[s[8]]
v0 += v5
v15 ^= v0
v15 = v15<<(64-32) | v15>>32
v15 = bits.RotateLeft64(v15, -32)
v10 += v15
v5 ^= v10
v5 = v5<<(64-24) | v5>>24
v5 = bits.RotateLeft64(v5, -24)
v1 += m[s[9]]
v1 += v6
v12 ^= v1
v12 = v12<<(64-32) | v12>>32
v12 = bits.RotateLeft64(v12, -32)
v11 += v12
v6 ^= v11
v6 = v6<<(64-24) | v6>>24
v6 = bits.RotateLeft64(v6, -24)
v2 += m[s[10]]
v2 += v7
v13 ^= v2
v13 = v13<<(64-32) | v13>>32
v13 = bits.RotateLeft64(v13, -32)
v8 += v13
v7 ^= v8
v7 = v7<<(64-24) | v7>>24
v7 = bits.RotateLeft64(v7, -24)
v3 += m[s[11]]
v3 += v4
v14 ^= v3
v14 = v14<<(64-32) | v14>>32
v14 = bits.RotateLeft64(v14, -32)
v9 += v14
v4 ^= v9
v4 = v4<<(64-24) | v4>>24
v4 = bits.RotateLeft64(v4, -24)
v0 += m[s[12]]
v0 += v5
v15 ^= v0
v15 = v15<<(64-16) | v15>>16
v15 = bits.RotateLeft64(v15, -16)
v10 += v15
v5 ^= v10
v5 = v5<<(64-63) | v5>>63
v5 = bits.RotateLeft64(v5, -63)
v1 += m[s[13]]
v1 += v6
v12 ^= v1
v12 = v12<<(64-16) | v12>>16
v12 = bits.RotateLeft64(v12, -16)
v11 += v12
v6 ^= v11
v6 = v6<<(64-63) | v6>>63
v6 = bits.RotateLeft64(v6, -63)
v2 += m[s[14]]
v2 += v7
v13 ^= v2
v13 = v13<<(64-16) | v13>>16
v13 = bits.RotateLeft64(v13, -16)
v8 += v13
v7 ^= v8
v7 = v7<<(64-63) | v7>>63
v7 = bits.RotateLeft64(v7, -63)
v3 += m[s[15]]
v3 += v4
v14 ^= v3
v14 = v14<<(64-16) | v14>>16
v14 = bits.RotateLeft64(v14, -16)
v9 += v14
v4 ^= v9
v4 = v4<<(64-63) | v4>>63
v4 = bits.RotateLeft64(v4, -63)
}

View File

@ -4,6 +4,10 @@
package blake2s
import (
"math/bits"
)
// the precomputed values for BLAKE2s
// there are 10 16-byte arrays - one for each round
// the entries are calculated from the sigma constants.
@ -47,118 +51,118 @@ func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) {
v0 += m[s[0]]
v0 += v4
v12 ^= v0
v12 = v12<<(32-16) | v12>>16
v12 = bits.RotateLeft32(v12, -16)
v8 += v12
v4 ^= v8
v4 = v4<<(32-12) | v4>>12
v4 = bits.RotateLeft32(v4, -12)
v1 += m[s[1]]
v1 += v5
v13 ^= v1
v13 = v13<<(32-16) | v13>>16
v13 = bits.RotateLeft32(v13, -16)
v9 += v13
v5 ^= v9
v5 = v5<<(32-12) | v5>>12
v5 = bits.RotateLeft32(v5, -12)
v2 += m[s[2]]
v2 += v6
v14 ^= v2
v14 = v14<<(32-16) | v14>>16
v14 = bits.RotateLeft32(v14, -16)
v10 += v14
v6 ^= v10
v6 = v6<<(32-12) | v6>>12
v6 = bits.RotateLeft32(v6, -12)
v3 += m[s[3]]
v3 += v7
v15 ^= v3
v15 = v15<<(32-16) | v15>>16
v15 = bits.RotateLeft32(v15, -16)
v11 += v15
v7 ^= v11
v7 = v7<<(32-12) | v7>>12
v7 = bits.RotateLeft32(v7, -12)
v0 += m[s[4]]
v0 += v4
v12 ^= v0
v12 = v12<<(32-8) | v12>>8
v12 = bits.RotateLeft32(v12, -8)
v8 += v12
v4 ^= v8
v4 = v4<<(32-7) | v4>>7
v4 = bits.RotateLeft32(v4, -7)
v1 += m[s[5]]
v1 += v5
v13 ^= v1
v13 = v13<<(32-8) | v13>>8
v13 = bits.RotateLeft32(v13, -8)
v9 += v13
v5 ^= v9
v5 = v5<<(32-7) | v5>>7
v5 = bits.RotateLeft32(v5, -7)
v2 += m[s[6]]
v2 += v6
v14 ^= v2
v14 = v14<<(32-8) | v14>>8
v14 = bits.RotateLeft32(v14, -8)
v10 += v14
v6 ^= v10
v6 = v6<<(32-7) | v6>>7
v6 = bits.RotateLeft32(v6, -7)
v3 += m[s[7]]
v3 += v7
v15 ^= v3
v15 = v15<<(32-8) | v15>>8
v15 = bits.RotateLeft32(v15, -8)
v11 += v15
v7 ^= v11
v7 = v7<<(32-7) | v7>>7
v7 = bits.RotateLeft32(v7, -7)
v0 += m[s[8]]
v0 += v5
v15 ^= v0
v15 = v15<<(32-16) | v15>>16
v15 = bits.RotateLeft32(v15, -16)
v10 += v15
v5 ^= v10
v5 = v5<<(32-12) | v5>>12
v5 = bits.RotateLeft32(v5, -12)
v1 += m[s[9]]
v1 += v6
v12 ^= v1
v12 = v12<<(32-16) | v12>>16
v12 = bits.RotateLeft32(v12, -16)
v11 += v12
v6 ^= v11
v6 = v6<<(32-12) | v6>>12
v6 = bits.RotateLeft32(v6, -12)
v2 += m[s[10]]
v2 += v7
v13 ^= v2
v13 = v13<<(32-16) | v13>>16
v13 = bits.RotateLeft32(v13, -16)
v8 += v13
v7 ^= v8
v7 = v7<<(32-12) | v7>>12
v7 = bits.RotateLeft32(v7, -12)
v3 += m[s[11]]
v3 += v4
v14 ^= v3
v14 = v14<<(32-16) | v14>>16
v14 = bits.RotateLeft32(v14, -16)
v9 += v14
v4 ^= v9
v4 = v4<<(32-12) | v4>>12
v4 = bits.RotateLeft32(v4, -12)
v0 += m[s[12]]
v0 += v5
v15 ^= v0
v15 = v15<<(32-8) | v15>>8
v15 = bits.RotateLeft32(v15, -8)
v10 += v15
v5 ^= v10
v5 = v5<<(32-7) | v5>>7
v5 = bits.RotateLeft32(v5, -7)
v1 += m[s[13]]
v1 += v6
v12 ^= v1
v12 = v12<<(32-8) | v12>>8
v12 = bits.RotateLeft32(v12, -8)
v11 += v12
v6 ^= v11
v6 = v6<<(32-7) | v6>>7
v6 = bits.RotateLeft32(v6, -7)
v2 += m[s[14]]
v2 += v7
v13 ^= v2
v13 = v13<<(32-8) | v13>>8
v13 = bits.RotateLeft32(v13, -8)
v8 += v13
v7 ^= v8
v7 = v7<<(32-7) | v7>>7
v7 = bits.RotateLeft32(v7, -7)
v3 += m[s[15]]
v3 += v4
v14 ^= v3
v14 = v14<<(32-8) | v14>>8
v14 = bits.RotateLeft32(v14, -8)
v9 += v14
v4 ^= v9
v4 = v4<<(32-7) | v4>>7
v4 = bits.RotateLeft32(v4, -7)
}
h[0] ^= v0 ^ v8

View File

@ -3,6 +3,14 @@
// license that can be found in the LICENSE file.
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
//
// Blowfish is a legacy cipher and its short block size makes it vulnerable to
// birthday bound attacks (see https://sweet32.info). It should only be used
// where compatibility with legacy systems, not security, is the goal.
//
// 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"
// The code is a port of Bruce Schneier's C implementation.

View File

@ -15,9 +15,20 @@
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
// with the implementation described in that paper.
//
<<<<<<< HEAD
// (This package previously claimed to operate at a 128-bit security level.
// However, recent improvements in attacks mean that is no longer true. See
// https://moderncrypto.org/mail-archive/curves/2016/000740.html.)
=======
// This package previously claimed to operate at a 128-bit security level.
// However, recent improvements in attacks mean that is no longer true. See
// https://moderncrypto.org/mail-archive/curves/2016/000740.html.
//
// Deprecated: due to its weakened security, new systems should not rely on this
// 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.
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
package bn256 // import "golang.org/x/crypto/bn256"
import (
@ -26,9 +37,6 @@ import (
"math/big"
)
// BUG(agl): this implementation is not constant time.
// TODO(agl): keep GF(p²) elements in Mongomery form.
// G1 is an abstract cyclic group. The zero value is suitable for use as the
// output of an operation, but cannot be used as an input.
type G1 struct {
@ -54,6 +62,12 @@ func RandomG1(r io.Reader) (*big.Int, *G1, error) {
}
func (e *G1) String() string {
<<<<<<< HEAD
=======
if e.p == nil {
return "bn256.G1" + newCurvePoint(nil).String()
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return "bn256.G1" + e.p.String()
}
@ -77,7 +91,8 @@ func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
}
// Add sets e to a+b and then returns e.
// BUG(agl): this function is not complete: a==b fails.
//
// Warning: this function is not complete, it fails for a equal to b.
func (e *G1) Add(a, b *G1) *G1 {
if e.p == nil {
e.p = newCurvePoint(nil)
@ -175,6 +190,12 @@ func RandomG2(r io.Reader) (*big.Int, *G2, error) {
}
func (e *G2) String() string {
<<<<<<< HEAD
=======
if e.p == nil {
return "bn256.G2" + newTwistPoint(nil).String()
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return "bn256.G2" + e.p.String()
}
@ -198,7 +219,8 @@ func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
}
// Add sets e to a+b and then returns e.
// BUG(agl): this function is not complete: a==b fails.
//
// Warning: this function is not complete, it fails for a equal to b.
func (e *G2) Add(a, b *G2) *G2 {
if e.p == nil {
e.p = newTwistPoint(nil)
@ -277,8 +299,11 @@ type GT struct {
p *gfP12
}
func (g *GT) String() string {
return "bn256.GT" + g.p.String()
func (e *GT) String() string {
if e.p == nil {
return "bn256.GT" + newGFp12(nil).String()
}
return "bn256.GT" + e.p.String()
}
// ScalarMult sets e to a*k and then returns e.

View File

@ -125,8 +125,8 @@ func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
}
func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
e.x.Mul(e.x, b, pool)
e.y.Mul(e.y, b, pool)
e.x.Mul(a.x, b, pool)
e.y.Mul(a.y, b, pool)
return e
}

View File

@ -2,8 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
// OpenPGP cipher.
// Package cast5 implements CAST5, as defined in RFC 2144.
//
// CAST5 is a legacy cipher and its short block size makes it vulnerable to
// birthday bound attacks (see https://sweet32.info). It should only be used
// where compatibility with legacy systems, not security, is the goal.
//
// 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"
import "errors"

View File

@ -200,7 +200,7 @@ GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240
#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, t2:t3; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2
#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
@ -248,7 +248,7 @@ hashADTail:
ADDQ itr2, adp
hashADTailLoop:
SHLQ $8, t1:t0
SHLQ $8, t0, t1
SHLQ $8, t0
MOVB -1(adp), t2
XORQ t2, t0

View File

@ -86,7 +86,7 @@ func feFromBytes(dst *fieldElement, src *[32]byte) {
h6 := load3(src[20:]) << 7
h7 := load3(src[23:]) << 5
h8 := load3(src[26:]) << 4
h9 := load3(src[29:]) << 2
h9 := (load3(src[29:]) & 0x7fffff) << 2
var carry [10]int64
carry[9] = (h9 + 1<<24) >> 25

View File

@ -5,6 +5,8 @@
package curve25519
import (
"bytes"
"crypto/rand"
"fmt"
"testing"
)
@ -28,6 +30,44 @@ func TestBaseScalarMult(t *testing.T) {
}
}
func TestTestVectors(t *testing.T) {
for _, tv := range testVectors {
var got [32]byte
ScalarMult(&got, &tv.In, &tv.Base)
if !bytes.Equal(got[:], tv.Expect[:]) {
t.Logf(" in = %x", tv.In)
t.Logf(" base = %x", tv.Base)
t.Logf(" got = %x", got)
t.Logf("expect = %x", tv.Expect)
t.Fail()
}
}
}
// TestHighBitIgnored tests the following requirement in RFC 7748:
//
// When receiving such an array, implementations of X25519 (but not X448) MUST
// mask the most significant bit in the final byte.
//
// Regression test for issue #30095.
func TestHighBitIgnored(t *testing.T) {
var s, u [32]byte
rand.Read(s[:])
rand.Read(u[:])
var hi0, hi1 [32]byte
u[31] &= 0x7f
ScalarMult(&hi0, &s, &u)
u[31] |= 0x80
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

View File

@ -121,18 +121,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -236,18 +236,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -441,18 +441,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -591,18 +591,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -731,18 +731,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -846,18 +846,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -996,18 +996,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -1146,18 +1146,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -1332,18 +1332,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
SHLQ $13,SI,CX
ANDQ DX,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX

View File

@ -124,18 +124,18 @@ TEXT ·mul(SB),0,$16-24
ADDQ AX,R14
ADCQ DX,R15
MOVQ $REDMASK51,SI
SHLQ $13,R9:R8
SHLQ $13,R8,R9
ANDQ SI,R8
SHLQ $13,R11:R10
SHLQ $13,R10,R11
ANDQ SI,R10
ADDQ R9,R10
SHLQ $13,R13:R12
SHLQ $13,R12,R13
ANDQ SI,R12
ADDQ R11,R12
SHLQ $13,R15:R14
SHLQ $13,R14,R15
ANDQ SI,R14
ADDQ R13,R14
SHLQ $13,BP:BX
SHLQ $13,BX,BP
ANDQ SI,BX
ADDQ R15,BX
IMUL3Q $19,BP,DX

View File

@ -87,18 +87,18 @@ TEXT ·square(SB),7,$0-16
ADDQ AX,R13
ADCQ DX,R14
MOVQ $REDMASK51,SI
SHLQ $13,R8:CX
SHLQ $13,CX,R8
ANDQ SI,CX
SHLQ $13,R10:R9
SHLQ $13,R9,R10
ANDQ SI,R9
ADDQ R8,R9
SHLQ $13,R12:R11
SHLQ $13,R11,R12
ANDQ SI,R11
ADDQ R10,R11
SHLQ $13,R14:R13
SHLQ $13,R13,R14
ANDQ SI,R13
ADDQ R12,R13
SHLQ $13,BX:R15
SHLQ $13,R15,BX
ANDQ SI,R15
ADDQ R14,R15
IMUL3Q $19,BX,DX

View File

@ -0,0 +1,93 @@
// 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 curve25519
// testVectors generated with BoringSSL.
var testVectors = []struct {
In [32]byte
Base [32]byte
Expect [32]byte
}{
{
In: [32]byte{0x66, 0x8f, 0xb9, 0xf7, 0x6a, 0xd9, 0x71, 0xc8, 0x1a, 0xc9, 0x0, 0x7, 0x1a, 0x15, 0x60, 0xbc, 0xe2, 0xca, 0x0, 0xca, 0xc7, 0xe6, 0x7a, 0xf9, 0x93, 0x48, 0x91, 0x37, 0x61, 0x43, 0x40, 0x14},
Base: [32]byte{0xdb, 0x5f, 0x32, 0xb7, 0xf8, 0x41, 0xe7, 0xa1, 0xa0, 0x9, 0x68, 0xef, 0xfd, 0xed, 0x12, 0x73, 0x5f, 0xc4, 0x7a, 0x3e, 0xb1, 0x3b, 0x57, 0x9a, 0xac, 0xad, 0xea, 0xe8, 0x9, 0x39, 0xa7, 0xdd},
Expect: [32]byte{0x9, 0xd, 0x85, 0xe5, 0x99, 0xea, 0x8e, 0x2b, 0xee, 0xb6, 0x13, 0x4, 0xd3, 0x7b, 0xe1, 0xe, 0xc5, 0xc9, 0x5, 0xf9, 0x92, 0x7d, 0x32, 0xf4, 0x2a, 0x9a, 0xa, 0xfb, 0x3e, 0xb, 0x40, 0x74},
},
{
In: [32]byte{0x63, 0x66, 0x95, 0xe3, 0x4f, 0x75, 0xb9, 0xa2, 0x79, 0xc8, 0x70, 0x6f, 0xad, 0x12, 0x89, 0xf2, 0xc0, 0xb1, 0xe2, 0x2e, 0x16, 0xf8, 0xb8, 0x86, 0x17, 0x29, 0xc1, 0xa, 0x58, 0x29, 0x58, 0xaf},
Base: [32]byte{0x9, 0xd, 0x7, 0x1, 0xf8, 0xfd, 0xe2, 0x8f, 0x70, 0x4, 0x3b, 0x83, 0xf2, 0x34, 0x62, 0x25, 0x41, 0x9b, 0x18, 0xa7, 0xf2, 0x7e, 0x9e, 0x3d, 0x2b, 0xfd, 0x4, 0xe1, 0xf, 0x3d, 0x21, 0x3e},
Expect: [32]byte{0xbf, 0x26, 0xec, 0x7e, 0xc4, 0x13, 0x6, 0x17, 0x33, 0xd4, 0x40, 0x70, 0xea, 0x67, 0xca, 0xb0, 0x2a, 0x85, 0xdc, 0x1b, 0xe8, 0xcf, 0xe1, 0xff, 0x73, 0xd5, 0x41, 0xcc, 0x8, 0x32, 0x55, 0x6},
},
{
In: [32]byte{0x73, 0x41, 0x81, 0xcd, 0x1a, 0x94, 0x6, 0x52, 0x2a, 0x56, 0xfe, 0x25, 0xe4, 0x3e, 0xcb, 0xf0, 0x29, 0x5d, 0xb5, 0xdd, 0xd0, 0x60, 0x9b, 0x3c, 0x2b, 0x4e, 0x79, 0xc0, 0x6f, 0x8b, 0xd4, 0x6d},
Base: [32]byte{0xf8, 0xa8, 0x42, 0x1c, 0x7d, 0x21, 0xa9, 0x2d, 0xb3, 0xed, 0xe9, 0x79, 0xe1, 0xfa, 0x6a, 0xcb, 0x6, 0x2b, 0x56, 0xb1, 0x88, 0x5c, 0x71, 0xc5, 0x11, 0x53, 0xcc, 0xb8, 0x80, 0xac, 0x73, 0x15},
Expect: [32]byte{0x11, 0x76, 0xd0, 0x16, 0x81, 0xf2, 0xcf, 0x92, 0x9d, 0xa2, 0xc7, 0xa3, 0xdf, 0x66, 0xb5, 0xd7, 0x72, 0x9f, 0xd4, 0x22, 0x22, 0x6f, 0xd6, 0x37, 0x42, 0x16, 0xbf, 0x7e, 0x2, 0xfd, 0xf, 0x62},
},
{
In: [32]byte{0x1f, 0x70, 0x39, 0x1f, 0x6b, 0xa8, 0x58, 0x12, 0x94, 0x13, 0xbd, 0x80, 0x1b, 0x12, 0xac, 0xbf, 0x66, 0x23, 0x62, 0x82, 0x5c, 0xa2, 0x50, 0x9c, 0x81, 0x87, 0x59, 0xa, 0x2b, 0xe, 0x61, 0x72},
Base: [32]byte{0xd3, 0xea, 0xd0, 0x7a, 0x0, 0x8, 0xf4, 0x45, 0x2, 0xd5, 0x80, 0x8b, 0xff, 0xc8, 0x97, 0x9f, 0x25, 0xa8, 0x59, 0xd5, 0xad, 0xf4, 0x31, 0x2e, 0xa4, 0x87, 0x48, 0x9c, 0x30, 0xe0, 0x1b, 0x3b},
Expect: [32]byte{0xf8, 0x48, 0x2f, 0x2e, 0x9e, 0x58, 0xbb, 0x6, 0x7e, 0x86, 0xb2, 0x87, 0x24, 0xb3, 0xc0, 0xa3, 0xbb, 0xb5, 0x7, 0x3e, 0x4c, 0x6a, 0xcd, 0x93, 0xdf, 0x54, 0x5e, 0xff, 0xdb, 0xba, 0x50, 0x5f},
},
{
In: [32]byte{0x3a, 0x7a, 0xe6, 0xcf, 0x8b, 0x88, 0x9d, 0x2b, 0x7a, 0x60, 0xa4, 0x70, 0xad, 0x6a, 0xd9, 0x99, 0x20, 0x6b, 0xf5, 0x7d, 0x90, 0x30, 0xdd, 0xf7, 0xf8, 0x68, 0xc, 0x8b, 0x1a, 0x64, 0x5d, 0xaa},
Base: [32]byte{0x4d, 0x25, 0x4c, 0x80, 0x83, 0xd8, 0x7f, 0x1a, 0x9b, 0x3e, 0xa7, 0x31, 0xef, 0xcf, 0xf8, 0xa6, 0xf2, 0x31, 0x2d, 0x6f, 0xed, 0x68, 0xe, 0xf8, 0x29, 0x18, 0x51, 0x61, 0xc8, 0xfc, 0x50, 0x60},
Expect: [32]byte{0x47, 0xb3, 0x56, 0xd5, 0x81, 0x8d, 0xe8, 0xef, 0xac, 0x77, 0x4b, 0x71, 0x4c, 0x42, 0xc4, 0x4b, 0xe6, 0x85, 0x23, 0xdd, 0x57, 0xdb, 0xd7, 0x39, 0x62, 0xd5, 0xa5, 0x26, 0x31, 0x87, 0x62, 0x37},
},
{
In: [32]byte{0x20, 0x31, 0x61, 0xc3, 0x15, 0x9a, 0x87, 0x6a, 0x2b, 0xea, 0xec, 0x29, 0xd2, 0x42, 0x7f, 0xb0, 0xc7, 0xc3, 0xd, 0x38, 0x2c, 0xd0, 0x13, 0xd2, 0x7c, 0xc3, 0xd3, 0x93, 0xdb, 0xd, 0xaf, 0x6f},
Base: [32]byte{0x6a, 0xb9, 0x5d, 0x1a, 0xbe, 0x68, 0xc0, 0x9b, 0x0, 0x5c, 0x3d, 0xb9, 0x4, 0x2c, 0xc9, 0x1a, 0xc8, 0x49, 0xf7, 0xe9, 0x4a, 0x2a, 0x4a, 0x9b, 0x89, 0x36, 0x78, 0x97, 0xb, 0x7b, 0x95, 0xbf},
Expect: [32]byte{0x11, 0xed, 0xae, 0xdc, 0x95, 0xff, 0x78, 0xf5, 0x63, 0xa1, 0xc8, 0xf1, 0x55, 0x91, 0xc0, 0x71, 0xde, 0xa0, 0x92, 0xb4, 0xd7, 0xec, 0xaa, 0xc8, 0xe0, 0x38, 0x7b, 0x5a, 0x16, 0xc, 0x4e, 0x5d},
},
{
In: [32]byte{0x13, 0xd6, 0x54, 0x91, 0xfe, 0x75, 0xf2, 0x3, 0xa0, 0x8, 0xb4, 0x41, 0x5a, 0xbc, 0x60, 0xd5, 0x32, 0xe6, 0x95, 0xdb, 0xd2, 0xf1, 0xe8, 0x3, 0xac, 0xcb, 0x34, 0xb2, 0xb7, 0x2c, 0x3d, 0x70},
Base: [32]byte{0x2e, 0x78, 0x4e, 0x4, 0xca, 0x0, 0x73, 0x33, 0x62, 0x56, 0xa8, 0x39, 0x25, 0x5e, 0xd2, 0xf7, 0xd4, 0x79, 0x6a, 0x64, 0xcd, 0xc3, 0x7f, 0x1e, 0xb0, 0xe5, 0xc4, 0xc8, 0xd1, 0xd1, 0xe0, 0xf5},
Expect: [32]byte{0x56, 0x3e, 0x8c, 0x9a, 0xda, 0xa7, 0xd7, 0x31, 0x1, 0xb0, 0xf2, 0xea, 0xd3, 0xca, 0xe1, 0xea, 0x5d, 0x8f, 0xcd, 0x5c, 0xd3, 0x60, 0x80, 0xbb, 0x8e, 0x6e, 0xc0, 0x3d, 0x61, 0x45, 0x9, 0x17},
},
{
In: [32]byte{0x68, 0x6f, 0x7d, 0xa9, 0x3b, 0xf2, 0x68, 0xe5, 0x88, 0x6, 0x98, 0x31, 0xf0, 0x47, 0x16, 0x3f, 0x33, 0x58, 0x99, 0x89, 0xd0, 0x82, 0x6e, 0x98, 0x8, 0xfb, 0x67, 0x8e, 0xd5, 0x7e, 0x67, 0x49},
Base: [32]byte{0x8b, 0x54, 0x9b, 0x2d, 0xf6, 0x42, 0xd3, 0xb2, 0x5f, 0xe8, 0x38, 0xf, 0x8c, 0xc4, 0x37, 0x5f, 0x99, 0xb7, 0xbb, 0x4d, 0x27, 0x5f, 0x77, 0x9f, 0x3b, 0x7c, 0x81, 0xb8, 0xa2, 0xbb, 0xc1, 0x29},
Expect: [32]byte{0x1, 0x47, 0x69, 0x65, 0x42, 0x6b, 0x61, 0x71, 0x74, 0x9a, 0x8a, 0xdd, 0x92, 0x35, 0x2, 0x5c, 0xe5, 0xf5, 0x57, 0xfe, 0x40, 0x9, 0xf7, 0x39, 0x30, 0x44, 0xeb, 0xbb, 0x8a, 0xe9, 0x52, 0x79},
},
{
In: [32]byte{0x82, 0xd6, 0x1c, 0xce, 0xdc, 0x80, 0x6a, 0x60, 0x60, 0xa3, 0x34, 0x9a, 0x5e, 0x87, 0xcb, 0xc7, 0xac, 0x11, 0x5e, 0x4f, 0x87, 0x77, 0x62, 0x50, 0xae, 0x25, 0x60, 0x98, 0xa7, 0xc4, 0x49, 0x59},
Base: [32]byte{0x8b, 0x6b, 0x9d, 0x8, 0xf6, 0x1f, 0xc9, 0x1f, 0xe8, 0xb3, 0x29, 0x53, 0xc4, 0x23, 0x40, 0xf0, 0x7, 0xb5, 0x71, 0xdc, 0xb0, 0xa5, 0x6d, 0x10, 0x72, 0x4e, 0xce, 0xf9, 0x95, 0xc, 0xfb, 0x25},
Expect: [32]byte{0x9c, 0x49, 0x94, 0x1f, 0x9c, 0x4f, 0x18, 0x71, 0xfa, 0x40, 0x91, 0xfe, 0xd7, 0x16, 0xd3, 0x49, 0x99, 0xc9, 0x52, 0x34, 0xed, 0xf2, 0xfd, 0xfb, 0xa6, 0xd1, 0x4a, 0x5a, 0xfe, 0x9e, 0x5, 0x58},
},
{
In: [32]byte{0x7d, 0xc7, 0x64, 0x4, 0x83, 0x13, 0x97, 0xd5, 0x88, 0x4f, 0xdf, 0x6f, 0x97, 0xe1, 0x74, 0x4c, 0x9e, 0xb1, 0x18, 0xa3, 0x1a, 0x7b, 0x23, 0xf8, 0xd7, 0x9f, 0x48, 0xce, 0x9c, 0xad, 0x15, 0x4b},
Base: [32]byte{0x1a, 0xcd, 0x29, 0x27, 0x84, 0xf4, 0x79, 0x19, 0xd4, 0x55, 0xf8, 0x87, 0x44, 0x83, 0x58, 0x61, 0xb, 0xb9, 0x45, 0x96, 0x70, 0xeb, 0x99, 0xde, 0xe4, 0x60, 0x5, 0xf6, 0x89, 0xca, 0x5f, 0xb6},
Expect: [32]byte{0x0, 0xf4, 0x3c, 0x2, 0x2e, 0x94, 0xea, 0x38, 0x19, 0xb0, 0x36, 0xae, 0x2b, 0x36, 0xb2, 0xa7, 0x61, 0x36, 0xaf, 0x62, 0x8a, 0x75, 0x1f, 0xe5, 0xd0, 0x1e, 0x3, 0xd, 0x44, 0x25, 0x88, 0x59},
},
{
In: [32]byte{0xfb, 0xc4, 0x51, 0x1d, 0x23, 0xa6, 0x82, 0xae, 0x4e, 0xfd, 0x8, 0xc8, 0x17, 0x9c, 0x1c, 0x6, 0x7f, 0x9c, 0x8b, 0xe7, 0x9b, 0xbc, 0x4e, 0xff, 0x5c, 0xe2, 0x96, 0xc6, 0xbc, 0x1f, 0xf4, 0x45},
Base: [32]byte{0x55, 0xca, 0xff, 0x21, 0x81, 0xf2, 0x13, 0x6b, 0xe, 0xd0, 0xe1, 0xe2, 0x99, 0x44, 0x48, 0xe1, 0x6c, 0xc9, 0x70, 0x64, 0x6a, 0x98, 0x3d, 0x14, 0xd, 0xc4, 0xea, 0xb3, 0xd9, 0x4c, 0x28, 0x4e},
Expect: [32]byte{0xae, 0x39, 0xd8, 0x16, 0x53, 0x23, 0x45, 0x79, 0x4d, 0x26, 0x91, 0xe0, 0x80, 0x1c, 0xaa, 0x52, 0x5f, 0xc3, 0x63, 0x4d, 0x40, 0x2c, 0xe9, 0x58, 0xb, 0x33, 0x38, 0xb4, 0x6f, 0x8b, 0xb9, 0x72},
},
{
In: [32]byte{0x4e, 0x6, 0xc, 0xe1, 0xc, 0xeb, 0xf0, 0x95, 0x9, 0x87, 0x16, 0xc8, 0x66, 0x19, 0xeb, 0x9f, 0x7d, 0xf6, 0x65, 0x24, 0x69, 0x8b, 0xa7, 0x98, 0x8c, 0x3b, 0x90, 0x95, 0xd9, 0xf5, 0x1, 0x34},
Base: [32]byte{0x57, 0x73, 0x3f, 0x2d, 0x86, 0x96, 0x90, 0xd0, 0xd2, 0xed, 0xae, 0xc9, 0x52, 0x3d, 0xaa, 0x2d, 0xa9, 0x54, 0x45, 0xf4, 0x4f, 0x57, 0x83, 0xc1, 0xfa, 0xec, 0x6c, 0x3a, 0x98, 0x28, 0x18, 0xf3},
Expect: [32]byte{0xa6, 0x1e, 0x74, 0x55, 0x2c, 0xce, 0x75, 0xf5, 0xe9, 0x72, 0xe4, 0x24, 0xf2, 0xcc, 0xb0, 0x9c, 0x83, 0xbc, 0x1b, 0x67, 0x1, 0x47, 0x48, 0xf0, 0x2c, 0x37, 0x1a, 0x20, 0x9e, 0xf2, 0xfb, 0x2c},
},
{
In: [32]byte{0x5c, 0x49, 0x2c, 0xba, 0x2c, 0xc8, 0x92, 0x48, 0x8a, 0x9c, 0xeb, 0x91, 0x86, 0xc2, 0xaa, 0xc2, 0x2f, 0x1, 0x5b, 0xf3, 0xef, 0x8d, 0x3e, 0xcc, 0x9c, 0x41, 0x76, 0x97, 0x62, 0x61, 0xaa, 0xb1},
Base: [32]byte{0x67, 0x97, 0xc2, 0xe7, 0xdc, 0x92, 0xcc, 0xbe, 0x7c, 0x5, 0x6b, 0xec, 0x35, 0xa, 0xb6, 0xd3, 0xbd, 0x2a, 0x2c, 0x6b, 0xc5, 0xa8, 0x7, 0xbb, 0xca, 0xe1, 0xf6, 0xc2, 0xaf, 0x80, 0x36, 0x44},
Expect: [32]byte{0xfc, 0xf3, 0x7, 0xdf, 0xbc, 0x19, 0x2, 0xb, 0x28, 0xa6, 0x61, 0x8c, 0x6c, 0x62, 0x2f, 0x31, 0x7e, 0x45, 0x96, 0x7d, 0xac, 0xf4, 0xae, 0x4a, 0xa, 0x69, 0x9a, 0x10, 0x76, 0x9f, 0xde, 0x14},
},
{
In: [32]byte{0xea, 0x33, 0x34, 0x92, 0x96, 0x5, 0x5a, 0x4e, 0x8b, 0x19, 0x2e, 0x3c, 0x23, 0xc5, 0xf4, 0xc8, 0x44, 0x28, 0x2a, 0x3b, 0xfc, 0x19, 0xec, 0xc9, 0xdc, 0x64, 0x6a, 0x42, 0xc3, 0x8d, 0xc2, 0x48},
Base: [32]byte{0x2c, 0x75, 0xd8, 0x51, 0x42, 0xec, 0xad, 0x3e, 0x69, 0x44, 0x70, 0x4, 0x54, 0xc, 0x1c, 0x23, 0x54, 0x8f, 0xc8, 0xf4, 0x86, 0x25, 0x1b, 0x8a, 0x19, 0x46, 0x3f, 0x3d, 0xf6, 0xf8, 0xac, 0x61},
Expect: [32]byte{0x5d, 0xca, 0xb6, 0x89, 0x73, 0xf9, 0x5b, 0xd3, 0xae, 0x4b, 0x34, 0xfa, 0xb9, 0x49, 0xfb, 0x7f, 0xb1, 0x5a, 0xf1, 0xd8, 0xca, 0xe2, 0x8c, 0xd6, 0x99, 0xf9, 0xc1, 0xaa, 0x33, 0x37, 0x34, 0x2f},
},
{
In: [32]byte{0x4f, 0x29, 0x79, 0xb1, 0xec, 0x86, 0x19, 0xe4, 0x5c, 0xa, 0xb, 0x2b, 0x52, 0x9, 0x34, 0x54, 0x1a, 0xb9, 0x44, 0x7, 0xb6, 0x4d, 0x19, 0xa, 0x76, 0xf3, 0x23, 0x14, 0xef, 0xe1, 0x84, 0xe7},
Base: [32]byte{0xf7, 0xca, 0xe1, 0x8d, 0x8d, 0x36, 0xa7, 0xf5, 0x61, 0x17, 0xb8, 0xb7, 0xe, 0x25, 0x52, 0x27, 0x7f, 0xfc, 0x99, 0xdf, 0x87, 0x56, 0xb5, 0xe1, 0x38, 0xbf, 0x63, 0x68, 0xbc, 0x87, 0xf7, 0x4c},
Expect: [32]byte{0xe4, 0xe6, 0x34, 0xeb, 0xb4, 0xfb, 0x66, 0x4f, 0xe8, 0xb2, 0xcf, 0xa1, 0x61, 0x5f, 0x0, 0xe6, 0x46, 0x6f, 0xff, 0x73, 0x2c, 0xe1, 0xf8, 0xa0, 0xc8, 0xd2, 0x72, 0x74, 0x31, 0xd1, 0x6f, 0x14},
},
{
In: [32]byte{0xf5, 0xd8, 0xa9, 0x27, 0x90, 0x1d, 0x4f, 0xa4, 0x24, 0x90, 0x86, 0xb7, 0xff, 0xec, 0x24, 0xf5, 0x29, 0x7d, 0x80, 0x11, 0x8e, 0x4a, 0xc9, 0xd3, 0xfc, 0x9a, 0x82, 0x37, 0x95, 0x1e, 0x3b, 0x7f},
Base: [32]byte{0x3c, 0x23, 0x5e, 0xdc, 0x2, 0xf9, 0x11, 0x56, 0x41, 0xdb, 0xf5, 0x16, 0xd5, 0xde, 0x8a, 0x73, 0x5d, 0x6e, 0x53, 0xe2, 0x2a, 0xa2, 0xac, 0x14, 0x36, 0x56, 0x4, 0x5f, 0xf2, 0xe9, 0x52, 0x49},
Expect: [32]byte{0xab, 0x95, 0x15, 0xab, 0x14, 0xaf, 0x9d, 0x27, 0xe, 0x1d, 0xae, 0xc, 0x56, 0x80, 0xcb, 0xc8, 0x88, 0xb, 0xd8, 0xa8, 0xe7, 0xeb, 0x67, 0xb4, 0xda, 0x42, 0xa6, 0x61, 0x96, 0x1e, 0xfc, 0xb},
},
}

6
x/crypto/go.mod Normal file
View File

@ -0,0 +1,6 @@
module golang.org/x/crypto
require (
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
golang.org/x/sys v0.0.0-20190412213103-97732733099d
)

8
x/crypto/go.sum Normal file
View File

@ -0,0 +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=

View File

@ -0,0 +1,308 @@
// 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,!appengine
#include "textflag.h"
#define NUM_ROUNDS 10
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
MOVD dst+0(FP), R1
MOVD src+24(FP), R2
MOVD src_len+32(FP), R3
MOVD key+48(FP), R4
MOVD nonce+56(FP), R6
MOVD counter+64(FP), R7
MOVD $·constants(SB), R10
MOVD $·incRotMatrix(SB), R11
MOVW (R7), R20
AND $~255, R3, R13
ADD R2, R13, R12 // R12 for block end
AND $255, R3, R13
loop:
MOVD $NUM_ROUNDS, R21
VLD1 (R11), [V30.S4, V31.S4]
// load contants
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
WORD $0x4D60E940
// load keys
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4]
WORD $0x4DFFE884
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4]
WORD $0x4DFFE888
SUB $32, R4
// load counter + nonce
// VLD1R (R7), [V12.S4]
WORD $0x4D40C8EC
// VLD3R (R6), [V13.S4, V14.S4, V15.S4]
WORD $0x4D40E8CD
// update counter
VADD V30.S4, V12.S4, V12.S4
chacha:
// V0..V3 += V4..V7
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16)
VADD V0.S4, V4.S4, V0.S4
VADD V1.S4, V5.S4, V1.S4
VADD V2.S4, V6.S4, V2.S4
VADD V3.S4, V7.S4, V3.S4
VEOR V12.B16, V0.B16, V12.B16
VEOR V13.B16, V1.B16, V13.B16
VEOR V14.B16, V2.B16, V14.B16
VEOR V15.B16, V3.B16, V15.B16
VREV32 V12.H8, V12.H8
VREV32 V13.H8, V13.H8
VREV32 V14.H8, V14.H8
VREV32 V15.H8, V15.H8
// V8..V11 += V12..V15
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12)
VADD V8.S4, V12.S4, V8.S4
VADD V9.S4, V13.S4, V9.S4
VADD V10.S4, V14.S4, V10.S4
VADD V11.S4, V15.S4, V11.S4
VEOR V8.B16, V4.B16, V16.B16
VEOR V9.B16, V5.B16, V17.B16
VEOR V10.B16, V6.B16, V18.B16
VEOR V11.B16, V7.B16, V19.B16
VSHL $12, V16.S4, V4.S4
VSHL $12, V17.S4, V5.S4
VSHL $12, V18.S4, V6.S4
VSHL $12, V19.S4, V7.S4
VSRI $20, V16.S4, V4.S4
VSRI $20, V17.S4, V5.S4
VSRI $20, V18.S4, V6.S4
VSRI $20, V19.S4, V7.S4
// V0..V3 += V4..V7
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8)
VADD V0.S4, V4.S4, V0.S4
VADD V1.S4, V5.S4, V1.S4
VADD V2.S4, V6.S4, V2.S4
VADD V3.S4, V7.S4, V3.S4
VEOR V12.B16, V0.B16, V12.B16
VEOR V13.B16, V1.B16, V13.B16
VEOR V14.B16, V2.B16, V14.B16
VEOR V15.B16, V3.B16, V15.B16
VTBL V31.B16, [V12.B16], V12.B16
VTBL V31.B16, [V13.B16], V13.B16
VTBL V31.B16, [V14.B16], V14.B16
VTBL V31.B16, [V15.B16], V15.B16
// V8..V11 += V12..V15
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7)
VADD V12.S4, V8.S4, V8.S4
VADD V13.S4, V9.S4, V9.S4
VADD V14.S4, V10.S4, V10.S4
VADD V15.S4, V11.S4, V11.S4
VEOR V8.B16, V4.B16, V16.B16
VEOR V9.B16, V5.B16, V17.B16
VEOR V10.B16, V6.B16, V18.B16
VEOR V11.B16, V7.B16, V19.B16
VSHL $7, V16.S4, V4.S4
VSHL $7, V17.S4, V5.S4
VSHL $7, V18.S4, V6.S4
VSHL $7, V19.S4, V7.S4
VSRI $25, V16.S4, V4.S4
VSRI $25, V17.S4, V5.S4
VSRI $25, V18.S4, V6.S4
VSRI $25, V19.S4, V7.S4
// V0..V3 += V5..V7, V4
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16)
VADD V0.S4, V5.S4, V0.S4
VADD V1.S4, V6.S4, V1.S4
VADD V2.S4, V7.S4, V2.S4
VADD V3.S4, V4.S4, V3.S4
VEOR V15.B16, V0.B16, V15.B16
VEOR V12.B16, V1.B16, V12.B16
VEOR V13.B16, V2.B16, V13.B16
VEOR V14.B16, V3.B16, V14.B16
VREV32 V12.H8, V12.H8
VREV32 V13.H8, V13.H8
VREV32 V14.H8, V14.H8
VREV32 V15.H8, V15.H8
// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
// ...
VADD V15.S4, V10.S4, V10.S4
VADD V12.S4, V11.S4, V11.S4
VADD V13.S4, V8.S4, V8.S4
VADD V14.S4, V9.S4, V9.S4
VEOR V10.B16, V5.B16, V16.B16
VEOR V11.B16, V6.B16, V17.B16
VEOR V8.B16, V7.B16, V18.B16
VEOR V9.B16, V4.B16, V19.B16
VSHL $12, V16.S4, V5.S4
VSHL $12, V17.S4, V6.S4
VSHL $12, V18.S4, V7.S4
VSHL $12, V19.S4, V4.S4
VSRI $20, V16.S4, V5.S4
VSRI $20, V17.S4, V6.S4
VSRI $20, V18.S4, V7.S4
VSRI $20, V19.S4, V4.S4
// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
// ...
VADD V5.S4, V0.S4, V0.S4
VADD V6.S4, V1.S4, V1.S4
VADD V7.S4, V2.S4, V2.S4
VADD V4.S4, V3.S4, V3.S4
VEOR V0.B16, V15.B16, V15.B16
VEOR V1.B16, V12.B16, V12.B16
VEOR V2.B16, V13.B16, V13.B16
VEOR V3.B16, V14.B16, V14.B16
VTBL V31.B16, [V12.B16], V12.B16
VTBL V31.B16, [V13.B16], V13.B16
VTBL V31.B16, [V14.B16], V14.B16
VTBL V31.B16, [V15.B16], V15.B16
// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
// ...
VADD V15.S4, V10.S4, V10.S4
VADD V12.S4, V11.S4, V11.S4
VADD V13.S4, V8.S4, V8.S4
VADD V14.S4, V9.S4, V9.S4
VEOR V10.B16, V5.B16, V16.B16
VEOR V11.B16, V6.B16, V17.B16
VEOR V8.B16, V7.B16, V18.B16
VEOR V9.B16, V4.B16, V19.B16
VSHL $7, V16.S4, V5.S4
VSHL $7, V17.S4, V6.S4
VSHL $7, V18.S4, V7.S4
VSHL $7, V19.S4, V4.S4
VSRI $25, V16.S4, V5.S4
VSRI $25, V17.S4, V6.S4
VSRI $25, V18.S4, V7.S4
VSRI $25, V19.S4, V4.S4
SUB $1, R21
CBNZ R21, chacha
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4]
WORD $0x4D60E950
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4]
WORD $0x4DFFE894
VADD V30.S4, V12.S4, V12.S4
VADD V16.S4, V0.S4, V0.S4
VADD V17.S4, V1.S4, V1.S4
VADD V18.S4, V2.S4, V2.S4
VADD V19.S4, V3.S4, V3.S4
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4]
WORD $0x4DFFE898
// restore R4
SUB $32, R4
// load counter + nonce
// VLD1R (R7), [V28.S4]
WORD $0x4D40C8FC
// VLD3R (R6), [V29.S4, V30.S4, V31.S4]
WORD $0x4D40E8DD
VADD V20.S4, V4.S4, V4.S4
VADD V21.S4, V5.S4, V5.S4
VADD V22.S4, V6.S4, V6.S4
VADD V23.S4, V7.S4, V7.S4
VADD V24.S4, V8.S4, V8.S4
VADD V25.S4, V9.S4, V9.S4
VADD V26.S4, V10.S4, V10.S4
VADD V27.S4, V11.S4, V11.S4
VADD V28.S4, V12.S4, V12.S4
VADD V29.S4, V13.S4, V13.S4
VADD V30.S4, V14.S4, V14.S4
VADD V31.S4, V15.S4, V15.S4
VZIP1 V1.S4, V0.S4, V16.S4
VZIP2 V1.S4, V0.S4, V17.S4
VZIP1 V3.S4, V2.S4, V18.S4
VZIP2 V3.S4, V2.S4, V19.S4
VZIP1 V5.S4, V4.S4, V20.S4
VZIP2 V5.S4, V4.S4, V21.S4
VZIP1 V7.S4, V6.S4, V22.S4
VZIP2 V7.S4, V6.S4, V23.S4
VZIP1 V9.S4, V8.S4, V24.S4
VZIP2 V9.S4, V8.S4, V25.S4
VZIP1 V11.S4, V10.S4, V26.S4
VZIP2 V11.S4, V10.S4, V27.S4
VZIP1 V13.S4, V12.S4, V28.S4
VZIP2 V13.S4, V12.S4, V29.S4
VZIP1 V15.S4, V14.S4, V30.S4
VZIP2 V15.S4, V14.S4, V31.S4
VZIP1 V18.D2, V16.D2, V0.D2
VZIP2 V18.D2, V16.D2, V4.D2
VZIP1 V19.D2, V17.D2, V8.D2
VZIP2 V19.D2, V17.D2, V12.D2
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16]
VZIP1 V22.D2, V20.D2, V1.D2
VZIP2 V22.D2, V20.D2, V5.D2
VZIP1 V23.D2, V21.D2, V9.D2
VZIP2 V23.D2, V21.D2, V13.D2
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16]
VZIP1 V26.D2, V24.D2, V2.D2
VZIP2 V26.D2, V24.D2, V6.D2
VZIP1 V27.D2, V25.D2, V10.D2
VZIP2 V27.D2, V25.D2, V14.D2
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16]
VZIP1 V30.D2, V28.D2, V3.D2
VZIP2 V30.D2, V28.D2, V7.D2
VZIP1 V31.D2, V29.D2, V11.D2
VZIP2 V31.D2, V29.D2, V15.D2
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16]
VEOR V0.B16, V16.B16, V16.B16
VEOR V1.B16, V17.B16, V17.B16
VEOR V2.B16, V18.B16, V18.B16
VEOR V3.B16, V19.B16, V19.B16
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1)
VEOR V4.B16, V20.B16, V20.B16
VEOR V5.B16, V21.B16, V21.B16
VEOR V6.B16, V22.B16, V22.B16
VEOR V7.B16, V23.B16, V23.B16
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1)
VEOR V8.B16, V24.B16, V24.B16
VEOR V9.B16, V25.B16, V25.B16
VEOR V10.B16, V26.B16, V26.B16
VEOR V11.B16, V27.B16, V27.B16
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1)
VEOR V12.B16, V28.B16, V28.B16
VEOR V13.B16, V29.B16, V29.B16
VEOR V14.B16, V30.B16, V30.B16
VEOR V15.B16, V31.B16, V31.B16
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1)
ADD $4, R20
MOVW R20, (R7) // update counter
CMP R2, R12
BGT loop
RET
DATA ·constants+0x00(SB)/4, $0x61707865
DATA ·constants+0x04(SB)/4, $0x3320646e
DATA ·constants+0x08(SB)/4, $0x79622d32
DATA ·constants+0x0c(SB)/4, $0x6b206574
GLOBL ·constants(SB), NOPTR|RODATA, $32
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32

View File

@ -0,0 +1,31 @@
// 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])
}
}

View File

@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
<<<<<<< HEAD
// +build !s390x gccgo appengine
=======
// +build !arm64,!s390x arm64,!go1.11 gccgo appengine
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
package chacha20

View File

@ -6,6 +6,7 @@
package chacha20
<<<<<<< HEAD
var haveAsm = hasVectorFacility()
const bufSize = 256
@ -14,6 +15,15 @@ const bufSize = 256
// facility (vx).
// Implementation in asm_s390x.s.
func hasVectorFacility() bool
=======
import (
"golang.org/x/sys/cpu"
)
var haveAsm = cpu.S390X.HasVX
const bufSize = 256
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
// be called when the vector facility is available.

View File

@ -258,6 +258,7 @@ tail:
MOVD R8, R3
MOVD $0, R4
JMP continue
<<<<<<< HEAD
// func hasVectorFacility() bool
TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
@ -281,3 +282,5 @@ vectorinstalled:
novector:
MOVB $0, ret+0(FP) // no vx
RET
=======
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a

View File

@ -3,6 +3,10 @@
// license that can be found in the LICENSE file.
// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
//
// Deprecated: MD4 is cryptographically broken and should 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"
import (

View File

@ -40,7 +40,11 @@ func TestOpen(t *testing.T) {
if !bytes.Equal(message, testMessage) {
t.Fatalf("message did not match, got\n%x\n, expected\n%x", message, testMessage)
}
<<<<<<< HEAD
message, ok = Open(nil, testSignedMessage[1:], &testPublicKey)
=======
_, ok = Open(nil, testSignedMessage[1:], &testPublicKey)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if ok {
t.Fatalf("invalid signed message successfully verified")
}

View File

@ -487,6 +487,12 @@ func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Respon
if err != nil {
return nil, err
}
<<<<<<< HEAD
=======
if len(rest) > 0 {
return nil, ParseError("trailing data in OCSP response")
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 {
return nil, ParseError("OCSP response contains bad number of responses")

View File

@ -18,6 +18,7 @@ import (
"io"
"net/textproto"
"strconv"
"strings"
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/errors"
@ -27,7 +28,7 @@ import (
// A Block represents a clearsigned message. A signature on a Block can
// be checked by passing Bytes into openpgp.CheckDetachedSignature.
type Block struct {
Headers textproto.MIMEHeader // Optional message headers
Headers textproto.MIMEHeader // Optional unverified Hash headers
Plaintext []byte // The original message text
Bytes []byte // The signed message
ArmoredSignature *armor.Block // The signature block
@ -69,8 +70,13 @@ func getLine(data []byte) (line, rest []byte) {
return data[0:i], data[j:]
}
// Decode finds the first clearsigned message in data and returns it, as well
// as the suffix of data which remains after the message.
// Decode finds the first clearsigned message in data and returns it, as well as
// the suffix of data which remains after the message. Any prefix data is
// discarded.
//
// If no message is found, or if the message is invalid, Decode returns nil and
// the whole data slice. The only allowed header type is Hash, and it is not
// verified against the signature hash.
func Decode(data []byte) (b *Block, rest []byte) {
// start begins with a newline. However, at the very beginning of
// the byte array, we'll accept the start string without it.
@ -83,8 +89,11 @@ func Decode(data []byte) (b *Block, rest []byte) {
return nil, data
}
// Consume the start line.
_, rest = getLine(rest)
// Consume the start line and check it does not have a suffix.
suffix, rest := getLine(rest)
if len(suffix) != 0 {
return nil, data
}
var line []byte
b = &Block{
@ -103,15 +112,25 @@ func Decode(data []byte) (b *Block, rest []byte) {
break
}
// Reject headers with control or Unicode characters.
if i := bytes.IndexFunc(line, func(r rune) bool {
return r < 0x20 || r > 0x7e
}); i != -1 {
return nil, data
}
i := bytes.Index(line, []byte{':'})
if i == -1 {
return nil, data
}
key, val := line[0:i], line[i+1:]
key = bytes.TrimSpace(key)
val = bytes.TrimSpace(val)
b.Headers.Add(string(key), string(val))
key, val := string(line[0:i]), string(line[i+1:])
key = strings.TrimSpace(key)
if key != "Hash" {
return nil, data
}
val = strings.TrimSpace(val)
b.Headers.Add(key, val)
}
firstLine := true

View File

@ -47,12 +47,6 @@ func TestParse(t *testing.T) {
testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n")
}
func TestParseInvalid(t *testing.T) {
if b, _ := Decode(clearsignInput3); b != nil {
t.Fatal("decoded a bad clearsigned message without any error")
}
}
func TestParseWithNoNewlineAtEnd(t *testing.T) {
input := clearsignInput
input = input[:len(input)-len("trailing")-1]
@ -140,6 +134,13 @@ func (qr *quickRand) Read(p []byte) (int, error) {
}
func TestMultiSign(t *testing.T) {
<<<<<<< HEAD
=======
if testing.Short() {
t.Skip("skipping long test in -short mode")
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
zero := quickRand(0)
config := packet.Config{Rand: &zero}
@ -193,6 +194,62 @@ func TestMultiSign(t *testing.T) {
}
}
<<<<<<< HEAD
=======
const signatureBlock = `
-----BEGIN PGP SIGNATURE-----
Version: OpenPrivacy 0.99
yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
vBSFjNSiVHsuAA==
=njUN
-----END PGP SIGNATURE-----
`
var invalidInputs = []string{
`
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
(This message was truncated.)
`,
`
-----BEGIN PGP SIGNED MESSAGE-----garbage
Hash: SHA256
_o/
` + signatureBlock,
`
garbage-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
_o/
` + signatureBlock,
`
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA` + "\x0b\x0b" + `256
_o/
` + signatureBlock,
`
-----BEGIN PGP SIGNED MESSAGE-----
NotHash: SHA256
_o/
` + signatureBlock,
}
func TestParseInvalid(t *testing.T) {
for i, input := range invalidInputs {
if b, rest := Decode([]byte(input)); b != nil {
t.Errorf("#%d: decoded a bad clearsigned message without any error", i)
} else if string(rest) != input {
t.Errorf("#%d: did not return all data with a bad message", i)
}
}
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
var clearsignInput = []byte(`
;lasjlkfdsa
@ -235,13 +292,6 @@ qZg6BaTvOxepqOxnhVU=
trailing`)
var clearsignInput3 = []byte(`
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
(This message was truncated.)
`)
var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)

View File

@ -504,7 +504,7 @@ const defaultRSAKeyBits = 2048
// which may be empty but must not contain any of "()<>\x00".
// If config is nil, sensible defaults will be used.
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
currentTime := config.Now()
creationTime := config.Now()
bits := defaultRSAKeyBits
if config != nil && config.RSABits != 0 {
@ -525,8 +525,8 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
}
e := &Entity{
PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv),
Identities: make(map[string]*Identity),
}
isPrimaryId := true
@ -534,7 +534,7 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
Name: uid.Id,
UserId: uid,
SelfSignature: &packet.Signature{
CreationTime: currentTime,
CreationTime: creationTime,
SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
@ -563,10 +563,10 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
e.Subkeys = make([]Subkey, 1)
e.Subkeys[0] = Subkey{
PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv),
Sig: &packet.Signature{
CreationTime: currentTime,
CreationTime: creationTime,
SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),

View File

@ -32,7 +32,7 @@ func TestOpaqueParseReason(t *testing.T) {
break
}
// try to parse opaque packet
p, err := op.Parse()
p, _ := op.Parse()
switch pkt := p.(type) {
case *UserId:
uid = pkt

View File

@ -36,49 +36,57 @@ type PrivateKey struct {
iv []byte
}
func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
// implements RSA or ECDSA.
func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey {
pk := new(PrivateKey)
// In general, the public Keys should be used as pointers. We still
// type-switch on the values, for backwards-compatibility.
switch pubkey := signer.Public().(type) {
case *rsa.PublicKey:
<<<<<<< HEAD
pk.PublicKey = *NewRSAPublicKey(currentTime, pubkey)
case rsa.PublicKey:
pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
case *ecdsa.PublicKey:
pk.PublicKey = *NewECDSAPublicKey(currentTime, pubkey)
=======
pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey)
case rsa.PublicKey:
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey)
case *ecdsa.PublicKey:
pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
case ecdsa.PublicKey:
pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey)
default:
panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
}

View File

@ -4,6 +4,10 @@
// Package otr implements the Off The Record protocol as specified in
// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
//
// 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"
import (
@ -637,7 +641,7 @@ func (c *Conversation) serializeDHKey() []byte {
}
func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) {
gy, in, ok := getMPI(in)
gy, _, ok := getMPI(in)
if !ok {
err = errors.New("otr: corrupt DH key message")
return

View File

@ -7,6 +7,9 @@
// 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 package is frozen. If it's missing functionality you need, consider
// an alternative like software.sslmate.com/src/go-pkcs12.
package pkcs12
import (
@ -100,7 +103,7 @@ func unmarshal(in []byte, out interface{}) error {
return nil
}
// ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks.
// ToPEM converts all "safe bags" contained in pfxData to PEM blocks.
func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) {
encodedPassword, err := bmpString(password)
if err != nil {
@ -208,7 +211,7 @@ func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error)
// Decode extracts a certificate and private key from pfxData. This function
// assumes that there is only one certificate and only one private key in the
// pfxData.
// pfxData; if there are more use ToPEM instead.
func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) {
encodedPassword, err := bmpString(password)
if err != nil {

View File

@ -0,0 +1,11 @@
// 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 !amd64 gccgo appengine
package poly1305
type mac struct{ macGeneric }
func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} }

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
<<<<<<< HEAD
/*
Package poly1305 implements Poly1305 one-time message authentication code as
specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
@ -17,6 +18,21 @@ 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 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.
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
package poly1305 // import "golang.org/x/crypto/poly1305"
import "crypto/subtle"
@ -31,3 +47,55 @@ func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
Sum(&tmp, m, key)
return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
}
// 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: newMAC(key),
finalized: false,
}
}
// 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 causes it to panic.
type MAC struct {
mac // platform-dependent implementation
finalized bool
}
// 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.
func (h *MAC) Write(p []byte) (n int, err error) {
if h.finalized {
panic("poly1305: write to MAC after Sum")
}
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 {
var mac [TagSize]byte
h.mac.Sum(&mac)
h.finalized = true
return append(b, mac[:]...)
}

View File

@ -100,7 +100,50 @@ func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) }
func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) }
func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) }
func benchmark(b *testing.B, size int, unaligned bool) {
func TestWriteGeneric(t *testing.T) { testWriteGeneric(t, false) }
func TestWriteGenericUnaligned(t *testing.T) { testWriteGeneric(t, true) }
func TestWrite(t *testing.T) { testWrite(t, false) }
func TestWriteUnaligned(t *testing.T) { testWrite(t, true) }
func testWriteGeneric(t *testing.T, unaligned bool) {
for i, v := range testData {
key := v.Key()
input := v.Input()
var out [16]byte
if unaligned {
input = unalignBytes(input)
}
h := newMACGeneric(&key)
h.Write(input[:len(input)/2])
h.Write(input[len(input)/2:])
h.Sum(&out)
if tag := v.Tag(); out != tag {
t.Errorf("%d: expected %x, got %x", i, tag[:], out[:])
}
}
}
func testWrite(t *testing.T, unaligned bool) {
for i, v := range testData {
key := v.Key()
input := v.Input()
var out [16]byte
if unaligned {
input = unalignBytes(input)
}
h := New(&key)
h.Write(input[:len(input)/2])
h.Write(input[len(input)/2:])
h.Sum(out[:0])
if tag := v.Tag(); out != tag {
t.Errorf("%d: expected %x, got %x", i, tag[:], out[:])
}
}
}
func benchmarkSum(b *testing.B, size int, unaligned bool) {
var out [16]byte
var key [32]byte
in := make([]byte, size)
@ -114,11 +157,41 @@ func benchmark(b *testing.B, size int, unaligned bool) {
}
}
<<<<<<< HEAD
func Benchmark64(b *testing.B) { benchmark(b, 64, false) }
func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) }
func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
func Benchmark2M(b *testing.B) { benchmark(b, 2097152, true) }
=======
func benchmarkWrite(b *testing.B, size int, unaligned bool) {
var key [32]byte
h := New(&key)
in := make([]byte, size)
if unaligned {
in = unalignBytes(in)
}
b.SetBytes(int64(len(in)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
h.Write(in)
}
}
func Benchmark64(b *testing.B) { benchmarkSum(b, 64, false) }
func Benchmark1K(b *testing.B) { benchmarkSum(b, 1024, false) }
func Benchmark2M(b *testing.B) { benchmarkSum(b, 2*1024*1024, false) }
func Benchmark64Unaligned(b *testing.B) { benchmarkSum(b, 64, true) }
func Benchmark1KUnaligned(b *testing.B) { benchmarkSum(b, 1024, true) }
func Benchmark2MUnaligned(b *testing.B) { benchmarkSum(b, 2*1024*1024, true) }
func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64, false) }
func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024, false) }
func BenchmarkWrite2M(b *testing.B) { benchmarkWrite(b, 2*1024*1024, false) }
func BenchmarkWrite64Unaligned(b *testing.B) { benchmarkWrite(b, 64, true) }
func BenchmarkWrite1KUnaligned(b *testing.B) { benchmarkWrite(b, 1024, true) }
func BenchmarkWrite2MUnaligned(b *testing.B) { benchmarkWrite(b, 2*1024*1024, true) }
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
func unalignBytes(in []byte) []byte {
out := make([]byte, len(in)+1)

View File

@ -6,17 +6,63 @@
package poly1305
// This function is implemented in sum_amd64.s
//go:noescape
func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
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) {
var mPtr *byte
if len(m) > 0 {
mPtr = &m[0]
}
poly1305(out, mPtr, uint64(len(m)), key)
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)
}

View File

@ -58,20 +58,17 @@ DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
GLOBL ·poly1305Mask<>(SB), RODATA, $16
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
TEXT ·poly1305(SB), $0-32
MOVQ out+0(FP), DI
MOVQ m+8(FP), SI
MOVQ mlen+16(FP), R15
MOVQ key+24(FP), AX
// 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(AX), R11
MOVQ 8(AX), R12
ANDQ ·poly1305Mask<>(SB), R11 // r0
ANDQ ·poly1305Mask<>+8(SB), R12 // r1
XORQ R8, R8 // h0
XORQ R9, R9 // h1
XORQ R10, R10 // h2
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
@ -109,16 +106,42 @@ flush_buffer:
JMP multiply
done:
MOVQ R8, AX
MOVQ R9, BX
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, R10
SBBQ $3, CX
CMOVQCS R8, AX
CMOVQCS R9, BX
MOVQ key+24(FP), R8
ADDQ 16(R8), AX
ADCQ 24(R8), BX
ADDQ 40(SI), AX
ADCQ 48(SI), BX
MOVQ AX, 0(DI)
MOVQ BX, 8(DI)

View File

@ -0,0 +1,172 @@
// 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)
}

View File

@ -10,5 +10,11 @@ package poly1305
// 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) {
<<<<<<< HEAD
sumGeneric(out, msg, key)
=======
h := newMAC(key)
h.Write(msg)
h.Sum(out)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}

View File

@ -6,6 +6,7 @@
package poly1305
<<<<<<< HEAD
// hasVectorFacility reports whether the machine supports
// the vector facility (vx).
func hasVectorFacility() bool
@ -16,6 +17,11 @@ func hasVMSLFacility() bool
var hasVX = hasVectorFacility()
var hasVMSL = hasVMSLFacility()
=======
import (
"golang.org/x/sys/cpu"
)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// poly1305vx is an assembly implementation of Poly1305 that uses vector
// instructions. It must only be called if the vector facility (vx) is
@ -33,12 +39,20 @@ func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
// 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) {
<<<<<<< HEAD
if hasVX {
=======
if cpu.S390X.HasVX {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
var mPtr *byte
if len(m) > 0 {
mPtr = &m[0]
}
<<<<<<< HEAD
if hasVMSL && len(m) > 256 {
=======
if cpu.S390X.HasVXE && len(m) > 256 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
poly1305vmsl(out, mPtr, uint64(len(m)), key)
} else {
poly1305vx(out, mPtr, uint64(len(m)), key)

View File

@ -376,6 +376,7 @@ b1:
MOVD $0, R3
BR multiply
<<<<<<< HEAD
TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
MOVD $x-24(SP), R1
@ -398,3 +399,5 @@ vectorinstalled:
novector:
MOVB $0, ret+0(FP) // no vx
RET
=======
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a

View File

@ -907,6 +907,7 @@ square:
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
<<<<<<< HEAD
TEXT ·hasVMSLFacility(SB), NOSPLIT, $24-1
MOVD $x-24(SP), R1
@ -929,3 +930,5 @@ vectorinstalled:
novmsl:
MOVB $0, ret+0(FP) // no vx
RET
=======
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a

View File

@ -3,6 +3,10 @@
// license that can be found in the LICENSE file.
// Package ripemd160 implements the RIPEMD-160 hash algorithm.
//
// 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"
// RIPEMD-160 is designed by Hans Dobbertin, Antoon Bosselaers, and Bart

View File

@ -6,10 +6,9 @@
package salsa
// This function is implemented in salsa2020_amd64.s.
//go:noescape
// salsa2020XORKeyStream is implemented in salsa20_amd64.s.
func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
// XORKeyStream crypts bytes from in to out using the given key and counters.

View File

@ -99,30 +99,24 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment
MOVL 36 (SP),CX
MOVL DX,288(SP)
MOVL CX,304(SP)
ADDQ $1,DX
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
SHLQ $32,CX
ADDQ CX,DX
MOVQ DX,CX
SHRQ $32,CX
MOVL DX, 296 (SP)
MOVL CX, 312 (SP)
ADDQ $1,DX
SHLQ $32,CX
ADDQ CX,DX
MOVQ DX,CX
SHRQ $32,CX
MOVL DX, 300 (SP)
MOVL CX, 316 (SP)
ADDQ $1,DX
SHLQ $32,CX
ADDQ CX,DX
MOVQ DX,CX
SHRQ $32,CX
MOVL DX,16(SP)

View File

@ -0,0 +1,31 @@
// 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 amd64,!appengine,!gccgo
package salsa
import (
"bytes"
"testing"
)
func TestCounterOverflow(t *testing.T) {
in := make([]byte, 4096)
key := &[32]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}
for n, counter := range []*[16]byte{
&[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // zero counter
&[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}, // counter about to overflow 32 bits
&[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff}, // counter above 32 bits
} {
out := make([]byte, 4096)
XORKeyStream(out, in, counter, key)
outGeneric := make([]byte, 4096)
genericXORKeyStream(outGeneric, in, counter, key)
if !bytes.Equal(out, outGeneric) {
t.Errorf("%d: assembly and go implementations disagree", n)
}
}
}

View File

@ -0,0 +1,14 @@
// 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 !amd64 appengine gccgo
package salsa
// 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 salsa20 counter bytes (both nonce and block counter).
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
genericXORKeyStream(out, in, counter, key)
}

View File

@ -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 !amd64 appengine gccgo
package salsa
const rounds = 20
@ -202,10 +200,16 @@ func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
out[63] = byte(x15 >> 24)
}
<<<<<<< HEAD
// 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 salsa20 counter bytes (both nonce and block counter).
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
=======
// genericXORKeyStream is the generic implementation of XORKeyStream to be used
// when no assembly implementation is available.
func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
var block [64]byte
var counterCopy [16]byte
copy(counterCopy[:], counter[:])

View File

@ -10,6 +10,7 @@ package scrypt // import "golang.org/x/crypto/scrypt"
import (
"crypto/sha256"
"errors"
"math/bits"
"golang.org/x/crypto/pbkdf2"
)
@ -52,77 +53,45 @@ func salsaXOR(tmp *[16]uint32, in, out []uint32) {
x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
for i := 0; i < 8; i += 2 {
u := x0 + x12
x4 ^= u<<7 | u>>(32-7)
u = x4 + x0
x8 ^= u<<9 | u>>(32-9)
u = x8 + x4
x12 ^= u<<13 | u>>(32-13)
u = x12 + x8
x0 ^= u<<18 | u>>(32-18)
x4 ^= bits.RotateLeft32(x0+x12, 7)
x8 ^= bits.RotateLeft32(x4+x0, 9)
x12 ^= bits.RotateLeft32(x8+x4, 13)
x0 ^= bits.RotateLeft32(x12+x8, 18)
u = x5 + x1
x9 ^= u<<7 | u>>(32-7)
u = x9 + x5
x13 ^= u<<9 | u>>(32-9)
u = x13 + x9
x1 ^= u<<13 | u>>(32-13)
u = x1 + x13
x5 ^= u<<18 | u>>(32-18)
x9 ^= bits.RotateLeft32(x5+x1, 7)
x13 ^= bits.RotateLeft32(x9+x5, 9)
x1 ^= bits.RotateLeft32(x13+x9, 13)
x5 ^= bits.RotateLeft32(x1+x13, 18)
u = x10 + x6
x14 ^= u<<7 | u>>(32-7)
u = x14 + x10
x2 ^= u<<9 | u>>(32-9)
u = x2 + x14
x6 ^= u<<13 | u>>(32-13)
u = x6 + x2
x10 ^= u<<18 | u>>(32-18)
x14 ^= bits.RotateLeft32(x10+x6, 7)
x2 ^= bits.RotateLeft32(x14+x10, 9)
x6 ^= bits.RotateLeft32(x2+x14, 13)
x10 ^= bits.RotateLeft32(x6+x2, 18)
u = x15 + x11
x3 ^= u<<7 | u>>(32-7)
u = x3 + x15
x7 ^= u<<9 | u>>(32-9)
u = x7 + x3
x11 ^= u<<13 | u>>(32-13)
u = x11 + x7
x15 ^= u<<18 | u>>(32-18)
x3 ^= bits.RotateLeft32(x15+x11, 7)
x7 ^= bits.RotateLeft32(x3+x15, 9)
x11 ^= bits.RotateLeft32(x7+x3, 13)
x15 ^= bits.RotateLeft32(x11+x7, 18)
u = x0 + x3
x1 ^= u<<7 | u>>(32-7)
u = x1 + x0
x2 ^= u<<9 | u>>(32-9)
u = x2 + x1
x3 ^= u<<13 | u>>(32-13)
u = x3 + x2
x0 ^= u<<18 | u>>(32-18)
x1 ^= bits.RotateLeft32(x0+x3, 7)
x2 ^= bits.RotateLeft32(x1+x0, 9)
x3 ^= bits.RotateLeft32(x2+x1, 13)
x0 ^= bits.RotateLeft32(x3+x2, 18)
u = x5 + x4
x6 ^= u<<7 | u>>(32-7)
u = x6 + x5
x7 ^= u<<9 | u>>(32-9)
u = x7 + x6
x4 ^= u<<13 | u>>(32-13)
u = x4 + x7
x5 ^= u<<18 | u>>(32-18)
x6 ^= bits.RotateLeft32(x5+x4, 7)
x7 ^= bits.RotateLeft32(x6+x5, 9)
x4 ^= bits.RotateLeft32(x7+x6, 13)
x5 ^= bits.RotateLeft32(x4+x7, 18)
u = x10 + x9
x11 ^= u<<7 | u>>(32-7)
u = x11 + x10
x8 ^= u<<9 | u>>(32-9)
u = x8 + x11
x9 ^= u<<13 | u>>(32-13)
u = x9 + x8
x10 ^= u<<18 | u>>(32-18)
x11 ^= bits.RotateLeft32(x10+x9, 7)
x8 ^= bits.RotateLeft32(x11+x10, 9)
x9 ^= bits.RotateLeft32(x8+x11, 13)
x10 ^= bits.RotateLeft32(x9+x8, 18)
u = x15 + x14
x12 ^= u<<7 | u>>(32-7)
u = x12 + x15
x13 ^= u<<9 | u>>(32-9)
u = x13 + x12
x14 ^= u<<13 | u>>(32-13)
u = x14 + x13
x15 ^= u<<18 | u>>(32-18)
x12 ^= bits.RotateLeft32(x15+x14, 7)
x13 ^= bits.RotateLeft32(x12+x15, 9)
x14 ^= bits.RotateLeft32(x13+x12, 13)
x15 ^= bits.RotateLeft32(x14+x13, 18)
}
x0 += w0
x1 += w1

View File

@ -57,6 +57,15 @@ func New512() hash.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: 136, outputLen: 32, dsbyte: 0x01} }
<<<<<<< HEAD
=======
// 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: 72, outputLen: 64, dsbyte: 0x01} }
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// Sum224 returns the SHA3-224 digest of the data.
func Sum224(data []byte) (digest [28]byte) {

View File

@ -12,6 +12,11 @@ package sha3
import (
"hash"
<<<<<<< HEAD
=======
"golang.org/x/sys/cpu"
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
)
// codes represent 7-bit KIMD/KLMD function codes as defined in
@ -29,6 +34,7 @@ const (
nopad = 0x100
)
<<<<<<< HEAD
// hasMSA6 reports whether the machine supports the SHA-3 and SHAKE function
// codes, as defined in message-security-assist extension 6.
func hasMSA6() bool
@ -36,6 +42,8 @@ func hasMSA6() bool
// hasAsm caches the result of hasMSA6 (which might be expensive to call).
var hasAsm = hasMSA6()
=======
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// 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
@ -237,7 +245,11 @@ func (s *asmState) Clone() ShakeHash {
// new224Asm returns an assembly implementation of SHA3-224 if available,
// otherwise it returns nil.
func new224Asm() hash.Hash {
<<<<<<< HEAD
if hasAsm {
=======
if cpu.S390X.HasSHA3 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return newAsmState(sha3_224)
}
return nil
@ -246,7 +258,11 @@ func new224Asm() hash.Hash {
// new256Asm returns an assembly implementation of SHA3-256 if available,
// otherwise it returns nil.
func new256Asm() hash.Hash {
<<<<<<< HEAD
if hasAsm {
=======
if cpu.S390X.HasSHA3 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return newAsmState(sha3_256)
}
return nil
@ -255,7 +271,11 @@ func new256Asm() hash.Hash {
// new384Asm returns an assembly implementation of SHA3-384 if available,
// otherwise it returns nil.
func new384Asm() hash.Hash {
<<<<<<< HEAD
if hasAsm {
=======
if cpu.S390X.HasSHA3 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return newAsmState(sha3_384)
}
return nil
@ -264,7 +284,11 @@ func new384Asm() hash.Hash {
// new512Asm returns an assembly implementation of SHA3-512 if available,
// otherwise it returns nil.
func new512Asm() hash.Hash {
<<<<<<< HEAD
if hasAsm {
=======
if cpu.S390X.HasSHA3 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return newAsmState(sha3_512)
}
return nil
@ -273,7 +297,11 @@ func new512Asm() hash.Hash {
// newShake128Asm returns an assembly implementation of SHAKE-128 if available,
// otherwise it returns nil.
func newShake128Asm() ShakeHash {
<<<<<<< HEAD
if hasAsm {
=======
if cpu.S390X.HasSHA3 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return newAsmState(shake_128)
}
return nil
@ -282,7 +310,11 @@ func newShake128Asm() ShakeHash {
// newShake256Asm returns an assembly implementation of SHAKE-256 if available,
// otherwise it returns nil.
func newShake256Asm() ShakeHash {
<<<<<<< HEAD
if hasAsm {
=======
if cpu.S390X.HasSHA3 {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return newAsmState(shake_256)
}
return nil

View File

@ -6,6 +6,7 @@
#include "textflag.h"
<<<<<<< HEAD
TEXT ·hasMSA6(SB), NOSPLIT, $16-1
MOVD $0, R0 // KIMD-Query function code
MOVD $tmp-16(SP), R1 // parameter block
@ -26,6 +27,12 @@ yes:
TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40
MOVD function+0(FP), R0
MOVD params+8(FP), R1
=======
// 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
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
LMG src+16(FP), R2, R3 // R2=base, R3=len
continue:
@ -34,11 +41,19 @@ continue:
MOVD $0, R0 // reset R0 for pre-go1.8 compilers
RET
<<<<<<< HEAD
// func klmd(function code, params *[200]byte, dst, src []byte)
TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64
// TODO: SHAKE support
MOVD function+0(FP), R0
MOVD params+8(FP), R1
=======
// 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
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
LMG dst+16(FP), R2, R3 // R2=base, R3=len
LMG src+40(FP), R4, R5 // R4=base, R5=len

View File

@ -27,14 +27,6 @@ const (
katFilename = "testdata/keccakKats.json.deflate"
)
// Internal-use instances of SHAKE used to test against KATs.
func newHashShake128() hash.Hash {
return &state{rate: 168, dsbyte: 0x1f, outputLen: 512}
}
func newHashShake256() hash.Hash {
return &state{rate: 136, dsbyte: 0x1f, outputLen: 512}
}
// testDigests contains functions returning hash.Hash instances
// with output-length equal to the KAT length for SHA-3, Keccak
// and SHAKE instances.
@ -44,15 +36,26 @@ var testDigests = map[string]func() hash.Hash{
"SHA3-384": New384,
"SHA3-512": New512,
"Keccak-256": NewLegacyKeccak256,
<<<<<<< HEAD
"SHAKE128": newHashShake128,
"SHAKE256": newHashShake256,
=======
"Keccak-512": NewLegacyKeccak512,
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}
// testShakes contains functions that return ShakeHash instances for
// testing the ShakeHash-specific interface.
var testShakes = map[string]func() ShakeHash{
"SHAKE128": NewShake128,
"SHAKE256": NewShake256,
// testShakes contains functions that return sha3.ShakeHash instances for
// with output-length equal to the KAT length.
var testShakes = map[string]struct {
constructor func(N []byte, S []byte) ShakeHash
defAlgoName string
defCustomStr string
}{
// NewCShake without customization produces same result as SHAKE
"SHAKE128": {NewCShake128, "", ""},
"SHAKE256": {NewCShake256, "", ""},
"cSHAKE128": {NewCShake128, "CSHAKE128", "CustomStrign"},
"cSHAKE256": {NewCShake256, "CSHAKE256", "CustomStrign"},
}
// decodeHex converts a hex-encoded string into a raw byte string.
@ -70,6 +73,10 @@ type KeccakKats struct {
Digest string `json:"digest"`
Length int64 `json:"length"`
Message string `json:"message"`
// Defined only for cSHAKE
N string `json:"N"`
S string `json:"S"`
}
}
@ -102,10 +109,9 @@ func TestKeccakKats(t *testing.T) {
t.Errorf("error decoding KATs: %s", err)
}
// Do the KATs.
for functionName, kats := range katSet.Kats {
d := testDigests[functionName]()
for _, kat := range kats {
for algo, function := range testDigests {
d := function()
for _, kat := range katSet.Kats[algo] {
d.Reset()
in, err := hex.DecodeString(kat.Message)
if err != nil {
@ -114,8 +120,39 @@ func TestKeccakKats(t *testing.T) {
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",
functionName, impl, kat.Length, kat.Message, 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, 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)
}
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()
}
@ -137,6 +174,14 @@ func TestKeccak(t *testing.T) {
[]byte("abc"),
"4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
},
<<<<<<< HEAD
=======
{
NewLegacyKeccak512,
[]byte("abc"),
"18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96",
},
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}
for _, u := range tests {
@ -178,6 +223,34 @@ func TestUnalignedWrite(t *testing.T) {
t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, 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
}
}
d.Read(got)
if !bytes.Equal(got, want) {
t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
}
}
})
}
@ -219,13 +292,13 @@ func TestAppendNoRealloc(t *testing.T) {
// the same output as repeatedly squeezing the instance.
func TestSqueezing(t *testing.T) {
testUnalignedAndGeneric(t, func(impl string) {
for functionName, newShakeHash := range testShakes {
d0 := newShakeHash()
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 := newShakeHash()
d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
d1.Write([]byte(testString))
var multiple []byte
for range ref {
@ -234,7 +307,7 @@ func TestSqueezing(t *testing.T) {
multiple = append(multiple, one...)
}
if !bytes.Equal(ref, multiple) {
t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref))
t.Errorf("%s (%s): squeezing %d bytes one at a time failed", algo, impl, len(ref))
}
}
})
@ -249,6 +322,50 @@ func sequentialBytes(size int) []byte {
return result
}
func TestReset(t *testing.T) {
out1 := make([]byte, 32)
out2 := make([]byte, 32)
for _, v := range testShakes {
// Calculate hash for the first time
c := v.constructor(nil, []byte{0x99, 0x98})
c.Write(sequentialBytes(0x100))
c.Read(out1)
// Calculate hash again
c.Reset()
c.Write(sequentialBytes(0x100))
c.Read(out2)
if !bytes.Equal(out1, out2) {
t.Error("\nExpected:\n", out1, "\ngot:\n", out2)
}
}
}
func TestClone(t *testing.T) {
out1 := make([]byte, 16)
out2 := make([]byte, 16)
in := sequentialBytes(0x100)
for _, v := range testShakes {
h1 := v.constructor(nil, []byte{0x01})
h1.Write([]byte{0x01})
h2 := h1.Clone()
h1.Write(in)
h1.Read(out1)
h2.Write(in)
h2.Read(out2)
if !bytes.Equal(out1, out2) {
t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2))
}
}
}
// BenchmarkPermutationFunction measures the speed of the permutation function
// with no input data.
func BenchmarkPermutationFunction(b *testing.B) {
@ -334,4 +451,41 @@ func Example_mac() {
d.Read(h)
fmt.Printf("%x\n", h)
// Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
<<<<<<< HEAD
=======
}
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
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}

View File

@ -5,10 +5,18 @@
package sha3
// This file defines the ShakeHash interface, and provides
// functions for creating SHAKE instances, as well as utility
// 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"
"io"
)
@ -31,8 +39,77 @@ type ShakeHash interface {
Reset()
}
func (d *state) Clone() ShakeHash {
return d.clone()
// 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.
@ -42,7 +119,11 @@ func NewShake128() ShakeHash {
if h := newShake128Asm(); h != nil {
return h
}
<<<<<<< HEAD
return &state{rate: 168, dsbyte: 0x1f}
=======
return &state{rate: rate128, dsbyte: dsbyteShake}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}
// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash.
@ -52,7 +133,37 @@ func NewShake256() ShakeHash {
if h := newShake256Asm(); h != nil {
return h
}
<<<<<<< HEAD
return &state{rate: 136, dsbyte: 0x1f}
=======
return &state{rate: rate256, dsbyte: dsbyteShake}
}
// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash,
// a customizable variant of SHAKE128.
// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is
// desired. S is a customization byte string used for domain separation - two cSHAKE
// 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)
}
// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash,
// a customizable variant of SHAKE256.
// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is
// desired. S is a customization byte string used for domain separation - two cSHAKE
// 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)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}
// ShakeSum128 writes an arbitrary-length digest of data into hash.

Binary file not shown.

View File

@ -8,11 +8,13 @@ import (
"bytes"
"crypto/rand"
"errors"
"io"
"net"
"os"
"os/exec"
"path/filepath"
"strconv"
"sync"
"testing"
"time"
@ -196,6 +198,63 @@ 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)
go func() {
defer wg.Done()
c, err := listener.Accept()
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)
}
}
}()
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)
}
c.Close()
wg.Wait()
}
var testCases = []struct {
name string
requestBytes []byte
wantServerErr bool
}{
{"Empty request", []byte{}, false},
{"Short header", []byte{0x00}, true},
{"Empty body", []byte{0x00, 0x00, 0x00, 0x00}, true},
{"Short body", []byte{0x00, 0x00, 0x00, 0x01}, false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { testCase(t, tc.requestBytes, tc.wantServerErr) })
}
}
func TestAgent(t *testing.T) {
for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
testOpenSSHAgent(t, testPrivateKeys[keyType], nil, 0)
@ -215,17 +274,26 @@ func TestCert(t *testing.T) {
testKeyringAgent(t, testPrivateKeys["rsa"], cert, 0)
}
// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
// therefore is buffered (net.Pipe deadlocks if both sides start with
// a write.)
func netPipe() (net.Conn, net.Conn, error) {
// netListener creates a localhost network listener.
func netListener() (net.Listener, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
listener, err = net.Listen("tcp", "[::1]:0")
if err != nil {
return nil, nil, err
return nil, err
}
}
return listener, nil
}
// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
// therefore is buffered (net.Pipe deadlocks if both sides start with
// a write.)
func netPipe() (net.Conn, net.Conn, error) {
listener, err := netListener()
if err != nil {
return nil, nil, err
}
defer listener.Close()
c1, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
@ -444,14 +512,22 @@ func (r *keyringExtended) Extension(extensionType string, contents []byte) ([]by
func TestAgentExtensions(t *testing.T) {
agent, _, cleanup := startOpenSSHAgent(t)
defer cleanup()
<<<<<<< HEAD
result, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02})
=======
_, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02})
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if err == nil {
t.Fatal("should have gotten agent extension failure")
}
agent, cleanup = startAgent(t, &keyringExtended{})
defer cleanup()
<<<<<<< HEAD
result, err = agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02})
=======
result, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02})
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if err != nil {
t.Fatalf("agent extension failure: %v", err)
}
@ -459,7 +535,11 @@ func TestAgentExtensions(t *testing.T) {
t.Fatalf("agent extension result invalid: %v", result)
}
<<<<<<< HEAD
result, err = agent.Extension("bad-extension@example.com", []byte{0x00, 0x01, 0x02})
=======
_, err = agent.Extension("bad-extension@example.com", []byte{0x00, 0x01, 0x02})
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if err == nil {
t.Fatal("should have gotten agent extension failure")
}

View File

@ -541,6 +541,9 @@ func ServeAgent(agent Agent, c io.ReadWriter) error {
return err
}
l := binary.BigEndian.Uint32(length[:])
if l == 0 {
return fmt.Errorf("agent: request size is 0")
}
if l > maxAgentResponseBytes {
// We also cap requests.
return fmt.Errorf("agent: request too large: %d", l)

View File

@ -93,6 +93,9 @@ func BenchmarkEndToEnd(b *testing.B) {
b.Fatalf("Client: %v", err)
}
ch, incoming, err := newCh.Accept()
if err != nil {
b.Fatalf("Accept: %v", err)
}
go DiscardRequests(incoming)
for i := 0; i < b.N; i++ {
if _, err := io.ReadFull(ch, output); err != nil {

View File

@ -149,8 +149,8 @@ type streamPacketCipher struct {
macResult []byte
}
// readPacket reads and decrypt a single packet from the reader argument.
func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
// readCipherPacket reads and decrypt a single packet from the reader argument.
func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
return nil, err
}
@ -221,8 +221,8 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
return s.packetData[:length-paddingLength-1], nil
}
// writePacket encrypts and sends a packet of data to the writer argument
func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
// writeCipherPacket encrypts and sends a packet of data to the writer argument
func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
if len(packet) > maxPacket {
return errors.New("ssh: packet too large")
}
@ -327,7 +327,7 @@ func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms)
const gcmTagSize = 16
func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
// Pad out to multiple of 16 bytes. This is different from the
// stream cipher because that encrypts the length too.
padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
@ -370,7 +370,7 @@ func (c *gcmCipher) incIV() {
}
}
func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
return nil, err
}
@ -486,8 +486,8 @@ type cbcError string
func (e cbcError) Error() string { return string(e) }
func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
p, err := c.readPacketLeaky(seqNum, r)
func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
p, err := c.readCipherPacketLeaky(seqNum, r)
if err != nil {
if _, ok := err.(cbcError); ok {
// Verification error: read a fixed amount of
@ -500,7 +500,7 @@ func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
return p, err
}
func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
blockSize := c.decrypter.BlockSize()
// Read the header, which will include some of the subsequent data in the
@ -576,7 +576,7 @@ func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error)
return c.packetData[prefixLen:paddingStart], nil
}
func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize())
// Length of encrypted portion of the packet (header, payload, padding).
@ -665,7 +665,11 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA
return c, nil
}
<<<<<<< HEAD
func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
=======
func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
s := chacha20.New(c.contentKey, nonce)
var polyKey [32]byte
@ -723,7 +727,11 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
return plain, nil
}
<<<<<<< HEAD
func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
=======
func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
s := chacha20.New(c.contentKey, nonce)
var polyKey [32]byte

View File

@ -56,6 +56,7 @@ func testPacketCipher(t *testing.T, cipher, mac string) {
want := "bla bla"
input := []byte(want)
buf := &bytes.Buffer{}
<<<<<<< HEAD
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
t.Fatalf("writePacket(%q, %q): %v", cipher, mac, err)
}
@ -63,6 +64,15 @@ func testPacketCipher(t *testing.T, cipher, mac string) {
packet, err := server.readPacket(0, buf)
if err != nil {
t.Fatalf("readPacket(%q, %q): %v", cipher, mac, err)
=======
if err := client.writeCipherPacket(0, buf, rand.Reader, input); err != nil {
t.Fatalf("writeCipherPacket(%q, %q): %v", cipher, mac, err)
}
packet, err := server.readCipherPacket(0, buf)
if err != nil {
t.Fatalf("readCipherPacket(%q, %q): %v", cipher, mac, err)
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}
if string(packet) != want {
@ -85,8 +95,8 @@ func TestCBCOracleCounterMeasure(t *testing.T) {
want := "bla bla"
input := []byte(want)
buf := &bytes.Buffer{}
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
t.Errorf("writePacket: %v", err)
if err := client.writeCipherPacket(0, buf, rand.Reader, input); err != nil {
t.Errorf("writeCipherPacket: %v", err)
}
packetSize := buf.Len()
@ -106,9 +116,9 @@ func TestCBCOracleCounterMeasure(t *testing.T) {
fresh.Bytes()[i] ^= 0x01
before := fresh.Len()
_, err = server.readPacket(0, fresh)
_, err = server.readCipherPacket(0, fresh)
if err == nil {
t.Errorf("corrupt byte %d: readPacket succeeded ", i)
t.Errorf("corrupt byte %d: readCipherPacket succeeded ", i)
continue
}
if _, ok := err.(cbcError); !ok {

View File

@ -10,6 +10,11 @@ import (
"errors"
"fmt"
"io"
<<<<<<< HEAD
=======
"log"
"net"
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
"os"
"strings"
"testing"
@ -477,7 +482,7 @@ func TestRetryableAuth(t *testing.T) {
}
}
func ExampleRetryableAuthMethod(t *testing.T) {
func ExampleRetryableAuthMethod() {
user := "testuser"
NumberOfPrompts := 3
@ -495,9 +500,17 @@ func ExampleRetryableAuthMethod(t *testing.T) {
},
}
if err := tryAuth(t, config); err != nil {
t.Fatalf("unable to dial remote side: %s", err)
host := "mysshserver"
netConn, err := net.Dial("tcp", host)
if err != nil {
log.Fatal(err)
}
sshConn, _, _, err := NewClientConn(netConn, host, config)
if err != nil {
log.Fatal(err)
}
_ = sshConn
}
// Test if username is received on server side when NoClientAuth is used

View File

@ -109,6 +109,7 @@ 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)
}
// directionAlgorithms records algorithm choices in one direction (either read or write)
type directionAlgorithms struct {
Cipher string
MAC string
@ -137,7 +138,7 @@ type algorithms struct {
r directionAlgorithms
}
func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
result := &algorithms{}
result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
@ -150,32 +151,37 @@ func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algor
return
}
result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
stoc, ctos := &result.w, &result.r
if isClient {
ctos, stoc = stoc, ctos
}
ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
if err != nil {
return
}
result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
if err != nil {
return
}
result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
if err != nil {
return
}
result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
if err != nil {
return
}
result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
if err != nil {
return
}
result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
if err != nil {
return
}

176
x/crypto/ssh/common_test.go Normal file
View File

@ -0,0 +1,176 @@
// 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 ssh
import (
"reflect"
"testing"
)
func TestFindAgreedAlgorithms(t *testing.T) {
initKex := func(k *kexInitMsg) {
if k.KexAlgos == nil {
k.KexAlgos = []string{"kex1"}
}
if k.ServerHostKeyAlgos == nil {
k.ServerHostKeyAlgos = []string{"hostkey1"}
}
if k.CiphersClientServer == nil {
k.CiphersClientServer = []string{"cipher1"}
}
if k.CiphersServerClient == nil {
k.CiphersServerClient = []string{"cipher1"}
}
if k.MACsClientServer == nil {
k.MACsClientServer = []string{"mac1"}
}
if k.MACsServerClient == nil {
k.MACsServerClient = []string{"mac1"}
}
if k.CompressionClientServer == nil {
k.CompressionClientServer = []string{"compression1"}
}
if k.CompressionServerClient == nil {
k.CompressionServerClient = []string{"compression1"}
}
if k.LanguagesClientServer == nil {
k.LanguagesClientServer = []string{"language1"}
}
if k.LanguagesServerClient == nil {
k.LanguagesServerClient = []string{"language1"}
}
}
initDirAlgs := func(a *directionAlgorithms) {
if a.Cipher == "" {
a.Cipher = "cipher1"
}
if a.MAC == "" {
a.MAC = "mac1"
}
if a.Compression == "" {
a.Compression = "compression1"
}
}
initAlgs := func(a *algorithms) {
if a.kex == "" {
a.kex = "kex1"
}
if a.hostKey == "" {
a.hostKey = "hostkey1"
}
initDirAlgs(&a.r)
initDirAlgs(&a.w)
}
type testcase struct {
name string
clientIn, serverIn kexInitMsg
wantClient, wantServer algorithms
wantErr bool
}
cases := []testcase{
testcase{
name: "standard",
},
testcase{
name: "no common hostkey",
serverIn: kexInitMsg{
ServerHostKeyAlgos: []string{"hostkey2"},
},
wantErr: true,
},
testcase{
name: "no common kex",
serverIn: kexInitMsg{
KexAlgos: []string{"kex2"},
},
wantErr: true,
},
testcase{
name: "no common cipher",
serverIn: kexInitMsg{
CiphersClientServer: []string{"cipher2"},
},
wantErr: true,
},
testcase{
name: "client decides cipher",
serverIn: kexInitMsg{
CiphersClientServer: []string{"cipher1", "cipher2"},
CiphersServerClient: []string{"cipher2", "cipher3"},
},
clientIn: kexInitMsg{
CiphersClientServer: []string{"cipher2", "cipher1"},
CiphersServerClient: []string{"cipher3", "cipher2"},
},
wantClient: algorithms{
r: directionAlgorithms{
Cipher: "cipher3",
},
w: directionAlgorithms{
Cipher: "cipher2",
},
},
wantServer: algorithms{
w: directionAlgorithms{
Cipher: "cipher3",
},
r: directionAlgorithms{
Cipher: "cipher2",
},
},
},
// TODO(hanwen): fix and add tests for AEAD ignoring
// the MACs field
}
for i := range cases {
initKex(&cases[i].clientIn)
initKex(&cases[i].serverIn)
initAlgs(&cases[i].wantClient)
initAlgs(&cases[i].wantServer)
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
serverAlgs, serverErr := findAgreedAlgorithms(false, &c.clientIn, &c.serverIn)
clientAlgs, clientErr := findAgreedAlgorithms(true, &c.clientIn, &c.serverIn)
serverHasErr := serverErr != nil
clientHasErr := clientErr != nil
if c.wantErr != serverHasErr || c.wantErr != clientHasErr {
t.Fatalf("got client/server error (%v, %v), want hasError %v",
clientErr, serverErr, c.wantErr)
}
if c.wantErr {
return
}
if !reflect.DeepEqual(serverAlgs, &c.wantServer) {
t.Errorf("server: got algs %#v, want %#v", serverAlgs, &c.wantServer)
}
if !reflect.DeepEqual(clientAlgs, &c.wantClient) {
t.Errorf("server: got algs %#v, want %#v", clientAlgs, &c.wantClient)
}
})
}
}

View File

@ -140,7 +140,7 @@ func ExampleNewServerConn() {
}
}
func ExampleHostKeyCheck() {
func ExampleClientConfig_HostKeyCallback() {
// Every client must provide a host key check. Here is a
// simple-minded parse of OpenSSH's known_hosts file
host := "hostname"

View File

@ -543,7 +543,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
clientInit := otherInit
serverInit := t.sentInitMsg
if len(t.hostKeys) == 0 {
isClient := len(t.hostKeys) == 0
if isClient {
clientInit, serverInit = serverInit, clientInit
magics.clientKexInit = t.sentInitPacket
@ -551,7 +552,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
}
var err error
t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit)
if err != nil {
return err
}

View File

@ -350,8 +350,8 @@ func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.Public
return db.checkAddr(hostToCheck, remoteKey)
}
// checkAddrs checks if we can find the given public key for any of
// the given addresses. If we only find an entry for the IP address,
// checkAddr checks if we can find the given public key for the
// given address. If we only find an entry for the IP address,
// or only the hostname, then this still succeeds.
func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error {
// TODO(hanwen): are these the right semantics? What if there

View File

@ -764,3 +764,29 @@ func decode(packet []byte) (interface{}, error) {
}
return msg, nil
}
var packetTypeNames = map[byte]string{
msgDisconnect: "disconnectMsg",
msgServiceRequest: "serviceRequestMsg",
msgServiceAccept: "serviceAcceptMsg",
msgKexInit: "kexInitMsg",
msgKexDHInit: "kexDHInitMsg",
msgKexDHReply: "kexDHReplyMsg",
msgUserAuthRequest: "userAuthRequestMsg",
msgUserAuthSuccess: "userAuthSuccessMsg",
msgUserAuthFailure: "userAuthFailureMsg",
msgUserAuthPubKeyOk: "userAuthPubKeyOkMsg",
msgGlobalRequest: "globalRequestMsg",
msgRequestSuccess: "globalRequestSuccessMsg",
msgRequestFailure: "globalRequestFailureMsg",
msgChannelOpen: "channelOpenMsg",
msgChannelData: "channelDataMsg",
msgChannelOpenConfirm: "channelOpenConfirmMsg",
msgChannelOpenFailure: "channelOpenFailureMsg",
msgChannelWindowAdjust: "windowAdjustMsg",
msgChannelEOF: "channelEOFMsg",
msgChannelClose: "channelCloseMsg",
msgChannelRequest: "channelRequestMsg",
msgChannelSuccess: "channelRequestSuccessMsg",
msgChannelFailure: "channelRequestFailureMsg",
}

View File

@ -35,7 +35,7 @@ func dial(handler serverType, t *testing.T) *Client {
}
conf.AddHostKey(testSigners["rsa"])
_, chans, reqs, err := NewServerConn(c1, &conf)
conn, chans, reqs, err := NewServerConn(c1, &conf)
if err != nil {
t.Fatalf("Unable to handshake: %v", err)
}
@ -56,6 +56,9 @@ func dial(handler serverType, t *testing.T) *Client {
handler(ch, inReqs, t)
}()
}
if err := conn.Wait(); err != io.EOF {
t.Logf("server exit reason: %v", err)
}
}()
config := &ClientConfig{
@ -358,10 +361,9 @@ func TestServerWindow(t *testing.T) {
}
written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes)
if err != nil {
t.Fatalf("failed to copy origBuf to serverStdin: %v", err)
}
if written != windowTestBytes {
t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes)
t.Errorf("failed to copy origBuf to serverStdin: %v", err)
} else if written != windowTestBytes {
t.Errorf("Wrote only %d of %d bytes to server", written, windowTestBytes)
}
echoedBytes := <-result

View File

@ -7,6 +7,7 @@ package terminal
import (
"bytes"
"io"
"strconv"
"sync"
"unicode/utf8"
)
@ -159,6 +160,10 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
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:]
}
}
@ -267,34 +272,44 @@ func (t *Terminal) moveCursorToPos(pos int) {
}
func (t *Terminal) move(up, down, left, right int) {
movement := make([]rune, 3*(up+down+left+right))
m := movement
for i := 0; i < up; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'A'
m = m[3:]
}
for i := 0; i < down; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'B'
m = m[3:]
}
for i := 0; i < left; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'D'
m = m[3:]
}
for i := 0; i < right; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'C'
m = m[3:]
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')
}
t.queue(movement)
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() {

View File

@ -91,6 +91,12 @@ var keyPressTests = []struct {
{
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",
@ -231,6 +237,49 @@ func TestKeyPresses(t *testing.T) {
}
}
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"),

View File

@ -64,13 +64,19 @@ func Restore(fd int, state *State) error {
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}
// GetSize returns the dimensions of the given terminal.
// 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
}
<<<<<<< HEAD
return int(info.Size.X), int(info.Size.Y), nil
=======
return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
}
// ReadPassword reads a line of input from a terminal without local echo. This

View File

@ -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 darwin dragonfly freebsd linux netbsd openbsd
// +build aix darwin dragonfly freebsd linux netbsd openbsd
package test

View File

@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
<<<<<<< HEAD
// +build darwin dragonfly freebsd linux netbsd openbsd
=======
// +build aix darwin dragonfly freebsd linux netbsd openbsd
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
package test

View File

@ -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 darwin dragonfly freebsd linux netbsd openbsd
// +build aix darwin dragonfly freebsd linux netbsd openbsd
package test

View File

@ -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
// +build !windows,!solaris,!js
package test
@ -104,8 +104,8 @@ func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) {
if c.LocalAddr().String() != x.listenAddr {
t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String())
}
if c.RemoteAddr().String() != "@" {
t.Fatalf("expected \"@\", got %q", c.RemoteAddr().String())
if c.RemoteAddr().String() != "@" && c.RemoteAddr().String() != "" {
t.Fatalf("expected \"@\" or \"\", got %q", c.RemoteAddr().String())
}
}

View File

@ -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 darwin dragonfly freebsd linux netbsd openbsd
// +build aix darwin dragonfly freebsd linux netbsd openbsd
package test

View File

@ -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
// +build !windows,!solaris,!js
package test
@ -13,6 +13,7 @@ import (
"errors"
"fmt"
"io"
"runtime"
"strings"
"testing"
@ -217,6 +218,11 @@ func TestKeyChange(t *testing.T) {
}
func TestInvalidTerminalMode(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())
@ -234,6 +240,11 @@ func TestInvalidTerminalMode(t *testing.T) {
}
func TestValidTerminalMode(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())
@ -278,6 +289,14 @@ func TestValidTerminalMode(t *testing.T) {
}
func TestWindowChange(t *testing.T) {
<<<<<<< HEAD
=======
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)
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
server := newServer(t)
defer server.Shutdown()
conn := server.Dial(clientConfig())
@ -351,7 +370,11 @@ func testOneCipher(t *testing.T, cipher string, cipherOrder []string) {
t.Fatalf("NewSession: %v", err)
}
<<<<<<< HEAD
out, err := session.Output(fmt.Sprintf("dd if=/dev/zero of=/dev/stdout bs=%d count=1", numBytes))
=======
out, err := session.Output(fmt.Sprintf("dd if=/dev/zero bs=%d count=1", numBytes))
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
if err != nil {
t.Fatalf("Output: %v", err)
}
@ -384,17 +407,19 @@ func TestMACs(t *testing.T) {
macOrder := config.MACs
for _, mac := range macOrder {
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)
}
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)
}
})
}
}
@ -403,17 +428,19 @@ func TestKeyExchanges(t *testing.T) {
config.SetDefaults()
kexOrder := config.KeyExchanges
for _, kex := range kexOrder {
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)
}
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)
}
})
}
}
@ -424,20 +451,22 @@ func TestClientAuthAlgorithms(t *testing.T) {
"ecdsa",
"ed25519",
} {
server := newServer(t)
conf := clientConfig()
conf.SetDefaults()
conf.Auth = []ssh.AuthMethod{
ssh.PublicKeys(testSigners[key]),
}
t.Run(key, func(t *testing.T) {
server := newServer(t)
conf := clientConfig()
conf.SetDefaults()
conf.Auth = []ssh.AuthMethod{
ssh.PublicKeys(testSigners[key]),
}
conn, err := server.TryDial(conf)
if err == nil {
conn.Close()
} else {
t.Errorf("failed for key %q", key)
}
conn, err := server.TryDial(conf)
if err == nil {
conn.Close()
} else {
t.Errorf("failed for key %q", key)
}
server.Shutdown()
server.Shutdown()
})
}
}

View File

@ -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 darwin dragonfly freebsd linux netbsd openbsd plan9
// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9
package test
@ -306,7 +306,17 @@ func newServerForConfig(t *testing.T, config string, configVars map[string]strin
if err != nil {
t.Fatalf("user.Current: %v", err)
}
<<<<<<< HEAD
if u.Name == "root" {
=======
uname := u.Name
if uname == "" {
// Check the value of u.Username as u.Name
// can be "" on some OSes like AIX.
uname = u.Username
}
if uname == "root" {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
t.Skip("skipping test because current user is root")
}
dir, err := ioutil.TempDir("", "sshtest")

View File

@ -53,14 +53,14 @@ type transport struct {
// packetCipher represents a combination of SSH encryption/MAC
// protocol. A single instance should be used for one direction only.
type packetCipher interface {
// writePacket encrypts the packet and writes it to w. The
// writeCipherPacket encrypts the packet and writes it to w. The
// contents of the packet are generally scrambled.
writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
// readPacket reads and decrypts a packet of data. The
// readCipherPacket reads and decrypts a packet of data. The
// returned packet may be overwritten by future calls of
// readPacket.
readPacket(seqnum uint32, r io.Reader) ([]byte, error)
readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error)
}
// connectionState represents one side (read or write) of the
@ -127,7 +127,7 @@ func (t *transport) readPacket() (p []byte, err error) {
}
func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
packet, err := s.packetCipher.readPacket(s.seqNum, r)
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
s.seqNum++
if err == nil && len(packet) == 0 {
err = errors.New("ssh: zero length packet")
@ -175,7 +175,7 @@ func (t *transport) writePacket(packet []byte) error {
func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
err := s.packetCipher.writePacket(s.seqNum, w, rand, packet)
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
if err != nil {
return err
}

View File

@ -5,6 +5,17 @@
// Package tea implements the TEA algorithm, as defined in Needham and
// Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See
// http://www.cix.co.uk/~klockstone/tea.pdf for details.
<<<<<<< HEAD
=======
//
// TEA is a legacy cipher and its short block size makes it vulnerable to
// birthday bound attacks (see https://sweet32.info). It should only be used
// where compatibility with legacy systems, not security, is the goal.
//
// 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).
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
package tea
import (

View File

@ -3,6 +3,12 @@
// license that can be found in the LICENSE file.
// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
//
// Deprecated: Twofish is a legacy cipher and should not be used for new
// applications. Also, this package does not and will not provide an optimized
// 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"
// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]

View File

@ -4,6 +4,14 @@
// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
// 1997 technical report, "Tea extensions."
//
// XTEA is a legacy cipher and its short block size makes it vulnerable to
// birthday bound attacks (see https://sweet32.info). It should only be used
// where compatibility with legacy systems, not security, is the goal.
//
// 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"
// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf

View File

@ -15,22 +15,28 @@
// effectively create a unique key for each sector.
//
// XTS does not provide any authentication. An attacker can manipulate the
// ciphertext and randomise a block (16 bytes) of the plaintext.
// ciphertext and randomise a block (16 bytes) of the plaintext. This package
// does not implement ciphertext-stealing so sectors must be a multiple of 16
// bytes.
//
// (Note: this package does not implement ciphertext-stealing so sectors must
// be a multiple of 16 bytes.)
// 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"
import (
"crypto/cipher"
"encoding/binary"
"errors"
<<<<<<< HEAD
=======
"sync"
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
"golang.org/x/crypto/internal/subtle"
)
// Cipher contains an expanded key structure. It doesn't contain mutable state
// and therefore can be used concurrently.
// Cipher contains an expanded key structure. It is safe for concurrent use if
// the underlying block cipher is safe for concurrent use.
type Cipher struct {
k1, k2 cipher.Block
}
@ -39,6 +45,12 @@ type Cipher struct {
// only defined for 16-byte ciphers.
const blockSize = 16
var tweakPool = sync.Pool{
New: func() interface{} {
return new([blockSize]byte)
},
}
// NewCipher creates a Cipher given a function for creating the underlying
// block cipher (which must have a block size of 16 bytes). The key must be
// twice the length of the underlying cipher's key.
@ -70,7 +82,14 @@ func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
panic("xts: invalid buffer overlap")
}
<<<<<<< HEAD
var tweak [blockSize]byte
=======
tweak := tweakPool.Get().(*[blockSize]byte)
for i := range tweak {
tweak[i] = 0
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
c.k2.Encrypt(tweak[:], tweak[:])
@ -86,8 +105,10 @@ func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
plaintext = plaintext[blockSize:]
ciphertext = ciphertext[blockSize:]
mul2(&tweak)
mul2(tweak)
}
tweakPool.Put(tweak)
}
// Decrypt decrypts a sector of ciphertext and puts the result into plaintext.
@ -104,7 +125,14 @@ func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
panic("xts: invalid buffer overlap")
}
<<<<<<< HEAD
var tweak [blockSize]byte
=======
tweak := tweakPool.Get().(*[blockSize]byte)
for i := range tweak {
tweak[i] = 0
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
binary.LittleEndian.PutUint64(tweak[:8], sectorNum)
c.k2.Encrypt(tweak[:], tweak[:])
@ -120,8 +148,10 @@ func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
plaintext = plaintext[blockSize:]
ciphertext = ciphertext[blockSize:]
mul2(&tweak)
mul2(tweak)
}
tweakPool.Put(tweak)
}
// mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of

View File

@ -103,3 +103,22 @@ func TestShorterCiphertext(t *testing.T) {
t.Errorf("En/Decryption is not inverse")
}
}
<<<<<<< HEAD
=======
func BenchmarkXTS(b *testing.B) {
b.ReportAllocs()
c, err := NewCipher(aes.NewCipher, make([]byte, 32))
if err != nil {
b.Fatalf("NewCipher failed: %s", err)
}
plaintext := make([]byte, 32)
encrypted := make([]byte, 48)
decrypted := make([]byte, 48)
for i := 0; i < b.N; i++ {
c.Encrypt(encrypted, plaintext, 0)
c.Decrypt(decrypted, encrypted[:len(plaintext)], 0)
}
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a

View File

@ -12,6 +12,8 @@ import (
"golang.org/x/net/bpf"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
"golang.org/x/net/nettest"
)
// A virtualMachine is a BPF virtual machine which can process an
@ -137,7 +139,7 @@ type osVirtualMachine struct {
// testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting
// packets into a UDP listener with a BPF program attached to it.
func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) {
l, err := net.ListenPacket("udp4", "127.0.0.1:0")
l, err := nettest.NewLocalPacketListener("udp")
if err != nil {
t.Fatalf("failed to open OS VM UDP listener: %v", err)
}
@ -147,12 +149,17 @@ func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) {
t.Fatalf("failed to compile BPF program: %v", err)
}
p := ipv4.NewPacketConn(l)
if err = p.SetBPF(prog); err != nil {
ip := l.LocalAddr().(*net.UDPAddr).IP
if ip.To4() != nil && ip.To16() == nil {
err = ipv4.NewPacketConn(l).SetBPF(prog)
} else {
err = ipv6.NewPacketConn(l).SetBPF(prog)
}
if err != nil {
t.Fatalf("failed to attach BPF program to listener: %v", err)
}
s, err := net.Dial("udp4", l.LocalAddr().String())
s, err := net.Dial(l.LocalAddr().Network(), l.LocalAddr().String())
if err != nil {
t.Fatalf("failed to dial connection to listener: %v", err)
}

6
x/net/go.mod Normal file
View File

@ -0,0 +1,6 @@
module golang.org/x/net
require (
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
golang.org/x/text v0.3.0
)

6
x/net/go.sum Normal file
View File

@ -0,0 +1,6 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -177,7 +177,11 @@ func (s *nodeStack) index(n *Node) int {
// contains returns whether a is within s.
func (s *nodeStack) contains(a atom.Atom) bool {
for _, n := range *s {
<<<<<<< HEAD
if n.DataAtom == a {
=======
if n.DataAtom == a && n.Namespace == "" {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
return true
}
}

View File

@ -439,9 +439,12 @@ func (p *parser) resetInsertionMode() {
case a.Select:
if !last {
for ancestor, first := n, p.oe[0]; ancestor != first; {
<<<<<<< HEAD
if ancestor == first {
break
}
=======
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
ancestor = p.oe[p.oe.index(ancestor)-1]
switch ancestor.DataAtom {
case a.Template:
@ -633,7 +636,16 @@ func inHeadIM(p *parser) bool {
p.oe.pop()
p.acknowledgeSelfClosingTag()
return true
case a.Script, a.Title, a.Noscript, a.Noframes, a.Style:
case a.Noscript:
p.addElement()
if p.scripting {
p.setOriginalIM()
p.im = textIM
} else {
p.im = inHeadNoscriptIM
}
return true
case a.Script, a.Title, a.Noframes, a.Style:
p.addElement()
p.setOriginalIM()
p.im = textIM
@ -695,6 +707,52 @@ func inHeadIM(p *parser) bool {
return false
}
<<<<<<< HEAD
=======
// 12.2.6.4.5.
func inHeadNoscriptIM(p *parser) bool {
switch p.tok.Type {
case DoctypeToken:
// Ignore the token.
return true
case StartTagToken:
switch p.tok.DataAtom {
case a.Html:
return inBodyIM(p)
case a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Style:
return inHeadIM(p)
case a.Head, a.Noscript:
// Ignore the token.
return true
}
case EndTagToken:
switch p.tok.DataAtom {
case a.Noscript, a.Br:
default:
// Ignore the token.
return true
}
case TextToken:
s := strings.TrimLeft(p.tok.Data, whitespace)
if len(s) == 0 {
// It was all whitespace.
return inHeadIM(p)
}
case CommentToken:
return inHeadIM(p)
}
p.oe.pop()
if p.top().DataAtom != a.Head {
panic("html: the new current node will be a head element.")
}
p.im = inHeadIM
if p.tok.DataAtom == a.Noscript {
return true
}
return false
}
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
// Section 12.2.6.4.6.
func afterHeadIM(p *parser) bool {
switch p.tok.Type {
@ -904,7 +962,7 @@ func inBodyIM(p *parser) bool {
case a.A:
for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
p.inBodyEndTagFormatting(a.A)
p.inBodyEndTagFormatting(a.A, "a")
p.oe.remove(n)
p.afe.remove(n)
break
@ -918,7 +976,7 @@ func inBodyIM(p *parser) bool {
case a.Nobr:
p.reconstructActiveFormattingElements()
if p.elementInScope(defaultScope, a.Nobr) {
p.inBodyEndTagFormatting(a.Nobr)
p.inBodyEndTagFormatting(a.Nobr, "nobr")
p.reconstructActiveFormattingElements()
}
p.addFormattingElement()
@ -1126,7 +1184,7 @@ func inBodyIM(p *parser) bool {
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
p.inBodyEndTagFormatting(p.tok.DataAtom)
p.inBodyEndTagFormatting(p.tok.DataAtom, p.tok.Data)
case a.Applet, a.Marquee, a.Object:
if p.popUntil(defaultScope, p.tok.DataAtom) {
p.clearActiveFormattingElements()
@ -1137,7 +1195,7 @@ func inBodyIM(p *parser) bool {
case a.Template:
return inHeadIM(p)
default:
p.inBodyEndTagOther(p.tok.DataAtom)
p.inBodyEndTagOther(p.tok.DataAtom, p.tok.Data)
}
case CommentToken:
p.addChild(&Node{
@ -1164,7 +1222,7 @@ func inBodyIM(p *parser) bool {
return true
}
func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
// This is the "adoption agency" algorithm, described at
// https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
@ -1186,7 +1244,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
}
}
if formattingElement == nil {
p.inBodyEndTagOther(tagAtom)
p.inBodyEndTagOther(tagAtom, tagName)
return
}
feIndex := p.oe.index(formattingElement)
@ -1291,9 +1349,17 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) {
for i := len(p.oe) - 1; i >= 0; i-- {
if p.oe[i].DataAtom == tagAtom {
// Two element nodes have the same tag if they have the same Data (a
// string-typed field). As an optimization, for common HTML tags, each
// Data string is assigned a unique, non-zero DataAtom (a uint32-typed
// field), since integer comparison is faster than string comparison.
// Uncommon (custom) tags get a zero DataAtom.
//
// The if condition here is equivalent to (p.oe[i].Data == tagName).
if (p.oe[i].DataAtom == tagAtom) &&
((tagAtom != 0) || (p.oe[i].Data == tagName)) {
p.oe = p.oe[:i]
break
}
@ -1687,8 +1753,9 @@ func inCellIM(p *parser) bool {
return true
}
// Close the cell and reprocess.
p.popUntil(tableScope, a.Td, a.Th)
p.clearActiveFormattingElements()
if p.popUntil(tableScope, a.Td, a.Th) {
p.clearActiveFormattingElements()
}
p.im = inRowIM
return false
}
@ -1719,8 +1786,12 @@ func inSelectIM(p *parser) bool {
}
p.addElement()
case a.Select:
p.tok.Type = EndTagToken
return false
if p.popUntil(selectScope, a.Select) {
p.resetInsertionMode()
} else {
// Ignore the token.
return true
}
case a.Input, a.Keygen, a.Textarea:
if p.elementInScope(selectScope, a.Select) {
p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
@ -1750,6 +1821,9 @@ func inSelectIM(p *parser) bool {
case a.Select:
if p.popUntil(selectScope, a.Select) {
p.resetInsertionMode()
} else {
// Ignore the token.
return true
}
case a.Template:
return inHeadIM(p)
@ -1775,13 +1849,22 @@ func inSelectInTableIM(p *parser) bool {
case StartTagToken, EndTagToken:
switch p.tok.DataAtom {
case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) {
p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
return false
} else {
if p.tok.Type == EndTagToken && !p.elementInScope(tableScope, p.tok.DataAtom) {
// Ignore the token.
return true
}
// This is like p.popUntil(selectScope, a.Select), but it also
// matches <math select>, not just <select>. Matching the MathML
// tag is arguably incorrect (conceptually), but it mimics what
// Chromium does.
for i := len(p.oe) - 1; i >= 0; i-- {
if n := p.oe[i]; n.DataAtom == a.Select {
p.oe = p.oe[:i]
break
}
}
p.resetInsertionMode()
return false
}
}
return inSelectIM(p)
@ -2226,6 +2309,33 @@ func (p *parser) parse() error {
//
// The input is assumed to be UTF-8 encoded.
func Parse(r io.Reader) (*Node, error) {
return ParseWithOptions(r)
}
// ParseFragment parses a fragment of HTML and returns the nodes that were
// found. If the fragment is the InnerHTML for an existing element, pass that
// element in context.
//
// It has the same intricacies as Parse.
func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
return ParseFragmentWithOptions(r, context)
}
// ParseOption configures a parser.
type ParseOption func(p *parser)
// ParseOptionEnableScripting configures the scripting flag.
// https://html.spec.whatwg.org/multipage/webappapis.html#enabling-and-disabling-scripting
//
// By default, scripting is enabled.
func ParseOptionEnableScripting(enable bool) ParseOption {
return func(p *parser) {
p.scripting = enable
}
}
// ParseWithOptions is like Parse, with options.
func ParseWithOptions(r io.Reader, opts ...ParseOption) (*Node, error) {
p := &parser{
tokenizer: NewTokenizer(r),
doc: &Node{
@ -2235,6 +2345,11 @@ func Parse(r io.Reader) (*Node, error) {
framesetOK: true,
im: initialIM,
}
for _, f := range opts {
f(p)
}
err := p.parse()
if err != nil {
return nil, err
@ -2242,12 +2357,17 @@ func Parse(r io.Reader) (*Node, error) {
return p.doc, nil
}
<<<<<<< HEAD
// ParseFragment parses a fragment of HTML and returns the nodes that were
// found. If the fragment is the InnerHTML for an existing element, pass that
// element in context.
//
// It has the same intricacies as Parse.
func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
=======
// ParseFragmentWithOptions is like ParseFragment, with options.
func ParseFragmentWithOptions(r io.Reader, context *Node, opts ...ParseOption) ([]*Node, error) {
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a
contextTag := ""
if context != nil {
if context.Type != ElementNode {
@ -2271,6 +2391,10 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
context: context,
}
for _, f := range opts {
f(p)
}
root := &Node{
Type: ElementNode,
DataAtom: a.Html,

View File

@ -238,11 +238,30 @@ func TestParser(t *testing.T) {
}
}
// Issue 16318
func TestParserWithoutScripting(t *testing.T) {
text := `<noscript><img src='https://golang.org/doc/gopher/frontpage.png' /></noscript><p><img src='https://golang.org/doc/gopher/doc.png' /></p>`
want := `| <html>
| <head>
| <noscript>
| <body>
| "<img src='https://golang.org/doc/gopher/frontpage.png' />"
| <p>
| <img>
| src="https://golang.org/doc/gopher/doc.png"
`
err := testParseCase(text, want, "", ParseOptionEnableScripting(false))
if err != nil {
t.Errorf("test with scripting is disabled, %q, %s", text, err)
}
}
// testParseCase tests one test case from the test files. If the test does not
// pass, it returns an error that explains the failure.
// text is the HTML to be parsed, want is a dump of the correct parse tree,
// and context is the name of the context node, if any.
func testParseCase(text, want, context string) (err error) {
func testParseCase(text, want, context string, opts ...ParseOption) (err error) {
defer func() {
if x := recover(); x != nil {
switch e := x.(type) {
@ -256,7 +275,7 @@ func testParseCase(text, want, context string) (err error) {
var doc *Node
if context == "" {
doc, err = Parse(strings.NewReader(text))
doc, err = ParseWithOptions(strings.NewReader(text), opts...)
if err != nil {
return err
}
@ -266,7 +285,7 @@ func testParseCase(text, want, context string) (err error) {
DataAtom: atom.Lookup([]byte(context)),
Data: context,
}
nodes, err := ParseFragment(strings.NewReader(text), contextNode)
nodes, err := ParseFragmentWithOptions(strings.NewReader(text), contextNode, opts...)
if err != nil {
return err
}
@ -367,7 +386,8 @@ var renderTestBlacklist = map[string]bool{
`<script><!--<script </s`: true,
// Reconstructing the active formatting elements results in a <plaintext>
// element that contains an <a> element.
`<!doctype html><p><a><plaintext>b`: true,
`<!doctype html><p><a><plaintext>b`: true,
`<table><math><select><mi><select></table>`: true,
}
func TestNodeConsistency(t *testing.T) {

View File

@ -0,0 +1,12 @@
#data
<table><math><th><mo><select></table>
#errors
#document
| <html>
| <head>
| <body>
| <math math>
| <math th>
| <math mo>
| <select>
| <table>

View File

@ -0,0 +1,11 @@
#data
<html><head></head><body><tag1><tag2 /><p></p></tag1><div></div></body></html>
#errors
#document
| <html>
| <head>
| <body>
| <tag1>
| <tag2>
| <p>
| <div>

12
x/net/html/testdata/go/select.dat vendored Normal file
View File

@ -0,0 +1,12 @@
#data
<table><math><select><mi><select></table>
#errors
#document
| <html>
| <head>
| <body>
| <math math>
| <math select>
| <math mi>
| <select>
| <table>

View File

@ -35,3 +35,31 @@
| <math mo>
| <template>
| content
<<<<<<< HEAD
=======
#data
<svg><template><desc><t><svg></template>
#errors
#document
| <html>
| <head>
| <body>
| <svg svg>
| <svg template>
| <svg desc>
| <t>
| <svg svg>
#data
<math><template><mn><b></template>
#errors
#document
| <html>
| <head>
| <body>
| <math math>
| <math template>
| <math mn>
| <b>
>>>>>>> bd25a1f6d07d2d464980e6a8576c1ed59bb3950a

Some files were not shown because too many files have changed in this diff Show More