update dependencies (#7390)
This commit is contained in:
parent
a237d66213
commit
9994307c6c
6
go.mod
6
go.mod
|
@ -91,14 +91,14 @@ require (
|
||||||
github.com/kr/pty v1.1.3 // indirect
|
github.com/kr/pty v1.1.3 // indirect
|
||||||
github.com/kr/text v0.1.0
|
github.com/kr/text v0.1.0
|
||||||
github.com/lib/pq v1.2.0
|
github.com/lib/pq v1.2.0
|
||||||
github.com/mattn/go-colorable v0.0.9
|
github.com/mattn/go-colorable v0.1.2
|
||||||
github.com/michaelklishin/rabbit-hole v1.5.0
|
github.com/michaelklishin/rabbit-hole v1.5.0
|
||||||
github.com/mitchellh/cli v1.0.0
|
github.com/mitchellh/cli v1.0.0
|
||||||
github.com/mitchellh/copystructure v1.0.0
|
github.com/mitchellh/copystructure v1.0.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0
|
github.com/mitchellh/go-testing-interface v1.0.0
|
||||||
github.com/mitchellh/mapstructure v1.1.2
|
github.com/mitchellh/mapstructure v1.1.2
|
||||||
github.com/mitchellh/reflectwalk v1.0.0
|
github.com/mitchellh/reflectwalk v1.0.1
|
||||||
github.com/ncw/swift v1.0.47
|
github.com/ncw/swift v1.0.47
|
||||||
github.com/oklog/run v1.0.0
|
github.com/oklog/run v1.0.0
|
||||||
github.com/onsi/ginkgo v1.7.0 // indirect
|
github.com/onsi/ginkgo v1.7.0 // indirect
|
||||||
|
@ -117,7 +117,7 @@ require (
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
go.etcd.io/bbolt v1.3.2
|
go.etcd.io/bbolt v1.3.2
|
||||||
go.etcd.io/etcd v0.0.0-20190412021913-f29b1ada1971
|
go.etcd.io/etcd v0.0.0-20190412021913-f29b1ada1971
|
||||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
|
||||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
|
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
|
||||||
google.golang.org/api v0.5.0
|
google.golang.org/api v0.5.0
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -409,9 +409,13 @@ github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJ
|
||||||
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI=
|
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI=
|
||||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||||
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.0 h1:YNOwxxSJzSUARoD9KRZLzM9Y858MNGCOACTvCW9TSAc=
|
github.com/matttproud/golang_protobuf_extensions v1.0.0 h1:YNOwxxSJzSUARoD9KRZLzM9Y858MNGCOACTvCW9TSAc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
@ -441,6 +445,8 @@ github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8 h1:1CO5
|
||||||
github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8=
|
github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
@ -602,6 +608,8 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0F
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo=
|
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo=
|
||||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
@ -657,6 +665,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
|
@ -29,6 +29,15 @@ const (
|
||||||
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
genericRead = 0x80000000
|
||||||
|
genericWrite = 0x40000000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
consoleTextmodeBuffer = 0x1
|
||||||
|
)
|
||||||
|
|
||||||
type wchar uint16
|
type wchar uint16
|
||||||
type short int16
|
type short int16
|
||||||
type dword uint32
|
type dword uint32
|
||||||
|
@ -69,14 +78,17 @@ var (
|
||||||
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
||||||
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
||||||
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
||||||
|
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer provide colorable Writer to the console
|
// Writer provide colorable Writer to the console
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
out io.Writer
|
out io.Writer
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
oldattr word
|
althandle syscall.Handle
|
||||||
oldpos coord
|
oldattr word
|
||||||
|
oldpos coord
|
||||||
|
rest bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewColorable return new instance of Writer which handle escape sequence from File.
|
// NewColorable return new instance of Writer which handle escape sequence from File.
|
||||||
|
@ -407,7 +419,18 @@ func (w *Writer) Write(data []byte) (n int, err error) {
|
||||||
var csbi consoleScreenBufferInfo
|
var csbi consoleScreenBufferInfo
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
|
||||||
er := bytes.NewReader(data)
|
handle := w.handle
|
||||||
|
|
||||||
|
var er *bytes.Reader
|
||||||
|
if w.rest.Len() > 0 {
|
||||||
|
var rest bytes.Buffer
|
||||||
|
w.rest.WriteTo(&rest)
|
||||||
|
w.rest.Reset()
|
||||||
|
rest.Write(data)
|
||||||
|
er = bytes.NewReader(rest.Bytes())
|
||||||
|
} else {
|
||||||
|
er = bytes.NewReader(data)
|
||||||
|
}
|
||||||
var bw [1]byte
|
var bw [1]byte
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
|
@ -425,29 +448,55 @@ loop:
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
|
||||||
if c2 == ']' {
|
switch c2 {
|
||||||
if err := doTitleSequence(er); err != nil {
|
case '>':
|
||||||
|
continue
|
||||||
|
case ']':
|
||||||
|
w.rest.WriteByte(c1)
|
||||||
|
w.rest.WriteByte(c2)
|
||||||
|
er.WriteTo(&w.rest)
|
||||||
|
if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
continue
|
er = bytes.NewReader(w.rest.Bytes()[2:])
|
||||||
}
|
err := doTitleSequence(er)
|
||||||
if c2 != 0x5b {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
var m byte
|
|
||||||
for {
|
|
||||||
c, err := er.ReadByte()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
w.rest.Reset()
|
||||||
|
continue
|
||||||
|
// https://github.com/mattn/go-colorable/issues/27
|
||||||
|
case '7':
|
||||||
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
|
w.oldpos = csbi.cursorPosition
|
||||||
|
continue
|
||||||
|
case '8':
|
||||||
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
||||||
|
continue
|
||||||
|
case 0x5b:
|
||||||
|
// execute part after switch
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
w.rest.WriteByte(c1)
|
||||||
|
w.rest.WriteByte(c2)
|
||||||
|
er.WriteTo(&w.rest)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
var m byte
|
||||||
|
for i, c := range w.rest.Bytes()[2:] {
|
||||||
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
||||||
m = c
|
m = c
|
||||||
|
er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
|
||||||
|
w.rest.Reset()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
buf.Write([]byte(string(c)))
|
buf.Write([]byte(string(c)))
|
||||||
}
|
}
|
||||||
|
if m == 0 {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
|
||||||
switch m {
|
switch m {
|
||||||
case 'A':
|
case 'A':
|
||||||
|
@ -455,61 +504,64 @@ loop:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.y -= short(n)
|
csbi.cursorPosition.y -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'B':
|
case 'B':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.y += short(n)
|
csbi.cursorPosition.y += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'C':
|
case 'C':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x += short(n)
|
csbi.cursorPosition.x += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'D':
|
case 'D':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x -= short(n)
|
csbi.cursorPosition.x -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
if csbi.cursorPosition.x < 0 {
|
||||||
|
csbi.cursorPosition.x = 0
|
||||||
|
}
|
||||||
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'E':
|
case 'E':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = 0
|
csbi.cursorPosition.x = 0
|
||||||
csbi.cursorPosition.y += short(n)
|
csbi.cursorPosition.y += short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'F':
|
case 'F':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = 0
|
csbi.cursorPosition.x = 0
|
||||||
csbi.cursorPosition.y -= short(n)
|
csbi.cursorPosition.y -= short(n)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'G':
|
case 'G':
|
||||||
n, err = strconv.Atoi(buf.String())
|
n, err = strconv.Atoi(buf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
csbi.cursorPosition.x = short(n - 1)
|
csbi.cursorPosition.x = short(n - 1)
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'H', 'f':
|
case 'H', 'f':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
token := strings.Split(buf.String(), ";")
|
token := strings.Split(buf.String(), ";")
|
||||||
switch len(token) {
|
switch len(token) {
|
||||||
|
@ -534,7 +586,7 @@ loop:
|
||||||
} else {
|
} else {
|
||||||
csbi.cursorPosition.y = 0
|
csbi.cursorPosition.y = 0
|
||||||
}
|
}
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
||||||
case 'J':
|
case 'J':
|
||||||
n := 0
|
n := 0
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
|
@ -545,20 +597,20 @@ loop:
|
||||||
}
|
}
|
||||||
var count, written dword
|
var count, written dword
|
||||||
var cursor coord
|
var cursor coord
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
switch n {
|
switch n {
|
||||||
case 0:
|
case 0:
|
||||||
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
|
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
|
||||||
case 1:
|
case 1:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x)
|
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
|
||||||
case 2:
|
case 2:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
|
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
|
||||||
}
|
}
|
||||||
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
case 'K':
|
case 'K':
|
||||||
n := 0
|
n := 0
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
|
@ -567,28 +619,28 @@ loop:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
var cursor coord
|
var cursor coord
|
||||||
var count, written dword
|
var count, written dword
|
||||||
switch n {
|
switch n {
|
||||||
case 0:
|
case 0:
|
||||||
cursor = coord{x: csbi.cursorPosition.x + 1, y: csbi.cursorPosition.y}
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x - 1)
|
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
||||||
case 1:
|
case 1:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
count = dword(csbi.size.x - csbi.cursorPosition.x)
|
||||||
case 2:
|
case 2:
|
||||||
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
|
||||||
count = dword(csbi.size.x)
|
count = dword(csbi.size.x)
|
||||||
}
|
}
|
||||||
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
||||||
case 'm':
|
case 'm':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
attr := csbi.attributes
|
attr := csbi.attributes
|
||||||
cs := buf.String()
|
cs := buf.String()
|
||||||
if cs == "" {
|
if cs == "" {
|
||||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
|
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
token := strings.Split(cs, ";")
|
token := strings.Split(cs, ";")
|
||||||
|
@ -627,6 +679,21 @@ loop:
|
||||||
attr |= n256foreAttr[n256]
|
attr |= n256foreAttr[n256]
|
||||||
i += 2
|
i += 2
|
||||||
}
|
}
|
||||||
|
} else if len(token) == 5 && token[i+1] == "2" {
|
||||||
|
var r, g, b int
|
||||||
|
r, _ = strconv.Atoi(token[i+2])
|
||||||
|
g, _ = strconv.Atoi(token[i+3])
|
||||||
|
b, _ = strconv.Atoi(token[i+4])
|
||||||
|
i += 4
|
||||||
|
if r > 127 {
|
||||||
|
attr |= foregroundRed
|
||||||
|
}
|
||||||
|
if g > 127 {
|
||||||
|
attr |= foregroundGreen
|
||||||
|
}
|
||||||
|
if b > 127 {
|
||||||
|
attr |= foregroundBlue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
attr = attr & (w.oldattr & backgroundMask)
|
attr = attr & (w.oldattr & backgroundMask)
|
||||||
}
|
}
|
||||||
|
@ -654,6 +721,21 @@ loop:
|
||||||
attr |= n256backAttr[n256]
|
attr |= n256backAttr[n256]
|
||||||
i += 2
|
i += 2
|
||||||
}
|
}
|
||||||
|
} else if len(token) == 5 && token[i+1] == "2" {
|
||||||
|
var r, g, b int
|
||||||
|
r, _ = strconv.Atoi(token[i+2])
|
||||||
|
g, _ = strconv.Atoi(token[i+3])
|
||||||
|
b, _ = strconv.Atoi(token[i+4])
|
||||||
|
i += 4
|
||||||
|
if r > 127 {
|
||||||
|
attr |= backgroundRed
|
||||||
|
}
|
||||||
|
if g > 127 {
|
||||||
|
attr |= backgroundGreen
|
||||||
|
}
|
||||||
|
if b > 127 {
|
||||||
|
attr |= backgroundBlue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
attr = attr & (w.oldattr & foregroundMask)
|
attr = attr & (w.oldattr & foregroundMask)
|
||||||
}
|
}
|
||||||
|
@ -685,38 +767,52 @@ loop:
|
||||||
attr |= backgroundBlue
|
attr |= backgroundBlue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
|
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'h':
|
case 'h':
|
||||||
var ci consoleCursorInfo
|
var ci consoleCursorInfo
|
||||||
cs := buf.String()
|
cs := buf.String()
|
||||||
if cs == "5>" {
|
if cs == "5>" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 0
|
ci.visible = 0
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
} else if cs == "?25" {
|
} else if cs == "?25" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 1
|
ci.visible = 1
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
|
} else if cs == "?1049" {
|
||||||
|
if w.althandle == 0 {
|
||||||
|
h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
|
||||||
|
w.althandle = syscall.Handle(h)
|
||||||
|
if w.althandle != 0 {
|
||||||
|
handle = w.althandle
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case 'l':
|
case 'l':
|
||||||
var ci consoleCursorInfo
|
var ci consoleCursorInfo
|
||||||
cs := buf.String()
|
cs := buf.String()
|
||||||
if cs == "5>" {
|
if cs == "5>" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 1
|
ci.visible = 1
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
} else if cs == "?25" {
|
} else if cs == "?25" {
|
||||||
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
ci.visible = 0
|
ci.visible = 0
|
||||||
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
||||||
|
} else if cs == "?1049" {
|
||||||
|
if w.althandle != 0 {
|
||||||
|
syscall.CloseHandle(w.althandle)
|
||||||
|
w.althandle = 0
|
||||||
|
handle = w.handle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case 's':
|
case 's':
|
||||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||||
w.oldpos = csbi.cursorPosition
|
w.oldpos = csbi.cursorPosition
|
||||||
case 'u':
|
case 'u':
|
||||||
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/mattn/go-colorable
|
||||||
|
|
||||||
|
require github.com/mattn/go-isatty v0.0.8
|
|
@ -0,0 +1,4 @@
|
||||||
|
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||||
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/mattn/go-isatty
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223
|
|
@ -0,0 +1,2 @@
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
@ -1,5 +1,4 @@
|
||||||
// +build linux
|
// +build android
|
||||||
// +build !appengine,!ppc64,!ppc64le
|
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
|
@ -16,3 +15,9 @@ func IsTerminal(fd uintptr) bool {
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||||
return err == 0
|
return err == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
// +build appengine
|
|
||||||
|
|
||||||
package isatty
|
|
||||||
|
|
||||||
// IsTerminal returns true if the file descriptor is terminal which
|
|
||||||
// is always false on on appengine classic which is a sandboxed PaaS.
|
|
||||||
func IsTerminal(fd uintptr) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
|
||||||
// terminal. This is also always false on this environment.
|
|
||||||
func IsCygwinTerminal(fd uintptr) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -16,3 +16,9 @@ func IsTerminal(fd uintptr) bool {
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||||
return err == 0
|
return err == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build ppc64 ppc64le
|
|
||||||
|
|
||||||
package isatty
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
syscall "golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TCGETS
|
|
||||||
|
|
||||||
// IsTerminal return true if the file descriptor is terminal.
|
|
||||||
func IsTerminal(fd uintptr) bool {
|
|
||||||
var termios syscall.Termios
|
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
|
||||||
return err == 0
|
|
||||||
}
|
|
|
@ -1,9 +1,14 @@
|
||||||
// +build !windows
|
// +build appengine js nacl
|
||||||
// +build !appengine
|
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
|
||||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
// IsTerminal returns true if the file descriptor is terminal which
|
||||||
|
// is always false on js and appengine classic which is a sandboxed PaaS.
|
||||||
|
func IsTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
|
||||||
// terminal. This is also always false on this environment.
|
// terminal. This is also always false on this environment.
|
||||||
func IsCygwinTerminal(fd uintptr) bool {
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -14,3 +14,9 @@ func IsTerminal(fd uintptr) bool {
|
||||||
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// +build linux aix
|
||||||
|
// +build !appengine
|
||||||
|
// +build !android
|
||||||
|
|
||||||
|
package isatty
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
// IsTerminal return true if the file descriptor is terminal.
|
||||||
|
func IsTerminal(fd uintptr) bool {
|
||||||
|
_, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
|
||||||
|
// terminal. This is also always false on this environment.
|
||||||
|
func IsCygwinTerminal(fd uintptr) bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -230,7 +230,8 @@ func walkMap(v reflect.Value, w interface{}) error {
|
||||||
ew.Enter(MapValue)
|
ew.Enter(MapValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := walk(kv, w); err != nil {
|
// get the map value again as it may have changed in the MapElem call
|
||||||
|
if err := walk(v.MapIndex(k), w); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// In Go 1.13, the ed25519 package was promoted to the standard library as
|
||||||
|
// crypto/ed25519, and this package became a wrapper for the standard library one.
|
||||||
|
//
|
||||||
|
// +build !go1.13
|
||||||
|
|
||||||
// Package ed25519 implements the Ed25519 signature algorithm. See
|
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||||
// https://ed25519.cr.yp.to/.
|
// https://ed25519.cr.yp.to/.
|
||||||
//
|
//
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build go1.13
|
||||||
|
|
||||||
|
// Package ed25519 implements the Ed25519 signature algorithm. See
|
||||||
|
// https://ed25519.cr.yp.to/.
|
||||||
|
//
|
||||||
|
// These functions are also compatible with the “Ed25519” function defined in
|
||||||
|
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
|
||||||
|
// representation includes a public key suffix to make multiple signing
|
||||||
|
// operations with the same key more efficient. This package refers to the RFC
|
||||||
|
// 8032 private key as the “seed”.
|
||||||
|
//
|
||||||
|
// Beginning with Go 1.13, the functionality of this package was moved to the
|
||||||
|
// standard library as crypto/ed25519. This package only acts as a compatibility
|
||||||
|
// wrapper.
|
||||||
|
package ed25519
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PublicKeySize is the size, in bytes, of public keys as used in this package.
|
||||||
|
PublicKeySize = 32
|
||||||
|
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
|
||||||
|
PrivateKeySize = 64
|
||||||
|
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
||||||
|
SignatureSize = 64
|
||||||
|
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
|
||||||
|
SeedSize = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicKey is the type of Ed25519 public keys.
|
||||||
|
//
|
||||||
|
// This type is an alias for crypto/ed25519's PublicKey type.
|
||||||
|
// See the crypto/ed25519 package for the methods on this type.
|
||||||
|
type PublicKey = ed25519.PublicKey
|
||||||
|
|
||||||
|
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
||||||
|
//
|
||||||
|
// This type is an alias for crypto/ed25519's PrivateKey type.
|
||||||
|
// See the crypto/ed25519 package for the methods on this type.
|
||||||
|
type PrivateKey = ed25519.PrivateKey
|
||||||
|
|
||||||
|
// GenerateKey generates a public/private key pair using entropy from rand.
|
||||||
|
// If rand is nil, crypto/rand.Reader will be used.
|
||||||
|
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
||||||
|
return ed25519.GenerateKey(rand)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
||||||
|
// len(seed) is not SeedSize. This function is provided for interoperability
|
||||||
|
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
||||||
|
// package.
|
||||||
|
func NewKeyFromSeed(seed []byte) PrivateKey {
|
||||||
|
return ed25519.NewKeyFromSeed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs the message with privateKey and returns a signature. It will
|
||||||
|
// panic if len(privateKey) is not PrivateKeySize.
|
||||||
|
func Sign(privateKey PrivateKey, message []byte) []byte {
|
||||||
|
return ed25519.Sign(privateKey, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify reports whether sig is a valid signature of message by publicKey. It
|
||||||
|
// will panic if len(publicKey) is not PublicKeySize.
|
||||||
|
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
||||||
|
return ed25519.Verify(publicKey, message, sig)
|
||||||
|
}
|
|
@ -0,0 +1,668 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Based on CRYPTOGAMS code with the following comment:
|
||||||
|
// # ====================================================================
|
||||||
|
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||||
|
// # project. The module is, however, dual licensed under OpenSSL and
|
||||||
|
// # CRYPTOGAMS licenses depending on where you obtain it. For further
|
||||||
|
// # details see http://www.openssl.org/~appro/cryptogams/.
|
||||||
|
// # ====================================================================
|
||||||
|
|
||||||
|
// Original code can be found at the link below:
|
||||||
|
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91e5c39ca79126a4a876d5d8ff
|
||||||
|
|
||||||
|
// There are some differences between CRYPTOGAMS code and this one. The round
|
||||||
|
// loop for "_int" isn't the same as the original. Some adjustments were
|
||||||
|
// necessary because there are less vector registers available. For example, some
|
||||||
|
// X variables (r12, r13, r14, and r15) share the same register used by the
|
||||||
|
// counter. The original code uses ctr to name the counter. Here we use CNT
|
||||||
|
// because golang uses CTR as the counter register name.
|
||||||
|
|
||||||
|
// +build ppc64le,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define OUT R3
|
||||||
|
#define INP R4
|
||||||
|
#define LEN R5
|
||||||
|
#define KEY R6
|
||||||
|
#define CNT R7
|
||||||
|
|
||||||
|
#define TEMP R8
|
||||||
|
|
||||||
|
#define X0 R11
|
||||||
|
#define X1 R12
|
||||||
|
#define X2 R14
|
||||||
|
#define X3 R15
|
||||||
|
#define X4 R16
|
||||||
|
#define X5 R17
|
||||||
|
#define X6 R18
|
||||||
|
#define X7 R19
|
||||||
|
#define X8 R20
|
||||||
|
#define X9 R21
|
||||||
|
#define X10 R22
|
||||||
|
#define X11 R23
|
||||||
|
#define X12 R24
|
||||||
|
#define X13 R25
|
||||||
|
#define X14 R26
|
||||||
|
#define X15 R27
|
||||||
|
|
||||||
|
#define CON0 X0
|
||||||
|
#define CON1 X1
|
||||||
|
#define CON2 X2
|
||||||
|
#define CON3 X3
|
||||||
|
|
||||||
|
#define KEY0 X4
|
||||||
|
#define KEY1 X5
|
||||||
|
#define KEY2 X6
|
||||||
|
#define KEY3 X7
|
||||||
|
#define KEY4 X8
|
||||||
|
#define KEY5 X9
|
||||||
|
#define KEY6 X10
|
||||||
|
#define KEY7 X11
|
||||||
|
|
||||||
|
#define CNT0 X12
|
||||||
|
#define CNT1 X13
|
||||||
|
#define CNT2 X14
|
||||||
|
#define CNT3 X15
|
||||||
|
|
||||||
|
#define TMP0 R9
|
||||||
|
#define TMP1 R10
|
||||||
|
#define TMP2 R28
|
||||||
|
#define TMP3 R29
|
||||||
|
|
||||||
|
#define CONSTS R8
|
||||||
|
|
||||||
|
#define A0 V0
|
||||||
|
#define B0 V1
|
||||||
|
#define C0 V2
|
||||||
|
#define D0 V3
|
||||||
|
#define A1 V4
|
||||||
|
#define B1 V5
|
||||||
|
#define C1 V6
|
||||||
|
#define D1 V7
|
||||||
|
#define A2 V8
|
||||||
|
#define B2 V9
|
||||||
|
#define C2 V10
|
||||||
|
#define D2 V11
|
||||||
|
#define T0 V12
|
||||||
|
#define T1 V13
|
||||||
|
#define T2 V14
|
||||||
|
|
||||||
|
#define K0 V15
|
||||||
|
#define K1 V16
|
||||||
|
#define K2 V17
|
||||||
|
#define K3 V18
|
||||||
|
#define K4 V19
|
||||||
|
#define K5 V20
|
||||||
|
|
||||||
|
#define FOUR V21
|
||||||
|
#define SIXTEEN V22
|
||||||
|
#define TWENTY4 V23
|
||||||
|
#define TWENTY V24
|
||||||
|
#define TWELVE V25
|
||||||
|
#define TWENTY5 V26
|
||||||
|
#define SEVEN V27
|
||||||
|
|
||||||
|
#define INPPERM V28
|
||||||
|
#define OUTPERM V29
|
||||||
|
#define OUTMASK V30
|
||||||
|
|
||||||
|
#define DD0 V31
|
||||||
|
#define DD1 SEVEN
|
||||||
|
#define DD2 T0
|
||||||
|
#define DD3 T1
|
||||||
|
#define DD4 T2
|
||||||
|
|
||||||
|
DATA ·consts+0x00(SB)/8, $0x3320646e61707865
|
||||||
|
DATA ·consts+0x08(SB)/8, $0x6b20657479622d32
|
||||||
|
DATA ·consts+0x10(SB)/8, $0x0000000000000001
|
||||||
|
DATA ·consts+0x18(SB)/8, $0x0000000000000000
|
||||||
|
DATA ·consts+0x20(SB)/8, $0x0000000000000004
|
||||||
|
DATA ·consts+0x28(SB)/8, $0x0000000000000000
|
||||||
|
DATA ·consts+0x30(SB)/8, $0x0a0b08090e0f0c0d
|
||||||
|
DATA ·consts+0x38(SB)/8, $0x0203000106070405
|
||||||
|
DATA ·consts+0x40(SB)/8, $0x090a0b080d0e0f0c
|
||||||
|
DATA ·consts+0x48(SB)/8, $0x0102030005060704
|
||||||
|
GLOBL ·consts(SB), RODATA, $80
|
||||||
|
|
||||||
|
//func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[32]byte, counter *[16]byte)
|
||||||
|
TEXT ·chaCha20_ctr32_vmx(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
// Load the arguments inside the registers
|
||||||
|
MOVD out+0(FP), OUT
|
||||||
|
MOVD inp+8(FP), INP
|
||||||
|
MOVD len+16(FP), LEN
|
||||||
|
MOVD key+24(FP), KEY
|
||||||
|
MOVD counter+32(FP), CNT
|
||||||
|
|
||||||
|
MOVD $·consts(SB), CONSTS // point to consts addr
|
||||||
|
|
||||||
|
MOVD $16, X0
|
||||||
|
MOVD $32, X1
|
||||||
|
MOVD $48, X2
|
||||||
|
MOVD $64, X3
|
||||||
|
MOVD $31, X4
|
||||||
|
MOVD $15, X5
|
||||||
|
|
||||||
|
// Load key
|
||||||
|
LVX (KEY)(R0), K1
|
||||||
|
LVSR (KEY)(R0), T0
|
||||||
|
LVX (KEY)(X0), K2
|
||||||
|
LVX (KEY)(X4), DD0
|
||||||
|
|
||||||
|
// Load counter
|
||||||
|
LVX (CNT)(R0), K3
|
||||||
|
LVSR (CNT)(R0), T1
|
||||||
|
LVX (CNT)(X5), DD1
|
||||||
|
|
||||||
|
// Load constants
|
||||||
|
LVX (CONSTS)(R0), K0
|
||||||
|
LVX (CONSTS)(X0), K5
|
||||||
|
LVX (CONSTS)(X1), FOUR
|
||||||
|
LVX (CONSTS)(X2), SIXTEEN
|
||||||
|
LVX (CONSTS)(X3), TWENTY4
|
||||||
|
|
||||||
|
// Align key and counter
|
||||||
|
VPERM K2, K1, T0, K1
|
||||||
|
VPERM DD0, K2, T0, K2
|
||||||
|
VPERM DD1, K3, T1, K3
|
||||||
|
|
||||||
|
// Load counter to GPR
|
||||||
|
MOVWZ 0(CNT), CNT0
|
||||||
|
MOVWZ 4(CNT), CNT1
|
||||||
|
MOVWZ 8(CNT), CNT2
|
||||||
|
MOVWZ 12(CNT), CNT3
|
||||||
|
|
||||||
|
// Adjust vectors for the initial state
|
||||||
|
VADDUWM K3, K5, K3
|
||||||
|
VADDUWM K3, K5, K4
|
||||||
|
VADDUWM K4, K5, K5
|
||||||
|
|
||||||
|
// Synthesized constants
|
||||||
|
VSPLTISW $-12, TWENTY
|
||||||
|
VSPLTISW $12, TWELVE
|
||||||
|
VSPLTISW $-7, TWENTY5
|
||||||
|
|
||||||
|
VXOR T0, T0, T0
|
||||||
|
VSPLTISW $-1, OUTMASK
|
||||||
|
LVSR (INP)(R0), INPPERM
|
||||||
|
LVSL (OUT)(R0), OUTPERM
|
||||||
|
VPERM OUTMASK, T0, OUTPERM, OUTMASK
|
||||||
|
|
||||||
|
loop_outer_vmx:
|
||||||
|
// Load constant
|
||||||
|
MOVD $0x61707865, CON0
|
||||||
|
MOVD $0x3320646e, CON1
|
||||||
|
MOVD $0x79622d32, CON2
|
||||||
|
MOVD $0x6b206574, CON3
|
||||||
|
|
||||||
|
VOR K0, K0, A0
|
||||||
|
VOR K0, K0, A1
|
||||||
|
VOR K0, K0, A2
|
||||||
|
VOR K1, K1, B0
|
||||||
|
|
||||||
|
MOVD $10, TEMP
|
||||||
|
|
||||||
|
// Load key to GPR
|
||||||
|
MOVWZ 0(KEY), X4
|
||||||
|
MOVWZ 4(KEY), X5
|
||||||
|
MOVWZ 8(KEY), X6
|
||||||
|
MOVWZ 12(KEY), X7
|
||||||
|
VOR K1, K1, B1
|
||||||
|
VOR K1, K1, B2
|
||||||
|
MOVWZ 16(KEY), X8
|
||||||
|
MOVWZ 0(CNT), X12
|
||||||
|
MOVWZ 20(KEY), X9
|
||||||
|
MOVWZ 4(CNT), X13
|
||||||
|
VOR K2, K2, C0
|
||||||
|
VOR K2, K2, C1
|
||||||
|
MOVWZ 24(KEY), X10
|
||||||
|
MOVWZ 8(CNT), X14
|
||||||
|
VOR K2, K2, C2
|
||||||
|
VOR K3, K3, D0
|
||||||
|
MOVWZ 28(KEY), X11
|
||||||
|
MOVWZ 12(CNT), X15
|
||||||
|
VOR K4, K4, D1
|
||||||
|
VOR K5, K5, D2
|
||||||
|
|
||||||
|
MOVD X4, TMP0
|
||||||
|
MOVD X5, TMP1
|
||||||
|
MOVD X6, TMP2
|
||||||
|
MOVD X7, TMP3
|
||||||
|
VSPLTISW $7, SEVEN
|
||||||
|
|
||||||
|
MOVD TEMP, CTR
|
||||||
|
|
||||||
|
loop_vmx:
|
||||||
|
// CRYPTOGAMS uses a macro to create a loop using perl. This isn't possible
|
||||||
|
// using assembly macros. Therefore, the macro expansion result was used
|
||||||
|
// in order to maintain the algorithm efficiency.
|
||||||
|
// This loop generates three keystream blocks using VMX instructions and,
|
||||||
|
// in parallel, one keystream block using scalar instructions.
|
||||||
|
ADD X4, X0, X0
|
||||||
|
ADD X5, X1, X1
|
||||||
|
VADDUWM A0, B0, A0
|
||||||
|
VADDUWM A1, B1, A1
|
||||||
|
ADD X6, X2, X2
|
||||||
|
ADD X7, X3, X3
|
||||||
|
VADDUWM A2, B2, A2
|
||||||
|
VXOR D0, A0, D0
|
||||||
|
XOR X0, X12, X12
|
||||||
|
XOR X1, X13, X13
|
||||||
|
VXOR D1, A1, D1
|
||||||
|
VXOR D2, A2, D2
|
||||||
|
XOR X2, X14, X14
|
||||||
|
XOR X3, X15, X15
|
||||||
|
VPERM D0, D0, SIXTEEN, D0
|
||||||
|
VPERM D1, D1, SIXTEEN, D1
|
||||||
|
ROTLW $16, X12, X12
|
||||||
|
ROTLW $16, X13, X13
|
||||||
|
VPERM D2, D2, SIXTEEN, D2
|
||||||
|
VADDUWM C0, D0, C0
|
||||||
|
ROTLW $16, X14, X14
|
||||||
|
ROTLW $16, X15, X15
|
||||||
|
VADDUWM C1, D1, C1
|
||||||
|
VADDUWM C2, D2, C2
|
||||||
|
ADD X12, X8, X8
|
||||||
|
ADD X13, X9, X9
|
||||||
|
VXOR B0, C0, T0
|
||||||
|
VXOR B1, C1, T1
|
||||||
|
ADD X14, X10, X10
|
||||||
|
ADD X15, X11, X11
|
||||||
|
VXOR B2, C2, T2
|
||||||
|
VRLW T0, TWELVE, B0
|
||||||
|
XOR X8, X4, X4
|
||||||
|
XOR X9, X5, X5
|
||||||
|
VRLW T1, TWELVE, B1
|
||||||
|
VRLW T2, TWELVE, B2
|
||||||
|
XOR X10, X6, X6
|
||||||
|
XOR X11, X7, X7
|
||||||
|
VADDUWM A0, B0, A0
|
||||||
|
VADDUWM A1, B1, A1
|
||||||
|
ROTLW $12, X4, X4
|
||||||
|
ROTLW $12, X5, X5
|
||||||
|
VADDUWM A2, B2, A2
|
||||||
|
VXOR D0, A0, D0
|
||||||
|
ROTLW $12, X6, X6
|
||||||
|
ROTLW $12, X7, X7
|
||||||
|
VXOR D1, A1, D1
|
||||||
|
VXOR D2, A2, D2
|
||||||
|
ADD X4, X0, X0
|
||||||
|
ADD X5, X1, X1
|
||||||
|
VPERM D0, D0, TWENTY4, D0
|
||||||
|
VPERM D1, D1, TWENTY4, D1
|
||||||
|
ADD X6, X2, X2
|
||||||
|
ADD X7, X3, X3
|
||||||
|
VPERM D2, D2, TWENTY4, D2
|
||||||
|
VADDUWM C0, D0, C0
|
||||||
|
XOR X0, X12, X12
|
||||||
|
XOR X1, X13, X13
|
||||||
|
VADDUWM C1, D1, C1
|
||||||
|
VADDUWM C2, D2, C2
|
||||||
|
XOR X2, X14, X14
|
||||||
|
XOR X3, X15, X15
|
||||||
|
VXOR B0, C0, T0
|
||||||
|
VXOR B1, C1, T1
|
||||||
|
ROTLW $8, X12, X12
|
||||||
|
ROTLW $8, X13, X13
|
||||||
|
VXOR B2, C2, T2
|
||||||
|
VRLW T0, SEVEN, B0
|
||||||
|
ROTLW $8, X14, X14
|
||||||
|
ROTLW $8, X15, X15
|
||||||
|
VRLW T1, SEVEN, B1
|
||||||
|
VRLW T2, SEVEN, B2
|
||||||
|
ADD X12, X8, X8
|
||||||
|
ADD X13, X9, X9
|
||||||
|
VSLDOI $8, C0, C0, C0
|
||||||
|
VSLDOI $8, C1, C1, C1
|
||||||
|
ADD X14, X10, X10
|
||||||
|
ADD X15, X11, X11
|
||||||
|
VSLDOI $8, C2, C2, C2
|
||||||
|
VSLDOI $12, B0, B0, B0
|
||||||
|
XOR X8, X4, X4
|
||||||
|
XOR X9, X5, X5
|
||||||
|
VSLDOI $12, B1, B1, B1
|
||||||
|
VSLDOI $12, B2, B2, B2
|
||||||
|
XOR X10, X6, X6
|
||||||
|
XOR X11, X7, X7
|
||||||
|
VSLDOI $4, D0, D0, D0
|
||||||
|
VSLDOI $4, D1, D1, D1
|
||||||
|
ROTLW $7, X4, X4
|
||||||
|
ROTLW $7, X5, X5
|
||||||
|
VSLDOI $4, D2, D2, D2
|
||||||
|
VADDUWM A0, B0, A0
|
||||||
|
ROTLW $7, X6, X6
|
||||||
|
ROTLW $7, X7, X7
|
||||||
|
VADDUWM A1, B1, A1
|
||||||
|
VADDUWM A2, B2, A2
|
||||||
|
ADD X5, X0, X0
|
||||||
|
ADD X6, X1, X1
|
||||||
|
VXOR D0, A0, D0
|
||||||
|
VXOR D1, A1, D1
|
||||||
|
ADD X7, X2, X2
|
||||||
|
ADD X4, X3, X3
|
||||||
|
VXOR D2, A2, D2
|
||||||
|
VPERM D0, D0, SIXTEEN, D0
|
||||||
|
XOR X0, X15, X15
|
||||||
|
XOR X1, X12, X12
|
||||||
|
VPERM D1, D1, SIXTEEN, D1
|
||||||
|
VPERM D2, D2, SIXTEEN, D2
|
||||||
|
XOR X2, X13, X13
|
||||||
|
XOR X3, X14, X14
|
||||||
|
VADDUWM C0, D0, C0
|
||||||
|
VADDUWM C1, D1, C1
|
||||||
|
ROTLW $16, X15, X15
|
||||||
|
ROTLW $16, X12, X12
|
||||||
|
VADDUWM C2, D2, C2
|
||||||
|
VXOR B0, C0, T0
|
||||||
|
ROTLW $16, X13, X13
|
||||||
|
ROTLW $16, X14, X14
|
||||||
|
VXOR B1, C1, T1
|
||||||
|
VXOR B2, C2, T2
|
||||||
|
ADD X15, X10, X10
|
||||||
|
ADD X12, X11, X11
|
||||||
|
VRLW T0, TWELVE, B0
|
||||||
|
VRLW T1, TWELVE, B1
|
||||||
|
ADD X13, X8, X8
|
||||||
|
ADD X14, X9, X9
|
||||||
|
VRLW T2, TWELVE, B2
|
||||||
|
VADDUWM A0, B0, A0
|
||||||
|
XOR X10, X5, X5
|
||||||
|
XOR X11, X6, X6
|
||||||
|
VADDUWM A1, B1, A1
|
||||||
|
VADDUWM A2, B2, A2
|
||||||
|
XOR X8, X7, X7
|
||||||
|
XOR X9, X4, X4
|
||||||
|
VXOR D0, A0, D0
|
||||||
|
VXOR D1, A1, D1
|
||||||
|
ROTLW $12, X5, X5
|
||||||
|
ROTLW $12, X6, X6
|
||||||
|
VXOR D2, A2, D2
|
||||||
|
VPERM D0, D0, TWENTY4, D0
|
||||||
|
ROTLW $12, X7, X7
|
||||||
|
ROTLW $12, X4, X4
|
||||||
|
VPERM D1, D1, TWENTY4, D1
|
||||||
|
VPERM D2, D2, TWENTY4, D2
|
||||||
|
ADD X5, X0, X0
|
||||||
|
ADD X6, X1, X1
|
||||||
|
VADDUWM C0, D0, C0
|
||||||
|
VADDUWM C1, D1, C1
|
||||||
|
ADD X7, X2, X2
|
||||||
|
ADD X4, X3, X3
|
||||||
|
VADDUWM C2, D2, C2
|
||||||
|
VXOR B0, C0, T0
|
||||||
|
XOR X0, X15, X15
|
||||||
|
XOR X1, X12, X12
|
||||||
|
VXOR B1, C1, T1
|
||||||
|
VXOR B2, C2, T2
|
||||||
|
XOR X2, X13, X13
|
||||||
|
XOR X3, X14, X14
|
||||||
|
VRLW T0, SEVEN, B0
|
||||||
|
VRLW T1, SEVEN, B1
|
||||||
|
ROTLW $8, X15, X15
|
||||||
|
ROTLW $8, X12, X12
|
||||||
|
VRLW T2, SEVEN, B2
|
||||||
|
VSLDOI $8, C0, C0, C0
|
||||||
|
ROTLW $8, X13, X13
|
||||||
|
ROTLW $8, X14, X14
|
||||||
|
VSLDOI $8, C1, C1, C1
|
||||||
|
VSLDOI $8, C2, C2, C2
|
||||||
|
ADD X15, X10, X10
|
||||||
|
ADD X12, X11, X11
|
||||||
|
VSLDOI $4, B0, B0, B0
|
||||||
|
VSLDOI $4, B1, B1, B1
|
||||||
|
ADD X13, X8, X8
|
||||||
|
ADD X14, X9, X9
|
||||||
|
VSLDOI $4, B2, B2, B2
|
||||||
|
VSLDOI $12, D0, D0, D0
|
||||||
|
XOR X10, X5, X5
|
||||||
|
XOR X11, X6, X6
|
||||||
|
VSLDOI $12, D1, D1, D1
|
||||||
|
VSLDOI $12, D2, D2, D2
|
||||||
|
XOR X8, X7, X7
|
||||||
|
XOR X9, X4, X4
|
||||||
|
ROTLW $7, X5, X5
|
||||||
|
ROTLW $7, X6, X6
|
||||||
|
ROTLW $7, X7, X7
|
||||||
|
ROTLW $7, X4, X4
|
||||||
|
BC 0x10, 0, loop_vmx
|
||||||
|
|
||||||
|
SUB $256, LEN, LEN
|
||||||
|
|
||||||
|
// Accumulate key block
|
||||||
|
ADD $0x61707865, X0, X0
|
||||||
|
ADD $0x3320646e, X1, X1
|
||||||
|
ADD $0x79622d32, X2, X2
|
||||||
|
ADD $0x6b206574, X3, X3
|
||||||
|
ADD TMP0, X4, X4
|
||||||
|
ADD TMP1, X5, X5
|
||||||
|
ADD TMP2, X6, X6
|
||||||
|
ADD TMP3, X7, X7
|
||||||
|
MOVWZ 16(KEY), TMP0
|
||||||
|
MOVWZ 20(KEY), TMP1
|
||||||
|
MOVWZ 24(KEY), TMP2
|
||||||
|
MOVWZ 28(KEY), TMP3
|
||||||
|
ADD TMP0, X8, X8
|
||||||
|
ADD TMP1, X9, X9
|
||||||
|
ADD TMP2, X10, X10
|
||||||
|
ADD TMP3, X11, X11
|
||||||
|
|
||||||
|
MOVWZ 12(CNT), TMP0
|
||||||
|
MOVWZ 8(CNT), TMP1
|
||||||
|
MOVWZ 4(CNT), TMP2
|
||||||
|
MOVWZ 0(CNT), TEMP
|
||||||
|
ADD TMP0, X15, X15
|
||||||
|
ADD TMP1, X14, X14
|
||||||
|
ADD TMP2, X13, X13
|
||||||
|
ADD TEMP, X12, X12
|
||||||
|
|
||||||
|
// Accumulate key block
|
||||||
|
VADDUWM A0, K0, A0
|
||||||
|
VADDUWM A1, K0, A1
|
||||||
|
VADDUWM A2, K0, A2
|
||||||
|
VADDUWM B0, K1, B0
|
||||||
|
VADDUWM B1, K1, B1
|
||||||
|
VADDUWM B2, K1, B2
|
||||||
|
VADDUWM C0, K2, C0
|
||||||
|
VADDUWM C1, K2, C1
|
||||||
|
VADDUWM C2, K2, C2
|
||||||
|
VADDUWM D0, K3, D0
|
||||||
|
VADDUWM D1, K4, D1
|
||||||
|
VADDUWM D2, K5, D2
|
||||||
|
|
||||||
|
// Increment counter
|
||||||
|
ADD $4, TEMP, TEMP
|
||||||
|
MOVW TEMP, 0(CNT)
|
||||||
|
|
||||||
|
VADDUWM K3, FOUR, K3
|
||||||
|
VADDUWM K4, FOUR, K4
|
||||||
|
VADDUWM K5, FOUR, K5
|
||||||
|
|
||||||
|
// XOR the input slice (INP) with the keystream, which is stored in GPRs (X0-X3).
|
||||||
|
|
||||||
|
// Load input (aligned or not)
|
||||||
|
MOVWZ 0(INP), TMP0
|
||||||
|
MOVWZ 4(INP), TMP1
|
||||||
|
MOVWZ 8(INP), TMP2
|
||||||
|
MOVWZ 12(INP), TMP3
|
||||||
|
|
||||||
|
// XOR with input
|
||||||
|
XOR TMP0, X0, X0
|
||||||
|
XOR TMP1, X1, X1
|
||||||
|
XOR TMP2, X2, X2
|
||||||
|
XOR TMP3, X3, X3
|
||||||
|
MOVWZ 16(INP), TMP0
|
||||||
|
MOVWZ 20(INP), TMP1
|
||||||
|
MOVWZ 24(INP), TMP2
|
||||||
|
MOVWZ 28(INP), TMP3
|
||||||
|
XOR TMP0, X4, X4
|
||||||
|
XOR TMP1, X5, X5
|
||||||
|
XOR TMP2, X6, X6
|
||||||
|
XOR TMP3, X7, X7
|
||||||
|
MOVWZ 32(INP), TMP0
|
||||||
|
MOVWZ 36(INP), TMP1
|
||||||
|
MOVWZ 40(INP), TMP2
|
||||||
|
MOVWZ 44(INP), TMP3
|
||||||
|
XOR TMP0, X8, X8
|
||||||
|
XOR TMP1, X9, X9
|
||||||
|
XOR TMP2, X10, X10
|
||||||
|
XOR TMP3, X11, X11
|
||||||
|
MOVWZ 48(INP), TMP0
|
||||||
|
MOVWZ 52(INP), TMP1
|
||||||
|
MOVWZ 56(INP), TMP2
|
||||||
|
MOVWZ 60(INP), TMP3
|
||||||
|
XOR TMP0, X12, X12
|
||||||
|
XOR TMP1, X13, X13
|
||||||
|
XOR TMP2, X14, X14
|
||||||
|
XOR TMP3, X15, X15
|
||||||
|
|
||||||
|
// Store output (aligned or not)
|
||||||
|
MOVW X0, 0(OUT)
|
||||||
|
MOVW X1, 4(OUT)
|
||||||
|
MOVW X2, 8(OUT)
|
||||||
|
MOVW X3, 12(OUT)
|
||||||
|
|
||||||
|
ADD $64, INP, INP // INP points to the end of the slice for the alignment code below
|
||||||
|
|
||||||
|
MOVW X4, 16(OUT)
|
||||||
|
MOVD $16, TMP0
|
||||||
|
MOVW X5, 20(OUT)
|
||||||
|
MOVD $32, TMP1
|
||||||
|
MOVW X6, 24(OUT)
|
||||||
|
MOVD $48, TMP2
|
||||||
|
MOVW X7, 28(OUT)
|
||||||
|
MOVD $64, TMP3
|
||||||
|
MOVW X8, 32(OUT)
|
||||||
|
MOVW X9, 36(OUT)
|
||||||
|
MOVW X10, 40(OUT)
|
||||||
|
MOVW X11, 44(OUT)
|
||||||
|
MOVW X12, 48(OUT)
|
||||||
|
MOVW X13, 52(OUT)
|
||||||
|
MOVW X14, 56(OUT)
|
||||||
|
MOVW X15, 60(OUT)
|
||||||
|
ADD $64, OUT, OUT
|
||||||
|
|
||||||
|
// Load input
|
||||||
|
LVX (INP)(R0), DD0
|
||||||
|
LVX (INP)(TMP0), DD1
|
||||||
|
LVX (INP)(TMP1), DD2
|
||||||
|
LVX (INP)(TMP2), DD3
|
||||||
|
LVX (INP)(TMP3), DD4
|
||||||
|
ADD $64, INP, INP
|
||||||
|
|
||||||
|
VPERM DD1, DD0, INPPERM, DD0 // Align input
|
||||||
|
VPERM DD2, DD1, INPPERM, DD1
|
||||||
|
VPERM DD3, DD2, INPPERM, DD2
|
||||||
|
VPERM DD4, DD3, INPPERM, DD3
|
||||||
|
VXOR A0, DD0, A0 // XOR with input
|
||||||
|
VXOR B0, DD1, B0
|
||||||
|
LVX (INP)(TMP0), DD1 // Keep loading input
|
||||||
|
VXOR C0, DD2, C0
|
||||||
|
LVX (INP)(TMP1), DD2
|
||||||
|
VXOR D0, DD3, D0
|
||||||
|
LVX (INP)(TMP2), DD3
|
||||||
|
LVX (INP)(TMP3), DD0
|
||||||
|
ADD $64, INP, INP
|
||||||
|
MOVD $63, TMP3 // 63 is not a typo
|
||||||
|
VPERM A0, A0, OUTPERM, A0
|
||||||
|
VPERM B0, B0, OUTPERM, B0
|
||||||
|
VPERM C0, C0, OUTPERM, C0
|
||||||
|
VPERM D0, D0, OUTPERM, D0
|
||||||
|
|
||||||
|
VPERM DD1, DD4, INPPERM, DD4 // Align input
|
||||||
|
VPERM DD2, DD1, INPPERM, DD1
|
||||||
|
VPERM DD3, DD2, INPPERM, DD2
|
||||||
|
VPERM DD0, DD3, INPPERM, DD3
|
||||||
|
VXOR A1, DD4, A1
|
||||||
|
VXOR B1, DD1, B1
|
||||||
|
LVX (INP)(TMP0), DD1 // Keep loading
|
||||||
|
VXOR C1, DD2, C1
|
||||||
|
LVX (INP)(TMP1), DD2
|
||||||
|
VXOR D1, DD3, D1
|
||||||
|
LVX (INP)(TMP2), DD3
|
||||||
|
|
||||||
|
// Note that the LVX address is always rounded down to the nearest 16-byte
|
||||||
|
// boundary, and that it always points to at most 15 bytes beyond the end of
|
||||||
|
// the slice, so we cannot cross a page boundary.
|
||||||
|
LVX (INP)(TMP3), DD4 // Redundant in aligned case.
|
||||||
|
ADD $64, INP, INP
|
||||||
|
VPERM A1, A1, OUTPERM, A1 // Pre-misalign output
|
||||||
|
VPERM B1, B1, OUTPERM, B1
|
||||||
|
VPERM C1, C1, OUTPERM, C1
|
||||||
|
VPERM D1, D1, OUTPERM, D1
|
||||||
|
|
||||||
|
VPERM DD1, DD0, INPPERM, DD0 // Align Input
|
||||||
|
VPERM DD2, DD1, INPPERM, DD1
|
||||||
|
VPERM DD3, DD2, INPPERM, DD2
|
||||||
|
VPERM DD4, DD3, INPPERM, DD3
|
||||||
|
VXOR A2, DD0, A2
|
||||||
|
VXOR B2, DD1, B2
|
||||||
|
VXOR C2, DD2, C2
|
||||||
|
VXOR D2, DD3, D2
|
||||||
|
VPERM A2, A2, OUTPERM, A2
|
||||||
|
VPERM B2, B2, OUTPERM, B2
|
||||||
|
VPERM C2, C2, OUTPERM, C2
|
||||||
|
VPERM D2, D2, OUTPERM, D2
|
||||||
|
|
||||||
|
ANDCC $15, OUT, X1 // Is out aligned?
|
||||||
|
MOVD OUT, X0
|
||||||
|
|
||||||
|
VSEL A0, B0, OUTMASK, DD0 // Collect pre-misaligned output
|
||||||
|
VSEL B0, C0, OUTMASK, DD1
|
||||||
|
VSEL C0, D0, OUTMASK, DD2
|
||||||
|
VSEL D0, A1, OUTMASK, DD3
|
||||||
|
VSEL A1, B1, OUTMASK, B0
|
||||||
|
VSEL B1, C1, OUTMASK, C0
|
||||||
|
VSEL C1, D1, OUTMASK, D0
|
||||||
|
VSEL D1, A2, OUTMASK, A1
|
||||||
|
VSEL A2, B2, OUTMASK, B1
|
||||||
|
VSEL B2, C2, OUTMASK, C1
|
||||||
|
VSEL C2, D2, OUTMASK, D1
|
||||||
|
|
||||||
|
STVX DD0, (OUT+TMP0)
|
||||||
|
STVX DD1, (OUT+TMP1)
|
||||||
|
STVX DD2, (OUT+TMP2)
|
||||||
|
ADD $64, OUT, OUT
|
||||||
|
STVX DD3, (OUT+R0)
|
||||||
|
STVX B0, (OUT+TMP0)
|
||||||
|
STVX C0, (OUT+TMP1)
|
||||||
|
STVX D0, (OUT+TMP2)
|
||||||
|
ADD $64, OUT, OUT
|
||||||
|
STVX A1, (OUT+R0)
|
||||||
|
STVX B1, (OUT+TMP0)
|
||||||
|
STVX C1, (OUT+TMP1)
|
||||||
|
STVX D1, (OUT+TMP2)
|
||||||
|
ADD $64, OUT, OUT
|
||||||
|
|
||||||
|
BEQ aligned_vmx
|
||||||
|
|
||||||
|
SUB X1, OUT, X2 // in misaligned case edges
|
||||||
|
MOVD $0, X3 // are written byte-by-byte
|
||||||
|
|
||||||
|
unaligned_tail_vmx:
|
||||||
|
STVEBX D2, (X2+X3)
|
||||||
|
ADD $1, X3, X3
|
||||||
|
CMPW X3, X1
|
||||||
|
BNE unaligned_tail_vmx
|
||||||
|
SUB X1, X0, X2
|
||||||
|
|
||||||
|
unaligned_head_vmx:
|
||||||
|
STVEBX A0, (X2+X1)
|
||||||
|
CMPW X1, $15
|
||||||
|
ADD $1, X1, X1
|
||||||
|
BNE unaligned_head_vmx
|
||||||
|
|
||||||
|
CMPU LEN, $255 // done with 256-byte block yet?
|
||||||
|
BGT loop_outer_vmx
|
||||||
|
|
||||||
|
JMP done_vmx
|
||||||
|
|
||||||
|
aligned_vmx:
|
||||||
|
STVX A0, (X0+R0)
|
||||||
|
CMPU LEN, $255 // done with 256-byte block yet?
|
||||||
|
BGT loop_outer_vmx
|
||||||
|
|
||||||
|
done_vmx:
|
||||||
|
RET
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !arm64,!s390x arm64,!go1.11 gccgo appengine
|
// +build !ppc64le,!arm64,!s390x arm64,!go1.11 gccgo appengine
|
||||||
|
|
||||||
package chacha20
|
package chacha20
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ppc64le,!gccgo,!appengine
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
import "encoding/binary"
|
||||||
|
|
||||||
|
const (
|
||||||
|
bufSize = 256
|
||||||
|
haveAsm = true
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||||
|
|
||||||
|
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
|
||||||
|
if len(src) >= bufSize {
|
||||||
|
chaCha20_ctr32_vmx(&dst[0], &src[0], len(src)-len(src)%bufSize, &c.key, &c.counter)
|
||||||
|
}
|
||||||
|
if len(src)%bufSize != 0 {
|
||||||
|
chaCha20_ctr32_vmx(&c.buf[0], &c.buf[0], bufSize, &c.key, &c.counter)
|
||||||
|
start := len(src) - len(src)%bufSize
|
||||||
|
ts, td, tb := src[start:], dst[start:], c.buf[:]
|
||||||
|
// Unroll loop to XOR 32 bytes per iteration.
|
||||||
|
for i := 0; i < len(ts)-32; i += 32 {
|
||||||
|
td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination
|
||||||
|
s0 := binary.LittleEndian.Uint64(ts[0:8])
|
||||||
|
s1 := binary.LittleEndian.Uint64(ts[8:16])
|
||||||
|
s2 := binary.LittleEndian.Uint64(ts[16:24])
|
||||||
|
s3 := binary.LittleEndian.Uint64(ts[24:32])
|
||||||
|
b0 := binary.LittleEndian.Uint64(tb[0:8])
|
||||||
|
b1 := binary.LittleEndian.Uint64(tb[8:16])
|
||||||
|
b2 := binary.LittleEndian.Uint64(tb[16:24])
|
||||||
|
b3 := binary.LittleEndian.Uint64(tb[24:32])
|
||||||
|
binary.LittleEndian.PutUint64(td[0:8], s0^b0)
|
||||||
|
binary.LittleEndian.PutUint64(td[8:16], s1^b1)
|
||||||
|
binary.LittleEndian.PutUint64(td[16:24], s2^b2)
|
||||||
|
binary.LittleEndian.PutUint64(td[24:32], s3^b3)
|
||||||
|
ts, td, tb = ts[32:], td[32:], tb[32:]
|
||||||
|
}
|
||||||
|
td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination
|
||||||
|
for i, v := range ts {
|
||||||
|
td[i] = tb[i] ^ v
|
||||||
|
}
|
||||||
|
c.len = bufSize - (len(src) % bufSize)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !amd64 gccgo appengine
|
// +build !amd64,!ppc64le gccgo appengine
|
||||||
|
|
||||||
package poly1305
|
package poly1305
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl
|
// +build s390x,!go1.11 !arm,!amd64,!s390x,!ppc64le gccgo appengine nacl
|
||||||
|
|
||||||
package poly1305
|
package poly1305
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ppc64le,!gccgo,!appengine
|
||||||
|
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func initialize(state *[7]uint64, key *[32]byte)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func update(state *[7]uint64, msg []byte)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func finalize(tag *[TagSize]byte, state *[7]uint64)
|
||||||
|
|
||||||
|
// Sum generates an authenticator for m using a one-time key and puts the
|
||||||
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
|
// key allows an attacker to forge messages at will.
|
||||||
|
func Sum(out *[16]byte, m []byte, key *[32]byte) {
|
||||||
|
h := newMAC(key)
|
||||||
|
h.Write(m)
|
||||||
|
h.Sum(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMAC(key *[32]byte) (h mac) {
|
||||||
|
initialize(&h.state, key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type mac struct {
|
||||||
|
state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 }
|
||||||
|
|
||||||
|
buffer [TagSize]byte
|
||||||
|
offset int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *mac) Write(p []byte) (n int, err error) {
|
||||||
|
n = len(p)
|
||||||
|
if h.offset > 0 {
|
||||||
|
remaining := TagSize - h.offset
|
||||||
|
if n < remaining {
|
||||||
|
h.offset += copy(h.buffer[h.offset:], p)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
copy(h.buffer[h.offset:], p[:remaining])
|
||||||
|
p = p[remaining:]
|
||||||
|
h.offset = 0
|
||||||
|
update(&h.state, h.buffer[:])
|
||||||
|
}
|
||||||
|
if nn := len(p) - (len(p) % TagSize); nn > 0 {
|
||||||
|
update(&h.state, p[:nn])
|
||||||
|
p = p[nn:]
|
||||||
|
}
|
||||||
|
if len(p) > 0 {
|
||||||
|
h.offset += copy(h.buffer[h.offset:], p)
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *mac) Sum(out *[16]byte) {
|
||||||
|
state := h.state
|
||||||
|
if h.offset > 0 {
|
||||||
|
update(&state, h.buffer[:h.offset])
|
||||||
|
}
|
||||||
|
finalize(out, &state)
|
||||||
|
}
|
|
@ -0,0 +1,247 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ppc64le,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// This was ported from the amd64 implementation.
|
||||||
|
|
||||||
|
#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \
|
||||||
|
MOVD (msg), t0; \
|
||||||
|
MOVD 8(msg), t1; \
|
||||||
|
MOVD $1, t2; \
|
||||||
|
ADDC t0, h0, h0; \
|
||||||
|
ADDE t1, h1, h1; \
|
||||||
|
ADDE t2, h2; \
|
||||||
|
ADD $16, msg
|
||||||
|
|
||||||
|
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
|
||||||
|
MULLD r0, h0, t0; \
|
||||||
|
MULLD r0, h1, t4; \
|
||||||
|
MULHDU r0, h0, t1; \
|
||||||
|
MULHDU r0, h1, t5; \
|
||||||
|
ADDC t4, t1, t1; \
|
||||||
|
MULLD r0, h2, t2; \
|
||||||
|
ADDZE t5; \
|
||||||
|
MULHDU r1, h0, t4; \
|
||||||
|
MULLD r1, h0, h0; \
|
||||||
|
ADD t5, t2, t2; \
|
||||||
|
ADDC h0, t1, t1; \
|
||||||
|
MULLD h2, r1, t3; \
|
||||||
|
ADDZE t4, h0; \
|
||||||
|
MULHDU r1, h1, t5; \
|
||||||
|
MULLD r1, h1, t4; \
|
||||||
|
ADDC t4, t2, t2; \
|
||||||
|
ADDE t5, t3, t3; \
|
||||||
|
ADDC h0, t2, t2; \
|
||||||
|
MOVD $-4, t4; \
|
||||||
|
MOVD t0, h0; \
|
||||||
|
MOVD t1, h1; \
|
||||||
|
ADDZE t3; \
|
||||||
|
ANDCC $3, t2, h2; \
|
||||||
|
AND t2, t4, t0; \
|
||||||
|
ADDC t0, h0, h0; \
|
||||||
|
ADDE t3, h1, h1; \
|
||||||
|
SLD $62, t3, t4; \
|
||||||
|
SRD $2, t2; \
|
||||||
|
ADDZE h2; \
|
||||||
|
OR t4, t2, t2; \
|
||||||
|
SRD $2, t3; \
|
||||||
|
ADDC t2, h0, h0; \
|
||||||
|
ADDE t3, h1, h1; \
|
||||||
|
ADDZE h2
|
||||||
|
|
||||||
|
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||||
|
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||||
|
GLOBL ·poly1305Mask<>(SB), RODATA, $16
|
||||||
|
|
||||||
|
// func update(state *[7]uint64, msg []byte)
|
||||||
|
|
||||||
|
TEXT ·update(SB), $0-32
|
||||||
|
MOVD state+0(FP), R3
|
||||||
|
MOVD msg_base+8(FP), R4
|
||||||
|
MOVD msg_len+16(FP), R5
|
||||||
|
|
||||||
|
MOVD 0(R3), R8 // h0
|
||||||
|
MOVD 8(R3), R9 // h1
|
||||||
|
MOVD 16(R3), R10 // h2
|
||||||
|
MOVD 24(R3), R11 // r0
|
||||||
|
MOVD 32(R3), R12 // r1
|
||||||
|
|
||||||
|
CMP R5, $16
|
||||||
|
BLT bytes_between_0_and_15
|
||||||
|
|
||||||
|
loop:
|
||||||
|
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
|
||||||
|
|
||||||
|
multiply:
|
||||||
|
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
|
||||||
|
ADD $-16, R5
|
||||||
|
CMP R5, $16
|
||||||
|
BGE loop
|
||||||
|
|
||||||
|
bytes_between_0_and_15:
|
||||||
|
CMP $0, R5
|
||||||
|
BEQ done
|
||||||
|
MOVD $0, R16 // h0
|
||||||
|
MOVD $0, R17 // h1
|
||||||
|
|
||||||
|
flush_buffer:
|
||||||
|
CMP R5, $8
|
||||||
|
BLE just1
|
||||||
|
|
||||||
|
MOVD $8, R21
|
||||||
|
SUB R21, R5, R21
|
||||||
|
|
||||||
|
// Greater than 8 -- load the rightmost remaining bytes in msg
|
||||||
|
// and put into R17 (h1)
|
||||||
|
MOVD (R4)(R21), R17
|
||||||
|
MOVD $16, R22
|
||||||
|
|
||||||
|
// Find the offset to those bytes
|
||||||
|
SUB R5, R22, R22
|
||||||
|
SLD $3, R22
|
||||||
|
|
||||||
|
// Shift to get only the bytes in msg
|
||||||
|
SRD R22, R17, R17
|
||||||
|
|
||||||
|
// Put 1 at high end
|
||||||
|
MOVD $1, R23
|
||||||
|
SLD $3, R21
|
||||||
|
SLD R21, R23, R23
|
||||||
|
OR R23, R17, R17
|
||||||
|
|
||||||
|
// Remainder is 8
|
||||||
|
MOVD $8, R5
|
||||||
|
|
||||||
|
just1:
|
||||||
|
CMP R5, $8
|
||||||
|
BLT less8
|
||||||
|
|
||||||
|
// Exactly 8
|
||||||
|
MOVD (R4), R16
|
||||||
|
|
||||||
|
CMP $0, R17
|
||||||
|
|
||||||
|
// Check if we've already set R17; if not
|
||||||
|
// set 1 to indicate end of msg.
|
||||||
|
BNE carry
|
||||||
|
MOVD $1, R17
|
||||||
|
BR carry
|
||||||
|
|
||||||
|
less8:
|
||||||
|
MOVD $0, R16 // h0
|
||||||
|
MOVD $0, R22 // shift count
|
||||||
|
CMP R5, $4
|
||||||
|
BLT less4
|
||||||
|
MOVWZ (R4), R16
|
||||||
|
ADD $4, R4
|
||||||
|
ADD $-4, R5
|
||||||
|
MOVD $32, R22
|
||||||
|
|
||||||
|
less4:
|
||||||
|
CMP R5, $2
|
||||||
|
BLT less2
|
||||||
|
MOVHZ (R4), R21
|
||||||
|
SLD R22, R21, R21
|
||||||
|
OR R16, R21, R16
|
||||||
|
ADD $16, R22
|
||||||
|
ADD $-2, R5
|
||||||
|
ADD $2, R4
|
||||||
|
|
||||||
|
less2:
|
||||||
|
CMP $0, R5
|
||||||
|
BEQ insert1
|
||||||
|
MOVBZ (R4), R21
|
||||||
|
SLD R22, R21, R21
|
||||||
|
OR R16, R21, R16
|
||||||
|
ADD $8, R22
|
||||||
|
|
||||||
|
insert1:
|
||||||
|
// Insert 1 at end of msg
|
||||||
|
MOVD $1, R21
|
||||||
|
SLD R22, R21, R21
|
||||||
|
OR R16, R21, R16
|
||||||
|
|
||||||
|
carry:
|
||||||
|
// Add new values to h0, h1, h2
|
||||||
|
ADDC R16, R8
|
||||||
|
ADDE R17, R9
|
||||||
|
ADDE $0, R10
|
||||||
|
MOVD $16, R5
|
||||||
|
ADD R5, R4
|
||||||
|
BR multiply
|
||||||
|
|
||||||
|
done:
|
||||||
|
// Save h0, h1, h2 in state
|
||||||
|
MOVD R8, 0(R3)
|
||||||
|
MOVD R9, 8(R3)
|
||||||
|
MOVD R10, 16(R3)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func initialize(state *[7]uint64, key *[32]byte)
|
||||||
|
TEXT ·initialize(SB), $0-16
|
||||||
|
MOVD state+0(FP), R3
|
||||||
|
MOVD key+8(FP), R4
|
||||||
|
|
||||||
|
// state[0...7] is initialized with zero
|
||||||
|
// Load key
|
||||||
|
MOVD 0(R4), R5
|
||||||
|
MOVD 8(R4), R6
|
||||||
|
MOVD 16(R4), R7
|
||||||
|
MOVD 24(R4), R8
|
||||||
|
|
||||||
|
// Address of key mask
|
||||||
|
MOVD $·poly1305Mask<>(SB), R9
|
||||||
|
|
||||||
|
// Save original key in state
|
||||||
|
MOVD R7, 40(R3)
|
||||||
|
MOVD R8, 48(R3)
|
||||||
|
|
||||||
|
// Get mask
|
||||||
|
MOVD (R9), R7
|
||||||
|
MOVD 8(R9), R8
|
||||||
|
|
||||||
|
// And with key
|
||||||
|
AND R5, R7, R5
|
||||||
|
AND R6, R8, R6
|
||||||
|
|
||||||
|
// Save masked key in state
|
||||||
|
MOVD R5, 24(R3)
|
||||||
|
MOVD R6, 32(R3)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func finalize(tag *[TagSize]byte, state *[7]uint64)
|
||||||
|
TEXT ·finalize(SB), $0-16
|
||||||
|
MOVD tag+0(FP), R3
|
||||||
|
MOVD state+8(FP), R4
|
||||||
|
|
||||||
|
// Get h0, h1, h2 from state
|
||||||
|
MOVD 0(R4), R5
|
||||||
|
MOVD 8(R4), R6
|
||||||
|
MOVD 16(R4), R7
|
||||||
|
|
||||||
|
// Save h0, h1
|
||||||
|
MOVD R5, R8
|
||||||
|
MOVD R6, R9
|
||||||
|
MOVD $3, R20
|
||||||
|
MOVD $-1, R21
|
||||||
|
SUBC $-5, R5
|
||||||
|
SUBE R21, R6
|
||||||
|
SUBE R20, R7
|
||||||
|
MOVD $0, R21
|
||||||
|
SUBZE R21
|
||||||
|
|
||||||
|
// Check for carry
|
||||||
|
CMP $0, R21
|
||||||
|
ISEL $2, R5, R8, R5
|
||||||
|
ISEL $2, R6, R9, R6
|
||||||
|
MOVD 40(R4), R8
|
||||||
|
MOVD 48(R4), R9
|
||||||
|
ADDC R8, R5
|
||||||
|
ADDE R9, R6
|
||||||
|
MOVD R5, 0(R3)
|
||||||
|
MOVD R6, 8(R3)
|
||||||
|
RET
|
|
@ -51,6 +51,13 @@ var supportedKexAlgos = []string{
|
||||||
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
|
||||||
|
// for the server half.
|
||||||
|
var serverForbiddenKexAlgos = map[string]struct{}{
|
||||||
|
kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests
|
||||||
|
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
|
||||||
|
}
|
||||||
|
|
||||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||||
// of authenticating servers) in preference order.
|
// of authenticating servers) in preference order.
|
||||||
var supportedHostKeyAlgos = []string{
|
var supportedHostKeyAlgos = []string{
|
||||||
|
|
|
@ -10,7 +10,9 @@ import (
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
@ -24,6 +26,12 @@ const (
|
||||||
kexAlgoECDH384 = "ecdh-sha2-nistp384"
|
kexAlgoECDH384 = "ecdh-sha2-nistp384"
|
||||||
kexAlgoECDH521 = "ecdh-sha2-nistp521"
|
kexAlgoECDH521 = "ecdh-sha2-nistp521"
|
||||||
kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
|
kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
|
||||||
|
|
||||||
|
// For the following kex only the client half contains a production
|
||||||
|
// ready implementation. The server half only consists of a minimal
|
||||||
|
// implementation to satisfy the automated tests.
|
||||||
|
kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
|
||||||
|
kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
|
||||||
)
|
)
|
||||||
|
|
||||||
// kexResult captures the outcome of a key exchange.
|
// kexResult captures the outcome of a key exchange.
|
||||||
|
@ -402,6 +410,8 @@ func init() {
|
||||||
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
|
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
|
||||||
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
|
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
|
||||||
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
|
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
|
||||||
|
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
|
||||||
|
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
|
||||||
}
|
}
|
||||||
|
|
||||||
// curve25519sha256 implements the curve25519-sha256@libssh.org key
|
// curve25519sha256 implements the curve25519-sha256@libssh.org key
|
||||||
|
@ -538,3 +548,242 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
|
||||||
Hash: crypto.SHA256,
|
Hash: crypto.SHA256,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and
|
||||||
|
// diffie-hellman-group-exchange-sha256 key agreement protocols,
|
||||||
|
// as described in RFC 4419
|
||||||
|
type dhGEXSHA struct {
|
||||||
|
g, p *big.Int
|
||||||
|
hashFunc crypto.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
const numMRTests = 64
|
||||||
|
|
||||||
|
const (
|
||||||
|
dhGroupExchangeMinimumBits = 2048
|
||||||
|
dhGroupExchangePreferredBits = 2048
|
||||||
|
dhGroupExchangeMaximumBits = 8192
|
||||||
|
)
|
||||||
|
|
||||||
|
func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
|
||||||
|
if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 {
|
||||||
|
return nil, fmt.Errorf("ssh: DH parameter out of bounds")
|
||||||
|
}
|
||||||
|
return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||||
|
// Send GexRequest
|
||||||
|
kexDHGexRequest := kexDHGexRequestMsg{
|
||||||
|
MinBits: dhGroupExchangeMinimumBits,
|
||||||
|
PreferedBits: dhGroupExchangePreferredBits,
|
||||||
|
MaxBits: dhGroupExchangeMaximumBits,
|
||||||
|
}
|
||||||
|
if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive GexGroup
|
||||||
|
packet, err := c.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var kexDHGexGroup kexDHGexGroupMsg
|
||||||
|
if err = Unmarshal(packet, &kexDHGexGroup); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
|
||||||
|
if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits {
|
||||||
|
return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen())
|
||||||
|
}
|
||||||
|
|
||||||
|
gex.p = kexDHGexGroup.P
|
||||||
|
gex.g = kexDHGexGroup.G
|
||||||
|
|
||||||
|
// Check if p is safe by verifing that p and (p-1)/2 are primes
|
||||||
|
one := big.NewInt(1)
|
||||||
|
var pHalf = &big.Int{}
|
||||||
|
pHalf.Rsh(gex.p, 1)
|
||||||
|
if !gex.p.ProbablyPrime(numMRTests) || !pHalf.ProbablyPrime(numMRTests) {
|
||||||
|
return nil, fmt.Errorf("ssh: server provided gex p is not safe")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if g is safe by verifing that g > 1 and g < p - 1
|
||||||
|
var pMinusOne = &big.Int{}
|
||||||
|
pMinusOne.Sub(gex.p, one)
|
||||||
|
if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
|
||||||
|
return nil, fmt.Errorf("ssh: server provided gex g is not safe")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send GexInit
|
||||||
|
x, err := rand.Int(randSource, pHalf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
X := new(big.Int).Exp(gex.g, x, gex.p)
|
||||||
|
kexDHGexInit := kexDHGexInitMsg{
|
||||||
|
X: X,
|
||||||
|
}
|
||||||
|
if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive GexReply
|
||||||
|
packet, err = c.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var kexDHGexReply kexDHGexReplyMsg
|
||||||
|
if err = Unmarshal(packet, &kexDHGexReply); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
kInt, err := gex.diffieHellman(kexDHGexReply.Y, x)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if k is safe by verifing that k > 1 and k < p - 1
|
||||||
|
if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 {
|
||||||
|
return nil, fmt.Errorf("ssh: derived k is not safe")
|
||||||
|
}
|
||||||
|
|
||||||
|
h := gex.hashFunc.New()
|
||||||
|
magics.write(h)
|
||||||
|
writeString(h, kexDHGexReply.HostKey)
|
||||||
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
||||||
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
||||||
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
||||||
|
writeInt(h, gex.p)
|
||||||
|
writeInt(h, gex.g)
|
||||||
|
writeInt(h, X)
|
||||||
|
writeInt(h, kexDHGexReply.Y)
|
||||||
|
K := make([]byte, intLength(kInt))
|
||||||
|
marshalInt(K, kInt)
|
||||||
|
h.Write(K)
|
||||||
|
|
||||||
|
return &kexResult{
|
||||||
|
H: h.Sum(nil),
|
||||||
|
K: K,
|
||||||
|
HostKey: kexDHGexReply.HostKey,
|
||||||
|
Signature: kexDHGexReply.Signature,
|
||||||
|
Hash: gex.hashFunc,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
|
||||||
|
//
|
||||||
|
// This is a minimal implementation to satisfy the automated tests.
|
||||||
|
func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
|
||||||
|
// Receive GexRequest
|
||||||
|
packet, err := c.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var kexDHGexRequest kexDHGexRequestMsg
|
||||||
|
if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// smoosh the user's preferred size into our own limits
|
||||||
|
if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits {
|
||||||
|
kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits
|
||||||
|
}
|
||||||
|
if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits {
|
||||||
|
kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits
|
||||||
|
}
|
||||||
|
// fix min/max if they're inconsistent. technically, we could just pout
|
||||||
|
// and hang up, but there's no harm in giving them the benefit of the
|
||||||
|
// doubt and just picking a bitsize for them.
|
||||||
|
if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits {
|
||||||
|
kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits
|
||||||
|
}
|
||||||
|
if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits {
|
||||||
|
kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send GexGroup
|
||||||
|
// This is the group called diffie-hellman-group14-sha1 in RFC
|
||||||
|
// 4253 and Oakley Group 14 in RFC 3526.
|
||||||
|
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
||||||
|
gex.p = p
|
||||||
|
gex.g = big.NewInt(2)
|
||||||
|
|
||||||
|
kexDHGexGroup := kexDHGexGroupMsg{
|
||||||
|
P: gex.p,
|
||||||
|
G: gex.g,
|
||||||
|
}
|
||||||
|
if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive GexInit
|
||||||
|
packet, err = c.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var kexDHGexInit kexDHGexInitMsg
|
||||||
|
if err = Unmarshal(packet, &kexDHGexInit); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var pHalf = &big.Int{}
|
||||||
|
pHalf.Rsh(gex.p, 1)
|
||||||
|
|
||||||
|
y, err := rand.Int(randSource, pHalf)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Y := new(big.Int).Exp(gex.g, y, gex.p)
|
||||||
|
kInt, err := gex.diffieHellman(kexDHGexInit.X, y)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hostKeyBytes := priv.PublicKey().Marshal()
|
||||||
|
|
||||||
|
h := gex.hashFunc.New()
|
||||||
|
magics.write(h)
|
||||||
|
writeString(h, hostKeyBytes)
|
||||||
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
||||||
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
||||||
|
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
||||||
|
writeInt(h, gex.p)
|
||||||
|
writeInt(h, gex.g)
|
||||||
|
writeInt(h, kexDHGexInit.X)
|
||||||
|
writeInt(h, Y)
|
||||||
|
|
||||||
|
K := make([]byte, intLength(kInt))
|
||||||
|
marshalInt(K, kInt)
|
||||||
|
h.Write(K)
|
||||||
|
|
||||||
|
H := h.Sum(nil)
|
||||||
|
|
||||||
|
// H is already a hash, but the hostkey signing will apply its
|
||||||
|
// own key-specific hash algorithm.
|
||||||
|
sig, err := signAndMarshal(priv, randSource, H)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
kexDHGexReply := kexDHGexReplyMsg{
|
||||||
|
HostKey: hostKeyBytes,
|
||||||
|
Y: Y,
|
||||||
|
Signature: sig,
|
||||||
|
}
|
||||||
|
packet = Marshal(&kexDHGexReply)
|
||||||
|
|
||||||
|
err = c.writePacket(packet)
|
||||||
|
|
||||||
|
return &kexResult{
|
||||||
|
H: H,
|
||||||
|
K: K,
|
||||||
|
HostKey: hostKeyBytes,
|
||||||
|
Signature: sig,
|
||||||
|
Hash: gex.hashFunc,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
|
@ -97,6 +97,36 @@ type kexDHReplyMsg struct {
|
||||||
Signature []byte
|
Signature []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See RFC 4419, section 5.
|
||||||
|
const msgKexDHGexGroup = 31
|
||||||
|
|
||||||
|
type kexDHGexGroupMsg struct {
|
||||||
|
P *big.Int `sshtype:"31"`
|
||||||
|
G *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgKexDHGexInit = 32
|
||||||
|
|
||||||
|
type kexDHGexInitMsg struct {
|
||||||
|
X *big.Int `sshtype:"32"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgKexDHGexReply = 33
|
||||||
|
|
||||||
|
type kexDHGexReplyMsg struct {
|
||||||
|
HostKey []byte `sshtype:"33"`
|
||||||
|
Y *big.Int
|
||||||
|
Signature []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgKexDHGexRequest = 34
|
||||||
|
|
||||||
|
type kexDHGexRequestMsg struct {
|
||||||
|
MinBits uint32 `sshtype:"34"`
|
||||||
|
PreferedBits uint32
|
||||||
|
MaxBits uint32
|
||||||
|
}
|
||||||
|
|
||||||
// See RFC 4253, section 10.
|
// See RFC 4253, section 10.
|
||||||
const msgServiceRequest = 5
|
const msgServiceRequest = 5
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,12 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
||||||
if fullConf.MaxAuthTries == 0 {
|
if fullConf.MaxAuthTries == 0 {
|
||||||
fullConf.MaxAuthTries = 6
|
fullConf.MaxAuthTries = 6
|
||||||
}
|
}
|
||||||
|
// Check if the config contains any unsupported key exchanges
|
||||||
|
for _, kex := range fullConf.KeyExchanges {
|
||||||
|
if _, ok := serverForbiddenKexAlgos[kex]; ok {
|
||||||
|
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s := &connection{
|
s := &connection{
|
||||||
sshConn: sshConn{conn: c},
|
sshConn: sshConn{conn: c},
|
||||||
|
|
|
@ -469,9 +469,9 @@ github.com/kr/text
|
||||||
github.com/lib/pq
|
github.com/lib/pq
|
||||||
github.com/lib/pq/oid
|
github.com/lib/pq/oid
|
||||||
github.com/lib/pq/scram
|
github.com/lib/pq/scram
|
||||||
# github.com/mattn/go-colorable v0.0.9
|
# github.com/mattn/go-colorable v0.1.2
|
||||||
github.com/mattn/go-colorable
|
github.com/mattn/go-colorable
|
||||||
# github.com/mattn/go-isatty v0.0.4
|
# github.com/mattn/go-isatty v0.0.8
|
||||||
github.com/mattn/go-isatty
|
github.com/mattn/go-isatty
|
||||||
# github.com/matttproud/golang_protobuf_extensions v1.0.1
|
# github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
github.com/matttproud/golang_protobuf_extensions/pbutil
|
github.com/matttproud/golang_protobuf_extensions/pbutil
|
||||||
|
@ -489,7 +489,7 @@ github.com/mitchellh/go-testing-interface
|
||||||
github.com/mitchellh/mapstructure
|
github.com/mitchellh/mapstructure
|
||||||
# github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8
|
# github.com/mitchellh/pointerstructure v0.0.0-20190430161007-f252a8fd71c8
|
||||||
github.com/mitchellh/pointerstructure
|
github.com/mitchellh/pointerstructure
|
||||||
# github.com/mitchellh/reflectwalk v1.0.0
|
# github.com/mitchellh/reflectwalk v1.0.1
|
||||||
github.com/mitchellh/reflectwalk
|
github.com/mitchellh/reflectwalk
|
||||||
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
|
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
|
||||||
github.com/modern-go/concurrent
|
github.com/modern-go/concurrent
|
||||||
|
@ -637,7 +637,7 @@ go.uber.org/zap/internal/bufferpool
|
||||||
go.uber.org/zap/buffer
|
go.uber.org/zap/buffer
|
||||||
go.uber.org/zap/internal/color
|
go.uber.org/zap/internal/color
|
||||||
go.uber.org/zap/internal/exit
|
go.uber.org/zap/internal/exit
|
||||||
# golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f
|
# golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||||
golang.org/x/crypto/bcrypt
|
golang.org/x/crypto/bcrypt
|
||||||
golang.org/x/crypto/ed25519
|
golang.org/x/crypto/ed25519
|
||||||
golang.org/x/crypto/ssh
|
golang.org/x/crypto/ssh
|
||||||
|
|
Loading…
Reference in New Issue