Browse code

Add support for swarm init lock and swarm unlock

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2016/10/22 10:07:55
Showing 32 changed files
... ...
@@ -64,7 +64,7 @@ func maskSecretKeys(inp interface{}) {
64 64
 	if form, ok := inp.(map[string]interface{}); ok {
65 65
 	loop0:
66 66
 		for k, v := range form {
67
-			for _, m := range []string{"password", "secret", "jointoken"} {
67
+			for _, m := range []string{"password", "secret", "jointoken", "lockkey"} {
68 68
 				if strings.EqualFold(m, k) {
69 69
 					form[k] = "*****"
70 70
 					continue loop0
... ...
@@ -12,6 +12,7 @@ type Backend interface {
12 12
 	Leave(force bool) error
13 13
 	Inspect() (types.Swarm, error)
14 14
 	Update(uint64, types.Spec, types.UpdateFlags) error
15
+	UnlockSwarm(req types.UnlockRequest) error
15 16
 	GetServices(basictypes.ServiceListOptions) ([]types.Service, error)
16 17
 	GetService(string) (types.Service, error)
17 18
 	CreateService(types.ServiceSpec, string) (string, error)
... ...
@@ -29,6 +29,7 @@ func (sr *swarmRouter) initRoutes() {
29 29
 		router.NewPostRoute("/swarm/leave", sr.leaveCluster),
30 30
 		router.NewGetRoute("/swarm", sr.inspectCluster),
31 31
 		router.NewPostRoute("/swarm/update", sr.updateCluster),
32
+		router.NewPostRoute("/swarm/unlock", sr.unlockCluster),
32 33
 		router.NewGetRoute("/services", sr.getServices),
33 34
 		router.NewGetRoute("/services/{id:.*}", sr.getService),
34 35
 		router.NewPostRoute("/services/create", sr.createService),
... ...
@@ -94,6 +94,19 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
94 94
 	return nil
95 95
 }
96 96
 
97
+func (sr *swarmRouter) unlockCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
98
+	var req types.UnlockRequest
99
+	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
100
+		return err
101
+	}
102
+
103
+	if err := sr.backend.UnlockSwarm(req); err != nil {
104
+		logrus.Errorf("Error unlocking swarm: %+v", err)
105
+		return err
106
+	}
107
+	return nil
108
+}
109
+
97 110
 func (sr *swarmRouter) getServices(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
98 111
 	if err := httputils.ParseForm(r); err != nil {
99 112
 		return err
... ...
@@ -125,6 +125,7 @@ type InitRequest struct {
125 125
 	AdvertiseAddr   string
126 126
 	ForceNewCluster bool
127 127
 	Spec            Spec
128
+	LockKey         string
128 129
 }
129 130
 
130 131
 // JoinRequest is the request used to join a swarm.
... ...
@@ -135,6 +136,11 @@ type JoinRequest struct {
135 135
 	JoinToken     string // accept by secret
136 136
 }
137 137
 
138
+// UnlockRequest is the request used to unlock a swarm.
139
+type UnlockRequest struct {
140
+	LockKey string
141
+}
142
+
138 143
 // LocalNodeState represents the state of the local node.
139 144
 type LocalNodeState string
140 145
 
... ...
@@ -147,6 +153,8 @@ const (
147 147
 	LocalNodeStateActive LocalNodeState = "active"
148 148
 	// LocalNodeStateError ERROR
149 149
 	LocalNodeStateError LocalNodeState = "error"
150
+	// LocalNodeStateLocked LOCKED
151
+	LocalNodeStateLocked LocalNodeState = "locked"
150 152
 )
151 153
 
152 154
 // Info represents generic information about swarm.
... ...
@@ -24,6 +24,7 @@ func NewSwarmCommand(dockerCli *command.DockerCli) *cobra.Command {
24 24
 		newJoinTokenCommand(dockerCli),
25 25
 		newUpdateCommand(dockerCli),
26 26
 		newLeaveCommand(dockerCli),
27
+		newUnlockCommand(dockerCli),
27 28
 	)
28 29
 	return cmd
29 30
 }
... ...
@@ -1,10 +1,15 @@
1 1
 package swarm
2 2
 
3 3
 import (
4
+	"bufio"
5
+	"crypto/rand"
4 6
 	"errors"
5 7
 	"fmt"
8
+	"io"
9
+	"math/big"
6 10
 	"strings"
7 11
 
12
+	"golang.org/x/crypto/ssh/terminal"
8 13
 	"golang.org/x/net/context"
9 14
 
10 15
 	"github.com/docker/docker/api/types/swarm"
... ...
@@ -20,6 +25,7 @@ type initOptions struct {
20 20
 	// Not a NodeAddrOption because it has no default port.
21 21
 	advertiseAddr   string
22 22
 	forceNewCluster bool
23
+	lockKey         bool
23 24
 }
24 25
 
25 26
 func newInitCommand(dockerCli *command.DockerCli) *cobra.Command {
... ...
@@ -39,6 +45,7 @@ func newInitCommand(dockerCli *command.DockerCli) *cobra.Command {
39 39
 	flags := cmd.Flags()
40 40
 	flags.Var(&opts.listenAddr, flagListenAddr, "Listen address (format: <ip|interface>[:port])")
41 41
 	flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", "Advertised address (format: <ip|interface>[:port])")
42
+	flags.BoolVar(&opts.lockKey, flagLockKey, false, "Encrypt swarm with optionally provided key from stdin")
42 43
 	flags.BoolVar(&opts.forceNewCluster, "force-new-cluster", false, "Force create a new cluster from current state")
43 44
 	addSwarmFlags(flags, &opts.swarmOptions)
44 45
 	return cmd
... ...
@@ -48,11 +55,31 @@ func runInit(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts initOption
48 48
 	client := dockerCli.Client()
49 49
 	ctx := context.Background()
50 50
 
51
+	var lockKey string
52
+	if opts.lockKey {
53
+		var err error
54
+		lockKey, err = readKey(dockerCli.In(), "Please enter key for encrypting swarm(leave empty to generate): ")
55
+		if err != nil {
56
+			return err
57
+		}
58
+		if len(lockKey) == 0 {
59
+			randBytes := make([]byte, 16)
60
+			if _, err := rand.Read(randBytes[:]); err != nil {
61
+				panic(fmt.Errorf("failed to general random lock key: %v", err))
62
+			}
63
+
64
+			var n big.Int
65
+			n.SetBytes(randBytes[:])
66
+			lockKey = n.Text(36)
67
+		}
68
+	}
69
+
51 70
 	req := swarm.InitRequest{
52 71
 		ListenAddr:      opts.listenAddr.String(),
53 72
 		AdvertiseAddr:   opts.advertiseAddr,
54 73
 		ForceNewCluster: opts.forceNewCluster,
55 74
 		Spec:            opts.swarmOptions.ToSpec(flags),
75
+		LockKey:         lockKey,
56 76
 	}
57 77
 
58 78
 	nodeID, err := client.SwarmInit(ctx, req)
... ...
@@ -65,6 +92,10 @@ func runInit(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts initOption
65 65
 
66 66
 	fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID)
67 67
 
68
+	if len(lockKey) > 0 {
69
+		fmt.Fprintf(dockerCli.Out(), "Swarm is encrypted. When a node is restarted it needs to be unlocked by running command:\n\n    echo '%s' | docker swarm unlock\n\n", lockKey)
70
+	}
71
+
68 72
 	if err := printJoinCommand(ctx, dockerCli, nodeID, true, false); err != nil {
69 73
 		return err
70 74
 	}
... ...
@@ -72,3 +103,18 @@ func runInit(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts initOption
72 72
 	fmt.Fprint(dockerCli.Out(), "To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.\n\n")
73 73
 	return nil
74 74
 }
75
+
76
+func readKey(in *command.InStream, prompt string) (string, error) {
77
+	if in.IsTerminal() {
78
+		fmt.Print(prompt)
79
+		dt, err := terminal.ReadPassword(int(in.FD()))
80
+		fmt.Println()
81
+		return string(dt), err
82
+	} else {
83
+		key, err := bufio.NewReader(in).ReadString('\n')
84
+		if err == io.EOF {
85
+			err = nil
86
+		}
87
+		return strings.TrimSpace(key), err
88
+	}
89
+}
... ...
@@ -26,6 +26,7 @@ const (
26 26
 	flagExternalCA          = "external-ca"
27 27
 	flagMaxSnapshots        = "max-snapshots"
28 28
 	flagSnapshotInterval    = "snapshot-interval"
29
+	flagLockKey             = "lock-key"
29 30
 )
30 31
 
31 32
 type swarmOptions struct {
32 33
new file mode 100644
... ...
@@ -0,0 +1,35 @@
0
+package swarm
1
+
2
+import (
3
+	"context"
4
+
5
+	"github.com/spf13/cobra"
6
+
7
+	"github.com/docker/docker/api/types/swarm"
8
+	"github.com/docker/docker/cli"
9
+	"github.com/docker/docker/cli/command"
10
+)
11
+
12
+func newUnlockCommand(dockerCli *command.DockerCli) *cobra.Command {
13
+	cmd := &cobra.Command{
14
+		Use:   "unlock",
15
+		Short: "Unlock swarm",
16
+		Args:  cli.ExactArgs(0),
17
+		RunE: func(cmd *cobra.Command, args []string) error {
18
+			client := dockerCli.Client()
19
+			ctx := context.Background()
20
+
21
+			key, err := readKey(dockerCli.In(), "Please enter unlock key: ")
22
+			if err != nil {
23
+				return err
24
+			}
25
+			req := swarm.UnlockRequest{
26
+				LockKey: string(key),
27
+			}
28
+
29
+			return client.SwarmUnlock(ctx, req)
30
+		},
31
+	}
32
+
33
+	return cmd
34
+}
... ...
@@ -96,7 +96,7 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
96 96
 	}
97 97
 
98 98
 	fmt.Fprintf(dockerCli.Out(), "Swarm: %v\n", info.Swarm.LocalNodeState)
99
-	if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive {
99
+	if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked {
100 100
 		fmt.Fprintf(dockerCli.Out(), " NodeID: %s\n", info.Swarm.NodeID)
101 101
 		if info.Swarm.Error != "" {
102 102
 			fmt.Fprintf(dockerCli.Out(), " Error: %v\n", info.Swarm.Error)
... ...
@@ -119,6 +119,7 @@ type ServiceAPIClient interface {
119 119
 type SwarmAPIClient interface {
120 120
 	SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error)
121 121
 	SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
122
+	SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error
122 123
 	SwarmLeave(ctx context.Context, force bool) error
123 124
 	SwarmInspect(ctx context.Context) (swarm.Swarm, error)
124 125
 	SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error
125 126
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+package client
1
+
2
+import (
3
+	"github.com/docker/docker/api/types/swarm"
4
+	"golang.org/x/net/context"
5
+)
6
+
7
+// SwarmUnlock unlockes locked swarm.
8
+func (cli *Client) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error {
9
+	serverResp, err := cli.post(ctx, "/swarm/unlock", nil, req, nil)
10
+	if err != nil {
11
+		return err
12
+	}
13
+
14
+	ensureReaderClosed(serverResp)
15
+	return err
16
+}
... ...
@@ -1,6 +1,7 @@
1 1
 package cluster
2 2
 
3 3
 import (
4
+	"crypto/x509"
4 5
 	"encoding/json"
5 6
 	"fmt"
6 7
 	"io/ioutil"
... ...
@@ -12,10 +13,8 @@ import (
12 12
 	"sync"
13 13
 	"time"
14 14
 
15
-	"google.golang.org/grpc"
16
-
17 15
 	"github.com/Sirupsen/logrus"
18
-	"github.com/docker/docker/api/errors"
16
+	apierrors "github.com/docker/docker/api/errors"
19 17
 	apitypes "github.com/docker/docker/api/types"
20 18
 	"github.com/docker/docker/api/types/filters"
21 19
 	"github.com/docker/docker/api/types/network"
... ...
@@ -29,7 +28,9 @@ import (
29 29
 	"github.com/docker/docker/runconfig"
30 30
 	swarmapi "github.com/docker/swarmkit/api"
31 31
 	swarmnode "github.com/docker/swarmkit/node"
32
+	"github.com/pkg/errors"
32 33
 	"golang.org/x/net/context"
34
+	"google.golang.org/grpc"
33 35
 )
34 36
 
35 37
 const swarmDirName = "swarm"
... ...
@@ -56,6 +57,9 @@ var ErrPendingSwarmExists = fmt.Errorf("This node is processing an existing join
56 56
 // ErrSwarmJoinTimeoutReached is returned when cluster join could not complete before timeout was reached.
57 57
 var ErrSwarmJoinTimeoutReached = fmt.Errorf("Timeout was reached before node was joined. The attempt to join the swarm will continue in the background. Use the \"docker info\" command to see the current swarm status of your node.")
58 58
 
59
+// ErrSwarmLocked is returned if the swarm is encrypted and needs a key to unlock it.
60
+var ErrSwarmLocked = fmt.Errorf("Swarm is encrypted and needs to be unlocked before it can be used. Please use \"docker swarm unlock\" to unlock it.")
61
+
59 62
 // NetworkSubnetsProvider exposes functions for retrieving the subnets
60 63
 // of networks managed by Docker, so they can be filtered.
61 64
 type NetworkSubnetsProvider interface {
... ...
@@ -92,6 +96,8 @@ type Cluster struct {
92 92
 	err             error
93 93
 	cancelDelay     func()
94 94
 	attachers       map[string]*attacher
95
+	locked          bool
96
+	lastNodeConfig  *nodeStartConfig
95 97
 }
96 98
 
97 99
 // attacher manages the in-memory attachment state of a container
... ...
@@ -133,6 +139,7 @@ type nodeStartConfig struct {
133 133
 	joinAddr        string
134 134
 	forceNewCluster bool
135 135
 	joinToken       string
136
+	lockKey         []byte
136 137
 }
137 138
 
138 139
 // New creates a new Cluster instance using provided config.
... ...
@@ -165,6 +172,12 @@ func New(config Config) (*Cluster, error) {
165 165
 
166 166
 	n, err := c.startNewNode(*nodeConfig)
167 167
 	if err != nil {
168
+		if errors.Cause(err) == ErrSwarmLocked {
169
+			logrus.Warnf("swarm component could not be started: %v", err)
170
+			c.locked = true
171
+			c.lastNodeConfig = nodeConfig
172
+			return c, nil
173
+		}
168 174
 		return nil, err
169 175
 	}
170 176
 
... ...
@@ -300,8 +313,16 @@ func (c *Cluster) startNewNode(conf nodeStartConfig) (*node, error) {
300 300
 		Executor:           container.NewExecutor(c.config.Backend),
301 301
 		HeartbeatTick:      1,
302 302
 		ElectionTick:       3,
303
+		UnlockKey:          conf.lockKey,
303 304
 	})
305
+
304 306
 	if err != nil {
307
+		err = detectLockedError(err)
308
+		if errors.Cause(err) == ErrSwarmLocked {
309
+			c.locked = true
310
+			confClone := conf
311
+			c.lastNodeConfig = &confClone
312
+		}
305 313
 		return nil, err
306 314
 	}
307 315
 	ctx := context.Background()
... ...
@@ -365,7 +386,7 @@ func (c *Cluster) startNewNode(conf nodeStartConfig) (*node, error) {
365 365
 // Init initializes new cluster from user provided request.
366 366
 func (c *Cluster) Init(req types.InitRequest) (string, error) {
367 367
 	c.Lock()
368
-	if node := c.node; node != nil {
368
+	if node := c.node; node != nil || c.locked {
369 369
 		if !req.ForceNewCluster {
370 370
 			c.Unlock()
371 371
 			return "", ErrSwarmExists
... ...
@@ -422,12 +443,18 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
422 422
 		localAddr = advertiseIP.String()
423 423
 	}
424 424
 
425
+	var key []byte
426
+	if len(req.LockKey) > 0 {
427
+		key = []byte(req.LockKey)
428
+	}
429
+
425 430
 	// todo: check current state existing
426 431
 	n, err := c.startNewNode(nodeStartConfig{
427 432
 		forceNewCluster: req.ForceNewCluster,
428 433
 		LocalAddr:       localAddr,
429 434
 		ListenAddr:      net.JoinHostPort(listenHost, listenPort),
430 435
 		AdvertiseAddr:   net.JoinHostPort(advertiseHost, advertisePort),
436
+		lockKey:         key,
431 437
 	})
432 438
 	if err != nil {
433 439
 		c.Unlock()
... ...
@@ -457,7 +484,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
457 457
 // Join makes current Cluster part of an existing swarm cluster.
458 458
 func (c *Cluster) Join(req types.JoinRequest) error {
459 459
 	c.Lock()
460
-	if node := c.node; node != nil {
460
+	if node := c.node; node != nil || c.locked {
461 461
 		c.Unlock()
462 462
 		return ErrSwarmExists
463 463
 	}
... ...
@@ -518,6 +545,60 @@ func (c *Cluster) Join(req types.JoinRequest) error {
518 518
 	}
519 519
 }
520 520
 
521
+// GetUnlockKey returns the unlock key for the swarm.
522
+func (c *Cluster) GetUnlockKey() (string, error) {
523
+	c.RLock()
524
+	defer c.RUnlock()
525
+
526
+	if !c.isActiveManager() {
527
+		return "", c.errNoManager()
528
+	}
529
+
530
+	ctx, cancel := c.getRequestContext()
531
+	defer cancel()
532
+
533
+	client := swarmapi.NewCAClient(c.conn)
534
+
535
+	r, err := client.GetUnlockKey(ctx, &swarmapi.GetUnlockKeyRequest{})
536
+	if err != nil {
537
+		return "", err
538
+	}
539
+
540
+	return encryption.HumanReadableKey(r.UnlockKey), nil
541
+}
542
+
543
+// UnlockSwarm provides a key to decrypt data that is encrypted at rest.
544
+func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error {
545
+	if len(req.LockKey) == 0 {
546
+		return errors.New("unlock key can't be empty")
547
+	}
548
+
549
+	c.Lock()
550
+	if c.node != nil || c.locked != true {
551
+		c.Unlock()
552
+		return errors.New("swarm is not locked")
553
+	}
554
+
555
+	config := *c.lastNodeConfig
556
+	config.lockKey = []byte(req.LockKey)
557
+	n, err := c.startNewNode(config)
558
+	if err != nil {
559
+		c.Unlock()
560
+		if errors.Cause(err) == ErrSwarmLocked {
561
+			return errors.New("swarm could not be unlocked: invalid key provided")
562
+		}
563
+		return err
564
+	}
565
+	c.Unlock()
566
+	select {
567
+	case <-n.Ready():
568
+	case <-n.done:
569
+		return fmt.Errorf("swarm component could not be started: %v", c.err)
570
+	}
571
+	go c.reconnectOnFailure(n)
572
+	return nil
573
+}
574
+
521 575
 // stopNode is a helper that stops the active c.node and waits until it has
522 576
 // shut down. Call while keeping the cluster lock.
523 577
 func (c *Cluster) stopNode() error {
... ...
@@ -555,47 +636,53 @@ func (c *Cluster) Leave(force bool) error {
555 555
 	c.Lock()
556 556
 	node := c.node
557 557
 	if node == nil {
558
-		c.Unlock()
559
-		return ErrNoSwarm
560
-	}
561
-
562
-	if node.Manager() != nil && !force {
563
-		msg := "You are attempting to leave the swarm on a node that is participating as a manager. "
564
-		if c.isActiveManager() {
565
-			active, reachable, unreachable, err := c.managerStats()
566
-			if err == nil {
567
-				if active && removingManagerCausesLossOfQuorum(reachable, unreachable) {
568
-					if isLastManager(reachable, unreachable) {
569
-						msg += "Removing the last manager erases all current state of the swarm. Use `--force` to ignore this message. "
570
-						c.Unlock()
571
-						return fmt.Errorf(msg)
558
+		if c.locked {
559
+			c.locked = false
560
+			c.lastNodeConfig = nil
561
+			c.Unlock()
562
+		} else {
563
+			c.Unlock()
564
+			return ErrNoSwarm
565
+		}
566
+	} else {
567
+		if node.Manager() != nil && !force {
568
+			msg := "You are attempting to leave the swarm on a node that is participating as a manager. "
569
+			if c.isActiveManager() {
570
+				active, reachable, unreachable, err := c.managerStats()
571
+				if err == nil {
572
+					if active && removingManagerCausesLossOfQuorum(reachable, unreachable) {
573
+						if isLastManager(reachable, unreachable) {
574
+							msg += "Removing the last manager erases all current state of the swarm. Use `--force` to ignore this message. "
575
+							c.Unlock()
576
+							return fmt.Errorf(msg)
577
+						}
578
+						msg += fmt.Sprintf("Removing this node leaves %v managers out of %v. Without a Raft quorum your swarm will be inaccessible. ", reachable-1, reachable+unreachable)
572 579
 					}
573
-					msg += fmt.Sprintf("Removing this node leaves %v managers out of %v. Without a Raft quorum your swarm will be inaccessible. ", reachable-1, reachable+unreachable)
574 580
 				}
581
+			} else {
582
+				msg += "Doing so may lose the consensus of your cluster. "
575 583
 			}
576
-		} else {
577
-			msg += "Doing so may lose the consensus of your cluster. "
578
-		}
579 584
 
580
-		msg += "The only way to restore a swarm that has lost consensus is to reinitialize it with `--force-new-cluster`. Use `--force` to suppress this message."
581
-		c.Unlock()
582
-		return fmt.Errorf(msg)
583
-	}
584
-	if err := c.stopNode(); err != nil {
585
-		logrus.Errorf("failed to shut down cluster node: %v", err)
586
-		signal.DumpStacks("")
587
-		c.Unlock()
588
-		return err
589
-	}
590
-	c.Unlock()
591
-	if nodeID := node.NodeID(); nodeID != "" {
592
-		nodeContainers, err := c.listContainerForNode(nodeID)
593
-		if err != nil {
585
+			msg += "The only way to restore a swarm that has lost consensus is to reinitialize it with `--force-new-cluster`. Use `--force` to suppress this message."
586
+			c.Unlock()
587
+			return fmt.Errorf(msg)
588
+		}
589
+		if err := c.stopNode(); err != nil {
590
+			logrus.Errorf("failed to shut down cluster node: %v", err)
591
+			signal.DumpStacks("")
592
+			c.Unlock()
594 593
 			return err
595 594
 		}
596
-		for _, id := range nodeContainers {
597
-			if err := c.config.Backend.ContainerRm(id, &apitypes.ContainerRmConfig{ForceRemove: true}); err != nil {
598
-				logrus.Errorf("error removing %v: %v", id, err)
595
+		c.Unlock()
596
+		if nodeID := node.NodeID(); nodeID != "" {
597
+			nodeContainers, err := c.listContainerForNode(nodeID)
598
+			if err != nil {
599
+				return err
600
+			}
601
+			for _, id := range nodeContainers {
602
+				if err := c.config.Backend.ContainerRm(id, &apitypes.ContainerRmConfig{ForceRemove: true}); err != nil {
603
+					logrus.Errorf("error removing %v: %v", id, err)
604
+				}
599 605
 			}
600 606
 		}
601 607
 	}
... ...
@@ -786,6 +873,9 @@ func (c *Cluster) Info() types.Info {
786 786
 		if c.cancelDelay != nil {
787 787
 			info.LocalNodeState = types.LocalNodeStateError
788 788
 		}
789
+		if c.locked {
790
+			info.LocalNodeState = types.LocalNodeStateLocked
791
+		}
789 792
 	} else {
790 793
 		info.LocalNodeState = types.LocalNodeStatePending
791 794
 		if c.ready == true {
... ...
@@ -838,6 +928,9 @@ func (c *Cluster) isActiveManager() bool {
838 838
 // Call with read lock.
839 839
 func (c *Cluster) errNoManager() error {
840 840
 	if c.node == nil {
841
+		if c.locked {
842
+			return ErrSwarmLocked
843
+		}
841 844
 		return fmt.Errorf("This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again.")
842 845
 	}
843 846
 	if c.node.Manager() != nil {
... ...
@@ -1396,7 +1489,7 @@ func (c *Cluster) CreateNetwork(s apitypes.NetworkCreateRequest) (string, error)
1396 1396
 
1397 1397
 	if runconfig.IsPreDefinedNetwork(s.Name) {
1398 1398
 		err := fmt.Errorf("%s is a pre-defined network and cannot be created", s.Name)
1399
-		return "", errors.NewRequestForbiddenError(err)
1399
+		return "", apierrors.NewRequestForbiddenError(err)
1400 1400
 	}
1401 1401
 
1402 1402
 	ctx, cancel := c.getRequestContext()
... ...
@@ -1447,7 +1540,7 @@ func (c *Cluster) populateNetworkID(ctx context.Context, client swarmapi.Control
1447 1447
 		if err != nil {
1448 1448
 			if ln, _ := c.config.Backend.FindNetwork(n.Target); ln != nil && !ln.Info().Dynamic() {
1449 1449
 				err = fmt.Errorf("network %s is not eligible for docker services", ln.Name())
1450
-				return errors.NewRequestForbiddenError(err)
1450
+				return apierrors.NewRequestForbiddenError(err)
1451 1451
 			}
1452 1452
 			return err
1453 1453
 		}
... ...
@@ -1613,3 +1706,10 @@ func initClusterSpec(node *node, spec types.Spec) error {
1613 1613
 	}
1614 1614
 	return ctx.Err()
1615 1615
 }
1616
+
1617
+func detectLockedError(err error) error {
1618
+	if errors.Cause(err) == x509.IncorrectPasswordError || errors.Cause(err).Error() == "tls: failed to parse private key" { // todo: better to export typed error
1619
+		return errors.WithStack(ErrSwarmLocked)
1620
+	}
1621
+	return err
1622
+}
1616 1623
new file mode 100644
... ...
@@ -0,0 +1,149 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+/*
5
+Package secretbox encrypts and authenticates small messages.
6
+
7
+Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
8
+secret-key cryptography. The length of messages is not hidden.
9
+
10
+It is the caller's responsibility to ensure the uniqueness of nonces—for
11
+example, by using nonce 1 for the first message, nonce 2 for the second
12
+message, etc. Nonces are long enough that randomly generated nonces have
13
+negligible risk of collision.
14
+
15
+This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html.
16
+*/
17
+package secretbox // import "golang.org/x/crypto/nacl/secretbox"
18
+
19
+import (
20
+	"golang.org/x/crypto/poly1305"
21
+	"golang.org/x/crypto/salsa20/salsa"
22
+)
23
+
24
+// Overhead is the number of bytes of overhead when boxing a message.
25
+const Overhead = poly1305.TagSize
26
+
27
+// setup produces a sub-key and Salsa20 counter given a nonce and key.
28
+func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
29
+	// We use XSalsa20 for encryption so first we need to generate a
30
+	// key and nonce with HSalsa20.
31
+	var hNonce [16]byte
32
+	copy(hNonce[:], nonce[:])
33
+	salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
34
+
35
+	// The final 8 bytes of the original nonce form the new nonce.
36
+	copy(counter[:], nonce[16:])
37
+}
38
+
39
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
40
+// slice with the contents of the given slice followed by that many bytes and a
41
+// second slice that aliases into it and contains only the extra bytes. If the
42
+// original slice has sufficient capacity then no allocation is performed.
43
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
44
+	if total := len(in) + n; cap(in) >= total {
45
+		head = in[:total]
46
+	} else {
47
+		head = make([]byte, total)
48
+		copy(head, in)
49
+	}
50
+	tail = head[len(in):]
51
+	return
52
+}
53
+
54
+// Seal appends an encrypted and authenticated copy of message to out, which
55
+// must not overlap message. The key and nonce pair must be unique for each
56
+// distinct message and the output will be Overhead bytes longer than message.
57
+func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
58
+	var subKey [32]byte
59
+	var counter [16]byte
60
+	setup(&subKey, &counter, nonce, key)
61
+
62
+	// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
63
+	// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
64
+	// keystream as a side effect.
65
+	var firstBlock [64]byte
66
+	salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
67
+
68
+	var poly1305Key [32]byte
69
+	copy(poly1305Key[:], firstBlock[:])
70
+
71
+	ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
72
+
73
+	// We XOR up to 32 bytes of message with the keystream generated from
74
+	// the first block.
75
+	firstMessageBlock := message
76
+	if len(firstMessageBlock) > 32 {
77
+		firstMessageBlock = firstMessageBlock[:32]
78
+	}
79
+
80
+	tagOut := out
81
+	out = out[poly1305.TagSize:]
82
+	for i, x := range firstMessageBlock {
83
+		out[i] = firstBlock[32+i] ^ x
84
+	}
85
+	message = message[len(firstMessageBlock):]
86
+	ciphertext := out
87
+	out = out[len(firstMessageBlock):]
88
+
89
+	// Now encrypt the rest.
90
+	counter[8] = 1
91
+	salsa.XORKeyStream(out, message, &counter, &subKey)
92
+
93
+	var tag [poly1305.TagSize]byte
94
+	poly1305.Sum(&tag, ciphertext, &poly1305Key)
95
+	copy(tagOut, tag[:])
96
+
97
+	return ret
98
+}
99
+
100
+// Open authenticates and decrypts a box produced by Seal and appends the
101
+// message to out, which must not overlap box. The output will be Overhead
102
+// bytes smaller than box.
103
+func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
104
+	if len(box) < Overhead {
105
+		return nil, false
106
+	}
107
+
108
+	var subKey [32]byte
109
+	var counter [16]byte
110
+	setup(&subKey, &counter, nonce, key)
111
+
112
+	// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
113
+	// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
114
+	// keystream as a side effect.
115
+	var firstBlock [64]byte
116
+	salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
117
+
118
+	var poly1305Key [32]byte
119
+	copy(poly1305Key[:], firstBlock[:])
120
+	var tag [poly1305.TagSize]byte
121
+	copy(tag[:], box)
122
+
123
+	if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
124
+		return nil, false
125
+	}
126
+
127
+	ret, out := sliceForAppend(out, len(box)-Overhead)
128
+
129
+	// We XOR up to 32 bytes of box with the keystream generated from
130
+	// the first block.
131
+	box = box[Overhead:]
132
+	firstMessageBlock := box
133
+	if len(firstMessageBlock) > 32 {
134
+		firstMessageBlock = firstMessageBlock[:32]
135
+	}
136
+	for i, x := range firstMessageBlock {
137
+		out[i] = firstBlock[32+i] ^ x
138
+	}
139
+
140
+	box = box[len(firstMessageBlock):]
141
+	out = out[len(firstMessageBlock):]
142
+
143
+	// Now decrypt the rest.
144
+	counter[8] = 1
145
+	salsa.XORKeyStream(out, box, &counter, &subKey)
146
+
147
+	return ret, true
148
+}
0 149
new file mode 100644
... ...
@@ -0,0 +1,45 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// This code was translated into a form compatible with 6a from the public
5
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
6
+
7
+// +build amd64,!gccgo,!appengine
8
+
9
+DATA ·SCALE(SB)/8, $0x37F4000000000000
10
+GLOBL ·SCALE(SB), 8, $8
11
+DATA ·TWO32(SB)/8, $0x41F0000000000000
12
+GLOBL ·TWO32(SB), 8, $8
13
+DATA ·TWO64(SB)/8, $0x43F0000000000000
14
+GLOBL ·TWO64(SB), 8, $8
15
+DATA ·TWO96(SB)/8, $0x45F0000000000000
16
+GLOBL ·TWO96(SB), 8, $8
17
+DATA ·ALPHA32(SB)/8, $0x45E8000000000000
18
+GLOBL ·ALPHA32(SB), 8, $8
19
+DATA ·ALPHA64(SB)/8, $0x47E8000000000000
20
+GLOBL ·ALPHA64(SB), 8, $8
21
+DATA ·ALPHA96(SB)/8, $0x49E8000000000000
22
+GLOBL ·ALPHA96(SB), 8, $8
23
+DATA ·ALPHA130(SB)/8, $0x4C08000000000000
24
+GLOBL ·ALPHA130(SB), 8, $8
25
+DATA ·DOFFSET0(SB)/8, $0x4330000000000000
26
+GLOBL ·DOFFSET0(SB), 8, $8
27
+DATA ·DOFFSET1(SB)/8, $0x4530000000000000
28
+GLOBL ·DOFFSET1(SB), 8, $8
29
+DATA ·DOFFSET2(SB)/8, $0x4730000000000000
30
+GLOBL ·DOFFSET2(SB), 8, $8
31
+DATA ·DOFFSET3(SB)/8, $0x4930000000000000
32
+GLOBL ·DOFFSET3(SB), 8, $8
33
+DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000
34
+GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8
35
+DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB
36
+GLOBL ·HOFFSET0(SB), 8, $8
37
+DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE
38
+GLOBL ·HOFFSET1(SB), 8, $8
39
+DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE
40
+GLOBL ·HOFFSET2(SB), 8, $8
41
+DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE
42
+GLOBL ·HOFFSET3(SB), 8, $8
43
+DATA ·ROUNDING(SB)/2, $0x137f
44
+GLOBL ·ROUNDING(SB), 8, $2
0 45
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+/*
5
+Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
6
+
7
+Poly1305 is a fast, one-time authentication function. It is infeasible for an
8
+attacker to generate an authenticator for a message without the key. However, a
9
+key must only be used for a single message. Authenticating two different
10
+messages with the same key allows an attacker to forge authenticators for other
11
+messages with the same key.
12
+
13
+Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
14
+used with a fixed key in order to generate one-time keys from an nonce.
15
+However, in this package AES isn't used and the one-time key is specified
16
+directly.
17
+*/
18
+package poly1305 // import "golang.org/x/crypto/poly1305"
19
+
20
+import "crypto/subtle"
21
+
22
+// TagSize is the size, in bytes, of a poly1305 authenticator.
23
+const TagSize = 16
24
+
25
+// Verify returns true if mac is a valid authenticator for m with the given
26
+// key.
27
+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
28
+	var tmp [16]byte
29
+	Sum(&tmp, m, key)
30
+	return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
31
+}
0 32
new file mode 100644
... ...
@@ -0,0 +1,497 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// This code was translated into a form compatible with 6a from the public
5
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
6
+
7
+// +build amd64,!gccgo,!appengine
8
+
9
+// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
10
+TEXT ·poly1305(SB),0,$224-32
11
+	MOVQ out+0(FP),DI
12
+	MOVQ m+8(FP),SI
13
+	MOVQ mlen+16(FP),DX
14
+	MOVQ key+24(FP),CX
15
+
16
+	MOVQ SP,R11
17
+	MOVQ $31,R9
18
+	NOTQ R9
19
+	ANDQ R9,SP
20
+	ADDQ $32,SP
21
+
22
+	MOVQ R11,32(SP)
23
+	MOVQ R12,40(SP)
24
+	MOVQ R13,48(SP)
25
+	MOVQ R14,56(SP)
26
+	MOVQ R15,64(SP)
27
+	MOVQ BX,72(SP)
28
+	MOVQ BP,80(SP)
29
+	FLDCW ·ROUNDING(SB)
30
+	MOVL 0(CX),R8
31
+	MOVL 4(CX),R9
32
+	MOVL 8(CX),AX
33
+	MOVL 12(CX),R10
34
+	MOVQ DI,88(SP)
35
+	MOVQ CX,96(SP)
36
+	MOVL $0X43300000,108(SP)
37
+	MOVL $0X45300000,116(SP)
38
+	MOVL $0X47300000,124(SP)
39
+	MOVL $0X49300000,132(SP)
40
+	ANDL $0X0FFFFFFF,R8
41
+	ANDL $0X0FFFFFFC,R9
42
+	ANDL $0X0FFFFFFC,AX
43
+	ANDL $0X0FFFFFFC,R10
44
+	MOVL R8,104(SP)
45
+	MOVL R9,112(SP)
46
+	MOVL AX,120(SP)
47
+	MOVL R10,128(SP)
48
+	FMOVD 104(SP), F0
49
+	FSUBD ·DOFFSET0(SB), F0
50
+	FMOVD 112(SP), F0
51
+	FSUBD ·DOFFSET1(SB), F0
52
+	FMOVD 120(SP), F0
53
+	FSUBD ·DOFFSET2(SB), F0
54
+	FMOVD 128(SP), F0
55
+	FSUBD ·DOFFSET3(SB), F0
56
+	FXCHD F0, F3
57
+	FMOVDP F0, 136(SP)
58
+	FXCHD F0, F1
59
+	FMOVD F0, 144(SP)
60
+	FMULD ·SCALE(SB), F0
61
+	FMOVDP F0, 152(SP)
62
+	FMOVD F0, 160(SP)
63
+	FMULD ·SCALE(SB), F0
64
+	FMOVDP F0, 168(SP)
65
+	FMOVD F0, 176(SP)
66
+	FMULD ·SCALE(SB), F0
67
+	FMOVDP F0, 184(SP)
68
+	FLDZ
69
+	FLDZ
70
+	FLDZ
71
+	FLDZ
72
+	CMPQ DX,$16
73
+	JB ADDATMOST15BYTES
74
+	INITIALATLEAST16BYTES:
75
+	MOVL 12(SI),DI
76
+	MOVL 8(SI),CX
77
+	MOVL 4(SI),R8
78
+	MOVL 0(SI),R9
79
+	MOVL DI,128(SP)
80
+	MOVL CX,120(SP)
81
+	MOVL R8,112(SP)
82
+	MOVL R9,104(SP)
83
+	ADDQ $16,SI
84
+	SUBQ $16,DX
85
+	FXCHD F0, F3
86
+	FADDD 128(SP), F0
87
+	FSUBD ·DOFFSET3MINUSTWO128(SB), F0
88
+	FXCHD F0, F1
89
+	FADDD 112(SP), F0
90
+	FSUBD ·DOFFSET1(SB), F0
91
+	FXCHD F0, F2
92
+	FADDD 120(SP), F0
93
+	FSUBD ·DOFFSET2(SB), F0
94
+	FXCHD F0, F3
95
+	FADDD 104(SP), F0
96
+	FSUBD ·DOFFSET0(SB), F0
97
+	CMPQ DX,$16
98
+	JB MULTIPLYADDATMOST15BYTES
99
+	MULTIPLYADDATLEAST16BYTES:
100
+	MOVL 12(SI),DI
101
+	MOVL 8(SI),CX
102
+	MOVL 4(SI),R8
103
+	MOVL 0(SI),R9
104
+	MOVL DI,128(SP)
105
+	MOVL CX,120(SP)
106
+	MOVL R8,112(SP)
107
+	MOVL R9,104(SP)
108
+	ADDQ $16,SI
109
+	SUBQ $16,DX
110
+	FMOVD ·ALPHA130(SB), F0
111
+	FADDD F2,F0
112
+	FSUBD ·ALPHA130(SB), F0
113
+	FSUBD F0,F2
114
+	FMULD ·SCALE(SB), F0
115
+	FMOVD ·ALPHA32(SB), F0
116
+	FADDD F2,F0
117
+	FSUBD ·ALPHA32(SB), F0
118
+	FSUBD F0,F2
119
+	FXCHD F0, F2
120
+	FADDDP F0,F1
121
+	FMOVD ·ALPHA64(SB), F0
122
+	FADDD F4,F0
123
+	FSUBD ·ALPHA64(SB), F0
124
+	FSUBD F0,F4
125
+	FMOVD ·ALPHA96(SB), F0
126
+	FADDD F6,F0
127
+	FSUBD ·ALPHA96(SB), F0
128
+	FSUBD F0,F6
129
+	FXCHD F0, F6
130
+	FADDDP F0,F1
131
+	FXCHD F0, F3
132
+	FADDDP F0,F5
133
+	FXCHD F0, F3
134
+	FADDDP F0,F1
135
+	FMOVD 176(SP), F0
136
+	FMULD F3,F0
137
+	FMOVD 160(SP), F0
138
+	FMULD F4,F0
139
+	FMOVD 144(SP), F0
140
+	FMULD F5,F0
141
+	FMOVD 136(SP), F0
142
+	FMULDP F0,F6
143
+	FMOVD 160(SP), F0
144
+	FMULD F4,F0
145
+	FADDDP F0,F3
146
+	FMOVD 144(SP), F0
147
+	FMULD F4,F0
148
+	FADDDP F0,F2
149
+	FMOVD 136(SP), F0
150
+	FMULD F4,F0
151
+	FADDDP F0,F1
152
+	FMOVD 184(SP), F0
153
+	FMULDP F0,F4
154
+	FXCHD F0, F3
155
+	FADDDP F0,F5
156
+	FMOVD 144(SP), F0
157
+	FMULD F4,F0
158
+	FADDDP F0,F2
159
+	FMOVD 136(SP), F0
160
+	FMULD F4,F0
161
+	FADDDP F0,F1
162
+	FMOVD 184(SP), F0
163
+	FMULD F4,F0
164
+	FADDDP F0,F3
165
+	FMOVD 168(SP), F0
166
+	FMULDP F0,F4
167
+	FXCHD F0, F3
168
+	FADDDP F0,F4
169
+	FMOVD 136(SP), F0
170
+	FMULD F5,F0
171
+	FADDDP F0,F1
172
+	FXCHD F0, F3
173
+	FMOVD 184(SP), F0
174
+	FMULD F5,F0
175
+	FADDDP F0,F3
176
+	FXCHD F0, F1
177
+	FMOVD 168(SP), F0
178
+	FMULD F5,F0
179
+	FADDDP F0,F1
180
+	FMOVD 152(SP), F0
181
+	FMULDP F0,F5
182
+	FXCHD F0, F4
183
+	FADDDP F0,F1
184
+	CMPQ DX,$16
185
+	FXCHD F0, F2
186
+	FMOVD 128(SP), F0
187
+	FSUBD ·DOFFSET3MINUSTWO128(SB), F0
188
+	FADDDP F0,F1
189
+	FXCHD F0, F1
190
+	FMOVD 120(SP), F0
191
+	FSUBD ·DOFFSET2(SB), F0
192
+	FADDDP F0,F1
193
+	FXCHD F0, F3
194
+	FMOVD 112(SP), F0
195
+	FSUBD ·DOFFSET1(SB), F0
196
+	FADDDP F0,F1
197
+	FXCHD F0, F2
198
+	FMOVD 104(SP), F0
199
+	FSUBD ·DOFFSET0(SB), F0
200
+	FADDDP F0,F1
201
+	JAE MULTIPLYADDATLEAST16BYTES
202
+	MULTIPLYADDATMOST15BYTES:
203
+	FMOVD ·ALPHA130(SB), F0
204
+	FADDD F2,F0
205
+	FSUBD ·ALPHA130(SB), F0
206
+	FSUBD F0,F2
207
+	FMULD ·SCALE(SB), F0
208
+	FMOVD ·ALPHA32(SB), F0
209
+	FADDD F2,F0
210
+	FSUBD ·ALPHA32(SB), F0
211
+	FSUBD F0,F2
212
+	FMOVD ·ALPHA64(SB), F0
213
+	FADDD F5,F0
214
+	FSUBD ·ALPHA64(SB), F0
215
+	FSUBD F0,F5
216
+	FMOVD ·ALPHA96(SB), F0
217
+	FADDD F7,F0
218
+	FSUBD ·ALPHA96(SB), F0
219
+	FSUBD F0,F7
220
+	FXCHD F0, F7
221
+	FADDDP F0,F1
222
+	FXCHD F0, F5
223
+	FADDDP F0,F1
224
+	FXCHD F0, F3
225
+	FADDDP F0,F5
226
+	FADDDP F0,F1
227
+	FMOVD 176(SP), F0
228
+	FMULD F1,F0
229
+	FMOVD 160(SP), F0
230
+	FMULD F2,F0
231
+	FMOVD 144(SP), F0
232
+	FMULD F3,F0
233
+	FMOVD 136(SP), F0
234
+	FMULDP F0,F4
235
+	FMOVD 160(SP), F0
236
+	FMULD F5,F0
237
+	FADDDP F0,F3
238
+	FMOVD 144(SP), F0
239
+	FMULD F5,F0
240
+	FADDDP F0,F2
241
+	FMOVD 136(SP), F0
242
+	FMULD F5,F0
243
+	FADDDP F0,F1
244
+	FMOVD 184(SP), F0
245
+	FMULDP F0,F5
246
+	FXCHD F0, F4
247
+	FADDDP F0,F3
248
+	FMOVD 144(SP), F0
249
+	FMULD F5,F0
250
+	FADDDP F0,F2
251
+	FMOVD 136(SP), F0
252
+	FMULD F5,F0
253
+	FADDDP F0,F1
254
+	FMOVD 184(SP), F0
255
+	FMULD F5,F0
256
+	FADDDP F0,F4
257
+	FMOVD 168(SP), F0
258
+	FMULDP F0,F5
259
+	FXCHD F0, F4
260
+	FADDDP F0,F2
261
+	FMOVD 136(SP), F0
262
+	FMULD F5,F0
263
+	FADDDP F0,F1
264
+	FMOVD 184(SP), F0
265
+	FMULD F5,F0
266
+	FADDDP F0,F4
267
+	FMOVD 168(SP), F0
268
+	FMULD F5,F0
269
+	FADDDP F0,F3
270
+	FMOVD 152(SP), F0
271
+	FMULDP F0,F5
272
+	FXCHD F0, F4
273
+	FADDDP F0,F1
274
+	ADDATMOST15BYTES:
275
+	CMPQ DX,$0
276
+	JE NOMOREBYTES
277
+	MOVL $0,0(SP)
278
+	MOVL $0, 4 (SP)
279
+	MOVL $0, 8 (SP)
280
+	MOVL $0, 12 (SP)
281
+	LEAQ 0(SP),DI
282
+	MOVQ DX,CX
283
+	REP; MOVSB
284
+	MOVB $1,0(DI)
285
+	MOVL  12 (SP),DI
286
+	MOVL  8 (SP),SI
287
+	MOVL  4 (SP),DX
288
+	MOVL 0(SP),CX
289
+	MOVL DI,128(SP)
290
+	MOVL SI,120(SP)
291
+	MOVL DX,112(SP)
292
+	MOVL CX,104(SP)
293
+	FXCHD F0, F3
294
+	FADDD 128(SP), F0
295
+	FSUBD ·DOFFSET3(SB), F0
296
+	FXCHD F0, F2
297
+	FADDD 120(SP), F0
298
+	FSUBD ·DOFFSET2(SB), F0
299
+	FXCHD F0, F1
300
+	FADDD 112(SP), F0
301
+	FSUBD ·DOFFSET1(SB), F0
302
+	FXCHD F0, F3
303
+	FADDD 104(SP), F0
304
+	FSUBD ·DOFFSET0(SB), F0
305
+	FMOVD ·ALPHA130(SB), F0
306
+	FADDD F3,F0
307
+	FSUBD ·ALPHA130(SB), F0
308
+	FSUBD F0,F3
309
+	FMULD ·SCALE(SB), F0
310
+	FMOVD ·ALPHA32(SB), F0
311
+	FADDD F2,F0
312
+	FSUBD ·ALPHA32(SB), F0
313
+	FSUBD F0,F2
314
+	FMOVD ·ALPHA64(SB), F0
315
+	FADDD F6,F0
316
+	FSUBD ·ALPHA64(SB), F0
317
+	FSUBD F0,F6
318
+	FMOVD ·ALPHA96(SB), F0
319
+	FADDD F5,F0
320
+	FSUBD ·ALPHA96(SB), F0
321
+	FSUBD F0,F5
322
+	FXCHD F0, F4
323
+	FADDDP F0,F3
324
+	FXCHD F0, F6
325
+	FADDDP F0,F1
326
+	FXCHD F0, F3
327
+	FADDDP F0,F5
328
+	FXCHD F0, F3
329
+	FADDDP F0,F1
330
+	FMOVD 176(SP), F0
331
+	FMULD F3,F0
332
+	FMOVD 160(SP), F0
333
+	FMULD F4,F0
334
+	FMOVD 144(SP), F0
335
+	FMULD F5,F0
336
+	FMOVD 136(SP), F0
337
+	FMULDP F0,F6
338
+	FMOVD 160(SP), F0
339
+	FMULD F5,F0
340
+	FADDDP F0,F3
341
+	FMOVD 144(SP), F0
342
+	FMULD F5,F0
343
+	FADDDP F0,F2
344
+	FMOVD 136(SP), F0
345
+	FMULD F5,F0
346
+	FADDDP F0,F1
347
+	FMOVD 184(SP), F0
348
+	FMULDP F0,F5
349
+	FXCHD F0, F4
350
+	FADDDP F0,F5
351
+	FMOVD 144(SP), F0
352
+	FMULD F6,F0
353
+	FADDDP F0,F2
354
+	FMOVD 136(SP), F0
355
+	FMULD F6,F0
356
+	FADDDP F0,F1
357
+	FMOVD 184(SP), F0
358
+	FMULD F6,F0
359
+	FADDDP F0,F4
360
+	FMOVD 168(SP), F0
361
+	FMULDP F0,F6
362
+	FXCHD F0, F5
363
+	FADDDP F0,F4
364
+	FMOVD 136(SP), F0
365
+	FMULD F2,F0
366
+	FADDDP F0,F1
367
+	FMOVD 184(SP), F0
368
+	FMULD F2,F0
369
+	FADDDP F0,F5
370
+	FMOVD 168(SP), F0
371
+	FMULD F2,F0
372
+	FADDDP F0,F3
373
+	FMOVD 152(SP), F0
374
+	FMULDP F0,F2
375
+	FXCHD F0, F1
376
+	FADDDP F0,F3
377
+	FXCHD F0, F3
378
+	FXCHD F0, F2
379
+	NOMOREBYTES:
380
+	MOVL $0,R10
381
+	FMOVD ·ALPHA130(SB), F0
382
+	FADDD F4,F0
383
+	FSUBD ·ALPHA130(SB), F0
384
+	FSUBD F0,F4
385
+	FMULD ·SCALE(SB), F0
386
+	FMOVD ·ALPHA32(SB), F0
387
+	FADDD F2,F0
388
+	FSUBD ·ALPHA32(SB), F0
389
+	FSUBD F0,F2
390
+	FMOVD ·ALPHA64(SB), F0
391
+	FADDD F4,F0
392
+	FSUBD ·ALPHA64(SB), F0
393
+	FSUBD F0,F4
394
+	FMOVD ·ALPHA96(SB), F0
395
+	FADDD F6,F0
396
+	FSUBD ·ALPHA96(SB), F0
397
+	FXCHD F0, F6
398
+	FSUBD F6,F0
399
+	FXCHD F0, F4
400
+	FADDDP F0,F3
401
+	FXCHD F0, F4
402
+	FADDDP F0,F1
403
+	FXCHD F0, F2
404
+	FADDDP F0,F3
405
+	FXCHD F0, F4
406
+	FADDDP F0,F3
407
+	FXCHD F0, F3
408
+	FADDD ·HOFFSET0(SB), F0
409
+	FXCHD F0, F3
410
+	FADDD ·HOFFSET1(SB), F0
411
+	FXCHD F0, F1
412
+	FADDD ·HOFFSET2(SB), F0
413
+	FXCHD F0, F2
414
+	FADDD ·HOFFSET3(SB), F0
415
+	FXCHD F0, F3
416
+	FMOVDP F0, 104(SP)
417
+	FMOVDP F0, 112(SP)
418
+	FMOVDP F0, 120(SP)
419
+	FMOVDP F0, 128(SP)
420
+	MOVL 108(SP),DI
421
+	ANDL $63,DI
422
+	MOVL 116(SP),SI
423
+	ANDL $63,SI
424
+	MOVL 124(SP),DX
425
+	ANDL $63,DX
426
+	MOVL 132(SP),CX
427
+	ANDL $63,CX
428
+	MOVL 112(SP),R8
429
+	ADDL DI,R8
430
+	MOVQ R8,112(SP)
431
+	MOVL 120(SP),DI
432
+	ADCL SI,DI
433
+	MOVQ DI,120(SP)
434
+	MOVL 128(SP),DI
435
+	ADCL DX,DI
436
+	MOVQ DI,128(SP)
437
+	MOVL R10,DI
438
+	ADCL CX,DI
439
+	MOVQ DI,136(SP)
440
+	MOVQ $5,DI
441
+	MOVL 104(SP),SI
442
+	ADDL SI,DI
443
+	MOVQ DI,104(SP)
444
+	MOVL R10,DI
445
+	MOVQ 112(SP),DX
446
+	ADCL DX,DI
447
+	MOVQ DI,112(SP)
448
+	MOVL R10,DI
449
+	MOVQ 120(SP),CX
450
+	ADCL CX,DI
451
+	MOVQ DI,120(SP)
452
+	MOVL R10,DI
453
+	MOVQ 128(SP),R8
454
+	ADCL R8,DI
455
+	MOVQ DI,128(SP)
456
+	MOVQ $0XFFFFFFFC,DI
457
+	MOVQ 136(SP),R9
458
+	ADCL R9,DI
459
+	SARL $16,DI
460
+	MOVQ DI,R9
461
+	XORL $0XFFFFFFFF,R9
462
+	ANDQ DI,SI
463
+	MOVQ 104(SP),AX
464
+	ANDQ R9,AX
465
+	ORQ AX,SI
466
+	ANDQ DI,DX
467
+	MOVQ 112(SP),AX
468
+	ANDQ R9,AX
469
+	ORQ AX,DX
470
+	ANDQ DI,CX
471
+	MOVQ 120(SP),AX
472
+	ANDQ R9,AX
473
+	ORQ AX,CX
474
+	ANDQ DI,R8
475
+	MOVQ 128(SP),DI
476
+	ANDQ R9,DI
477
+	ORQ DI,R8
478
+	MOVQ 88(SP),DI
479
+	MOVQ 96(SP),R9
480
+	ADDL 16(R9),SI
481
+	ADCL 20(R9),DX
482
+	ADCL 24(R9),CX
483
+	ADCL 28(R9),R8
484
+	MOVL SI,0(DI)
485
+	MOVL DX,4(DI)
486
+	MOVL CX,8(DI)
487
+	MOVL R8,12(DI)
488
+	MOVQ 32(SP),R11
489
+	MOVQ 40(SP),R12
490
+	MOVQ 48(SP),R13
491
+	MOVQ 56(SP),R14
492
+	MOVQ 64(SP),R15
493
+	MOVQ 72(SP),BX
494
+	MOVQ 80(SP),BP
495
+	MOVQ R11,SP
496
+	RET
0 497
new file mode 100644
... ...
@@ -0,0 +1,379 @@
0
+// Copyright 2015 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// This code was translated into a form compatible with 5a from the public
5
+// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
6
+
7
+// +build arm,!gccgo,!appengine
8
+
9
+DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
10
+DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
11
+DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
12
+DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
13
+DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
14
+GLOBL poly1305_init_constants_armv6<>(SB), 8, $20
15
+
16
+// Warning: the linker may use R11 to synthesize certain instructions. Please
17
+// take care and verify that no synthetic instructions use it.
18
+
19
+TEXT poly1305_init_ext_armv6<>(SB),4,$-4
20
+  MOVM.DB.W [R4-R11], (R13)
21
+  MOVM.IA.W (R1), [R2-R5]
22
+  MOVW $poly1305_init_constants_armv6<>(SB), R7
23
+  MOVW R2, R8
24
+  MOVW R2>>26, R9
25
+  MOVW R3>>20, g
26
+  MOVW R4>>14, R11
27
+  MOVW R5>>8, R12
28
+  ORR R3<<6, R9, R9
29
+  ORR R4<<12, g, g
30
+  ORR R5<<18, R11, R11
31
+  MOVM.IA (R7), [R2-R6]
32
+  AND R8, R2, R2
33
+  AND R9, R3, R3
34
+  AND g, R4, R4
35
+  AND R11, R5, R5
36
+  AND R12, R6, R6
37
+  MOVM.IA.W [R2-R6], (R0)
38
+  EOR R2, R2, R2
39
+  EOR R3, R3, R3
40
+  EOR R4, R4, R4
41
+  EOR R5, R5, R5
42
+  EOR R6, R6, R6
43
+  MOVM.IA.W [R2-R6], (R0)
44
+  MOVM.IA.W (R1), [R2-R5]
45
+  MOVM.IA [R2-R6], (R0)
46
+  MOVM.IA.W (R13), [R4-R11]
47
+  RET
48
+
49
+#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
50
+  MOVBU (offset+0)(Rsrc), Rtmp; \
51
+  MOVBU Rtmp, (offset+0)(Rdst); \
52
+  MOVBU (offset+1)(Rsrc), Rtmp; \
53
+  MOVBU Rtmp, (offset+1)(Rdst); \
54
+  MOVBU (offset+2)(Rsrc), Rtmp; \
55
+  MOVBU Rtmp, (offset+2)(Rdst); \
56
+  MOVBU (offset+3)(Rsrc), Rtmp; \
57
+  MOVBU Rtmp, (offset+3)(Rdst)
58
+
59
+TEXT poly1305_blocks_armv6<>(SB),4,$-4
60
+  MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
61
+  SUB $128, R13
62
+  MOVW R0, 36(R13)
63
+  MOVW R1, 40(R13)
64
+  MOVW R2, 44(R13)
65
+  MOVW R1, R14
66
+  MOVW R2, R12
67
+  MOVW 56(R0), R8
68
+  WORD $0xe1180008 // TST R8, R8 not working see issue 5921
69
+  EOR R6, R6, R6
70
+  MOVW.EQ $(1<<24), R6
71
+  MOVW R6, 32(R13)
72
+  ADD $64, R13, g
73
+  MOVM.IA (R0), [R0-R9]
74
+  MOVM.IA [R0-R4], (g)
75
+  CMP $16, R12
76
+  BLO poly1305_blocks_armv6_done
77
+poly1305_blocks_armv6_mainloop:
78
+  WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
79
+  BEQ poly1305_blocks_armv6_mainloop_aligned
80
+  ADD $48, R13, g
81
+  MOVW_UNALIGNED(R14, g, R0, 0)
82
+  MOVW_UNALIGNED(R14, g, R0, 4)
83
+  MOVW_UNALIGNED(R14, g, R0, 8)
84
+  MOVW_UNALIGNED(R14, g, R0, 12)
85
+  MOVM.IA (g), [R0-R3]
86
+  ADD $16, R14
87
+  B poly1305_blocks_armv6_mainloop_loaded
88
+poly1305_blocks_armv6_mainloop_aligned:
89
+  MOVM.IA.W (R14), [R0-R3]
90
+poly1305_blocks_armv6_mainloop_loaded:
91
+  MOVW R0>>26, g
92
+  MOVW R1>>20, R11
93
+  MOVW R2>>14, R12
94
+  MOVW R14, 40(R13)
95
+  MOVW R3>>8, R4
96
+  ORR R1<<6, g, g
97
+  ORR R2<<12, R11, R11
98
+  ORR R3<<18, R12, R12
99
+  BIC $0xfc000000, R0, R0
100
+  BIC $0xfc000000, g, g
101
+  MOVW 32(R13), R3
102
+  BIC $0xfc000000, R11, R11
103
+  BIC $0xfc000000, R12, R12
104
+  ADD R0, R5, R5
105
+  ADD g, R6, R6
106
+  ORR R3, R4, R4
107
+  ADD R11, R7, R7
108
+  ADD $64, R13, R14
109
+  ADD R12, R8, R8
110
+  ADD R4, R9, R9
111
+  MOVM.IA (R14), [R0-R4]
112
+  MULLU R4, R5, (R11, g)
113
+  MULLU R3, R5, (R14, R12)
114
+  MULALU R3, R6, (R11, g)
115
+  MULALU R2, R6, (R14, R12)
116
+  MULALU R2, R7, (R11, g)
117
+  MULALU R1, R7, (R14, R12)
118
+  ADD R4<<2, R4, R4
119
+  ADD R3<<2, R3, R3
120
+  MULALU R1, R8, (R11, g)
121
+  MULALU R0, R8, (R14, R12)
122
+  MULALU R0, R9, (R11, g)
123
+  MULALU R4, R9, (R14, R12)
124
+  MOVW g, 24(R13)
125
+  MOVW R11, 28(R13)
126
+  MOVW R12, 16(R13)
127
+  MOVW R14, 20(R13)
128
+  MULLU R2, R5, (R11, g)
129
+  MULLU R1, R5, (R14, R12)
130
+  MULALU R1, R6, (R11, g)
131
+  MULALU R0, R6, (R14, R12)
132
+  MULALU R0, R7, (R11, g)
133
+  MULALU R4, R7, (R14, R12)
134
+  ADD R2<<2, R2, R2
135
+  ADD R1<<2, R1, R1
136
+  MULALU R4, R8, (R11, g)
137
+  MULALU R3, R8, (R14, R12)
138
+  MULALU R3, R9, (R11, g)
139
+  MULALU R2, R9, (R14, R12)
140
+  MOVW g, 8(R13)
141
+  MOVW R11, 12(R13)
142
+  MOVW R12, 0(R13)
143
+  MOVW R14, w+4(SP)
144
+  MULLU R0, R5, (R11, g)
145
+  MULALU R4, R6, (R11, g)
146
+  MULALU R3, R7, (R11, g)
147
+  MULALU R2, R8, (R11, g)
148
+  MULALU R1, R9, (R11, g)
149
+  MOVM.IA (R13), [R0-R7]
150
+  MOVW g>>26, R12
151
+  MOVW R4>>26, R14
152
+  ORR R11<<6, R12, R12
153
+  ORR R5<<6, R14, R14
154
+  BIC $0xfc000000, g, g
155
+  BIC $0xfc000000, R4, R4
156
+  ADD.S R12, R0, R0
157
+  ADC $0, R1, R1
158
+  ADD.S R14, R6, R6
159
+  ADC $0, R7, R7
160
+  MOVW R0>>26, R12
161
+  MOVW R6>>26, R14
162
+  ORR R1<<6, R12, R12
163
+  ORR R7<<6, R14, R14
164
+  BIC $0xfc000000, R0, R0
165
+  BIC $0xfc000000, R6, R6
166
+  ADD R14<<2, R14, R14
167
+  ADD.S R12, R2, R2
168
+  ADC $0, R3, R3
169
+  ADD R14, g, g
170
+  MOVW R2>>26, R12
171
+  MOVW g>>26, R14
172
+  ORR R3<<6, R12, R12
173
+  BIC $0xfc000000, g, R5
174
+  BIC $0xfc000000, R2, R7
175
+  ADD R12, R4, R4
176
+  ADD R14, R0, R0
177
+  MOVW R4>>26, R12
178
+  BIC $0xfc000000, R4, R8
179
+  ADD R12, R6, R9
180
+  MOVW w+44(SP), R12
181
+  MOVW w+40(SP), R14
182
+  MOVW R0, R6
183
+  CMP $32, R12
184
+  SUB $16, R12, R12
185
+  MOVW R12, 44(R13)
186
+  BHS poly1305_blocks_armv6_mainloop
187
+poly1305_blocks_armv6_done:
188
+  MOVW 36(R13), R12
189
+  MOVW R5, 20(R12)
190
+  MOVW R6, 24(R12)
191
+  MOVW R7, 28(R12)
192
+  MOVW R8, 32(R12)
193
+  MOVW R9, 36(R12)
194
+  ADD $128, R13, R13
195
+  MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
196
+  RET
197
+
198
+#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
199
+  MOVBU.P 1(Rsrc), Rtmp; \
200
+  MOVBU.P Rtmp, 1(Rdst); \
201
+  MOVBU.P 1(Rsrc), Rtmp; \
202
+  MOVBU.P Rtmp, 1(Rdst)
203
+
204
+#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
205
+  MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
206
+  MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
207
+
208
+TEXT poly1305_finish_ext_armv6<>(SB),4,$-4
209
+  MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
210
+  SUB $16, R13, R13
211
+  MOVW R0, R5
212
+  MOVW R1, R6
213
+  MOVW R2, R7
214
+  MOVW R3, R8
215
+  AND.S R2, R2, R2
216
+  BEQ poly1305_finish_ext_armv6_noremaining
217
+  EOR R0, R0
218
+  MOVW R13, R9
219
+  MOVW R0, 0(R13)
220
+  MOVW R0, 4(R13)
221
+  MOVW R0, 8(R13)
222
+  MOVW R0, 12(R13)
223
+  WORD $0xe3110003 // TST R1, #3 not working see issue 5921
224
+  BEQ poly1305_finish_ext_armv6_aligned
225
+  WORD $0xe3120008 // TST R2, #8 not working see issue 5921
226
+  BEQ poly1305_finish_ext_armv6_skip8
227
+  MOVWP_UNALIGNED(R1, R9, g)
228
+  MOVWP_UNALIGNED(R1, R9, g)
229
+poly1305_finish_ext_armv6_skip8:
230
+  WORD $0xe3120004 // TST $4, R2 not working see issue 5921
231
+  BEQ poly1305_finish_ext_armv6_skip4
232
+  MOVWP_UNALIGNED(R1, R9, g)
233
+poly1305_finish_ext_armv6_skip4:
234
+  WORD $0xe3120002 // TST $2, R2 not working see issue 5921
235
+  BEQ poly1305_finish_ext_armv6_skip2
236
+  MOVHUP_UNALIGNED(R1, R9, g)
237
+  B poly1305_finish_ext_armv6_skip2
238
+poly1305_finish_ext_armv6_aligned:
239
+  WORD $0xe3120008 // TST R2, #8 not working see issue 5921
240
+  BEQ poly1305_finish_ext_armv6_skip8_aligned
241
+  MOVM.IA.W (R1), [g-R11]
242
+  MOVM.IA.W [g-R11], (R9)
243
+poly1305_finish_ext_armv6_skip8_aligned:
244
+  WORD $0xe3120004 // TST $4, R2 not working see issue 5921
245
+  BEQ poly1305_finish_ext_armv6_skip4_aligned
246
+  MOVW.P 4(R1), g
247
+  MOVW.P g, 4(R9)
248
+poly1305_finish_ext_armv6_skip4_aligned:
249
+  WORD $0xe3120002 // TST $2, R2 not working see issue 5921
250
+  BEQ poly1305_finish_ext_armv6_skip2
251
+  MOVHU.P 2(R1), g
252
+  MOVH.P g, 2(R9)
253
+poly1305_finish_ext_armv6_skip2:
254
+  WORD $0xe3120001 // TST $1, R2 not working see issue 5921
255
+  BEQ poly1305_finish_ext_armv6_skip1
256
+  MOVBU.P 1(R1), g
257
+  MOVBU.P g, 1(R9)
258
+poly1305_finish_ext_armv6_skip1:
259
+  MOVW $1, R11
260
+  MOVBU R11, 0(R9)
261
+  MOVW R11, 56(R5)
262
+  MOVW R5, R0
263
+  MOVW R13, R1
264
+  MOVW $16, R2
265
+  BL poly1305_blocks_armv6<>(SB)
266
+poly1305_finish_ext_armv6_noremaining:
267
+  MOVW 20(R5), R0
268
+  MOVW 24(R5), R1
269
+  MOVW 28(R5), R2
270
+  MOVW 32(R5), R3
271
+  MOVW 36(R5), R4
272
+  MOVW R4>>26, R12
273
+  BIC $0xfc000000, R4, R4
274
+  ADD R12<<2, R12, R12
275
+  ADD R12, R0, R0
276
+  MOVW R0>>26, R12
277
+  BIC $0xfc000000, R0, R0
278
+  ADD R12, R1, R1
279
+  MOVW R1>>26, R12
280
+  BIC $0xfc000000, R1, R1
281
+  ADD R12, R2, R2
282
+  MOVW R2>>26, R12
283
+  BIC $0xfc000000, R2, R2
284
+  ADD R12, R3, R3
285
+  MOVW R3>>26, R12
286
+  BIC $0xfc000000, R3, R3
287
+  ADD R12, R4, R4
288
+  ADD $5, R0, R6
289
+  MOVW R6>>26, R12
290
+  BIC $0xfc000000, R6, R6
291
+  ADD R12, R1, R7
292
+  MOVW R7>>26, R12
293
+  BIC $0xfc000000, R7, R7
294
+  ADD R12, R2, g
295
+  MOVW g>>26, R12
296
+  BIC $0xfc000000, g, g
297
+  ADD R12, R3, R11
298
+  MOVW $-(1<<26), R12
299
+  ADD R11>>26, R12, R12
300
+  BIC $0xfc000000, R11, R11
301
+  ADD R12, R4, R14
302
+  MOVW R14>>31, R12
303
+  SUB $1, R12
304
+  AND R12, R6, R6
305
+  AND R12, R7, R7
306
+  AND R12, g, g
307
+  AND R12, R11, R11
308
+  AND R12, R14, R14
309
+  MVN R12, R12
310
+  AND R12, R0, R0
311
+  AND R12, R1, R1
312
+  AND R12, R2, R2
313
+  AND R12, R3, R3
314
+  AND R12, R4, R4
315
+  ORR R6, R0, R0
316
+  ORR R7, R1, R1
317
+  ORR g, R2, R2
318
+  ORR R11, R3, R3
319
+  ORR R14, R4, R4
320
+  ORR R1<<26, R0, R0
321
+  MOVW R1>>6, R1
322
+  ORR R2<<20, R1, R1
323
+  MOVW R2>>12, R2
324
+  ORR R3<<14, R2, R2
325
+  MOVW R3>>18, R3
326
+  ORR R4<<8, R3, R3
327
+  MOVW 40(R5), R6
328
+  MOVW 44(R5), R7
329
+  MOVW 48(R5), g
330
+  MOVW 52(R5), R11
331
+  ADD.S R6, R0, R0
332
+  ADC.S R7, R1, R1
333
+  ADC.S g, R2, R2
334
+  ADC.S R11, R3, R3
335
+  MOVM.IA [R0-R3], (R8)
336
+  MOVW R5, R12
337
+  EOR R0, R0, R0
338
+  EOR R1, R1, R1
339
+  EOR R2, R2, R2
340
+  EOR R3, R3, R3
341
+  EOR R4, R4, R4
342
+  EOR R5, R5, R5
343
+  EOR R6, R6, R6
344
+  EOR R7, R7, R7
345
+  MOVM.IA.W [R0-R7], (R12)
346
+  MOVM.IA [R0-R7], (R12)
347
+  ADD $16, R13, R13
348
+  MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
349
+  RET
350
+
351
+// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
352
+TEXT ·poly1305_auth_armv6(SB),0,$280-16
353
+  MOVW  out+0(FP), R4
354
+  MOVW  m+4(FP), R5
355
+  MOVW  mlen+8(FP), R6
356
+  MOVW  key+12(FP), R7
357
+
358
+  MOVW R13, R8
359
+  BIC $63, R13
360
+  SUB $64, R13, R13
361
+  MOVW  R13, R0
362
+  MOVW  R7, R1
363
+  BL poly1305_init_ext_armv6<>(SB)
364
+  BIC.S $15, R6, R2
365
+  BEQ poly1305_auth_armv6_noblocks
366
+  MOVW R13, R0
367
+  MOVW R5, R1
368
+  ADD R2, R5, R5
369
+  SUB R2, R6, R6
370
+  BL poly1305_blocks_armv6<>(SB)
371
+poly1305_auth_armv6_noblocks:
372
+  MOVW R13, R0
373
+  MOVW R5, R1
374
+  MOVW R6, R2
375
+  MOVW R4, R3
376
+  BL poly1305_finish_ext_armv6<>(SB)
377
+  MOVW R8, R13
378
+  RET
0 379
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build amd64,!gccgo,!appengine
5
+
6
+package poly1305
7
+
8
+// This function is implemented in poly1305_amd64.s
9
+
10
+//go:noescape
11
+
12
+func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
13
+
14
+// Sum generates an authenticator for m using a one-time key and puts the
15
+// 16-byte result into out. Authenticating two different messages with the same
16
+// key allows an attacker to forge messages at will.
17
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
18
+	var mPtr *byte
19
+	if len(m) > 0 {
20
+		mPtr = &m[0]
21
+	}
22
+	poly1305(out, mPtr, uint64(len(m)), key)
23
+}
0 24
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+// Copyright 2015 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build arm,!gccgo,!appengine
5
+
6
+package poly1305
7
+
8
+// This function is implemented in poly1305_arm.s
9
+
10
+//go:noescape
11
+
12
+func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
13
+
14
+// Sum generates an authenticator for m using a one-time key and puts the
15
+// 16-byte result into out. Authenticating two different messages with the same
16
+// key allows an attacker to forge messages at will.
17
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
18
+	var mPtr *byte
19
+	if len(m) > 0 {
20
+		mPtr = &m[0]
21
+	}
22
+	poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
23
+}
0 24
new file mode 100644
... ...
@@ -0,0 +1,1531 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build !amd64,!arm gccgo appengine
5
+
6
+package poly1305
7
+
8
+// Based on original, public domain implementation from NaCl by D. J.
9
+// Bernstein.
10
+
11
+import "math"
12
+
13
+const (
14
+	alpham80 = 0.00000000558793544769287109375
15
+	alpham48 = 24.0
16
+	alpham16 = 103079215104.0
17
+	alpha0   = 6755399441055744.0
18
+	alpha18  = 1770887431076116955136.0
19
+	alpha32  = 29014219670751100192948224.0
20
+	alpha50  = 7605903601369376408980219232256.0
21
+	alpha64  = 124615124604835863084731911901282304.0
22
+	alpha82  = 32667107224410092492483962313449748299776.0
23
+	alpha96  = 535217884764734955396857238543560676143529984.0
24
+	alpha112 = 35076039295941670036888435985190792471742381031424.0
25
+	alpha130 = 9194973245195333150150082162901855101712434733101613056.0
26
+	scale    = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125
27
+	offset0  = 6755408030990331.0
28
+	offset1  = 29014256564239239022116864.0
29
+	offset2  = 124615283061160854719918951570079744.0
30
+	offset3  = 535219245894202480694386063513315216128475136.0
31
+)
32
+
33
+// Sum generates an authenticator for m using a one-time key and puts the
34
+// 16-byte result into out. Authenticating two different messages with the same
35
+// key allows an attacker to forge messages at will.
36
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
37
+	r := key
38
+	s := key[16:]
39
+	var (
40
+		y7        float64
41
+		y6        float64
42
+		y1        float64
43
+		y0        float64
44
+		y5        float64
45
+		y4        float64
46
+		x7        float64
47
+		x6        float64
48
+		x1        float64
49
+		x0        float64
50
+		y3        float64
51
+		y2        float64
52
+		x5        float64
53
+		r3lowx0   float64
54
+		x4        float64
55
+		r0lowx6   float64
56
+		x3        float64
57
+		r3highx0  float64
58
+		x2        float64
59
+		r0highx6  float64
60
+		r0lowx0   float64
61
+		sr1lowx6  float64
62
+		r0highx0  float64
63
+		sr1highx6 float64
64
+		sr3low    float64
65
+		r1lowx0   float64
66
+		sr2lowx6  float64
67
+		r1highx0  float64
68
+		sr2highx6 float64
69
+		r2lowx0   float64
70
+		sr3lowx6  float64
71
+		r2highx0  float64
72
+		sr3highx6 float64
73
+		r1highx4  float64
74
+		r1lowx4   float64
75
+		r0highx4  float64
76
+		r0lowx4   float64
77
+		sr3highx4 float64
78
+		sr3lowx4  float64
79
+		sr2highx4 float64
80
+		sr2lowx4  float64
81
+		r0lowx2   float64
82
+		r0highx2  float64
83
+		r1lowx2   float64
84
+		r1highx2  float64
85
+		r2lowx2   float64
86
+		r2highx2  float64
87
+		sr3lowx2  float64
88
+		sr3highx2 float64
89
+		z0        float64
90
+		z1        float64
91
+		z2        float64
92
+		z3        float64
93
+		m0        int64
94
+		m1        int64
95
+		m2        int64
96
+		m3        int64
97
+		m00       uint32
98
+		m01       uint32
99
+		m02       uint32
100
+		m03       uint32
101
+		m10       uint32
102
+		m11       uint32
103
+		m12       uint32
104
+		m13       uint32
105
+		m20       uint32
106
+		m21       uint32
107
+		m22       uint32
108
+		m23       uint32
109
+		m30       uint32
110
+		m31       uint32
111
+		m32       uint32
112
+		m33       uint64
113
+		lbelow2   int32
114
+		lbelow3   int32
115
+		lbelow4   int32
116
+		lbelow5   int32
117
+		lbelow6   int32
118
+		lbelow7   int32
119
+		lbelow8   int32
120
+		lbelow9   int32
121
+		lbelow10  int32
122
+		lbelow11  int32
123
+		lbelow12  int32
124
+		lbelow13  int32
125
+		lbelow14  int32
126
+		lbelow15  int32
127
+		s00       uint32
128
+		s01       uint32
129
+		s02       uint32
130
+		s03       uint32
131
+		s10       uint32
132
+		s11       uint32
133
+		s12       uint32
134
+		s13       uint32
135
+		s20       uint32
136
+		s21       uint32
137
+		s22       uint32
138
+		s23       uint32
139
+		s30       uint32
140
+		s31       uint32
141
+		s32       uint32
142
+		s33       uint32
143
+		bits32    uint64
144
+		f         uint64
145
+		f0        uint64
146
+		f1        uint64
147
+		f2        uint64
148
+		f3        uint64
149
+		f4        uint64
150
+		g         uint64
151
+		g0        uint64
152
+		g1        uint64
153
+		g2        uint64
154
+		g3        uint64
155
+		g4        uint64
156
+	)
157
+
158
+	var p int32
159
+
160
+	l := int32(len(m))
161
+
162
+	r00 := uint32(r[0])
163
+
164
+	r01 := uint32(r[1])
165
+
166
+	r02 := uint32(r[2])
167
+	r0 := int64(2151)
168
+
169
+	r03 := uint32(r[3])
170
+	r03 &= 15
171
+	r0 <<= 51
172
+
173
+	r10 := uint32(r[4])
174
+	r10 &= 252
175
+	r01 <<= 8
176
+	r0 += int64(r00)
177
+
178
+	r11 := uint32(r[5])
179
+	r02 <<= 16
180
+	r0 += int64(r01)
181
+
182
+	r12 := uint32(r[6])
183
+	r03 <<= 24
184
+	r0 += int64(r02)
185
+
186
+	r13 := uint32(r[7])
187
+	r13 &= 15
188
+	r1 := int64(2215)
189
+	r0 += int64(r03)
190
+
191
+	d0 := r0
192
+	r1 <<= 51
193
+	r2 := int64(2279)
194
+
195
+	r20 := uint32(r[8])
196
+	r20 &= 252
197
+	r11 <<= 8
198
+	r1 += int64(r10)
199
+
200
+	r21 := uint32(r[9])
201
+	r12 <<= 16
202
+	r1 += int64(r11)
203
+
204
+	r22 := uint32(r[10])
205
+	r13 <<= 24
206
+	r1 += int64(r12)
207
+
208
+	r23 := uint32(r[11])
209
+	r23 &= 15
210
+	r2 <<= 51
211
+	r1 += int64(r13)
212
+
213
+	d1 := r1
214
+	r21 <<= 8
215
+	r2 += int64(r20)
216
+
217
+	r30 := uint32(r[12])
218
+	r30 &= 252
219
+	r22 <<= 16
220
+	r2 += int64(r21)
221
+
222
+	r31 := uint32(r[13])
223
+	r23 <<= 24
224
+	r2 += int64(r22)
225
+
226
+	r32 := uint32(r[14])
227
+	r2 += int64(r23)
228
+	r3 := int64(2343)
229
+
230
+	d2 := r2
231
+	r3 <<= 51
232
+
233
+	r33 := uint32(r[15])
234
+	r33 &= 15
235
+	r31 <<= 8
236
+	r3 += int64(r30)
237
+
238
+	r32 <<= 16
239
+	r3 += int64(r31)
240
+
241
+	r33 <<= 24
242
+	r3 += int64(r32)
243
+
244
+	r3 += int64(r33)
245
+	h0 := alpha32 - alpha32
246
+
247
+	d3 := r3
248
+	h1 := alpha32 - alpha32
249
+
250
+	h2 := alpha32 - alpha32
251
+
252
+	h3 := alpha32 - alpha32
253
+
254
+	h4 := alpha32 - alpha32
255
+
256
+	r0low := math.Float64frombits(uint64(d0))
257
+	h5 := alpha32 - alpha32
258
+
259
+	r1low := math.Float64frombits(uint64(d1))
260
+	h6 := alpha32 - alpha32
261
+
262
+	r2low := math.Float64frombits(uint64(d2))
263
+	h7 := alpha32 - alpha32
264
+
265
+	r0low -= alpha0
266
+
267
+	r1low -= alpha32
268
+
269
+	r2low -= alpha64
270
+
271
+	r0high := r0low + alpha18
272
+
273
+	r3low := math.Float64frombits(uint64(d3))
274
+
275
+	r1high := r1low + alpha50
276
+	sr1low := scale * r1low
277
+
278
+	r2high := r2low + alpha82
279
+	sr2low := scale * r2low
280
+
281
+	r0high -= alpha18
282
+	r0high_stack := r0high
283
+
284
+	r3low -= alpha96
285
+
286
+	r1high -= alpha50
287
+	r1high_stack := r1high
288
+
289
+	sr1high := sr1low + alpham80
290
+
291
+	r0low -= r0high
292
+
293
+	r2high -= alpha82
294
+	sr3low = scale * r3low
295
+
296
+	sr2high := sr2low + alpham48
297
+
298
+	r1low -= r1high
299
+	r1low_stack := r1low
300
+
301
+	sr1high -= alpham80
302
+	sr1high_stack := sr1high
303
+
304
+	r2low -= r2high
305
+	r2low_stack := r2low
306
+
307
+	sr2high -= alpham48
308
+	sr2high_stack := sr2high
309
+
310
+	r3high := r3low + alpha112
311
+	r0low_stack := r0low
312
+
313
+	sr1low -= sr1high
314
+	sr1low_stack := sr1low
315
+
316
+	sr3high := sr3low + alpham16
317
+	r2high_stack := r2high
318
+
319
+	sr2low -= sr2high
320
+	sr2low_stack := sr2low
321
+
322
+	r3high -= alpha112
323
+	r3high_stack := r3high
324
+
325
+	sr3high -= alpham16
326
+	sr3high_stack := sr3high
327
+
328
+	r3low -= r3high
329
+	r3low_stack := r3low
330
+
331
+	sr3low -= sr3high
332
+	sr3low_stack := sr3low
333
+
334
+	if l < 16 {
335
+		goto addatmost15bytes
336
+	}
337
+
338
+	m00 = uint32(m[p+0])
339
+	m0 = 2151
340
+
341
+	m0 <<= 51
342
+	m1 = 2215
343
+	m01 = uint32(m[p+1])
344
+
345
+	m1 <<= 51
346
+	m2 = 2279
347
+	m02 = uint32(m[p+2])
348
+
349
+	m2 <<= 51
350
+	m3 = 2343
351
+	m03 = uint32(m[p+3])
352
+
353
+	m10 = uint32(m[p+4])
354
+	m01 <<= 8
355
+	m0 += int64(m00)
356
+
357
+	m11 = uint32(m[p+5])
358
+	m02 <<= 16
359
+	m0 += int64(m01)
360
+
361
+	m12 = uint32(m[p+6])
362
+	m03 <<= 24
363
+	m0 += int64(m02)
364
+
365
+	m13 = uint32(m[p+7])
366
+	m3 <<= 51
367
+	m0 += int64(m03)
368
+
369
+	m20 = uint32(m[p+8])
370
+	m11 <<= 8
371
+	m1 += int64(m10)
372
+
373
+	m21 = uint32(m[p+9])
374
+	m12 <<= 16
375
+	m1 += int64(m11)
376
+
377
+	m22 = uint32(m[p+10])
378
+	m13 <<= 24
379
+	m1 += int64(m12)
380
+
381
+	m23 = uint32(m[p+11])
382
+	m1 += int64(m13)
383
+
384
+	m30 = uint32(m[p+12])
385
+	m21 <<= 8
386
+	m2 += int64(m20)
387
+
388
+	m31 = uint32(m[p+13])
389
+	m22 <<= 16
390
+	m2 += int64(m21)
391
+
392
+	m32 = uint32(m[p+14])
393
+	m23 <<= 24
394
+	m2 += int64(m22)
395
+
396
+	m33 = uint64(m[p+15])
397
+	m2 += int64(m23)
398
+
399
+	d0 = m0
400
+	m31 <<= 8
401
+	m3 += int64(m30)
402
+
403
+	d1 = m1
404
+	m32 <<= 16
405
+	m3 += int64(m31)
406
+
407
+	d2 = m2
408
+	m33 += 256
409
+
410
+	m33 <<= 24
411
+	m3 += int64(m32)
412
+
413
+	m3 += int64(m33)
414
+	d3 = m3
415
+
416
+	p += 16
417
+	l -= 16
418
+
419
+	z0 = math.Float64frombits(uint64(d0))
420
+
421
+	z1 = math.Float64frombits(uint64(d1))
422
+
423
+	z2 = math.Float64frombits(uint64(d2))
424
+
425
+	z3 = math.Float64frombits(uint64(d3))
426
+
427
+	z0 -= alpha0
428
+
429
+	z1 -= alpha32
430
+
431
+	z2 -= alpha64
432
+
433
+	z3 -= alpha96
434
+
435
+	h0 += z0
436
+
437
+	h1 += z1
438
+
439
+	h3 += z2
440
+
441
+	h5 += z3
442
+
443
+	if l < 16 {
444
+		goto multiplyaddatmost15bytes
445
+	}
446
+
447
+multiplyaddatleast16bytes:
448
+
449
+	m2 = 2279
450
+	m20 = uint32(m[p+8])
451
+	y7 = h7 + alpha130
452
+
453
+	m2 <<= 51
454
+	m3 = 2343
455
+	m21 = uint32(m[p+9])
456
+	y6 = h6 + alpha130
457
+
458
+	m3 <<= 51
459
+	m0 = 2151
460
+	m22 = uint32(m[p+10])
461
+	y1 = h1 + alpha32
462
+
463
+	m0 <<= 51
464
+	m1 = 2215
465
+	m23 = uint32(m[p+11])
466
+	y0 = h0 + alpha32
467
+
468
+	m1 <<= 51
469
+	m30 = uint32(m[p+12])
470
+	y7 -= alpha130
471
+
472
+	m21 <<= 8
473
+	m2 += int64(m20)
474
+	m31 = uint32(m[p+13])
475
+	y6 -= alpha130
476
+
477
+	m22 <<= 16
478
+	m2 += int64(m21)
479
+	m32 = uint32(m[p+14])
480
+	y1 -= alpha32
481
+
482
+	m23 <<= 24
483
+	m2 += int64(m22)
484
+	m33 = uint64(m[p+15])
485
+	y0 -= alpha32
486
+
487
+	m2 += int64(m23)
488
+	m00 = uint32(m[p+0])
489
+	y5 = h5 + alpha96
490
+
491
+	m31 <<= 8
492
+	m3 += int64(m30)
493
+	m01 = uint32(m[p+1])
494
+	y4 = h4 + alpha96
495
+
496
+	m32 <<= 16
497
+	m02 = uint32(m[p+2])
498
+	x7 = h7 - y7
499
+	y7 *= scale
500
+
501
+	m33 += 256
502
+	m03 = uint32(m[p+3])
503
+	x6 = h6 - y6
504
+	y6 *= scale
505
+
506
+	m33 <<= 24
507
+	m3 += int64(m31)
508
+	m10 = uint32(m[p+4])
509
+	x1 = h1 - y1
510
+
511
+	m01 <<= 8
512
+	m3 += int64(m32)
513
+	m11 = uint32(m[p+5])
514
+	x0 = h0 - y0
515
+
516
+	m3 += int64(m33)
517
+	m0 += int64(m00)
518
+	m12 = uint32(m[p+6])
519
+	y5 -= alpha96
520
+
521
+	m02 <<= 16
522
+	m0 += int64(m01)
523
+	m13 = uint32(m[p+7])
524
+	y4 -= alpha96
525
+
526
+	m03 <<= 24
527
+	m0 += int64(m02)
528
+	d2 = m2
529
+	x1 += y7
530
+
531
+	m0 += int64(m03)
532
+	d3 = m3
533
+	x0 += y6
534
+
535
+	m11 <<= 8
536
+	m1 += int64(m10)
537
+	d0 = m0
538
+	x7 += y5
539
+
540
+	m12 <<= 16
541
+	m1 += int64(m11)
542
+	x6 += y4
543
+
544
+	m13 <<= 24
545
+	m1 += int64(m12)
546
+	y3 = h3 + alpha64
547
+
548
+	m1 += int64(m13)
549
+	d1 = m1
550
+	y2 = h2 + alpha64
551
+
552
+	x0 += x1
553
+
554
+	x6 += x7
555
+
556
+	y3 -= alpha64
557
+	r3low = r3low_stack
558
+
559
+	y2 -= alpha64
560
+	r0low = r0low_stack
561
+
562
+	x5 = h5 - y5
563
+	r3lowx0 = r3low * x0
564
+	r3high = r3high_stack
565
+
566
+	x4 = h4 - y4
567
+	r0lowx6 = r0low * x6
568
+	r0high = r0high_stack
569
+
570
+	x3 = h3 - y3
571
+	r3highx0 = r3high * x0
572
+	sr1low = sr1low_stack
573
+
574
+	x2 = h2 - y2
575
+	r0highx6 = r0high * x6
576
+	sr1high = sr1high_stack
577
+
578
+	x5 += y3
579
+	r0lowx0 = r0low * x0
580
+	r1low = r1low_stack
581
+
582
+	h6 = r3lowx0 + r0lowx6
583
+	sr1lowx6 = sr1low * x6
584
+	r1high = r1high_stack
585
+
586
+	x4 += y2
587
+	r0highx0 = r0high * x0
588
+	sr2low = sr2low_stack
589
+
590
+	h7 = r3highx0 + r0highx6
591
+	sr1highx6 = sr1high * x6
592
+	sr2high = sr2high_stack
593
+
594
+	x3 += y1
595
+	r1lowx0 = r1low * x0
596
+	r2low = r2low_stack
597
+
598
+	h0 = r0lowx0 + sr1lowx6
599
+	sr2lowx6 = sr2low * x6
600
+	r2high = r2high_stack
601
+
602
+	x2 += y0
603
+	r1highx0 = r1high * x0
604
+	sr3low = sr3low_stack
605
+
606
+	h1 = r0highx0 + sr1highx6
607
+	sr2highx6 = sr2high * x6
608
+	sr3high = sr3high_stack
609
+
610
+	x4 += x5
611
+	r2lowx0 = r2low * x0
612
+	z2 = math.Float64frombits(uint64(d2))
613
+
614
+	h2 = r1lowx0 + sr2lowx6
615
+	sr3lowx6 = sr3low * x6
616
+
617
+	x2 += x3
618
+	r2highx0 = r2high * x0
619
+	z3 = math.Float64frombits(uint64(d3))
620
+
621
+	h3 = r1highx0 + sr2highx6
622
+	sr3highx6 = sr3high * x6
623
+
624
+	r1highx4 = r1high * x4
625
+	z2 -= alpha64
626
+
627
+	h4 = r2lowx0 + sr3lowx6
628
+	r1lowx4 = r1low * x4
629
+
630
+	r0highx4 = r0high * x4
631
+	z3 -= alpha96
632
+
633
+	h5 = r2highx0 + sr3highx6
634
+	r0lowx4 = r0low * x4
635
+
636
+	h7 += r1highx4
637
+	sr3highx4 = sr3high * x4
638
+
639
+	h6 += r1lowx4
640
+	sr3lowx4 = sr3low * x4
641
+
642
+	h5 += r0highx4
643
+	sr2highx4 = sr2high * x4
644
+
645
+	h4 += r0lowx4
646
+	sr2lowx4 = sr2low * x4
647
+
648
+	h3 += sr3highx4
649
+	r0lowx2 = r0low * x2
650
+
651
+	h2 += sr3lowx4
652
+	r0highx2 = r0high * x2
653
+
654
+	h1 += sr2highx4
655
+	r1lowx2 = r1low * x2
656
+
657
+	h0 += sr2lowx4
658
+	r1highx2 = r1high * x2
659
+
660
+	h2 += r0lowx2
661
+	r2lowx2 = r2low * x2
662
+
663
+	h3 += r0highx2
664
+	r2highx2 = r2high * x2
665
+
666
+	h4 += r1lowx2
667
+	sr3lowx2 = sr3low * x2
668
+
669
+	h5 += r1highx2
670
+	sr3highx2 = sr3high * x2
671
+
672
+	p += 16
673
+	l -= 16
674
+	h6 += r2lowx2
675
+
676
+	h7 += r2highx2
677
+
678
+	z1 = math.Float64frombits(uint64(d1))
679
+	h0 += sr3lowx2
680
+
681
+	z0 = math.Float64frombits(uint64(d0))
682
+	h1 += sr3highx2
683
+
684
+	z1 -= alpha32
685
+
686
+	z0 -= alpha0
687
+
688
+	h5 += z3
689
+
690
+	h3 += z2
691
+
692
+	h1 += z1
693
+
694
+	h0 += z0
695
+
696
+	if l >= 16 {
697
+		goto multiplyaddatleast16bytes
698
+	}
699
+
700
+multiplyaddatmost15bytes:
701
+
702
+	y7 = h7 + alpha130
703
+
704
+	y6 = h6 + alpha130
705
+
706
+	y1 = h1 + alpha32
707
+
708
+	y0 = h0 + alpha32
709
+
710
+	y7 -= alpha130
711
+
712
+	y6 -= alpha130
713
+
714
+	y1 -= alpha32
715
+
716
+	y0 -= alpha32
717
+
718
+	y5 = h5 + alpha96
719
+
720
+	y4 = h4 + alpha96
721
+
722
+	x7 = h7 - y7
723
+	y7 *= scale
724
+
725
+	x6 = h6 - y6
726
+	y6 *= scale
727
+
728
+	x1 = h1 - y1
729
+
730
+	x0 = h0 - y0
731
+
732
+	y5 -= alpha96
733
+
734
+	y4 -= alpha96
735
+
736
+	x1 += y7
737
+
738
+	x0 += y6
739
+
740
+	x7 += y5
741
+
742
+	x6 += y4
743
+
744
+	y3 = h3 + alpha64
745
+
746
+	y2 = h2 + alpha64
747
+
748
+	x0 += x1
749
+
750
+	x6 += x7
751
+
752
+	y3 -= alpha64
753
+	r3low = r3low_stack
754
+
755
+	y2 -= alpha64
756
+	r0low = r0low_stack
757
+
758
+	x5 = h5 - y5
759
+	r3lowx0 = r3low * x0
760
+	r3high = r3high_stack
761
+
762
+	x4 = h4 - y4
763
+	r0lowx6 = r0low * x6
764
+	r0high = r0high_stack
765
+
766
+	x3 = h3 - y3
767
+	r3highx0 = r3high * x0
768
+	sr1low = sr1low_stack
769
+
770
+	x2 = h2 - y2
771
+	r0highx6 = r0high * x6
772
+	sr1high = sr1high_stack
773
+
774
+	x5 += y3
775
+	r0lowx0 = r0low * x0
776
+	r1low = r1low_stack
777
+
778
+	h6 = r3lowx0 + r0lowx6
779
+	sr1lowx6 = sr1low * x6
780
+	r1high = r1high_stack
781
+
782
+	x4 += y2
783
+	r0highx0 = r0high * x0
784
+	sr2low = sr2low_stack
785
+
786
+	h7 = r3highx0 + r0highx6
787
+	sr1highx6 = sr1high * x6
788
+	sr2high = sr2high_stack
789
+
790
+	x3 += y1
791
+	r1lowx0 = r1low * x0
792
+	r2low = r2low_stack
793
+
794
+	h0 = r0lowx0 + sr1lowx6
795
+	sr2lowx6 = sr2low * x6
796
+	r2high = r2high_stack
797
+
798
+	x2 += y0
799
+	r1highx0 = r1high * x0
800
+	sr3low = sr3low_stack
801
+
802
+	h1 = r0highx0 + sr1highx6
803
+	sr2highx6 = sr2high * x6
804
+	sr3high = sr3high_stack
805
+
806
+	x4 += x5
807
+	r2lowx0 = r2low * x0
808
+
809
+	h2 = r1lowx0 + sr2lowx6
810
+	sr3lowx6 = sr3low * x6
811
+
812
+	x2 += x3
813
+	r2highx0 = r2high * x0
814
+
815
+	h3 = r1highx0 + sr2highx6
816
+	sr3highx6 = sr3high * x6
817
+
818
+	r1highx4 = r1high * x4
819
+
820
+	h4 = r2lowx0 + sr3lowx6
821
+	r1lowx4 = r1low * x4
822
+
823
+	r0highx4 = r0high * x4
824
+
825
+	h5 = r2highx0 + sr3highx6
826
+	r0lowx4 = r0low * x4
827
+
828
+	h7 += r1highx4
829
+	sr3highx4 = sr3high * x4
830
+
831
+	h6 += r1lowx4
832
+	sr3lowx4 = sr3low * x4
833
+
834
+	h5 += r0highx4
835
+	sr2highx4 = sr2high * x4
836
+
837
+	h4 += r0lowx4
838
+	sr2lowx4 = sr2low * x4
839
+
840
+	h3 += sr3highx4
841
+	r0lowx2 = r0low * x2
842
+
843
+	h2 += sr3lowx4
844
+	r0highx2 = r0high * x2
845
+
846
+	h1 += sr2highx4
847
+	r1lowx2 = r1low * x2
848
+
849
+	h0 += sr2lowx4
850
+	r1highx2 = r1high * x2
851
+
852
+	h2 += r0lowx2
853
+	r2lowx2 = r2low * x2
854
+
855
+	h3 += r0highx2
856
+	r2highx2 = r2high * x2
857
+
858
+	h4 += r1lowx2
859
+	sr3lowx2 = sr3low * x2
860
+
861
+	h5 += r1highx2
862
+	sr3highx2 = sr3high * x2
863
+
864
+	h6 += r2lowx2
865
+
866
+	h7 += r2highx2
867
+
868
+	h0 += sr3lowx2
869
+
870
+	h1 += sr3highx2
871
+
872
+addatmost15bytes:
873
+
874
+	if l == 0 {
875
+		goto nomorebytes
876
+	}
877
+
878
+	lbelow2 = l - 2
879
+
880
+	lbelow3 = l - 3
881
+
882
+	lbelow2 >>= 31
883
+	lbelow4 = l - 4
884
+
885
+	m00 = uint32(m[p+0])
886
+	lbelow3 >>= 31
887
+	p += lbelow2
888
+
889
+	m01 = uint32(m[p+1])
890
+	lbelow4 >>= 31
891
+	p += lbelow3
892
+
893
+	m02 = uint32(m[p+2])
894
+	p += lbelow4
895
+	m0 = 2151
896
+
897
+	m03 = uint32(m[p+3])
898
+	m0 <<= 51
899
+	m1 = 2215
900
+
901
+	m0 += int64(m00)
902
+	m01 &^= uint32(lbelow2)
903
+
904
+	m02 &^= uint32(lbelow3)
905
+	m01 -= uint32(lbelow2)
906
+
907
+	m01 <<= 8
908
+	m03 &^= uint32(lbelow4)
909
+
910
+	m0 += int64(m01)
911
+	lbelow2 -= lbelow3
912
+
913
+	m02 += uint32(lbelow2)
914
+	lbelow3 -= lbelow4
915
+
916
+	m02 <<= 16
917
+	m03 += uint32(lbelow3)
918
+
919
+	m03 <<= 24
920
+	m0 += int64(m02)
921
+
922
+	m0 += int64(m03)
923
+	lbelow5 = l - 5
924
+
925
+	lbelow6 = l - 6
926
+	lbelow7 = l - 7
927
+
928
+	lbelow5 >>= 31
929
+	lbelow8 = l - 8
930
+
931
+	lbelow6 >>= 31
932
+	p += lbelow5
933
+
934
+	m10 = uint32(m[p+4])
935
+	lbelow7 >>= 31
936
+	p += lbelow6
937
+
938
+	m11 = uint32(m[p+5])
939
+	lbelow8 >>= 31
940
+	p += lbelow7
941
+
942
+	m12 = uint32(m[p+6])
943
+	m1 <<= 51
944
+	p += lbelow8
945
+
946
+	m13 = uint32(m[p+7])
947
+	m10 &^= uint32(lbelow5)
948
+	lbelow4 -= lbelow5
949
+
950
+	m10 += uint32(lbelow4)
951
+	lbelow5 -= lbelow6
952
+
953
+	m11 &^= uint32(lbelow6)
954
+	m11 += uint32(lbelow5)
955
+
956
+	m11 <<= 8
957
+	m1 += int64(m10)
958
+
959
+	m1 += int64(m11)
960
+	m12 &^= uint32(lbelow7)
961
+
962
+	lbelow6 -= lbelow7
963
+	m13 &^= uint32(lbelow8)
964
+
965
+	m12 += uint32(lbelow6)
966
+	lbelow7 -= lbelow8
967
+
968
+	m12 <<= 16
969
+	m13 += uint32(lbelow7)
970
+
971
+	m13 <<= 24
972
+	m1 += int64(m12)
973
+
974
+	m1 += int64(m13)
975
+	m2 = 2279
976
+
977
+	lbelow9 = l - 9
978
+	m3 = 2343
979
+
980
+	lbelow10 = l - 10
981
+	lbelow11 = l - 11
982
+
983
+	lbelow9 >>= 31
984
+	lbelow12 = l - 12
985
+
986
+	lbelow10 >>= 31
987
+	p += lbelow9
988
+
989
+	m20 = uint32(m[p+8])
990
+	lbelow11 >>= 31
991
+	p += lbelow10
992
+
993
+	m21 = uint32(m[p+9])
994
+	lbelow12 >>= 31
995
+	p += lbelow11
996
+
997
+	m22 = uint32(m[p+10])
998
+	m2 <<= 51
999
+	p += lbelow12
1000
+
1001
+	m23 = uint32(m[p+11])
1002
+	m20 &^= uint32(lbelow9)
1003
+	lbelow8 -= lbelow9
1004
+
1005
+	m20 += uint32(lbelow8)
1006
+	lbelow9 -= lbelow10
1007
+
1008
+	m21 &^= uint32(lbelow10)
1009
+	m21 += uint32(lbelow9)
1010
+
1011
+	m21 <<= 8
1012
+	m2 += int64(m20)
1013
+
1014
+	m2 += int64(m21)
1015
+	m22 &^= uint32(lbelow11)
1016
+
1017
+	lbelow10 -= lbelow11
1018
+	m23 &^= uint32(lbelow12)
1019
+
1020
+	m22 += uint32(lbelow10)
1021
+	lbelow11 -= lbelow12
1022
+
1023
+	m22 <<= 16
1024
+	m23 += uint32(lbelow11)
1025
+
1026
+	m23 <<= 24
1027
+	m2 += int64(m22)
1028
+
1029
+	m3 <<= 51
1030
+	lbelow13 = l - 13
1031
+
1032
+	lbelow13 >>= 31
1033
+	lbelow14 = l - 14
1034
+
1035
+	lbelow14 >>= 31
1036
+	p += lbelow13
1037
+	lbelow15 = l - 15
1038
+
1039
+	m30 = uint32(m[p+12])
1040
+	lbelow15 >>= 31
1041
+	p += lbelow14
1042
+
1043
+	m31 = uint32(m[p+13])
1044
+	p += lbelow15
1045
+	m2 += int64(m23)
1046
+
1047
+	m32 = uint32(m[p+14])
1048
+	m30 &^= uint32(lbelow13)
1049
+	lbelow12 -= lbelow13
1050
+
1051
+	m30 += uint32(lbelow12)
1052
+	lbelow13 -= lbelow14
1053
+
1054
+	m3 += int64(m30)
1055
+	m31 &^= uint32(lbelow14)
1056
+
1057
+	m31 += uint32(lbelow13)
1058
+	m32 &^= uint32(lbelow15)
1059
+
1060
+	m31 <<= 8
1061
+	lbelow14 -= lbelow15
1062
+
1063
+	m3 += int64(m31)
1064
+	m32 += uint32(lbelow14)
1065
+	d0 = m0
1066
+
1067
+	m32 <<= 16
1068
+	m33 = uint64(lbelow15 + 1)
1069
+	d1 = m1
1070
+
1071
+	m33 <<= 24
1072
+	m3 += int64(m32)
1073
+	d2 = m2
1074
+
1075
+	m3 += int64(m33)
1076
+	d3 = m3
1077
+
1078
+	z3 = math.Float64frombits(uint64(d3))
1079
+
1080
+	z2 = math.Float64frombits(uint64(d2))
1081
+
1082
+	z1 = math.Float64frombits(uint64(d1))
1083
+
1084
+	z0 = math.Float64frombits(uint64(d0))
1085
+
1086
+	z3 -= alpha96
1087
+
1088
+	z2 -= alpha64
1089
+
1090
+	z1 -= alpha32
1091
+
1092
+	z0 -= alpha0
1093
+
1094
+	h5 += z3
1095
+
1096
+	h3 += z2
1097
+
1098
+	h1 += z1
1099
+
1100
+	h0 += z0
1101
+
1102
+	y7 = h7 + alpha130
1103
+
1104
+	y6 = h6 + alpha130
1105
+
1106
+	y1 = h1 + alpha32
1107
+
1108
+	y0 = h0 + alpha32
1109
+
1110
+	y7 -= alpha130
1111
+
1112
+	y6 -= alpha130
1113
+
1114
+	y1 -= alpha32
1115
+
1116
+	y0 -= alpha32
1117
+
1118
+	y5 = h5 + alpha96
1119
+
1120
+	y4 = h4 + alpha96
1121
+
1122
+	x7 = h7 - y7
1123
+	y7 *= scale
1124
+
1125
+	x6 = h6 - y6
1126
+	y6 *= scale
1127
+
1128
+	x1 = h1 - y1
1129
+
1130
+	x0 = h0 - y0
1131
+
1132
+	y5 -= alpha96
1133
+
1134
+	y4 -= alpha96
1135
+
1136
+	x1 += y7
1137
+
1138
+	x0 += y6
1139
+
1140
+	x7 += y5
1141
+
1142
+	x6 += y4
1143
+
1144
+	y3 = h3 + alpha64
1145
+
1146
+	y2 = h2 + alpha64
1147
+
1148
+	x0 += x1
1149
+
1150
+	x6 += x7
1151
+
1152
+	y3 -= alpha64
1153
+	r3low = r3low_stack
1154
+
1155
+	y2 -= alpha64
1156
+	r0low = r0low_stack
1157
+
1158
+	x5 = h5 - y5
1159
+	r3lowx0 = r3low * x0
1160
+	r3high = r3high_stack
1161
+
1162
+	x4 = h4 - y4
1163
+	r0lowx6 = r0low * x6
1164
+	r0high = r0high_stack
1165
+
1166
+	x3 = h3 - y3
1167
+	r3highx0 = r3high * x0
1168
+	sr1low = sr1low_stack
1169
+
1170
+	x2 = h2 - y2
1171
+	r0highx6 = r0high * x6
1172
+	sr1high = sr1high_stack
1173
+
1174
+	x5 += y3
1175
+	r0lowx0 = r0low * x0
1176
+	r1low = r1low_stack
1177
+
1178
+	h6 = r3lowx0 + r0lowx6
1179
+	sr1lowx6 = sr1low * x6
1180
+	r1high = r1high_stack
1181
+
1182
+	x4 += y2
1183
+	r0highx0 = r0high * x0
1184
+	sr2low = sr2low_stack
1185
+
1186
+	h7 = r3highx0 + r0highx6
1187
+	sr1highx6 = sr1high * x6
1188
+	sr2high = sr2high_stack
1189
+
1190
+	x3 += y1
1191
+	r1lowx0 = r1low * x0
1192
+	r2low = r2low_stack
1193
+
1194
+	h0 = r0lowx0 + sr1lowx6
1195
+	sr2lowx6 = sr2low * x6
1196
+	r2high = r2high_stack
1197
+
1198
+	x2 += y0
1199
+	r1highx0 = r1high * x0
1200
+	sr3low = sr3low_stack
1201
+
1202
+	h1 = r0highx0 + sr1highx6
1203
+	sr2highx6 = sr2high * x6
1204
+	sr3high = sr3high_stack
1205
+
1206
+	x4 += x5
1207
+	r2lowx0 = r2low * x0
1208
+
1209
+	h2 = r1lowx0 + sr2lowx6
1210
+	sr3lowx6 = sr3low * x6
1211
+
1212
+	x2 += x3
1213
+	r2highx0 = r2high * x0
1214
+
1215
+	h3 = r1highx0 + sr2highx6
1216
+	sr3highx6 = sr3high * x6
1217
+
1218
+	r1highx4 = r1high * x4
1219
+
1220
+	h4 = r2lowx0 + sr3lowx6
1221
+	r1lowx4 = r1low * x4
1222
+
1223
+	r0highx4 = r0high * x4
1224
+
1225
+	h5 = r2highx0 + sr3highx6
1226
+	r0lowx4 = r0low * x4
1227
+
1228
+	h7 += r1highx4
1229
+	sr3highx4 = sr3high * x4
1230
+
1231
+	h6 += r1lowx4
1232
+	sr3lowx4 = sr3low * x4
1233
+
1234
+	h5 += r0highx4
1235
+	sr2highx4 = sr2high * x4
1236
+
1237
+	h4 += r0lowx4
1238
+	sr2lowx4 = sr2low * x4
1239
+
1240
+	h3 += sr3highx4
1241
+	r0lowx2 = r0low * x2
1242
+
1243
+	h2 += sr3lowx4
1244
+	r0highx2 = r0high * x2
1245
+
1246
+	h1 += sr2highx4
1247
+	r1lowx2 = r1low * x2
1248
+
1249
+	h0 += sr2lowx4
1250
+	r1highx2 = r1high * x2
1251
+
1252
+	h2 += r0lowx2
1253
+	r2lowx2 = r2low * x2
1254
+
1255
+	h3 += r0highx2
1256
+	r2highx2 = r2high * x2
1257
+
1258
+	h4 += r1lowx2
1259
+	sr3lowx2 = sr3low * x2
1260
+
1261
+	h5 += r1highx2
1262
+	sr3highx2 = sr3high * x2
1263
+
1264
+	h6 += r2lowx2
1265
+
1266
+	h7 += r2highx2
1267
+
1268
+	h0 += sr3lowx2
1269
+
1270
+	h1 += sr3highx2
1271
+
1272
+nomorebytes:
1273
+
1274
+	y7 = h7 + alpha130
1275
+
1276
+	y0 = h0 + alpha32
1277
+
1278
+	y1 = h1 + alpha32
1279
+
1280
+	y2 = h2 + alpha64
1281
+
1282
+	y7 -= alpha130
1283
+
1284
+	y3 = h3 + alpha64
1285
+
1286
+	y4 = h4 + alpha96
1287
+
1288
+	y5 = h5 + alpha96
1289
+
1290
+	x7 = h7 - y7
1291
+	y7 *= scale
1292
+
1293
+	y0 -= alpha32
1294
+
1295
+	y1 -= alpha32
1296
+
1297
+	y2 -= alpha64
1298
+
1299
+	h6 += x7
1300
+
1301
+	y3 -= alpha64
1302
+
1303
+	y4 -= alpha96
1304
+
1305
+	y5 -= alpha96
1306
+
1307
+	y6 = h6 + alpha130
1308
+
1309
+	x0 = h0 - y0
1310
+
1311
+	x1 = h1 - y1
1312
+
1313
+	x2 = h2 - y2
1314
+
1315
+	y6 -= alpha130
1316
+
1317
+	x0 += y7
1318
+
1319
+	x3 = h3 - y3
1320
+
1321
+	x4 = h4 - y4
1322
+
1323
+	x5 = h5 - y5
1324
+
1325
+	x6 = h6 - y6
1326
+
1327
+	y6 *= scale
1328
+
1329
+	x2 += y0
1330
+
1331
+	x3 += y1
1332
+
1333
+	x4 += y2
1334
+
1335
+	x0 += y6
1336
+
1337
+	x5 += y3
1338
+
1339
+	x6 += y4
1340
+
1341
+	x2 += x3
1342
+
1343
+	x0 += x1
1344
+
1345
+	x4 += x5
1346
+
1347
+	x6 += y5
1348
+
1349
+	x2 += offset1
1350
+	d1 = int64(math.Float64bits(x2))
1351
+
1352
+	x0 += offset0
1353
+	d0 = int64(math.Float64bits(x0))
1354
+
1355
+	x4 += offset2
1356
+	d2 = int64(math.Float64bits(x4))
1357
+
1358
+	x6 += offset3
1359
+	d3 = int64(math.Float64bits(x6))
1360
+
1361
+	f0 = uint64(d0)
1362
+
1363
+	f1 = uint64(d1)
1364
+	bits32 = math.MaxUint64
1365
+
1366
+	f2 = uint64(d2)
1367
+	bits32 >>= 32
1368
+
1369
+	f3 = uint64(d3)
1370
+	f = f0 >> 32
1371
+
1372
+	f0 &= bits32
1373
+	f &= 255
1374
+
1375
+	f1 += f
1376
+	g0 = f0 + 5
1377
+
1378
+	g = g0 >> 32
1379
+	g0 &= bits32
1380
+
1381
+	f = f1 >> 32
1382
+	f1 &= bits32
1383
+
1384
+	f &= 255
1385
+	g1 = f1 + g
1386
+
1387
+	g = g1 >> 32
1388
+	f2 += f
1389
+
1390
+	f = f2 >> 32
1391
+	g1 &= bits32
1392
+
1393
+	f2 &= bits32
1394
+	f &= 255
1395
+
1396
+	f3 += f
1397
+	g2 = f2 + g
1398
+
1399
+	g = g2 >> 32
1400
+	g2 &= bits32
1401
+
1402
+	f4 = f3 >> 32
1403
+	f3 &= bits32
1404
+
1405
+	f4 &= 255
1406
+	g3 = f3 + g
1407
+
1408
+	g = g3 >> 32
1409
+	g3 &= bits32
1410
+
1411
+	g4 = f4 + g
1412
+
1413
+	g4 = g4 - 4
1414
+	s00 = uint32(s[0])
1415
+
1416
+	f = uint64(int64(g4) >> 63)
1417
+	s01 = uint32(s[1])
1418
+
1419
+	f0 &= f
1420
+	g0 &^= f
1421
+	s02 = uint32(s[2])
1422
+
1423
+	f1 &= f
1424
+	f0 |= g0
1425
+	s03 = uint32(s[3])
1426
+
1427
+	g1 &^= f
1428
+	f2 &= f
1429
+	s10 = uint32(s[4])
1430
+
1431
+	f3 &= f
1432
+	g2 &^= f
1433
+	s11 = uint32(s[5])
1434
+
1435
+	g3 &^= f
1436
+	f1 |= g1
1437
+	s12 = uint32(s[6])
1438
+
1439
+	f2 |= g2
1440
+	f3 |= g3
1441
+	s13 = uint32(s[7])
1442
+
1443
+	s01 <<= 8
1444
+	f0 += uint64(s00)
1445
+	s20 = uint32(s[8])
1446
+
1447
+	s02 <<= 16
1448
+	f0 += uint64(s01)
1449
+	s21 = uint32(s[9])
1450
+
1451
+	s03 <<= 24
1452
+	f0 += uint64(s02)
1453
+	s22 = uint32(s[10])
1454
+
1455
+	s11 <<= 8
1456
+	f1 += uint64(s10)
1457
+	s23 = uint32(s[11])
1458
+
1459
+	s12 <<= 16
1460
+	f1 += uint64(s11)
1461
+	s30 = uint32(s[12])
1462
+
1463
+	s13 <<= 24
1464
+	f1 += uint64(s12)
1465
+	s31 = uint32(s[13])
1466
+
1467
+	f0 += uint64(s03)
1468
+	f1 += uint64(s13)
1469
+	s32 = uint32(s[14])
1470
+
1471
+	s21 <<= 8
1472
+	f2 += uint64(s20)
1473
+	s33 = uint32(s[15])
1474
+
1475
+	s22 <<= 16
1476
+	f2 += uint64(s21)
1477
+
1478
+	s23 <<= 24
1479
+	f2 += uint64(s22)
1480
+
1481
+	s31 <<= 8
1482
+	f3 += uint64(s30)
1483
+
1484
+	s32 <<= 16
1485
+	f3 += uint64(s31)
1486
+
1487
+	s33 <<= 24
1488
+	f3 += uint64(s32)
1489
+
1490
+	f2 += uint64(s23)
1491
+	f3 += uint64(s33)
1492
+
1493
+	out[0] = byte(f0)
1494
+	f0 >>= 8
1495
+	out[1] = byte(f0)
1496
+	f0 >>= 8
1497
+	out[2] = byte(f0)
1498
+	f0 >>= 8
1499
+	out[3] = byte(f0)
1500
+	f0 >>= 8
1501
+	f1 += f0
1502
+
1503
+	out[4] = byte(f1)
1504
+	f1 >>= 8
1505
+	out[5] = byte(f1)
1506
+	f1 >>= 8
1507
+	out[6] = byte(f1)
1508
+	f1 >>= 8
1509
+	out[7] = byte(f1)
1510
+	f1 >>= 8
1511
+	f2 += f1
1512
+
1513
+	out[8] = byte(f2)
1514
+	f2 >>= 8
1515
+	out[9] = byte(f2)
1516
+	f2 >>= 8
1517
+	out[10] = byte(f2)
1518
+	f2 >>= 8
1519
+	out[11] = byte(f2)
1520
+	f2 >>= 8
1521
+	f3 += f2
1522
+
1523
+	out[12] = byte(f3)
1524
+	f3 >>= 8
1525
+	out[13] = byte(f3)
1526
+	f3 >>= 8
1527
+	out[14] = byte(f3)
1528
+	f3 >>= 8
1529
+	out[15] = byte(f3)
1530
+}
0 1531
new file mode 100644
... ...
@@ -0,0 +1,144 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// Package salsa provides low-level access to functions in the Salsa family.
5
+package salsa // import "golang.org/x/crypto/salsa20/salsa"
6
+
7
+// Sigma is the Salsa20 constant for 256-bit keys.
8
+var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}
9
+
10
+// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte
11
+// key k, and 16-byte constant c, and puts the result into the 32-byte array
12
+// out.
13
+func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
14
+	x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
15
+	x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
16
+	x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
17
+	x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
18
+	x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
19
+	x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
20
+	x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
21
+	x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
22
+	x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
23
+	x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
24
+	x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
25
+	x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
26
+	x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
27
+	x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
28
+	x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
29
+	x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
30
+
31
+	for i := 0; i < 20; i += 2 {
32
+		u := x0 + x12
33
+		x4 ^= u<<7 | u>>(32-7)
34
+		u = x4 + x0
35
+		x8 ^= u<<9 | u>>(32-9)
36
+		u = x8 + x4
37
+		x12 ^= u<<13 | u>>(32-13)
38
+		u = x12 + x8
39
+		x0 ^= u<<18 | u>>(32-18)
40
+
41
+		u = x5 + x1
42
+		x9 ^= u<<7 | u>>(32-7)
43
+		u = x9 + x5
44
+		x13 ^= u<<9 | u>>(32-9)
45
+		u = x13 + x9
46
+		x1 ^= u<<13 | u>>(32-13)
47
+		u = x1 + x13
48
+		x5 ^= u<<18 | u>>(32-18)
49
+
50
+		u = x10 + x6
51
+		x14 ^= u<<7 | u>>(32-7)
52
+		u = x14 + x10
53
+		x2 ^= u<<9 | u>>(32-9)
54
+		u = x2 + x14
55
+		x6 ^= u<<13 | u>>(32-13)
56
+		u = x6 + x2
57
+		x10 ^= u<<18 | u>>(32-18)
58
+
59
+		u = x15 + x11
60
+		x3 ^= u<<7 | u>>(32-7)
61
+		u = x3 + x15
62
+		x7 ^= u<<9 | u>>(32-9)
63
+		u = x7 + x3
64
+		x11 ^= u<<13 | u>>(32-13)
65
+		u = x11 + x7
66
+		x15 ^= u<<18 | u>>(32-18)
67
+
68
+		u = x0 + x3
69
+		x1 ^= u<<7 | u>>(32-7)
70
+		u = x1 + x0
71
+		x2 ^= u<<9 | u>>(32-9)
72
+		u = x2 + x1
73
+		x3 ^= u<<13 | u>>(32-13)
74
+		u = x3 + x2
75
+		x0 ^= u<<18 | u>>(32-18)
76
+
77
+		u = x5 + x4
78
+		x6 ^= u<<7 | u>>(32-7)
79
+		u = x6 + x5
80
+		x7 ^= u<<9 | u>>(32-9)
81
+		u = x7 + x6
82
+		x4 ^= u<<13 | u>>(32-13)
83
+		u = x4 + x7
84
+		x5 ^= u<<18 | u>>(32-18)
85
+
86
+		u = x10 + x9
87
+		x11 ^= u<<7 | u>>(32-7)
88
+		u = x11 + x10
89
+		x8 ^= u<<9 | u>>(32-9)
90
+		u = x8 + x11
91
+		x9 ^= u<<13 | u>>(32-13)
92
+		u = x9 + x8
93
+		x10 ^= u<<18 | u>>(32-18)
94
+
95
+		u = x15 + x14
96
+		x12 ^= u<<7 | u>>(32-7)
97
+		u = x12 + x15
98
+		x13 ^= u<<9 | u>>(32-9)
99
+		u = x13 + x12
100
+		x14 ^= u<<13 | u>>(32-13)
101
+		u = x14 + x13
102
+		x15 ^= u<<18 | u>>(32-18)
103
+	}
104
+	out[0] = byte(x0)
105
+	out[1] = byte(x0 >> 8)
106
+	out[2] = byte(x0 >> 16)
107
+	out[3] = byte(x0 >> 24)
108
+
109
+	out[4] = byte(x5)
110
+	out[5] = byte(x5 >> 8)
111
+	out[6] = byte(x5 >> 16)
112
+	out[7] = byte(x5 >> 24)
113
+
114
+	out[8] = byte(x10)
115
+	out[9] = byte(x10 >> 8)
116
+	out[10] = byte(x10 >> 16)
117
+	out[11] = byte(x10 >> 24)
118
+
119
+	out[12] = byte(x15)
120
+	out[13] = byte(x15 >> 8)
121
+	out[14] = byte(x15 >> 16)
122
+	out[15] = byte(x15 >> 24)
123
+
124
+	out[16] = byte(x6)
125
+	out[17] = byte(x6 >> 8)
126
+	out[18] = byte(x6 >> 16)
127
+	out[19] = byte(x6 >> 24)
128
+
129
+	out[20] = byte(x7)
130
+	out[21] = byte(x7 >> 8)
131
+	out[22] = byte(x7 >> 16)
132
+	out[23] = byte(x7 >> 24)
133
+
134
+	out[24] = byte(x8)
135
+	out[25] = byte(x8 >> 8)
136
+	out[26] = byte(x8 >> 16)
137
+	out[27] = byte(x8 >> 24)
138
+
139
+	out[28] = byte(x9)
140
+	out[29] = byte(x9 >> 8)
141
+	out[30] = byte(x9 >> 16)
142
+	out[31] = byte(x9 >> 24)
143
+}
0 144
new file mode 100644
... ...
@@ -0,0 +1,902 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build amd64,!appengine,!gccgo
5
+
6
+// This code was translated into a form compatible with 6a from the public
7
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
8
+
9
+// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
10
+TEXT ·salsa2020XORKeyStream(SB),0,$512-40
11
+	MOVQ out+0(FP),DI
12
+	MOVQ in+8(FP),SI
13
+	MOVQ n+16(FP),DX
14
+	MOVQ nonce+24(FP),CX
15
+	MOVQ key+32(FP),R8
16
+
17
+	MOVQ SP,R11
18
+	MOVQ $31,R9
19
+	NOTQ R9
20
+	ANDQ R9,SP
21
+	ADDQ $32,SP
22
+
23
+	MOVQ R11,352(SP)
24
+	MOVQ R12,360(SP)
25
+	MOVQ R13,368(SP)
26
+	MOVQ R14,376(SP)
27
+	MOVQ R15,384(SP)
28
+	MOVQ BX,392(SP)
29
+	MOVQ BP,400(SP)
30
+	MOVQ DX,R9
31
+	MOVQ CX,DX
32
+	MOVQ R8,R10
33
+	CMPQ R9,$0
34
+	JBE DONE
35
+	START:
36
+	MOVL 20(R10),CX
37
+	MOVL 0(R10),R8
38
+	MOVL 0(DX),AX
39
+	MOVL 16(R10),R11
40
+	MOVL CX,0(SP)
41
+	MOVL R8, 4 (SP)
42
+	MOVL AX, 8 (SP)
43
+	MOVL R11, 12 (SP)
44
+	MOVL 8(DX),CX
45
+	MOVL 24(R10),R8
46
+	MOVL 4(R10),AX
47
+	MOVL 4(DX),R11
48
+	MOVL CX,16(SP)
49
+	MOVL R8, 20 (SP)
50
+	MOVL AX, 24 (SP)
51
+	MOVL R11, 28 (SP)
52
+	MOVL 12(DX),CX
53
+	MOVL 12(R10),DX
54
+	MOVL 28(R10),R8
55
+	MOVL 8(R10),AX
56
+	MOVL DX,32(SP)
57
+	MOVL CX, 36 (SP)
58
+	MOVL R8, 40 (SP)
59
+	MOVL AX, 44 (SP)
60
+	MOVQ $1634760805,DX
61
+	MOVQ $857760878,CX
62
+	MOVQ $2036477234,R8
63
+	MOVQ $1797285236,AX
64
+	MOVL DX,48(SP)
65
+	MOVL CX, 52 (SP)
66
+	MOVL R8, 56 (SP)
67
+	MOVL AX, 60 (SP)
68
+	CMPQ R9,$256
69
+	JB BYTESBETWEEN1AND255
70
+	MOVOA 48(SP),X0
71
+	PSHUFL $0X55,X0,X1
72
+	PSHUFL $0XAA,X0,X2
73
+	PSHUFL $0XFF,X0,X3
74
+	PSHUFL $0X00,X0,X0
75
+	MOVOA X1,64(SP)
76
+	MOVOA X2,80(SP)
77
+	MOVOA X3,96(SP)
78
+	MOVOA X0,112(SP)
79
+	MOVOA 0(SP),X0
80
+	PSHUFL $0XAA,X0,X1
81
+	PSHUFL $0XFF,X0,X2
82
+	PSHUFL $0X00,X0,X3
83
+	PSHUFL $0X55,X0,X0
84
+	MOVOA X1,128(SP)
85
+	MOVOA X2,144(SP)
86
+	MOVOA X3,160(SP)
87
+	MOVOA X0,176(SP)
88
+	MOVOA 16(SP),X0
89
+	PSHUFL $0XFF,X0,X1
90
+	PSHUFL $0X55,X0,X2
91
+	PSHUFL $0XAA,X0,X0
92
+	MOVOA X1,192(SP)
93
+	MOVOA X2,208(SP)
94
+	MOVOA X0,224(SP)
95
+	MOVOA 32(SP),X0
96
+	PSHUFL $0X00,X0,X1
97
+	PSHUFL $0XAA,X0,X2
98
+	PSHUFL $0XFF,X0,X0
99
+	MOVOA X1,240(SP)
100
+	MOVOA X2,256(SP)
101
+	MOVOA X0,272(SP)
102
+	BYTESATLEAST256:
103
+	MOVL 16(SP),DX
104
+	MOVL  36 (SP),CX
105
+	MOVL DX,288(SP)
106
+	MOVL CX,304(SP)
107
+	ADDQ $1,DX
108
+	SHLQ $32,CX
109
+	ADDQ CX,DX
110
+	MOVQ DX,CX
111
+	SHRQ $32,CX
112
+	MOVL DX, 292 (SP)
113
+	MOVL CX, 308 (SP)
114
+	ADDQ $1,DX
115
+	SHLQ $32,CX
116
+	ADDQ CX,DX
117
+	MOVQ DX,CX
118
+	SHRQ $32,CX
119
+	MOVL DX, 296 (SP)
120
+	MOVL CX, 312 (SP)
121
+	ADDQ $1,DX
122
+	SHLQ $32,CX
123
+	ADDQ CX,DX
124
+	MOVQ DX,CX
125
+	SHRQ $32,CX
126
+	MOVL DX, 300 (SP)
127
+	MOVL CX, 316 (SP)
128
+	ADDQ $1,DX
129
+	SHLQ $32,CX
130
+	ADDQ CX,DX
131
+	MOVQ DX,CX
132
+	SHRQ $32,CX
133
+	MOVL DX,16(SP)
134
+	MOVL CX, 36 (SP)
135
+	MOVQ R9,408(SP)
136
+	MOVQ $20,DX
137
+	MOVOA 64(SP),X0
138
+	MOVOA 80(SP),X1
139
+	MOVOA 96(SP),X2
140
+	MOVOA 256(SP),X3
141
+	MOVOA 272(SP),X4
142
+	MOVOA 128(SP),X5
143
+	MOVOA 144(SP),X6
144
+	MOVOA 176(SP),X7
145
+	MOVOA 192(SP),X8
146
+	MOVOA 208(SP),X9
147
+	MOVOA 224(SP),X10
148
+	MOVOA 304(SP),X11
149
+	MOVOA 112(SP),X12
150
+	MOVOA 160(SP),X13
151
+	MOVOA 240(SP),X14
152
+	MOVOA 288(SP),X15
153
+	MAINLOOP1:
154
+	MOVOA X1,320(SP)
155
+	MOVOA X2,336(SP)
156
+	MOVOA X13,X1
157
+	PADDL X12,X1
158
+	MOVOA X1,X2
159
+	PSLLL $7,X1
160
+	PXOR X1,X14
161
+	PSRLL $25,X2
162
+	PXOR X2,X14
163
+	MOVOA X7,X1
164
+	PADDL X0,X1
165
+	MOVOA X1,X2
166
+	PSLLL $7,X1
167
+	PXOR X1,X11
168
+	PSRLL $25,X2
169
+	PXOR X2,X11
170
+	MOVOA X12,X1
171
+	PADDL X14,X1
172
+	MOVOA X1,X2
173
+	PSLLL $9,X1
174
+	PXOR X1,X15
175
+	PSRLL $23,X2
176
+	PXOR X2,X15
177
+	MOVOA X0,X1
178
+	PADDL X11,X1
179
+	MOVOA X1,X2
180
+	PSLLL $9,X1
181
+	PXOR X1,X9
182
+	PSRLL $23,X2
183
+	PXOR X2,X9
184
+	MOVOA X14,X1
185
+	PADDL X15,X1
186
+	MOVOA X1,X2
187
+	PSLLL $13,X1
188
+	PXOR X1,X13
189
+	PSRLL $19,X2
190
+	PXOR X2,X13
191
+	MOVOA X11,X1
192
+	PADDL X9,X1
193
+	MOVOA X1,X2
194
+	PSLLL $13,X1
195
+	PXOR X1,X7
196
+	PSRLL $19,X2
197
+	PXOR X2,X7
198
+	MOVOA X15,X1
199
+	PADDL X13,X1
200
+	MOVOA X1,X2
201
+	PSLLL $18,X1
202
+	PXOR X1,X12
203
+	PSRLL $14,X2
204
+	PXOR X2,X12
205
+	MOVOA 320(SP),X1
206
+	MOVOA X12,320(SP)
207
+	MOVOA X9,X2
208
+	PADDL X7,X2
209
+	MOVOA X2,X12
210
+	PSLLL $18,X2
211
+	PXOR X2,X0
212
+	PSRLL $14,X12
213
+	PXOR X12,X0
214
+	MOVOA X5,X2
215
+	PADDL X1,X2
216
+	MOVOA X2,X12
217
+	PSLLL $7,X2
218
+	PXOR X2,X3
219
+	PSRLL $25,X12
220
+	PXOR X12,X3
221
+	MOVOA 336(SP),X2
222
+	MOVOA X0,336(SP)
223
+	MOVOA X6,X0
224
+	PADDL X2,X0
225
+	MOVOA X0,X12
226
+	PSLLL $7,X0
227
+	PXOR X0,X4
228
+	PSRLL $25,X12
229
+	PXOR X12,X4
230
+	MOVOA X1,X0
231
+	PADDL X3,X0
232
+	MOVOA X0,X12
233
+	PSLLL $9,X0
234
+	PXOR X0,X10
235
+	PSRLL $23,X12
236
+	PXOR X12,X10
237
+	MOVOA X2,X0
238
+	PADDL X4,X0
239
+	MOVOA X0,X12
240
+	PSLLL $9,X0
241
+	PXOR X0,X8
242
+	PSRLL $23,X12
243
+	PXOR X12,X8
244
+	MOVOA X3,X0
245
+	PADDL X10,X0
246
+	MOVOA X0,X12
247
+	PSLLL $13,X0
248
+	PXOR X0,X5
249
+	PSRLL $19,X12
250
+	PXOR X12,X5
251
+	MOVOA X4,X0
252
+	PADDL X8,X0
253
+	MOVOA X0,X12
254
+	PSLLL $13,X0
255
+	PXOR X0,X6
256
+	PSRLL $19,X12
257
+	PXOR X12,X6
258
+	MOVOA X10,X0
259
+	PADDL X5,X0
260
+	MOVOA X0,X12
261
+	PSLLL $18,X0
262
+	PXOR X0,X1
263
+	PSRLL $14,X12
264
+	PXOR X12,X1
265
+	MOVOA 320(SP),X0
266
+	MOVOA X1,320(SP)
267
+	MOVOA X4,X1
268
+	PADDL X0,X1
269
+	MOVOA X1,X12
270
+	PSLLL $7,X1
271
+	PXOR X1,X7
272
+	PSRLL $25,X12
273
+	PXOR X12,X7
274
+	MOVOA X8,X1
275
+	PADDL X6,X1
276
+	MOVOA X1,X12
277
+	PSLLL $18,X1
278
+	PXOR X1,X2
279
+	PSRLL $14,X12
280
+	PXOR X12,X2
281
+	MOVOA 336(SP),X12
282
+	MOVOA X2,336(SP)
283
+	MOVOA X14,X1
284
+	PADDL X12,X1
285
+	MOVOA X1,X2
286
+	PSLLL $7,X1
287
+	PXOR X1,X5
288
+	PSRLL $25,X2
289
+	PXOR X2,X5
290
+	MOVOA X0,X1
291
+	PADDL X7,X1
292
+	MOVOA X1,X2
293
+	PSLLL $9,X1
294
+	PXOR X1,X10
295
+	PSRLL $23,X2
296
+	PXOR X2,X10
297
+	MOVOA X12,X1
298
+	PADDL X5,X1
299
+	MOVOA X1,X2
300
+	PSLLL $9,X1
301
+	PXOR X1,X8
302
+	PSRLL $23,X2
303
+	PXOR X2,X8
304
+	MOVOA X7,X1
305
+	PADDL X10,X1
306
+	MOVOA X1,X2
307
+	PSLLL $13,X1
308
+	PXOR X1,X4
309
+	PSRLL $19,X2
310
+	PXOR X2,X4
311
+	MOVOA X5,X1
312
+	PADDL X8,X1
313
+	MOVOA X1,X2
314
+	PSLLL $13,X1
315
+	PXOR X1,X14
316
+	PSRLL $19,X2
317
+	PXOR X2,X14
318
+	MOVOA X10,X1
319
+	PADDL X4,X1
320
+	MOVOA X1,X2
321
+	PSLLL $18,X1
322
+	PXOR X1,X0
323
+	PSRLL $14,X2
324
+	PXOR X2,X0
325
+	MOVOA 320(SP),X1
326
+	MOVOA X0,320(SP)
327
+	MOVOA X8,X0
328
+	PADDL X14,X0
329
+	MOVOA X0,X2
330
+	PSLLL $18,X0
331
+	PXOR X0,X12
332
+	PSRLL $14,X2
333
+	PXOR X2,X12
334
+	MOVOA X11,X0
335
+	PADDL X1,X0
336
+	MOVOA X0,X2
337
+	PSLLL $7,X0
338
+	PXOR X0,X6
339
+	PSRLL $25,X2
340
+	PXOR X2,X6
341
+	MOVOA 336(SP),X2
342
+	MOVOA X12,336(SP)
343
+	MOVOA X3,X0
344
+	PADDL X2,X0
345
+	MOVOA X0,X12
346
+	PSLLL $7,X0
347
+	PXOR X0,X13
348
+	PSRLL $25,X12
349
+	PXOR X12,X13
350
+	MOVOA X1,X0
351
+	PADDL X6,X0
352
+	MOVOA X0,X12
353
+	PSLLL $9,X0
354
+	PXOR X0,X15
355
+	PSRLL $23,X12
356
+	PXOR X12,X15
357
+	MOVOA X2,X0
358
+	PADDL X13,X0
359
+	MOVOA X0,X12
360
+	PSLLL $9,X0
361
+	PXOR X0,X9
362
+	PSRLL $23,X12
363
+	PXOR X12,X9
364
+	MOVOA X6,X0
365
+	PADDL X15,X0
366
+	MOVOA X0,X12
367
+	PSLLL $13,X0
368
+	PXOR X0,X11
369
+	PSRLL $19,X12
370
+	PXOR X12,X11
371
+	MOVOA X13,X0
372
+	PADDL X9,X0
373
+	MOVOA X0,X12
374
+	PSLLL $13,X0
375
+	PXOR X0,X3
376
+	PSRLL $19,X12
377
+	PXOR X12,X3
378
+	MOVOA X15,X0
379
+	PADDL X11,X0
380
+	MOVOA X0,X12
381
+	PSLLL $18,X0
382
+	PXOR X0,X1
383
+	PSRLL $14,X12
384
+	PXOR X12,X1
385
+	MOVOA X9,X0
386
+	PADDL X3,X0
387
+	MOVOA X0,X12
388
+	PSLLL $18,X0
389
+	PXOR X0,X2
390
+	PSRLL $14,X12
391
+	PXOR X12,X2
392
+	MOVOA 320(SP),X12
393
+	MOVOA 336(SP),X0
394
+	SUBQ $2,DX
395
+	JA MAINLOOP1
396
+	PADDL 112(SP),X12
397
+	PADDL 176(SP),X7
398
+	PADDL 224(SP),X10
399
+	PADDL 272(SP),X4
400
+	MOVD X12,DX
401
+	MOVD X7,CX
402
+	MOVD X10,R8
403
+	MOVD X4,R9
404
+	PSHUFL $0X39,X12,X12
405
+	PSHUFL $0X39,X7,X7
406
+	PSHUFL $0X39,X10,X10
407
+	PSHUFL $0X39,X4,X4
408
+	XORL 0(SI),DX
409
+	XORL 4(SI),CX
410
+	XORL 8(SI),R8
411
+	XORL 12(SI),R9
412
+	MOVL DX,0(DI)
413
+	MOVL CX,4(DI)
414
+	MOVL R8,8(DI)
415
+	MOVL R9,12(DI)
416
+	MOVD X12,DX
417
+	MOVD X7,CX
418
+	MOVD X10,R8
419
+	MOVD X4,R9
420
+	PSHUFL $0X39,X12,X12
421
+	PSHUFL $0X39,X7,X7
422
+	PSHUFL $0X39,X10,X10
423
+	PSHUFL $0X39,X4,X4
424
+	XORL 64(SI),DX
425
+	XORL 68(SI),CX
426
+	XORL 72(SI),R8
427
+	XORL 76(SI),R9
428
+	MOVL DX,64(DI)
429
+	MOVL CX,68(DI)
430
+	MOVL R8,72(DI)
431
+	MOVL R9,76(DI)
432
+	MOVD X12,DX
433
+	MOVD X7,CX
434
+	MOVD X10,R8
435
+	MOVD X4,R9
436
+	PSHUFL $0X39,X12,X12
437
+	PSHUFL $0X39,X7,X7
438
+	PSHUFL $0X39,X10,X10
439
+	PSHUFL $0X39,X4,X4
440
+	XORL 128(SI),DX
441
+	XORL 132(SI),CX
442
+	XORL 136(SI),R8
443
+	XORL 140(SI),R9
444
+	MOVL DX,128(DI)
445
+	MOVL CX,132(DI)
446
+	MOVL R8,136(DI)
447
+	MOVL R9,140(DI)
448
+	MOVD X12,DX
449
+	MOVD X7,CX
450
+	MOVD X10,R8
451
+	MOVD X4,R9
452
+	XORL 192(SI),DX
453
+	XORL 196(SI),CX
454
+	XORL 200(SI),R8
455
+	XORL 204(SI),R9
456
+	MOVL DX,192(DI)
457
+	MOVL CX,196(DI)
458
+	MOVL R8,200(DI)
459
+	MOVL R9,204(DI)
460
+	PADDL 240(SP),X14
461
+	PADDL 64(SP),X0
462
+	PADDL 128(SP),X5
463
+	PADDL 192(SP),X8
464
+	MOVD X14,DX
465
+	MOVD X0,CX
466
+	MOVD X5,R8
467
+	MOVD X8,R9
468
+	PSHUFL $0X39,X14,X14
469
+	PSHUFL $0X39,X0,X0
470
+	PSHUFL $0X39,X5,X5
471
+	PSHUFL $0X39,X8,X8
472
+	XORL 16(SI),DX
473
+	XORL 20(SI),CX
474
+	XORL 24(SI),R8
475
+	XORL 28(SI),R9
476
+	MOVL DX,16(DI)
477
+	MOVL CX,20(DI)
478
+	MOVL R8,24(DI)
479
+	MOVL R9,28(DI)
480
+	MOVD X14,DX
481
+	MOVD X0,CX
482
+	MOVD X5,R8
483
+	MOVD X8,R9
484
+	PSHUFL $0X39,X14,X14
485
+	PSHUFL $0X39,X0,X0
486
+	PSHUFL $0X39,X5,X5
487
+	PSHUFL $0X39,X8,X8
488
+	XORL 80(SI),DX
489
+	XORL 84(SI),CX
490
+	XORL 88(SI),R8
491
+	XORL 92(SI),R9
492
+	MOVL DX,80(DI)
493
+	MOVL CX,84(DI)
494
+	MOVL R8,88(DI)
495
+	MOVL R9,92(DI)
496
+	MOVD X14,DX
497
+	MOVD X0,CX
498
+	MOVD X5,R8
499
+	MOVD X8,R9
500
+	PSHUFL $0X39,X14,X14
501
+	PSHUFL $0X39,X0,X0
502
+	PSHUFL $0X39,X5,X5
503
+	PSHUFL $0X39,X8,X8
504
+	XORL 144(SI),DX
505
+	XORL 148(SI),CX
506
+	XORL 152(SI),R8
507
+	XORL 156(SI),R9
508
+	MOVL DX,144(DI)
509
+	MOVL CX,148(DI)
510
+	MOVL R8,152(DI)
511
+	MOVL R9,156(DI)
512
+	MOVD X14,DX
513
+	MOVD X0,CX
514
+	MOVD X5,R8
515
+	MOVD X8,R9
516
+	XORL 208(SI),DX
517
+	XORL 212(SI),CX
518
+	XORL 216(SI),R8
519
+	XORL 220(SI),R9
520
+	MOVL DX,208(DI)
521
+	MOVL CX,212(DI)
522
+	MOVL R8,216(DI)
523
+	MOVL R9,220(DI)
524
+	PADDL 288(SP),X15
525
+	PADDL 304(SP),X11
526
+	PADDL 80(SP),X1
527
+	PADDL 144(SP),X6
528
+	MOVD X15,DX
529
+	MOVD X11,CX
530
+	MOVD X1,R8
531
+	MOVD X6,R9
532
+	PSHUFL $0X39,X15,X15
533
+	PSHUFL $0X39,X11,X11
534
+	PSHUFL $0X39,X1,X1
535
+	PSHUFL $0X39,X6,X6
536
+	XORL 32(SI),DX
537
+	XORL 36(SI),CX
538
+	XORL 40(SI),R8
539
+	XORL 44(SI),R9
540
+	MOVL DX,32(DI)
541
+	MOVL CX,36(DI)
542
+	MOVL R8,40(DI)
543
+	MOVL R9,44(DI)
544
+	MOVD X15,DX
545
+	MOVD X11,CX
546
+	MOVD X1,R8
547
+	MOVD X6,R9
548
+	PSHUFL $0X39,X15,X15
549
+	PSHUFL $0X39,X11,X11
550
+	PSHUFL $0X39,X1,X1
551
+	PSHUFL $0X39,X6,X6
552
+	XORL 96(SI),DX
553
+	XORL 100(SI),CX
554
+	XORL 104(SI),R8
555
+	XORL 108(SI),R9
556
+	MOVL DX,96(DI)
557
+	MOVL CX,100(DI)
558
+	MOVL R8,104(DI)
559
+	MOVL R9,108(DI)
560
+	MOVD X15,DX
561
+	MOVD X11,CX
562
+	MOVD X1,R8
563
+	MOVD X6,R9
564
+	PSHUFL $0X39,X15,X15
565
+	PSHUFL $0X39,X11,X11
566
+	PSHUFL $0X39,X1,X1
567
+	PSHUFL $0X39,X6,X6
568
+	XORL 160(SI),DX
569
+	XORL 164(SI),CX
570
+	XORL 168(SI),R8
571
+	XORL 172(SI),R9
572
+	MOVL DX,160(DI)
573
+	MOVL CX,164(DI)
574
+	MOVL R8,168(DI)
575
+	MOVL R9,172(DI)
576
+	MOVD X15,DX
577
+	MOVD X11,CX
578
+	MOVD X1,R8
579
+	MOVD X6,R9
580
+	XORL 224(SI),DX
581
+	XORL 228(SI),CX
582
+	XORL 232(SI),R8
583
+	XORL 236(SI),R9
584
+	MOVL DX,224(DI)
585
+	MOVL CX,228(DI)
586
+	MOVL R8,232(DI)
587
+	MOVL R9,236(DI)
588
+	PADDL 160(SP),X13
589
+	PADDL 208(SP),X9
590
+	PADDL 256(SP),X3
591
+	PADDL 96(SP),X2
592
+	MOVD X13,DX
593
+	MOVD X9,CX
594
+	MOVD X3,R8
595
+	MOVD X2,R9
596
+	PSHUFL $0X39,X13,X13
597
+	PSHUFL $0X39,X9,X9
598
+	PSHUFL $0X39,X3,X3
599
+	PSHUFL $0X39,X2,X2
600
+	XORL 48(SI),DX
601
+	XORL 52(SI),CX
602
+	XORL 56(SI),R8
603
+	XORL 60(SI),R9
604
+	MOVL DX,48(DI)
605
+	MOVL CX,52(DI)
606
+	MOVL R8,56(DI)
607
+	MOVL R9,60(DI)
608
+	MOVD X13,DX
609
+	MOVD X9,CX
610
+	MOVD X3,R8
611
+	MOVD X2,R9
612
+	PSHUFL $0X39,X13,X13
613
+	PSHUFL $0X39,X9,X9
614
+	PSHUFL $0X39,X3,X3
615
+	PSHUFL $0X39,X2,X2
616
+	XORL 112(SI),DX
617
+	XORL 116(SI),CX
618
+	XORL 120(SI),R8
619
+	XORL 124(SI),R9
620
+	MOVL DX,112(DI)
621
+	MOVL CX,116(DI)
622
+	MOVL R8,120(DI)
623
+	MOVL R9,124(DI)
624
+	MOVD X13,DX
625
+	MOVD X9,CX
626
+	MOVD X3,R8
627
+	MOVD X2,R9
628
+	PSHUFL $0X39,X13,X13
629
+	PSHUFL $0X39,X9,X9
630
+	PSHUFL $0X39,X3,X3
631
+	PSHUFL $0X39,X2,X2
632
+	XORL 176(SI),DX
633
+	XORL 180(SI),CX
634
+	XORL 184(SI),R8
635
+	XORL 188(SI),R9
636
+	MOVL DX,176(DI)
637
+	MOVL CX,180(DI)
638
+	MOVL R8,184(DI)
639
+	MOVL R9,188(DI)
640
+	MOVD X13,DX
641
+	MOVD X9,CX
642
+	MOVD X3,R8
643
+	MOVD X2,R9
644
+	XORL 240(SI),DX
645
+	XORL 244(SI),CX
646
+	XORL 248(SI),R8
647
+	XORL 252(SI),R9
648
+	MOVL DX,240(DI)
649
+	MOVL CX,244(DI)
650
+	MOVL R8,248(DI)
651
+	MOVL R9,252(DI)
652
+	MOVQ 408(SP),R9
653
+	SUBQ $256,R9
654
+	ADDQ $256,SI
655
+	ADDQ $256,DI
656
+	CMPQ R9,$256
657
+	JAE BYTESATLEAST256
658
+	CMPQ R9,$0
659
+	JBE DONE
660
+	BYTESBETWEEN1AND255:
661
+	CMPQ R9,$64
662
+	JAE NOCOPY
663
+	MOVQ DI,DX
664
+	LEAQ 416(SP),DI
665
+	MOVQ R9,CX
666
+	REP; MOVSB
667
+	LEAQ 416(SP),DI
668
+	LEAQ 416(SP),SI
669
+	NOCOPY:
670
+	MOVQ R9,408(SP)
671
+	MOVOA 48(SP),X0
672
+	MOVOA 0(SP),X1
673
+	MOVOA 16(SP),X2
674
+	MOVOA 32(SP),X3
675
+	MOVOA X1,X4
676
+	MOVQ $20,CX
677
+	MAINLOOP2:
678
+	PADDL X0,X4
679
+	MOVOA X0,X5
680
+	MOVOA X4,X6
681
+	PSLLL $7,X4
682
+	PSRLL $25,X6
683
+	PXOR X4,X3
684
+	PXOR X6,X3
685
+	PADDL X3,X5
686
+	MOVOA X3,X4
687
+	MOVOA X5,X6
688
+	PSLLL $9,X5
689
+	PSRLL $23,X6
690
+	PXOR X5,X2
691
+	PSHUFL $0X93,X3,X3
692
+	PXOR X6,X2
693
+	PADDL X2,X4
694
+	MOVOA X2,X5
695
+	MOVOA X4,X6
696
+	PSLLL $13,X4
697
+	PSRLL $19,X6
698
+	PXOR X4,X1
699
+	PSHUFL $0X4E,X2,X2
700
+	PXOR X6,X1
701
+	PADDL X1,X5
702
+	MOVOA X3,X4
703
+	MOVOA X5,X6
704
+	PSLLL $18,X5
705
+	PSRLL $14,X6
706
+	PXOR X5,X0
707
+	PSHUFL $0X39,X1,X1
708
+	PXOR X6,X0
709
+	PADDL X0,X4
710
+	MOVOA X0,X5
711
+	MOVOA X4,X6
712
+	PSLLL $7,X4
713
+	PSRLL $25,X6
714
+	PXOR X4,X1
715
+	PXOR X6,X1
716
+	PADDL X1,X5
717
+	MOVOA X1,X4
718
+	MOVOA X5,X6
719
+	PSLLL $9,X5
720
+	PSRLL $23,X6
721
+	PXOR X5,X2
722
+	PSHUFL $0X93,X1,X1
723
+	PXOR X6,X2
724
+	PADDL X2,X4
725
+	MOVOA X2,X5
726
+	MOVOA X4,X6
727
+	PSLLL $13,X4
728
+	PSRLL $19,X6
729
+	PXOR X4,X3
730
+	PSHUFL $0X4E,X2,X2
731
+	PXOR X6,X3
732
+	PADDL X3,X5
733
+	MOVOA X1,X4
734
+	MOVOA X5,X6
735
+	PSLLL $18,X5
736
+	PSRLL $14,X6
737
+	PXOR X5,X0
738
+	PSHUFL $0X39,X3,X3
739
+	PXOR X6,X0
740
+	PADDL X0,X4
741
+	MOVOA X0,X5
742
+	MOVOA X4,X6
743
+	PSLLL $7,X4
744
+	PSRLL $25,X6
745
+	PXOR X4,X3
746
+	PXOR X6,X3
747
+	PADDL X3,X5
748
+	MOVOA X3,X4
749
+	MOVOA X5,X6
750
+	PSLLL $9,X5
751
+	PSRLL $23,X6
752
+	PXOR X5,X2
753
+	PSHUFL $0X93,X3,X3
754
+	PXOR X6,X2
755
+	PADDL X2,X4
756
+	MOVOA X2,X5
757
+	MOVOA X4,X6
758
+	PSLLL $13,X4
759
+	PSRLL $19,X6
760
+	PXOR X4,X1
761
+	PSHUFL $0X4E,X2,X2
762
+	PXOR X6,X1
763
+	PADDL X1,X5
764
+	MOVOA X3,X4
765
+	MOVOA X5,X6
766
+	PSLLL $18,X5
767
+	PSRLL $14,X6
768
+	PXOR X5,X0
769
+	PSHUFL $0X39,X1,X1
770
+	PXOR X6,X0
771
+	PADDL X0,X4
772
+	MOVOA X0,X5
773
+	MOVOA X4,X6
774
+	PSLLL $7,X4
775
+	PSRLL $25,X6
776
+	PXOR X4,X1
777
+	PXOR X6,X1
778
+	PADDL X1,X5
779
+	MOVOA X1,X4
780
+	MOVOA X5,X6
781
+	PSLLL $9,X5
782
+	PSRLL $23,X6
783
+	PXOR X5,X2
784
+	PSHUFL $0X93,X1,X1
785
+	PXOR X6,X2
786
+	PADDL X2,X4
787
+	MOVOA X2,X5
788
+	MOVOA X4,X6
789
+	PSLLL $13,X4
790
+	PSRLL $19,X6
791
+	PXOR X4,X3
792
+	PSHUFL $0X4E,X2,X2
793
+	PXOR X6,X3
794
+	SUBQ $4,CX
795
+	PADDL X3,X5
796
+	MOVOA X1,X4
797
+	MOVOA X5,X6
798
+	PSLLL $18,X5
799
+	PXOR X7,X7
800
+	PSRLL $14,X6
801
+	PXOR X5,X0
802
+	PSHUFL $0X39,X3,X3
803
+	PXOR X6,X0
804
+	JA MAINLOOP2
805
+	PADDL 48(SP),X0
806
+	PADDL 0(SP),X1
807
+	PADDL 16(SP),X2
808
+	PADDL 32(SP),X3
809
+	MOVD X0,CX
810
+	MOVD X1,R8
811
+	MOVD X2,R9
812
+	MOVD X3,AX
813
+	PSHUFL $0X39,X0,X0
814
+	PSHUFL $0X39,X1,X1
815
+	PSHUFL $0X39,X2,X2
816
+	PSHUFL $0X39,X3,X3
817
+	XORL 0(SI),CX
818
+	XORL 48(SI),R8
819
+	XORL 32(SI),R9
820
+	XORL 16(SI),AX
821
+	MOVL CX,0(DI)
822
+	MOVL R8,48(DI)
823
+	MOVL R9,32(DI)
824
+	MOVL AX,16(DI)
825
+	MOVD X0,CX
826
+	MOVD X1,R8
827
+	MOVD X2,R9
828
+	MOVD X3,AX
829
+	PSHUFL $0X39,X0,X0
830
+	PSHUFL $0X39,X1,X1
831
+	PSHUFL $0X39,X2,X2
832
+	PSHUFL $0X39,X3,X3
833
+	XORL 20(SI),CX
834
+	XORL 4(SI),R8
835
+	XORL 52(SI),R9
836
+	XORL 36(SI),AX
837
+	MOVL CX,20(DI)
838
+	MOVL R8,4(DI)
839
+	MOVL R9,52(DI)
840
+	MOVL AX,36(DI)
841
+	MOVD X0,CX
842
+	MOVD X1,R8
843
+	MOVD X2,R9
844
+	MOVD X3,AX
845
+	PSHUFL $0X39,X0,X0
846
+	PSHUFL $0X39,X1,X1
847
+	PSHUFL $0X39,X2,X2
848
+	PSHUFL $0X39,X3,X3
849
+	XORL 40(SI),CX
850
+	XORL 24(SI),R8
851
+	XORL 8(SI),R9
852
+	XORL 56(SI),AX
853
+	MOVL CX,40(DI)
854
+	MOVL R8,24(DI)
855
+	MOVL R9,8(DI)
856
+	MOVL AX,56(DI)
857
+	MOVD X0,CX
858
+	MOVD X1,R8
859
+	MOVD X2,R9
860
+	MOVD X3,AX
861
+	XORL 60(SI),CX
862
+	XORL 44(SI),R8
863
+	XORL 28(SI),R9
864
+	XORL 12(SI),AX
865
+	MOVL CX,60(DI)
866
+	MOVL R8,44(DI)
867
+	MOVL R9,28(DI)
868
+	MOVL AX,12(DI)
869
+	MOVQ 408(SP),R9
870
+	MOVL 16(SP),CX
871
+	MOVL  36 (SP),R8
872
+	ADDQ $1,CX
873
+	SHLQ $32,R8
874
+	ADDQ R8,CX
875
+	MOVQ CX,R8
876
+	SHRQ $32,R8
877
+	MOVL CX,16(SP)
878
+	MOVL R8, 36 (SP)
879
+	CMPQ R9,$64
880
+	JA BYTESATLEAST65
881
+	JAE BYTESATLEAST64
882
+	MOVQ DI,SI
883
+	MOVQ DX,DI
884
+	MOVQ R9,CX
885
+	REP; MOVSB
886
+	BYTESATLEAST64:
887
+	DONE:
888
+	MOVQ 352(SP),R11
889
+	MOVQ 360(SP),R12
890
+	MOVQ 368(SP),R13
891
+	MOVQ 376(SP),R14
892
+	MOVQ 384(SP),R15
893
+	MOVQ 392(SP),BX
894
+	MOVQ 400(SP),BP
895
+	MOVQ R11,SP
896
+	RET
897
+	BYTESATLEAST65:
898
+	SUBQ $64,R9
899
+	ADDQ $64,DI
900
+	ADDQ $64,SI
901
+	JMP BYTESBETWEEN1AND255
0 902
new file mode 100644
... ...
@@ -0,0 +1,199 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package salsa
5
+
6
+// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts
7
+// the result into the 64-byte array out. The input and output may be the same array.
8
+func Core208(out *[64]byte, in *[64]byte) {
9
+	j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
10
+	j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
11
+	j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
12
+	j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
13
+	j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24
14
+	j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24
15
+	j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24
16
+	j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24
17
+	j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24
18
+	j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24
19
+	j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24
20
+	j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24
21
+	j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24
22
+	j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24
23
+	j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24
24
+	j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24
25
+
26
+	x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
27
+	x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
28
+
29
+	for i := 0; i < 8; i += 2 {
30
+		u := x0 + x12
31
+		x4 ^= u<<7 | u>>(32-7)
32
+		u = x4 + x0
33
+		x8 ^= u<<9 | u>>(32-9)
34
+		u = x8 + x4
35
+		x12 ^= u<<13 | u>>(32-13)
36
+		u = x12 + x8
37
+		x0 ^= u<<18 | u>>(32-18)
38
+
39
+		u = x5 + x1
40
+		x9 ^= u<<7 | u>>(32-7)
41
+		u = x9 + x5
42
+		x13 ^= u<<9 | u>>(32-9)
43
+		u = x13 + x9
44
+		x1 ^= u<<13 | u>>(32-13)
45
+		u = x1 + x13
46
+		x5 ^= u<<18 | u>>(32-18)
47
+
48
+		u = x10 + x6
49
+		x14 ^= u<<7 | u>>(32-7)
50
+		u = x14 + x10
51
+		x2 ^= u<<9 | u>>(32-9)
52
+		u = x2 + x14
53
+		x6 ^= u<<13 | u>>(32-13)
54
+		u = x6 + x2
55
+		x10 ^= u<<18 | u>>(32-18)
56
+
57
+		u = x15 + x11
58
+		x3 ^= u<<7 | u>>(32-7)
59
+		u = x3 + x15
60
+		x7 ^= u<<9 | u>>(32-9)
61
+		u = x7 + x3
62
+		x11 ^= u<<13 | u>>(32-13)
63
+		u = x11 + x7
64
+		x15 ^= u<<18 | u>>(32-18)
65
+
66
+		u = x0 + x3
67
+		x1 ^= u<<7 | u>>(32-7)
68
+		u = x1 + x0
69
+		x2 ^= u<<9 | u>>(32-9)
70
+		u = x2 + x1
71
+		x3 ^= u<<13 | u>>(32-13)
72
+		u = x3 + x2
73
+		x0 ^= u<<18 | u>>(32-18)
74
+
75
+		u = x5 + x4
76
+		x6 ^= u<<7 | u>>(32-7)
77
+		u = x6 + x5
78
+		x7 ^= u<<9 | u>>(32-9)
79
+		u = x7 + x6
80
+		x4 ^= u<<13 | u>>(32-13)
81
+		u = x4 + x7
82
+		x5 ^= u<<18 | u>>(32-18)
83
+
84
+		u = x10 + x9
85
+		x11 ^= u<<7 | u>>(32-7)
86
+		u = x11 + x10
87
+		x8 ^= u<<9 | u>>(32-9)
88
+		u = x8 + x11
89
+		x9 ^= u<<13 | u>>(32-13)
90
+		u = x9 + x8
91
+		x10 ^= u<<18 | u>>(32-18)
92
+
93
+		u = x15 + x14
94
+		x12 ^= u<<7 | u>>(32-7)
95
+		u = x12 + x15
96
+		x13 ^= u<<9 | u>>(32-9)
97
+		u = x13 + x12
98
+		x14 ^= u<<13 | u>>(32-13)
99
+		u = x14 + x13
100
+		x15 ^= u<<18 | u>>(32-18)
101
+	}
102
+	x0 += j0
103
+	x1 += j1
104
+	x2 += j2
105
+	x3 += j3
106
+	x4 += j4
107
+	x5 += j5
108
+	x6 += j6
109
+	x7 += j7
110
+	x8 += j8
111
+	x9 += j9
112
+	x10 += j10
113
+	x11 += j11
114
+	x12 += j12
115
+	x13 += j13
116
+	x14 += j14
117
+	x15 += j15
118
+
119
+	out[0] = byte(x0)
120
+	out[1] = byte(x0 >> 8)
121
+	out[2] = byte(x0 >> 16)
122
+	out[3] = byte(x0 >> 24)
123
+
124
+	out[4] = byte(x1)
125
+	out[5] = byte(x1 >> 8)
126
+	out[6] = byte(x1 >> 16)
127
+	out[7] = byte(x1 >> 24)
128
+
129
+	out[8] = byte(x2)
130
+	out[9] = byte(x2 >> 8)
131
+	out[10] = byte(x2 >> 16)
132
+	out[11] = byte(x2 >> 24)
133
+
134
+	out[12] = byte(x3)
135
+	out[13] = byte(x3 >> 8)
136
+	out[14] = byte(x3 >> 16)
137
+	out[15] = byte(x3 >> 24)
138
+
139
+	out[16] = byte(x4)
140
+	out[17] = byte(x4 >> 8)
141
+	out[18] = byte(x4 >> 16)
142
+	out[19] = byte(x4 >> 24)
143
+
144
+	out[20] = byte(x5)
145
+	out[21] = byte(x5 >> 8)
146
+	out[22] = byte(x5 >> 16)
147
+	out[23] = byte(x5 >> 24)
148
+
149
+	out[24] = byte(x6)
150
+	out[25] = byte(x6 >> 8)
151
+	out[26] = byte(x6 >> 16)
152
+	out[27] = byte(x6 >> 24)
153
+
154
+	out[28] = byte(x7)
155
+	out[29] = byte(x7 >> 8)
156
+	out[30] = byte(x7 >> 16)
157
+	out[31] = byte(x7 >> 24)
158
+
159
+	out[32] = byte(x8)
160
+	out[33] = byte(x8 >> 8)
161
+	out[34] = byte(x8 >> 16)
162
+	out[35] = byte(x8 >> 24)
163
+
164
+	out[36] = byte(x9)
165
+	out[37] = byte(x9 >> 8)
166
+	out[38] = byte(x9 >> 16)
167
+	out[39] = byte(x9 >> 24)
168
+
169
+	out[40] = byte(x10)
170
+	out[41] = byte(x10 >> 8)
171
+	out[42] = byte(x10 >> 16)
172
+	out[43] = byte(x10 >> 24)
173
+
174
+	out[44] = byte(x11)
175
+	out[45] = byte(x11 >> 8)
176
+	out[46] = byte(x11 >> 16)
177
+	out[47] = byte(x11 >> 24)
178
+
179
+	out[48] = byte(x12)
180
+	out[49] = byte(x12 >> 8)
181
+	out[50] = byte(x12 >> 16)
182
+	out[51] = byte(x12 >> 24)
183
+
184
+	out[52] = byte(x13)
185
+	out[53] = byte(x13 >> 8)
186
+	out[54] = byte(x13 >> 16)
187
+	out[55] = byte(x13 >> 24)
188
+
189
+	out[56] = byte(x14)
190
+	out[57] = byte(x14 >> 8)
191
+	out[58] = byte(x14 >> 16)
192
+	out[59] = byte(x14 >> 24)
193
+
194
+	out[60] = byte(x15)
195
+	out[61] = byte(x15 >> 8)
196
+	out[62] = byte(x15 >> 16)
197
+	out[63] = byte(x15 >> 24)
198
+}
0 199
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build amd64,!appengine,!gccgo
5
+
6
+package salsa
7
+
8
+// This function is implemented in salsa2020_amd64.s.
9
+
10
+//go:noescape
11
+
12
+func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
13
+
14
+// XORKeyStream crypts bytes from in to out using the given key and counters.
15
+// In and out may be the same slice but otherwise should not overlap. Counter
16
+// contains the raw salsa20 counter bytes (both nonce and block counter).
17
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
18
+	if len(in) == 0 {
19
+		return
20
+	}
21
+	salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0])
22
+}
0 23
new file mode 100644
... ...
@@ -0,0 +1,234 @@
0
+// Copyright 2012 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build !amd64 appengine gccgo
5
+
6
+package salsa
7
+
8
+const rounds = 20
9
+
10
+// core applies the Salsa20 core function to 16-byte input in, 32-byte key k,
11
+// and 16-byte constant c, and puts the result into 64-byte array out.
12
+func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
13
+	j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
14
+	j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
15
+	j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
16
+	j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
17
+	j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
18
+	j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
19
+	j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
20
+	j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
21
+	j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
22
+	j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
23
+	j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
24
+	j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
25
+	j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
26
+	j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
27
+	j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
28
+	j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
29
+
30
+	x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
31
+	x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
32
+
33
+	for i := 0; i < rounds; i += 2 {
34
+		u := x0 + x12
35
+		x4 ^= u<<7 | u>>(32-7)
36
+		u = x4 + x0
37
+		x8 ^= u<<9 | u>>(32-9)
38
+		u = x8 + x4
39
+		x12 ^= u<<13 | u>>(32-13)
40
+		u = x12 + x8
41
+		x0 ^= u<<18 | u>>(32-18)
42
+
43
+		u = x5 + x1
44
+		x9 ^= u<<7 | u>>(32-7)
45
+		u = x9 + x5
46
+		x13 ^= u<<9 | u>>(32-9)
47
+		u = x13 + x9
48
+		x1 ^= u<<13 | u>>(32-13)
49
+		u = x1 + x13
50
+		x5 ^= u<<18 | u>>(32-18)
51
+
52
+		u = x10 + x6
53
+		x14 ^= u<<7 | u>>(32-7)
54
+		u = x14 + x10
55
+		x2 ^= u<<9 | u>>(32-9)
56
+		u = x2 + x14
57
+		x6 ^= u<<13 | u>>(32-13)
58
+		u = x6 + x2
59
+		x10 ^= u<<18 | u>>(32-18)
60
+
61
+		u = x15 + x11
62
+		x3 ^= u<<7 | u>>(32-7)
63
+		u = x3 + x15
64
+		x7 ^= u<<9 | u>>(32-9)
65
+		u = x7 + x3
66
+		x11 ^= u<<13 | u>>(32-13)
67
+		u = x11 + x7
68
+		x15 ^= u<<18 | u>>(32-18)
69
+
70
+		u = x0 + x3
71
+		x1 ^= u<<7 | u>>(32-7)
72
+		u = x1 + x0
73
+		x2 ^= u<<9 | u>>(32-9)
74
+		u = x2 + x1
75
+		x3 ^= u<<13 | u>>(32-13)
76
+		u = x3 + x2
77
+		x0 ^= u<<18 | u>>(32-18)
78
+
79
+		u = x5 + x4
80
+		x6 ^= u<<7 | u>>(32-7)
81
+		u = x6 + x5
82
+		x7 ^= u<<9 | u>>(32-9)
83
+		u = x7 + x6
84
+		x4 ^= u<<13 | u>>(32-13)
85
+		u = x4 + x7
86
+		x5 ^= u<<18 | u>>(32-18)
87
+
88
+		u = x10 + x9
89
+		x11 ^= u<<7 | u>>(32-7)
90
+		u = x11 + x10
91
+		x8 ^= u<<9 | u>>(32-9)
92
+		u = x8 + x11
93
+		x9 ^= u<<13 | u>>(32-13)
94
+		u = x9 + x8
95
+		x10 ^= u<<18 | u>>(32-18)
96
+
97
+		u = x15 + x14
98
+		x12 ^= u<<7 | u>>(32-7)
99
+		u = x12 + x15
100
+		x13 ^= u<<9 | u>>(32-9)
101
+		u = x13 + x12
102
+		x14 ^= u<<13 | u>>(32-13)
103
+		u = x14 + x13
104
+		x15 ^= u<<18 | u>>(32-18)
105
+	}
106
+	x0 += j0
107
+	x1 += j1
108
+	x2 += j2
109
+	x3 += j3
110
+	x4 += j4
111
+	x5 += j5
112
+	x6 += j6
113
+	x7 += j7
114
+	x8 += j8
115
+	x9 += j9
116
+	x10 += j10
117
+	x11 += j11
118
+	x12 += j12
119
+	x13 += j13
120
+	x14 += j14
121
+	x15 += j15
122
+
123
+	out[0] = byte(x0)
124
+	out[1] = byte(x0 >> 8)
125
+	out[2] = byte(x0 >> 16)
126
+	out[3] = byte(x0 >> 24)
127
+
128
+	out[4] = byte(x1)
129
+	out[5] = byte(x1 >> 8)
130
+	out[6] = byte(x1 >> 16)
131
+	out[7] = byte(x1 >> 24)
132
+
133
+	out[8] = byte(x2)
134
+	out[9] = byte(x2 >> 8)
135
+	out[10] = byte(x2 >> 16)
136
+	out[11] = byte(x2 >> 24)
137
+
138
+	out[12] = byte(x3)
139
+	out[13] = byte(x3 >> 8)
140
+	out[14] = byte(x3 >> 16)
141
+	out[15] = byte(x3 >> 24)
142
+
143
+	out[16] = byte(x4)
144
+	out[17] = byte(x4 >> 8)
145
+	out[18] = byte(x4 >> 16)
146
+	out[19] = byte(x4 >> 24)
147
+
148
+	out[20] = byte(x5)
149
+	out[21] = byte(x5 >> 8)
150
+	out[22] = byte(x5 >> 16)
151
+	out[23] = byte(x5 >> 24)
152
+
153
+	out[24] = byte(x6)
154
+	out[25] = byte(x6 >> 8)
155
+	out[26] = byte(x6 >> 16)
156
+	out[27] = byte(x6 >> 24)
157
+
158
+	out[28] = byte(x7)
159
+	out[29] = byte(x7 >> 8)
160
+	out[30] = byte(x7 >> 16)
161
+	out[31] = byte(x7 >> 24)
162
+
163
+	out[32] = byte(x8)
164
+	out[33] = byte(x8 >> 8)
165
+	out[34] = byte(x8 >> 16)
166
+	out[35] = byte(x8 >> 24)
167
+
168
+	out[36] = byte(x9)
169
+	out[37] = byte(x9 >> 8)
170
+	out[38] = byte(x9 >> 16)
171
+	out[39] = byte(x9 >> 24)
172
+
173
+	out[40] = byte(x10)
174
+	out[41] = byte(x10 >> 8)
175
+	out[42] = byte(x10 >> 16)
176
+	out[43] = byte(x10 >> 24)
177
+
178
+	out[44] = byte(x11)
179
+	out[45] = byte(x11 >> 8)
180
+	out[46] = byte(x11 >> 16)
181
+	out[47] = byte(x11 >> 24)
182
+
183
+	out[48] = byte(x12)
184
+	out[49] = byte(x12 >> 8)
185
+	out[50] = byte(x12 >> 16)
186
+	out[51] = byte(x12 >> 24)
187
+
188
+	out[52] = byte(x13)
189
+	out[53] = byte(x13 >> 8)
190
+	out[54] = byte(x13 >> 16)
191
+	out[55] = byte(x13 >> 24)
192
+
193
+	out[56] = byte(x14)
194
+	out[57] = byte(x14 >> 8)
195
+	out[58] = byte(x14 >> 16)
196
+	out[59] = byte(x14 >> 24)
197
+
198
+	out[60] = byte(x15)
199
+	out[61] = byte(x15 >> 8)
200
+	out[62] = byte(x15 >> 16)
201
+	out[63] = byte(x15 >> 24)
202
+}
203
+
204
+// XORKeyStream crypts bytes from in to out using the given key and counters.
205
+// In and out may be the same slice but otherwise should not overlap. Counter
206
+// contains the raw salsa20 counter bytes (both nonce and block counter).
207
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
208
+	var block [64]byte
209
+	var counterCopy [16]byte
210
+	copy(counterCopy[:], counter[:])
211
+
212
+	for len(in) >= 64 {
213
+		core(&block, &counterCopy, key, &Sigma)
214
+		for i, x := range block {
215
+			out[i] = in[i] ^ x
216
+		}
217
+		u := uint32(1)
218
+		for i := 8; i < 16; i++ {
219
+			u += uint32(counterCopy[i])
220
+			counterCopy[i] = byte(u)
221
+			u >>= 8
222
+		}
223
+		in = in[64:]
224
+		out = out[64:]
225
+	}
226
+
227
+	if len(in) > 0 {
228
+		core(&block, &counterCopy, key, &Sigma)
229
+		for i, v := range in {
230
+			out[i] = v ^ block[i]
231
+		}
232
+	}
233
+}
0 234
new file mode 100644
... ...
@@ -0,0 +1,892 @@
0
+// Copyright 2011 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package terminal
5
+
6
+import (
7
+	"bytes"
8
+	"io"
9
+	"sync"
10
+	"unicode/utf8"
11
+)
12
+
13
+// EscapeCodes contains escape sequences that can be written to the terminal in
14
+// order to achieve different styles of text.
15
+type EscapeCodes struct {
16
+	// Foreground colors
17
+	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
18
+
19
+	// Reset all attributes
20
+	Reset []byte
21
+}
22
+
23
+var vt100EscapeCodes = EscapeCodes{
24
+	Black:   []byte{keyEscape, '[', '3', '0', 'm'},
25
+	Red:     []byte{keyEscape, '[', '3', '1', 'm'},
26
+	Green:   []byte{keyEscape, '[', '3', '2', 'm'},
27
+	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'},
28
+	Blue:    []byte{keyEscape, '[', '3', '4', 'm'},
29
+	Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
30
+	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'},
31
+	White:   []byte{keyEscape, '[', '3', '7', 'm'},
32
+
33
+	Reset: []byte{keyEscape, '[', '0', 'm'},
34
+}
35
+
36
+// Terminal contains the state for running a VT100 terminal that is capable of
37
+// reading lines of input.
38
+type Terminal struct {
39
+	// AutoCompleteCallback, if non-null, is called for each keypress with
40
+	// the full input line and the current position of the cursor (in
41
+	// bytes, as an index into |line|). If it returns ok=false, the key
42
+	// press is processed normally. Otherwise it returns a replacement line
43
+	// and the new cursor position.
44
+	AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
45
+
46
+	// Escape contains a pointer to the escape codes for this terminal.
47
+	// It's always a valid pointer, although the escape codes themselves
48
+	// may be empty if the terminal doesn't support them.
49
+	Escape *EscapeCodes
50
+
51
+	// lock protects the terminal and the state in this object from
52
+	// concurrent processing of a key press and a Write() call.
53
+	lock sync.Mutex
54
+
55
+	c      io.ReadWriter
56
+	prompt []rune
57
+
58
+	// line is the current line being entered.
59
+	line []rune
60
+	// pos is the logical position of the cursor in line
61
+	pos int
62
+	// echo is true if local echo is enabled
63
+	echo bool
64
+	// pasteActive is true iff there is a bracketed paste operation in
65
+	// progress.
66
+	pasteActive bool
67
+
68
+	// cursorX contains the current X value of the cursor where the left
69
+	// edge is 0. cursorY contains the row number where the first row of
70
+	// the current line is 0.
71
+	cursorX, cursorY int
72
+	// maxLine is the greatest value of cursorY so far.
73
+	maxLine int
74
+
75
+	termWidth, termHeight int
76
+
77
+	// outBuf contains the terminal data to be sent.
78
+	outBuf []byte
79
+	// remainder contains the remainder of any partial key sequences after
80
+	// a read. It aliases into inBuf.
81
+	remainder []byte
82
+	inBuf     [256]byte
83
+
84
+	// history contains previously entered commands so that they can be
85
+	// accessed with the up and down keys.
86
+	history stRingBuffer
87
+	// historyIndex stores the currently accessed history entry, where zero
88
+	// means the immediately previous entry.
89
+	historyIndex int
90
+	// When navigating up and down the history it's possible to return to
91
+	// the incomplete, initial line. That value is stored in
92
+	// historyPending.
93
+	historyPending string
94
+}
95
+
96
+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
97
+// a local terminal, that terminal must first have been put into raw mode.
98
+// prompt is a string that is written at the start of each input line (i.e.
99
+// "> ").
100
+func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
101
+	return &Terminal{
102
+		Escape:       &vt100EscapeCodes,
103
+		c:            c,
104
+		prompt:       []rune(prompt),
105
+		termWidth:    80,
106
+		termHeight:   24,
107
+		echo:         true,
108
+		historyIndex: -1,
109
+	}
110
+}
111
+
112
+const (
113
+	keyCtrlD     = 4
114
+	keyCtrlU     = 21
115
+	keyEnter     = '\r'
116
+	keyEscape    = 27
117
+	keyBackspace = 127
118
+	keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota
119
+	keyUp
120
+	keyDown
121
+	keyLeft
122
+	keyRight
123
+	keyAltLeft
124
+	keyAltRight
125
+	keyHome
126
+	keyEnd
127
+	keyDeleteWord
128
+	keyDeleteLine
129
+	keyClearScreen
130
+	keyPasteStart
131
+	keyPasteEnd
132
+)
133
+
134
+var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
135
+var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
136
+
137
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
138
+// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
139
+func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
140
+	if len(b) == 0 {
141
+		return utf8.RuneError, nil
142
+	}
143
+
144
+	if !pasteActive {
145
+		switch b[0] {
146
+		case 1: // ^A
147
+			return keyHome, b[1:]
148
+		case 5: // ^E
149
+			return keyEnd, b[1:]
150
+		case 8: // ^H
151
+			return keyBackspace, b[1:]
152
+		case 11: // ^K
153
+			return keyDeleteLine, b[1:]
154
+		case 12: // ^L
155
+			return keyClearScreen, b[1:]
156
+		case 23: // ^W
157
+			return keyDeleteWord, b[1:]
158
+		}
159
+	}
160
+
161
+	if b[0] != keyEscape {
162
+		if !utf8.FullRune(b) {
163
+			return utf8.RuneError, b
164
+		}
165
+		r, l := utf8.DecodeRune(b)
166
+		return r, b[l:]
167
+	}
168
+
169
+	if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
170
+		switch b[2] {
171
+		case 'A':
172
+			return keyUp, b[3:]
173
+		case 'B':
174
+			return keyDown, b[3:]
175
+		case 'C':
176
+			return keyRight, b[3:]
177
+		case 'D':
178
+			return keyLeft, b[3:]
179
+		case 'H':
180
+			return keyHome, b[3:]
181
+		case 'F':
182
+			return keyEnd, b[3:]
183
+		}
184
+	}
185
+
186
+	if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
187
+		switch b[5] {
188
+		case 'C':
189
+			return keyAltRight, b[6:]
190
+		case 'D':
191
+			return keyAltLeft, b[6:]
192
+		}
193
+	}
194
+
195
+	if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
196
+		return keyPasteStart, b[6:]
197
+	}
198
+
199
+	if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
200
+		return keyPasteEnd, b[6:]
201
+	}
202
+
203
+	// If we get here then we have a key that we don't recognise, or a
204
+	// partial sequence. It's not clear how one should find the end of a
205
+	// sequence without knowing them all, but it seems that [a-zA-Z~] only
206
+	// appears at the end of a sequence.
207
+	for i, c := range b[0:] {
208
+		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
209
+			return keyUnknown, b[i+1:]
210
+		}
211
+	}
212
+
213
+	return utf8.RuneError, b
214
+}
215
+
216
+// queue appends data to the end of t.outBuf
217
+func (t *Terminal) queue(data []rune) {
218
+	t.outBuf = append(t.outBuf, []byte(string(data))...)
219
+}
220
+
221
+var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'}
222
+var space = []rune{' '}
223
+
224
+func isPrintable(key rune) bool {
225
+	isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
226
+	return key >= 32 && !isInSurrogateArea
227
+}
228
+
229
+// moveCursorToPos appends data to t.outBuf which will move the cursor to the
230
+// given, logical position in the text.
231
+func (t *Terminal) moveCursorToPos(pos int) {
232
+	if !t.echo {
233
+		return
234
+	}
235
+
236
+	x := visualLength(t.prompt) + pos
237
+	y := x / t.termWidth
238
+	x = x % t.termWidth
239
+
240
+	up := 0
241
+	if y < t.cursorY {
242
+		up = t.cursorY - y
243
+	}
244
+
245
+	down := 0
246
+	if y > t.cursorY {
247
+		down = y - t.cursorY
248
+	}
249
+
250
+	left := 0
251
+	if x < t.cursorX {
252
+		left = t.cursorX - x
253
+	}
254
+
255
+	right := 0
256
+	if x > t.cursorX {
257
+		right = x - t.cursorX
258
+	}
259
+
260
+	t.cursorX = x
261
+	t.cursorY = y
262
+	t.move(up, down, left, right)
263
+}
264
+
265
+func (t *Terminal) move(up, down, left, right int) {
266
+	movement := make([]rune, 3*(up+down+left+right))
267
+	m := movement
268
+	for i := 0; i < up; i++ {
269
+		m[0] = keyEscape
270
+		m[1] = '['
271
+		m[2] = 'A'
272
+		m = m[3:]
273
+	}
274
+	for i := 0; i < down; i++ {
275
+		m[0] = keyEscape
276
+		m[1] = '['
277
+		m[2] = 'B'
278
+		m = m[3:]
279
+	}
280
+	for i := 0; i < left; i++ {
281
+		m[0] = keyEscape
282
+		m[1] = '['
283
+		m[2] = 'D'
284
+		m = m[3:]
285
+	}
286
+	for i := 0; i < right; i++ {
287
+		m[0] = keyEscape
288
+		m[1] = '['
289
+		m[2] = 'C'
290
+		m = m[3:]
291
+	}
292
+
293
+	t.queue(movement)
294
+}
295
+
296
+func (t *Terminal) clearLineToRight() {
297
+	op := []rune{keyEscape, '[', 'K'}
298
+	t.queue(op)
299
+}
300
+
301
+const maxLineLength = 4096
302
+
303
+func (t *Terminal) setLine(newLine []rune, newPos int) {
304
+	if t.echo {
305
+		t.moveCursorToPos(0)
306
+		t.writeLine(newLine)
307
+		for i := len(newLine); i < len(t.line); i++ {
308
+			t.writeLine(space)
309
+		}
310
+		t.moveCursorToPos(newPos)
311
+	}
312
+	t.line = newLine
313
+	t.pos = newPos
314
+}
315
+
316
+func (t *Terminal) advanceCursor(places int) {
317
+	t.cursorX += places
318
+	t.cursorY += t.cursorX / t.termWidth
319
+	if t.cursorY > t.maxLine {
320
+		t.maxLine = t.cursorY
321
+	}
322
+	t.cursorX = t.cursorX % t.termWidth
323
+
324
+	if places > 0 && t.cursorX == 0 {
325
+		// Normally terminals will advance the current position
326
+		// when writing a character. But that doesn't happen
327
+		// for the last character in a line. However, when
328
+		// writing a character (except a new line) that causes
329
+		// a line wrap, the position will be advanced two
330
+		// places.
331
+		//
332
+		// So, if we are stopping at the end of a line, we
333
+		// need to write a newline so that our cursor can be
334
+		// advanced to the next line.
335
+		t.outBuf = append(t.outBuf, '\n')
336
+	}
337
+}
338
+
339
+func (t *Terminal) eraseNPreviousChars(n int) {
340
+	if n == 0 {
341
+		return
342
+	}
343
+
344
+	if t.pos < n {
345
+		n = t.pos
346
+	}
347
+	t.pos -= n
348
+	t.moveCursorToPos(t.pos)
349
+
350
+	copy(t.line[t.pos:], t.line[n+t.pos:])
351
+	t.line = t.line[:len(t.line)-n]
352
+	if t.echo {
353
+		t.writeLine(t.line[t.pos:])
354
+		for i := 0; i < n; i++ {
355
+			t.queue(space)
356
+		}
357
+		t.advanceCursor(n)
358
+		t.moveCursorToPos(t.pos)
359
+	}
360
+}
361
+
362
+// countToLeftWord returns then number of characters from the cursor to the
363
+// start of the previous word.
364
+func (t *Terminal) countToLeftWord() int {
365
+	if t.pos == 0 {
366
+		return 0
367
+	}
368
+
369
+	pos := t.pos - 1
370
+	for pos > 0 {
371
+		if t.line[pos] != ' ' {
372
+			break
373
+		}
374
+		pos--
375
+	}
376
+	for pos > 0 {
377
+		if t.line[pos] == ' ' {
378
+			pos++
379
+			break
380
+		}
381
+		pos--
382
+	}
383
+
384
+	return t.pos - pos
385
+}
386
+
387
+// countToRightWord returns then number of characters from the cursor to the
388
+// start of the next word.
389
+func (t *Terminal) countToRightWord() int {
390
+	pos := t.pos
391
+	for pos < len(t.line) {
392
+		if t.line[pos] == ' ' {
393
+			break
394
+		}
395
+		pos++
396
+	}
397
+	for pos < len(t.line) {
398
+		if t.line[pos] != ' ' {
399
+			break
400
+		}
401
+		pos++
402
+	}
403
+	return pos - t.pos
404
+}
405
+
406
+// visualLength returns the number of visible glyphs in s.
407
+func visualLength(runes []rune) int {
408
+	inEscapeSeq := false
409
+	length := 0
410
+
411
+	for _, r := range runes {
412
+		switch {
413
+		case inEscapeSeq:
414
+			if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
415
+				inEscapeSeq = false
416
+			}
417
+		case r == '\x1b':
418
+			inEscapeSeq = true
419
+		default:
420
+			length++
421
+		}
422
+	}
423
+
424
+	return length
425
+}
426
+
427
+// handleKey processes the given key and, optionally, returns a line of text
428
+// that the user has entered.
429
+func (t *Terminal) handleKey(key rune) (line string, ok bool) {
430
+	if t.pasteActive && key != keyEnter {
431
+		t.addKeyToLine(key)
432
+		return
433
+	}
434
+
435
+	switch key {
436
+	case keyBackspace:
437
+		if t.pos == 0 {
438
+			return
439
+		}
440
+		t.eraseNPreviousChars(1)
441
+	case keyAltLeft:
442
+		// move left by a word.
443
+		t.pos -= t.countToLeftWord()
444
+		t.moveCursorToPos(t.pos)
445
+	case keyAltRight:
446
+		// move right by a word.
447
+		t.pos += t.countToRightWord()
448
+		t.moveCursorToPos(t.pos)
449
+	case keyLeft:
450
+		if t.pos == 0 {
451
+			return
452
+		}
453
+		t.pos--
454
+		t.moveCursorToPos(t.pos)
455
+	case keyRight:
456
+		if t.pos == len(t.line) {
457
+			return
458
+		}
459
+		t.pos++
460
+		t.moveCursorToPos(t.pos)
461
+	case keyHome:
462
+		if t.pos == 0 {
463
+			return
464
+		}
465
+		t.pos = 0
466
+		t.moveCursorToPos(t.pos)
467
+	case keyEnd:
468
+		if t.pos == len(t.line) {
469
+			return
470
+		}
471
+		t.pos = len(t.line)
472
+		t.moveCursorToPos(t.pos)
473
+	case keyUp:
474
+		entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
475
+		if !ok {
476
+			return "", false
477
+		}
478
+		if t.historyIndex == -1 {
479
+			t.historyPending = string(t.line)
480
+		}
481
+		t.historyIndex++
482
+		runes := []rune(entry)
483
+		t.setLine(runes, len(runes))
484
+	case keyDown:
485
+		switch t.historyIndex {
486
+		case -1:
487
+			return
488
+		case 0:
489
+			runes := []rune(t.historyPending)
490
+			t.setLine(runes, len(runes))
491
+			t.historyIndex--
492
+		default:
493
+			entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
494
+			if ok {
495
+				t.historyIndex--
496
+				runes := []rune(entry)
497
+				t.setLine(runes, len(runes))
498
+			}
499
+		}
500
+	case keyEnter:
501
+		t.moveCursorToPos(len(t.line))
502
+		t.queue([]rune("\r\n"))
503
+		line = string(t.line)
504
+		ok = true
505
+		t.line = t.line[:0]
506
+		t.pos = 0
507
+		t.cursorX = 0
508
+		t.cursorY = 0
509
+		t.maxLine = 0
510
+	case keyDeleteWord:
511
+		// Delete zero or more spaces and then one or more characters.
512
+		t.eraseNPreviousChars(t.countToLeftWord())
513
+	case keyDeleteLine:
514
+		// Delete everything from the current cursor position to the
515
+		// end of line.
516
+		for i := t.pos; i < len(t.line); i++ {
517
+			t.queue(space)
518
+			t.advanceCursor(1)
519
+		}
520
+		t.line = t.line[:t.pos]
521
+		t.moveCursorToPos(t.pos)
522
+	case keyCtrlD:
523
+		// Erase the character under the current position.
524
+		// The EOF case when the line is empty is handled in
525
+		// readLine().
526
+		if t.pos < len(t.line) {
527
+			t.pos++
528
+			t.eraseNPreviousChars(1)
529
+		}
530
+	case keyCtrlU:
531
+		t.eraseNPreviousChars(t.pos)
532
+	case keyClearScreen:
533
+		// Erases the screen and moves the cursor to the home position.
534
+		t.queue([]rune("\x1b[2J\x1b[H"))
535
+		t.queue(t.prompt)
536
+		t.cursorX, t.cursorY = 0, 0
537
+		t.advanceCursor(visualLength(t.prompt))
538
+		t.setLine(t.line, t.pos)
539
+	default:
540
+		if t.AutoCompleteCallback != nil {
541
+			prefix := string(t.line[:t.pos])
542
+			suffix := string(t.line[t.pos:])
543
+
544
+			t.lock.Unlock()
545
+			newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
546
+			t.lock.Lock()
547
+
548
+			if completeOk {
549
+				t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
550
+				return
551
+			}
552
+		}
553
+		if !isPrintable(key) {
554
+			return
555
+		}
556
+		if len(t.line) == maxLineLength {
557
+			return
558
+		}
559
+		t.addKeyToLine(key)
560
+	}
561
+	return
562
+}
563
+
564
+// addKeyToLine inserts the given key at the current position in the current
565
+// line.
566
+func (t *Terminal) addKeyToLine(key rune) {
567
+	if len(t.line) == cap(t.line) {
568
+		newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
569
+		copy(newLine, t.line)
570
+		t.line = newLine
571
+	}
572
+	t.line = t.line[:len(t.line)+1]
573
+	copy(t.line[t.pos+1:], t.line[t.pos:])
574
+	t.line[t.pos] = key
575
+	if t.echo {
576
+		t.writeLine(t.line[t.pos:])
577
+	}
578
+	t.pos++
579
+	t.moveCursorToPos(t.pos)
580
+}
581
+
582
+func (t *Terminal) writeLine(line []rune) {
583
+	for len(line) != 0 {
584
+		remainingOnLine := t.termWidth - t.cursorX
585
+		todo := len(line)
586
+		if todo > remainingOnLine {
587
+			todo = remainingOnLine
588
+		}
589
+		t.queue(line[:todo])
590
+		t.advanceCursor(visualLength(line[:todo]))
591
+		line = line[todo:]
592
+	}
593
+}
594
+
595
+func (t *Terminal) Write(buf []byte) (n int, err error) {
596
+	t.lock.Lock()
597
+	defer t.lock.Unlock()
598
+
599
+	if t.cursorX == 0 && t.cursorY == 0 {
600
+		// This is the easy case: there's nothing on the screen that we
601
+		// have to move out of the way.
602
+		return t.c.Write(buf)
603
+	}
604
+
605
+	// We have a prompt and possibly user input on the screen. We
606
+	// have to clear it first.
607
+	t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
608
+	t.cursorX = 0
609
+	t.clearLineToRight()
610
+
611
+	for t.cursorY > 0 {
612
+		t.move(1 /* up */, 0, 0, 0)
613
+		t.cursorY--
614
+		t.clearLineToRight()
615
+	}
616
+
617
+	if _, err = t.c.Write(t.outBuf); err != nil {
618
+		return
619
+	}
620
+	t.outBuf = t.outBuf[:0]
621
+
622
+	if n, err = t.c.Write(buf); err != nil {
623
+		return
624
+	}
625
+
626
+	t.writeLine(t.prompt)
627
+	if t.echo {
628
+		t.writeLine(t.line)
629
+	}
630
+
631
+	t.moveCursorToPos(t.pos)
632
+
633
+	if _, err = t.c.Write(t.outBuf); err != nil {
634
+		return
635
+	}
636
+	t.outBuf = t.outBuf[:0]
637
+	return
638
+}
639
+
640
+// ReadPassword temporarily changes the prompt and reads a password, without
641
+// echo, from the terminal.
642
+func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
643
+	t.lock.Lock()
644
+	defer t.lock.Unlock()
645
+
646
+	oldPrompt := t.prompt
647
+	t.prompt = []rune(prompt)
648
+	t.echo = false
649
+
650
+	line, err = t.readLine()
651
+
652
+	t.prompt = oldPrompt
653
+	t.echo = true
654
+
655
+	return
656
+}
657
+
658
+// ReadLine returns a line of input from the terminal.
659
+func (t *Terminal) ReadLine() (line string, err error) {
660
+	t.lock.Lock()
661
+	defer t.lock.Unlock()
662
+
663
+	return t.readLine()
664
+}
665
+
666
+func (t *Terminal) readLine() (line string, err error) {
667
+	// t.lock must be held at this point
668
+
669
+	if t.cursorX == 0 && t.cursorY == 0 {
670
+		t.writeLine(t.prompt)
671
+		t.c.Write(t.outBuf)
672
+		t.outBuf = t.outBuf[:0]
673
+	}
674
+
675
+	lineIsPasted := t.pasteActive
676
+
677
+	for {
678
+		rest := t.remainder
679
+		lineOk := false
680
+		for !lineOk {
681
+			var key rune
682
+			key, rest = bytesToKey(rest, t.pasteActive)
683
+			if key == utf8.RuneError {
684
+				break
685
+			}
686
+			if !t.pasteActive {
687
+				if key == keyCtrlD {
688
+					if len(t.line) == 0 {
689
+						return "", io.EOF
690
+					}
691
+				}
692
+				if key == keyPasteStart {
693
+					t.pasteActive = true
694
+					if len(t.line) == 0 {
695
+						lineIsPasted = true
696
+					}
697
+					continue
698
+				}
699
+			} else if key == keyPasteEnd {
700
+				t.pasteActive = false
701
+				continue
702
+			}
703
+			if !t.pasteActive {
704
+				lineIsPasted = false
705
+			}
706
+			line, lineOk = t.handleKey(key)
707
+		}
708
+		if len(rest) > 0 {
709
+			n := copy(t.inBuf[:], rest)
710
+			t.remainder = t.inBuf[:n]
711
+		} else {
712
+			t.remainder = nil
713
+		}
714
+		t.c.Write(t.outBuf)
715
+		t.outBuf = t.outBuf[:0]
716
+		if lineOk {
717
+			if t.echo {
718
+				t.historyIndex = -1
719
+				t.history.Add(line)
720
+			}
721
+			if lineIsPasted {
722
+				err = ErrPasteIndicator
723
+			}
724
+			return
725
+		}
726
+
727
+		// t.remainder is a slice at the beginning of t.inBuf
728
+		// containing a partial key sequence
729
+		readBuf := t.inBuf[len(t.remainder):]
730
+		var n int
731
+
732
+		t.lock.Unlock()
733
+		n, err = t.c.Read(readBuf)
734
+		t.lock.Lock()
735
+
736
+		if err != nil {
737
+			return
738
+		}
739
+
740
+		t.remainder = t.inBuf[:n+len(t.remainder)]
741
+	}
742
+
743
+	panic("unreachable") // for Go 1.0.
744
+}
745
+
746
+// SetPrompt sets the prompt to be used when reading subsequent lines.
747
+func (t *Terminal) SetPrompt(prompt string) {
748
+	t.lock.Lock()
749
+	defer t.lock.Unlock()
750
+
751
+	t.prompt = []rune(prompt)
752
+}
753
+
754
+func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
755
+	// Move cursor to column zero at the start of the line.
756
+	t.move(t.cursorY, 0, t.cursorX, 0)
757
+	t.cursorX, t.cursorY = 0, 0
758
+	t.clearLineToRight()
759
+	for t.cursorY < numPrevLines {
760
+		// Move down a line
761
+		t.move(0, 1, 0, 0)
762
+		t.cursorY++
763
+		t.clearLineToRight()
764
+	}
765
+	// Move back to beginning.
766
+	t.move(t.cursorY, 0, 0, 0)
767
+	t.cursorX, t.cursorY = 0, 0
768
+
769
+	t.queue(t.prompt)
770
+	t.advanceCursor(visualLength(t.prompt))
771
+	t.writeLine(t.line)
772
+	t.moveCursorToPos(t.pos)
773
+}
774
+
775
+func (t *Terminal) SetSize(width, height int) error {
776
+	t.lock.Lock()
777
+	defer t.lock.Unlock()
778
+
779
+	if width == 0 {
780
+		width = 1
781
+	}
782
+
783
+	oldWidth := t.termWidth
784
+	t.termWidth, t.termHeight = width, height
785
+
786
+	switch {
787
+	case width == oldWidth:
788
+		// If the width didn't change then nothing else needs to be
789
+		// done.
790
+		return nil
791
+	case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
792
+		// If there is nothing on current line and no prompt printed,
793
+		// just do nothing
794
+		return nil
795
+	case width < oldWidth:
796
+		// Some terminals (e.g. xterm) will truncate lines that were
797
+		// too long when shinking. Others, (e.g. gnome-terminal) will
798
+		// attempt to wrap them. For the former, repainting t.maxLine
799
+		// works great, but that behaviour goes badly wrong in the case
800
+		// of the latter because they have doubled every full line.
801
+
802
+		// We assume that we are working on a terminal that wraps lines
803
+		// and adjust the cursor position based on every previous line
804
+		// wrapping and turning into two. This causes the prompt on
805
+		// xterms to move upwards, which isn't great, but it avoids a
806
+		// huge mess with gnome-terminal.
807
+		if t.cursorX >= t.termWidth {
808
+			t.cursorX = t.termWidth - 1
809
+		}
810
+		t.cursorY *= 2
811
+		t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
812
+	case width > oldWidth:
813
+		// If the terminal expands then our position calculations will
814
+		// be wrong in the future because we think the cursor is
815
+		// |t.pos| chars into the string, but there will be a gap at
816
+		// the end of any wrapped line.
817
+		//
818
+		// But the position will actually be correct until we move, so
819
+		// we can move back to the beginning and repaint everything.
820
+		t.clearAndRepaintLinePlusNPrevious(t.maxLine)
821
+	}
822
+
823
+	_, err := t.c.Write(t.outBuf)
824
+	t.outBuf = t.outBuf[:0]
825
+	return err
826
+}
827
+
828
+type pasteIndicatorError struct{}
829
+
830
+func (pasteIndicatorError) Error() string {
831
+	return "terminal: ErrPasteIndicator not correctly handled"
832
+}
833
+
834
+// ErrPasteIndicator may be returned from ReadLine as the error, in addition
835
+// to valid line data. It indicates that bracketed paste mode is enabled and
836
+// that the returned line consists only of pasted data. Programs may wish to
837
+// interpret pasted data more literally than typed data.
838
+var ErrPasteIndicator = pasteIndicatorError{}
839
+
840
+// SetBracketedPasteMode requests that the terminal bracket paste operations
841
+// with markers. Not all terminals support this but, if it is supported, then
842
+// enabling this mode will stop any autocomplete callback from running due to
843
+// pastes. Additionally, any lines that are completely pasted will be returned
844
+// from ReadLine with the error set to ErrPasteIndicator.
845
+func (t *Terminal) SetBracketedPasteMode(on bool) {
846
+	if on {
847
+		io.WriteString(t.c, "\x1b[?2004h")
848
+	} else {
849
+		io.WriteString(t.c, "\x1b[?2004l")
850
+	}
851
+}
852
+
853
+// stRingBuffer is a ring buffer of strings.
854
+type stRingBuffer struct {
855
+	// entries contains max elements.
856
+	entries []string
857
+	max     int
858
+	// head contains the index of the element most recently added to the ring.
859
+	head int
860
+	// size contains the number of elements in the ring.
861
+	size int
862
+}
863
+
864
+func (s *stRingBuffer) Add(a string) {
865
+	if s.entries == nil {
866
+		const defaultNumEntries = 100
867
+		s.entries = make([]string, defaultNumEntries)
868
+		s.max = defaultNumEntries
869
+	}
870
+
871
+	s.head = (s.head + 1) % s.max
872
+	s.entries[s.head] = a
873
+	if s.size < s.max {
874
+		s.size++
875
+	}
876
+}
877
+
878
+// NthPreviousEntry returns the value passed to the nth previous call to Add.
879
+// If n is zero then the immediately prior value is returned, if one, then the
880
+// next most recent, and so on. If such an element doesn't exist then ok is
881
+// false.
882
+func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
883
+	if n >= s.size {
884
+		return "", false
885
+	}
886
+	index := s.head - n
887
+	if index < 0 {
888
+		index += s.max
889
+	}
890
+	return s.entries[index], true
891
+}
0 892
new file mode 100644
... ...
@@ -0,0 +1,128 @@
0
+// Copyright 2011 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
5
+
6
+// Package terminal provides support functions for dealing with terminals, as
7
+// commonly found on UNIX systems.
8
+//
9
+// Putting a terminal into raw mode is the most common requirement:
10
+//
11
+// 	oldState, err := terminal.MakeRaw(0)
12
+// 	if err != nil {
13
+// 	        panic(err)
14
+// 	}
15
+// 	defer terminal.Restore(0, oldState)
16
+package terminal // import "golang.org/x/crypto/ssh/terminal"
17
+
18
+import (
19
+	"io"
20
+	"syscall"
21
+	"unsafe"
22
+)
23
+
24
+// State contains the state of a terminal.
25
+type State struct {
26
+	termios syscall.Termios
27
+}
28
+
29
+// IsTerminal returns true if the given file descriptor is a terminal.
30
+func IsTerminal(fd int) bool {
31
+	var termios syscall.Termios
32
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
33
+	return err == 0
34
+}
35
+
36
+// MakeRaw put the terminal connected to the given file descriptor into raw
37
+// mode and returns the previous state of the terminal so that it can be
38
+// restored.
39
+func MakeRaw(fd int) (*State, error) {
40
+	var oldState State
41
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
42
+		return nil, err
43
+	}
44
+
45
+	newState := oldState.termios
46
+	newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF
47
+	newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG
48
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
49
+		return nil, err
50
+	}
51
+
52
+	return &oldState, nil
53
+}
54
+
55
+// GetState returns the current state of a terminal which may be useful to
56
+// restore the terminal after a signal.
57
+func GetState(fd int) (*State, error) {
58
+	var oldState State
59
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
60
+		return nil, err
61
+	}
62
+
63
+	return &oldState, nil
64
+}
65
+
66
+// Restore restores the terminal connected to the given file descriptor to a
67
+// previous state.
68
+func Restore(fd int, state *State) error {
69
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
70
+	return err
71
+}
72
+
73
+// GetSize returns the dimensions of the given terminal.
74
+func GetSize(fd int) (width, height int, err error) {
75
+	var dimensions [4]uint16
76
+
77
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
78
+		return -1, -1, err
79
+	}
80
+	return int(dimensions[1]), int(dimensions[0]), nil
81
+}
82
+
83
+// ReadPassword reads a line of input from a terminal without local echo.  This
84
+// is commonly used for inputting passwords and other sensitive data. The slice
85
+// returned does not include the \n.
86
+func ReadPassword(fd int) ([]byte, error) {
87
+	var oldState syscall.Termios
88
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
89
+		return nil, err
90
+	}
91
+
92
+	newState := oldState
93
+	newState.Lflag &^= syscall.ECHO
94
+	newState.Lflag |= syscall.ICANON | syscall.ISIG
95
+	newState.Iflag |= syscall.ICRNL
96
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
97
+		return nil, err
98
+	}
99
+
100
+	defer func() {
101
+		syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
102
+	}()
103
+
104
+	var buf [16]byte
105
+	var ret []byte
106
+	for {
107
+		n, err := syscall.Read(fd, buf[:])
108
+		if err != nil {
109
+			return nil, err
110
+		}
111
+		if n == 0 {
112
+			if len(ret) == 0 {
113
+				return nil, io.EOF
114
+			}
115
+			break
116
+		}
117
+		if buf[n-1] == '\n' {
118
+			n--
119
+		}
120
+		ret = append(ret, buf[:n]...)
121
+		if n < len(buf) {
122
+			break
123
+		}
124
+	}
125
+
126
+	return ret, nil
127
+}
0 128
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+// Copyright 2013 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build darwin dragonfly freebsd netbsd openbsd
5
+
6
+package terminal
7
+
8
+import "syscall"
9
+
10
+const ioctlReadTermios = syscall.TIOCGETA
11
+const ioctlWriteTermios = syscall.TIOCSETA
0 12
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+// Copyright 2013 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package terminal
5
+
6
+// These constants are declared here, rather than importing
7
+// them from the syscall package as some syscall packages, even
8
+// on linux, for example gccgo, do not declare them.
9
+const ioctlReadTermios = 0x5401  // syscall.TCGETS
10
+const ioctlWriteTermios = 0x5402 // syscall.TCSETS
0 11
new file mode 100644
... ...
@@ -0,0 +1,58 @@
0
+// Copyright 2016 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// Package terminal provides support functions for dealing with terminals, as
5
+// commonly found on UNIX systems.
6
+//
7
+// Putting a terminal into raw mode is the most common requirement:
8
+//
9
+// 	oldState, err := terminal.MakeRaw(0)
10
+// 	if err != nil {
11
+// 	        panic(err)
12
+// 	}
13
+// 	defer terminal.Restore(0, oldState)
14
+package terminal
15
+
16
+import (
17
+	"fmt"
18
+	"runtime"
19
+)
20
+
21
+type State struct{}
22
+
23
+// IsTerminal returns true if the given file descriptor is a terminal.
24
+func IsTerminal(fd int) bool {
25
+	return false
26
+}
27
+
28
+// MakeRaw put the terminal connected to the given file descriptor into raw
29
+// mode and returns the previous state of the terminal so that it can be
30
+// restored.
31
+func MakeRaw(fd int) (*State, error) {
32
+	return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
33
+}
34
+
35
+// GetState returns the current state of a terminal which may be useful to
36
+// restore the terminal after a signal.
37
+func GetState(fd int) (*State, error) {
38
+	return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
39
+}
40
+
41
+// Restore restores the terminal connected to the given file descriptor to a
42
+// previous state.
43
+func Restore(fd int, state *State) error {
44
+	return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
45
+}
46
+
47
+// GetSize returns the dimensions of the given terminal.
48
+func GetSize(fd int) (width, height int, err error) {
49
+	return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
50
+}
51
+
52
+// ReadPassword reads a line of input from a terminal without local echo.  This
53
+// is commonly used for inputting passwords and other sensitive data. The slice
54
+// returned does not include the \n.
55
+func ReadPassword(fd int) ([]byte, error) {
56
+	return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
57
+}
0 58
new file mode 100644
... ...
@@ -0,0 +1,174 @@
0
+// Copyright 2011 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// +build windows
5
+
6
+// Package terminal provides support functions for dealing with terminals, as
7
+// commonly found on UNIX systems.
8
+//
9
+// Putting a terminal into raw mode is the most common requirement:
10
+//
11
+// 	oldState, err := terminal.MakeRaw(0)
12
+// 	if err != nil {
13
+// 	        panic(err)
14
+// 	}
15
+// 	defer terminal.Restore(0, oldState)
16
+package terminal
17
+
18
+import (
19
+	"io"
20
+	"syscall"
21
+	"unsafe"
22
+)
23
+
24
+const (
25
+	enableLineInput       = 2
26
+	enableEchoInput       = 4
27
+	enableProcessedInput  = 1
28
+	enableWindowInput     = 8
29
+	enableMouseInput      = 16
30
+	enableInsertMode      = 32
31
+	enableQuickEditMode   = 64
32
+	enableExtendedFlags   = 128
33
+	enableAutoPosition    = 256
34
+	enableProcessedOutput = 1
35
+	enableWrapAtEolOutput = 2
36
+)
37
+
38
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
39
+
40
+var (
41
+	procGetConsoleMode             = kernel32.NewProc("GetConsoleMode")
42
+	procSetConsoleMode             = kernel32.NewProc("SetConsoleMode")
43
+	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
44
+)
45
+
46
+type (
47
+	short int16
48
+	word  uint16
49
+
50
+	coord struct {
51
+		x short
52
+		y short
53
+	}
54
+	smallRect struct {
55
+		left   short
56
+		top    short
57
+		right  short
58
+		bottom short
59
+	}
60
+	consoleScreenBufferInfo struct {
61
+		size              coord
62
+		cursorPosition    coord
63
+		attributes        word
64
+		window            smallRect
65
+		maximumWindowSize coord
66
+	}
67
+)
68
+
69
+type State struct {
70
+	mode uint32
71
+}
72
+
73
+// IsTerminal returns true if the given file descriptor is a terminal.
74
+func IsTerminal(fd int) bool {
75
+	var st uint32
76
+	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
77
+	return r != 0 && e == 0
78
+}
79
+
80
+// MakeRaw put the terminal connected to the given file descriptor into raw
81
+// mode and returns the previous state of the terminal so that it can be
82
+// restored.
83
+func MakeRaw(fd int) (*State, error) {
84
+	var st uint32
85
+	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
86
+	if e != 0 {
87
+		return nil, error(e)
88
+	}
89
+	raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
90
+	_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0)
91
+	if e != 0 {
92
+		return nil, error(e)
93
+	}
94
+	return &State{st}, nil
95
+}
96
+
97
+// GetState returns the current state of a terminal which may be useful to
98
+// restore the terminal after a signal.
99
+func GetState(fd int) (*State, error) {
100
+	var st uint32
101
+	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
102
+	if e != 0 {
103
+		return nil, error(e)
104
+	}
105
+	return &State{st}, nil
106
+}
107
+
108
+// Restore restores the terminal connected to the given file descriptor to a
109
+// previous state.
110
+func Restore(fd int, state *State) error {
111
+	_, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0)
112
+	return err
113
+}
114
+
115
+// GetSize returns the dimensions of the given terminal.
116
+func GetSize(fd int) (width, height int, err error) {
117
+	var info consoleScreenBufferInfo
118
+	_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0)
119
+	if e != 0 {
120
+		return 0, 0, error(e)
121
+	}
122
+	return int(info.size.x), int(info.size.y), nil
123
+}
124
+
125
+// ReadPassword reads a line of input from a terminal without local echo.  This
126
+// is commonly used for inputting passwords and other sensitive data. The slice
127
+// returned does not include the \n.
128
+func ReadPassword(fd int) ([]byte, error) {
129
+	var st uint32
130
+	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
131
+	if e != 0 {
132
+		return nil, error(e)
133
+	}
134
+	old := st
135
+
136
+	st &^= (enableEchoInput)
137
+	st |= (enableProcessedInput | enableLineInput | enableProcessedOutput)
138
+	_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0)
139
+	if e != 0 {
140
+		return nil, error(e)
141
+	}
142
+
143
+	defer func() {
144
+		syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
145
+	}()
146
+
147
+	var buf [16]byte
148
+	var ret []byte
149
+	for {
150
+		n, err := syscall.Read(syscall.Handle(fd), buf[:])
151
+		if err != nil {
152
+			return nil, err
153
+		}
154
+		if n == 0 {
155
+			if len(ret) == 0 {
156
+				return nil, io.EOF
157
+			}
158
+			break
159
+		}
160
+		if buf[n-1] == '\n' {
161
+			n--
162
+		}
163
+		if n > 0 && buf[n-1] == '\r' {
164
+			n--
165
+		}
166
+		ret = append(ret, buf[:n]...)
167
+		if n < len(buf) {
168
+			break
169
+		}
170
+	}
171
+
172
+	return ret, nil
173
+}