Grand test fixup (#138)

* start fixing up tests

* fix up tests + automate with drone

* fiddle with linting

* messing about with drone.yml

* some more fiddling

* hmmm

* add cache

* add vendor directory

* verbose

* ci updates

* update some little things

* update sig
This commit is contained in:
Tobi Smethurst 2021-08-12 21:03:24 +02:00 committed by GitHub
commit 98263a7de6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2677 changed files with 1090869 additions and 219 deletions

6
vendor/mellium.im/sasl/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
*.sw[op]
*.svg
*.xml
*.out
Gopkg.lock
vendor/

25
vendor/mellium.im/sasl/LICENSE.md vendored Normal file
View file

@ -0,0 +1,25 @@
## The BSD 2-Clause License
Copyright © 2014 The Mellium Contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

20
vendor/mellium.im/sasl/Makefile vendored Normal file
View file

@ -0,0 +1,20 @@
PACKAGES=$$(go list ./... | grep -v '/vendor/')
.PHONEY: test
test:
go test -cover $(PACKAGES)
.PHONEY: bench
bench:
go test -cover -bench . -benchmem -run 'Benchmark.*' $(PACKAGES)
.PHONEY: vet
vet:
go vet $(PACKAGES)
deps.svg: *.go
( echo "digraph G {"; \
go list -f '{{range .Imports}}{{printf "\t%q -> %q;\n" $$.ImportPath .}}{{end}}' \
$$(go list -f '{{join .Deps " "}}' .) .; \
echo "}"; \
) | dot -Tsvg -o $@

22
vendor/mellium.im/sasl/README.md vendored Normal file
View file

@ -0,0 +1,22 @@
# SASL
[![GoDoc](https://godoc.org/mellium.im/sasl?status.svg)](https://godoc.org/mellium.im/sasl)
[![License](https://img.shields.io/badge/license-FreeBSD-blue.svg)](https://opensource.org/licenses/BSD-2-Clause)
[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/purple_img.png)](https://www.buymeacoffee.com/samwhited)
A Go library implementing the Simple Authentication and Security Layer (SASL) as
defined by [RFC 4422][rfc4422].
## Issues and feature requests
To file a bug report, please use the [issue tracker][issues].
## License
The package may be used under the terms of the BSD 2-Clause License a copy of
which may be found in the file [LICENSE.md][LICENSE].
[rfc4422]: https://tools.ietf.org/html/rfc4422
[issues]: https://bitbucket.org/mellium/sasl/issues?status=new&status=open
[LICENSE]: ./LICENSE.md

View file

@ -0,0 +1,10 @@
image: golang:latest
pipelines:
default:
- step:
script:
- go version
- go vet ./...
- go test -race ./...
- go test -cover ./...
- go test -bench . -benchmem ./...

15
vendor/mellium.im/sasl/doc.go vendored Normal file
View file

@ -0,0 +1,15 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
// Package sasl implements the Simple Authentication and Security Layer (SASL)
// as defined by RFC 4422.
//
// Most users of this package will only need to create a Negotiator using
// NewClient or NewServer and call its Step method repeatedly.
// Authors implementing SASL mechanisms other than the builtin ones will want to
// create a Mechanism struct which will likely use the other methods on the
// Negotiator.
//
// Be advised: This API is still unstable and is subject to change.
package sasl // import "mellium.im/sasl"

3
vendor/mellium.im/sasl/go.mod vendored Normal file
View file

@ -0,0 +1,3 @@
module mellium.im/sasl
require golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b

2
vendor/mellium.im/sasl/go.sum vendored Normal file
View file

@ -0,0 +1,2 @@
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b h1:2b9XGzhjiYsYPnKXoEfL7klWZQIt8IfyRCz62gCqqlQ=
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=

58
vendor/mellium.im/sasl/mechanism.go vendored Normal file
View file

@ -0,0 +1,58 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
package sasl
import (
"crypto/sha1"
"crypto/sha256"
"errors"
)
// Define common errors used by SASL mechanisms and negotiators.
var (
ErrInvalidState = errors.New("Invalid state")
ErrInvalidChallenge = errors.New("Invalid or missing challenge")
ErrAuthn = errors.New("Authentication error")
ErrTooManySteps = errors.New("Step called too many times")
)
var (
// Plain is a Mechanism that implements the PLAIN authentication mechanism
// as defined by RFC 4616.
Plain Mechanism = plain
// ScramSha256Plus is a Mechanism that implements the SCRAM-SHA-256-PLUS
// authentication mechanism defined in RFC 7677. The only supported channel
// binding type is tls-unique as defined in RFC 5929.
ScramSha256Plus Mechanism = scram("SCRAM-SHA-256-PLUS", sha256.New)
// ScramSha256 is a Mechanism that implements the SCRAM-SHA-256
// authentication mechanism defined in RFC 7677.
ScramSha256 Mechanism = scram("SCRAM-SHA-256", sha256.New)
// ScramSha1Plus is a Mechanism that implements the SCRAM-SHA-1-PLUS
// authentication mechanism defined in RFC 5802. The only supported channel
// binding type is tls-unique as defined in RFC 5929.
ScramSha1Plus Mechanism = scram("SCRAM-SHA-1-PLUS", sha1.New)
// ScramSha1 is a Mechanism that implements the SCRAM-SHA-1 authentication
// mechanism defined in RFC 5802.
ScramSha1 Mechanism = scram("SCRAM-SHA-1", sha1.New)
)
// Mechanism represents a SASL mechanism that can be used by a Client or Server
// to perform the actual negotiation. Base64 encoding the final challenges and
// responses should not be performed by the mechanism.
//
// Mechanisms must be stateless and may be shared between goroutines. When a
// mechanism needs to store state between the different steps it can return
// anything that it needs to store and the value will be cached by the
// negotiator and passed in as the data parameter when the next challenge is
// received.
type Mechanism struct {
Name string
Start func(n *Negotiator) (more bool, resp []byte, cache interface{}, err error)
Next func(n *Negotiator, challenge []byte, data interface{}) (more bool, resp []byte, cache interface{}, err error)
}

192
vendor/mellium.im/sasl/negotiator.go vendored Normal file
View file

@ -0,0 +1,192 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
package sasl
import (
"crypto/rand"
"crypto/tls"
"strings"
)
// State represents the current state of a Negotiator.
// The first two bits represent the actual state of the state machine and the
// last 3 bits are a bitmask that define the machines behavior.
// The remaining bits should not be used.
type State uint8
// The current step of the Server or Client (represented by the first two bits
// of the state byte).
const (
Initial State = iota
AuthTextSent
ResponseSent
ValidServerResponse
// Bitmask used for extracting the step from the state byte.
StepMask = 0x3
)
const (
// RemoteCB bit is on if the remote client or server supports channel binding.
RemoteCB State = 1 << (iota + 3)
// Errored bit is on if the machine has errored.
Errored
// Receiving bit is on if the machine is a server.
Receiving
)
// NewClient creates a new SASL Negotiator that supports creating authentication
// requests using the given mechanism.
func NewClient(m Mechanism, opts ...Option) *Negotiator {
machine := &Negotiator{
mechanism: m,
nonce: nonce(noncerandlen, rand.Reader),
}
getOpts(machine, opts...)
for _, rname := range machine.remoteMechanisms {
lname := m.Name
if lname == rname && strings.HasSuffix(lname, "-PLUS") {
machine.state |= RemoteCB
return machine
}
}
return machine
}
// NewServer creates a new SASL Negotiator that supports receiving
// authentication requests using the given mechanism.
// A nil permissions function is the same as a function that always returns
// false.
func NewServer(m Mechanism, permissions func(*Negotiator) bool, opts ...Option) *Negotiator {
machine := &Negotiator{
mechanism: m,
nonce: nonce(noncerandlen, rand.Reader),
state: AuthTextSent | Receiving,
}
getOpts(machine, opts...)
if permissions != nil {
machine.permissions = permissions
}
for _, rname := range machine.remoteMechanisms {
lname := m.Name
if lname == rname && strings.HasSuffix(lname, "-PLUS") {
machine.state |= RemoteCB
return machine
}
}
return machine
}
// A Negotiator represents a SASL client or server state machine that can
// attempt to negotiate auth. Negotiators should not be used from multiple
// goroutines, and must be reset between negotiation attempts.
type Negotiator struct {
tlsState *tls.ConnectionState
remoteMechanisms []string
credentials func() (Username, Password, Identity []byte)
permissions func(*Negotiator) bool
mechanism Mechanism
state State
nonce []byte
cache interface{}
}
// Nonce returns a unique nonce that is reset for each negotiation attempt. It
// is used by SASL Mechanisms and should generally not be called directly.
func (c *Negotiator) Nonce() []byte {
return c.nonce
}
// Step attempts to transition the state machine to its next state. If Step is
// called after a previous invocation generates an error (and the state machine
// has not been reset to its initial state), Step panics.
func (c *Negotiator) Step(challenge []byte) (more bool, resp []byte, err error) {
if c.state&Errored == Errored {
panic("sasl: Step called on a SASL state machine that has errored")
}
defer func() {
if err != nil {
c.state |= Errored
}
}()
switch c.state & StepMask {
case Initial:
more, resp, c.cache, err = c.mechanism.Start(c)
c.state = c.state&^StepMask | AuthTextSent
case AuthTextSent:
more, resp, c.cache, err = c.mechanism.Next(c, challenge, c.cache)
c.state = c.state&^StepMask | ResponseSent
case ResponseSent:
more, resp, c.cache, err = c.mechanism.Next(c, challenge, c.cache)
c.state = c.state&^StepMask | ValidServerResponse
case ValidServerResponse:
more, resp, c.cache, err = c.mechanism.Next(c, challenge, c.cache)
}
if err != nil {
return false, nil, err
}
return more, resp, err
}
// State returns the internal state of the SASL state machine.
func (c *Negotiator) State() State {
return c.state
}
// Reset resets the state machine to its initial state so that it can be reused
// in another SASL exchange.
func (c *Negotiator) Reset() {
c.state = c.state & (Receiving | RemoteCB)
// Skip the start step for servers
if c.state&Receiving == Receiving {
c.state = c.state&^StepMask | AuthTextSent
}
c.nonce = nonce(noncerandlen, rand.Reader)
c.cache = nil
}
// Credentials returns a username, and password for authentication and optional
// identity for authorization.
func (c *Negotiator) Credentials() (username, password, identity []byte) {
if c.credentials != nil {
return c.credentials()
}
return
}
// Permissions is the callback used by the server to authenticate the user.
func (c *Negotiator) Permissions(opts ...Option) bool {
if c.permissions != nil {
nn := *c
getOpts(&nn, opts...)
return c.permissions(&nn)
}
return false
}
// TLSState is the state of any TLS connections being used to negotiate SASL
// (it can be used for channel binding).
func (c *Negotiator) TLSState() *tls.ConnectionState {
if c.tlsState != nil {
return c.tlsState
}
return nil
}
// RemoteMechanisms is a list of mechanisms as advertised by the other side of a
// SASL negotiation.
func (c *Negotiator) RemoteMechanisms() []string {
if c.remoteMechanisms != nil {
return c.remoteMechanisms
}
return nil
}

30
vendor/mellium.im/sasl/nonce.go vendored Normal file
View file

@ -0,0 +1,30 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
package sasl
import (
"encoding/base64"
"io"
)
// Generates a nonce with n random bytes base64 encoded to ensure that it meets
// the criteria for inclusion in a SCRAM message.
func nonce(n int, r io.Reader) []byte {
if n < 1 {
panic("Cannot generate zero or negative length nonce")
}
b := make([]byte, n)
n2, err := r.Read(b)
switch {
case err != nil:
panic(err)
case n2 != n:
panic("Could not read enough randomness to generate nonce")
}
val := make([]byte, base64.RawStdEncoding.EncodedLen(n))
base64.RawStdEncoding.Encode(val, b)
return val
}

53
vendor/mellium.im/sasl/options.go vendored Normal file
View file

@ -0,0 +1,53 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
package sasl
import (
"crypto/tls"
)
// An Option represents an input to a SASL state machine.
type Option func(*Negotiator)
func getOpts(n *Negotiator, o ...Option) {
n.credentials = func() (username, password, identity []byte) {
return
}
n.permissions = func(_ *Negotiator) bool {
return false
}
for _, f := range o {
f(n)
}
}
// TLSState lets the state machine negotiate channel binding with a TLS session
// if supported by the underlying mechanism.
func TLSState(cs tls.ConnectionState) Option {
return func(n *Negotiator) {
n.tlsState = &cs
}
}
// RemoteMechanisms sets a list of mechanisms supported by the remote client or
// server with which the state machine will be negotiating.
// It is used to determine if the server supports channel binding.
func RemoteMechanisms(m ...string) Option {
return func(n *Negotiator) {
n.remoteMechanisms = m
}
}
// Credentials provides the negotiator with a username and password to
// authenticate with and (optionally) an authorization identity.
// Identity will normally be left empty to act as the username.
// The Credentials function is called lazily and may be called multiple times by
// the mechanism.
// It is not memoized by the negotiator.
func Credentials(f func() (Username, Password, Identity []byte)) Option {
return func(n *Negotiator) {
n.credentials = f
}
}

52
vendor/mellium.im/sasl/plain.go vendored Normal file
View file

@ -0,0 +1,52 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
package sasl
import (
"bytes"
)
var plainSep = []byte{0}
var plain = Mechanism{
Name: "PLAIN",
Start: func(m *Negotiator) (more bool, resp []byte, _ interface{}, err error) {
username, password, identity := m.credentials()
payload := make([]byte, 0, len(identity)+len(username)+len(password)+2)
payload = append(payload, identity...)
payload = append(payload, '\x00')
payload = append(payload, username...)
payload = append(payload, '\x00')
payload = append(payload, password...)
return false, payload, nil, nil
},
Next: func(m *Negotiator, challenge []byte, _ interface{}) (more bool, resp []byte, _ interface{}, err error) {
// If we're a client, or we're a server that's past the AuthTextSent step,
// we should never actually hit this step.
if m.State()&Receiving != Receiving || m.State()&StepMask != AuthTextSent {
err = ErrTooManySteps
return
}
// If we're a server, validate that the challenge looks like:
// "Identity\x00Username\x00Password"
parts := bytes.Split(challenge, plainSep)
if len(parts) != 3 {
err = ErrInvalidChallenge
return
}
if m.Permissions(Credentials(func() (Username, Password, Identity []byte) {
return parts[1], parts[2], parts[0]
})) {
// Everything checks out as far as we know and the server should continue
// to authenticate the user.
return
}
err = ErrAuthn
return
},
}

227
vendor/mellium.im/sasl/scram.go vendored Normal file
View file

@ -0,0 +1,227 @@
// Copyright 2016 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause license that can be
// found in the LICENSE file.
package sasl
import (
"bytes"
"crypto/hmac"
"encoding/base64"
"errors"
"hash"
"strconv"
"strings"
"golang.org/x/crypto/pbkdf2"
)
const (
gs2HeaderCBSupport = "p=tls-unique,"
gs2HeaderNoServerCBSupport = "y,"
gs2HeaderNoCBSupport = "n,"
)
var (
clientKeyInput = []byte("Client Key")
serverKeyInput = []byte("Server Key")
)
// The number of random bytes to generate for a nonce.
const noncerandlen = 16
func getGS2Header(name string, n *Negotiator) (gs2Header []byte) {
_, _, identity := n.Credentials()
switch {
case n.TLSState() == nil || !strings.HasSuffix(name, "-PLUS"):
// We do not support channel binding
gs2Header = []byte(gs2HeaderNoCBSupport)
case n.State()&RemoteCB == RemoteCB:
// We support channel binding and the server does too
gs2Header = []byte(gs2HeaderCBSupport)
case n.State()&RemoteCB != RemoteCB:
// We support channel binding but the server does not
gs2Header = []byte(gs2HeaderNoServerCBSupport)
}
if len(identity) > 0 {
gs2Header = append(gs2Header, []byte(`a=`)...)
gs2Header = append(gs2Header, identity...)
}
gs2Header = append(gs2Header, ',')
return
}
func scram(name string, fn func() hash.Hash) Mechanism {
// BUG(ssw): We need a way to cache the SCRAM client and server key
// calculations.
return Mechanism{
Name: name,
Start: func(m *Negotiator) (bool, []byte, interface{}, error) {
user, _, _ := m.Credentials()
// Escape "=" and ",". This is mostly the same as bytes.Replace but
// faster because we can do both replacements in a single pass.
n := bytes.Count(user, []byte{'='}) + bytes.Count(user, []byte{','})
username := make([]byte, len(user)+(n*2))
w := 0
start := 0
for i := 0; i < n; i++ {
j := start
j += bytes.IndexAny(user[start:], "=,")
w += copy(username[w:], user[start:j])
switch user[j] {
case '=':
w += copy(username[w:], "=3D")
case ',':
w += copy(username[w:], "=2C")
}
start = j + 1
}
copy(username[w:], user[start:])
clientFirstMessage := make([]byte, 5+len(m.Nonce())+len(username))
copy(clientFirstMessage, "n=")
copy(clientFirstMessage[2:], username)
copy(clientFirstMessage[2+len(username):], ",r=")
copy(clientFirstMessage[5+len(username):], m.Nonce())
return true, append(getGS2Header(name, m), clientFirstMessage...), clientFirstMessage, nil
},
Next: func(m *Negotiator, challenge []byte, data interface{}) (more bool, resp []byte, cache interface{}, err error) {
if challenge == nil || len(challenge) == 0 {
return more, resp, cache, ErrInvalidChallenge
}
if m.State()&Receiving == Receiving {
panic("not yet implemented")
}
return scramClientNext(name, fn, m, challenge, data)
},
}
}
func scramClientNext(name string, fn func() hash.Hash, m *Negotiator, challenge []byte, data interface{}) (more bool, resp []byte, cache interface{}, err error) {
_, password, _ := m.Credentials()
state := m.State()
switch state & StepMask {
case AuthTextSent:
iter := -1
var salt, nonce []byte
for _, field := range bytes.Split(challenge, []byte{','}) {
if len(field) < 3 || (len(field) >= 2 && field[1] != '=') {
continue
}
switch field[0] {
case 'i':
ival := string(bytes.TrimRight(field[2:], "\x00"))
if iter, err = strconv.Atoi(ival); err != nil {
return
}
case 's':
salt = make([]byte, base64.StdEncoding.DecodedLen(len(field)-2))
var n int
n, err = base64.StdEncoding.Decode(salt, field[2:])
salt = salt[:n]
if err != nil {
return
}
case 'r':
nonce = field[2:]
case 'm':
// RFC 5802:
// m: This attribute is reserved for future extensibility. In this
// version of SCRAM, its presence in a client or a server message
// MUST cause authentication failure when the attribute is parsed by
// the other end.
err = errors.New("Server sent reserved attribute `m'")
return
}
}
switch {
case iter < 0:
err = errors.New("Iteration count is missing")
return
case iter < 0:
err = errors.New("Iteration count is invalid")
return
case nonce == nil || !bytes.HasPrefix(nonce, m.Nonce()):
err = errors.New("Server nonce does not match client nonce")
return
case salt == nil:
err = errors.New("Server sent empty salt")
return
}
gs2Header := getGS2Header(name, m)
tlsState := m.TLSState()
var channelBinding []byte
if tlsState != nil && strings.HasSuffix(name, "-PLUS") {
channelBinding = make(
[]byte,
2+base64.StdEncoding.EncodedLen(len(gs2Header)+len(tlsState.TLSUnique)),
)
base64.StdEncoding.Encode(channelBinding[2:], append(gs2Header, tlsState.TLSUnique...))
channelBinding[0] = 'c'
channelBinding[1] = '='
} else {
channelBinding = make(
[]byte,
2+base64.StdEncoding.EncodedLen(len(gs2Header)),
)
base64.StdEncoding.Encode(channelBinding[2:], gs2Header)
channelBinding[0] = 'c'
channelBinding[1] = '='
}
clientFinalMessageWithoutProof := append(channelBinding, []byte(",r=")...)
clientFinalMessageWithoutProof = append(clientFinalMessageWithoutProof, nonce...)
clientFirstMessage := data.([]byte)
authMessage := append(clientFirstMessage, ',')
authMessage = append(authMessage, challenge...)
authMessage = append(authMessage, ',')
authMessage = append(authMessage, clientFinalMessageWithoutProof...)
saltedPassword := pbkdf2.Key(password, salt, iter, fn().Size(), fn)
h := hmac.New(fn, saltedPassword)
h.Write(serverKeyInput)
serverKey := h.Sum(nil)
h.Reset()
h.Write(clientKeyInput)
clientKey := h.Sum(nil)
h = hmac.New(fn, serverKey)
h.Write(authMessage)
serverSignature := h.Sum(nil)
h = fn()
h.Write(clientKey)
storedKey := h.Sum(nil)
h = hmac.New(fn, storedKey)
h.Write(authMessage)
clientSignature := h.Sum(nil)
clientProof := make([]byte, len(clientKey))
xorBytes(clientProof, clientKey, clientSignature)
encodedClientProof := make([]byte, base64.StdEncoding.EncodedLen(len(clientProof)))
base64.StdEncoding.Encode(encodedClientProof, clientProof)
clientFinalMessage := append(clientFinalMessageWithoutProof, []byte(",p=")...)
clientFinalMessage = append(clientFinalMessage, encodedClientProof...)
return true, clientFinalMessage, serverSignature, nil
case ResponseSent:
clientCalculatedServerFinalMessage := "v=" + base64.StdEncoding.EncodeToString(data.([]byte))
if clientCalculatedServerFinalMessage != string(challenge) {
err = ErrAuthn
return
}
// Success!
return false, nil, nil, nil
}
err = ErrInvalidState
return
}

24
vendor/mellium.im/sasl/xor_generic.go vendored Normal file
View file

@ -0,0 +1,24 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file was split out from Go's crypto/cipher/xor.go
// +build !386,!amd64,!ppc64,!ppc64le,!s390x,!appengine
package sasl
func xorBytes(dst, a, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
for i := 0; i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
}
func xorWords(dst, a, b []byte) {
xorBytes(dst, a, b)
}

52
vendor/mellium.im/sasl/xor_unaligned.go vendored Normal file
View file

@ -0,0 +1,52 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file was split out from Go's crypto/cipher/xor.go
// +build 386 amd64 ppc64 ppc64le s390x appengine
package sasl
import (
"unsafe"
)
const wordSize = int(unsafe.Sizeof(uintptr(0)))
// xorBytes xors in bulk. It only works on architectures that support unaligned
// read/writes.
func xorBytes(dst, a, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
w := n / wordSize
if w > 0 {
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
aw := *(*[]uintptr)(unsafe.Pointer(&a))
bw := *(*[]uintptr)(unsafe.Pointer(&b))
for i := 0; i < w; i++ {
dw[i] = aw[i] ^ bw[i]
}
}
for i := (n - n%wordSize); i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
}
// xorWords XORs multiples of 4 or 8 bytes (depending on architecture.) The
// arguments are assumed to be of equal length.
func xorWords(dst, a, b []byte) {
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
aw := *(*[]uintptr)(unsafe.Pointer(&a))
bw := *(*[]uintptr)(unsafe.Pointer(&b))
n := len(b) / wordSize
for i := 0; i < n; i++ {
dw[i] = aw[i] ^ bw[i]
}
}