mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-03-04 02:14:40 +01:00
Add ODoH support. (#1653)
This commit is contained in:
parent
f7219b2bfa
commit
c748f93752
32 changed files with 5847 additions and 18 deletions
|
@ -146,3 +146,25 @@ t || dig -p${DNS_PORT} A MICROSOFT.COM @127.0.0.1 | grep -Fq "NOERROR" || fail
|
|||
|
||||
kill $(cat /tmp/dnscrypt-proxy.pidfile)
|
||||
sleep 5
|
||||
|
||||
section
|
||||
../dnscrypt-proxy/dnscrypt-proxy -loglevel 3 -config test-odoh-direct.toml -pidfile /tmp/odoh-direct.pidfile &
|
||||
sleep 5
|
||||
|
||||
section
|
||||
t || dig -p${DNS_PORT} A microsoft.com @127.0.0.1 | grep -Fq "NOERROR" || fail
|
||||
t || dig -p${DNS_PORT} A cloudflare.com @127.0.0.1 | grep -Fq "NOERROR" || fail
|
||||
|
||||
kill $(cat /tmp/odoh-direct.pidfile)
|
||||
sleep 5
|
||||
|
||||
section
|
||||
../dnscrypt-proxy/dnscrypt-proxy -loglevel 3 -config test-odoh-proxied.toml -pidfile /tmp/odoh-proxied.pidfile &
|
||||
sleep 5
|
||||
|
||||
section
|
||||
t || dig -p${DNS_PORT} A microsoft.com @127.0.0.1 | grep -Fq "NOERROR" || fail
|
||||
t || dig -p${DNS_PORT} A cloudflare.com @127.0.0.1 | grep -Fq "NOERROR" || fail
|
||||
|
||||
kill $(cat /tmp/odoh-proxied.pidfile)
|
||||
sleep 5
|
||||
|
|
1
.github/workflows/releases.yml
vendored
1
.github/workflows/releases.yml
vendored
|
@ -39,6 +39,7 @@ jobs:
|
|||
- name: Test suite
|
||||
run: |
|
||||
go version
|
||||
go mod vendor
|
||||
cd .ci
|
||||
./ci-test.sh
|
||||
cd -
|
||||
|
|
|
@ -718,8 +718,8 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
|||
hasSpecificRoutes := false
|
||||
for _, server := range proxy.registeredServers {
|
||||
if via, ok := (*proxy.routes)[server.name]; ok {
|
||||
if server.stamp.Proto != stamps.StampProtoTypeDNSCrypt {
|
||||
dlog.Errorf("DNS anonymization is only supported with the DNSCrypt protocol - Connections to [%v] cannot be anonymized", server.name)
|
||||
if server.stamp.Proto != stamps.StampProtoTypeDNSCrypt && server.stamp.Proto != stamps.StampProtoTypeODoHTarget {
|
||||
dlog.Errorf("DNS anonymization is only supported with the DNSCrypt and ODoH protocols - Connections to [%v] cannot be anonymized", server.name)
|
||||
} else {
|
||||
dlog.Noticef("Anonymized DNS: routing [%v] via %v", server.name, via)
|
||||
}
|
||||
|
|
186
dnscrypt-proxy/odoh.go
Normal file
186
dnscrypt-proxy/odoh.go
Normal file
|
@ -0,0 +1,186 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
hpkecompact "github.com/jedisct1/go-hpke-compact"
|
||||
)
|
||||
|
||||
const (
|
||||
odohVersion = uint16(0xff06)
|
||||
)
|
||||
|
||||
type ODoHTarget struct {
|
||||
suite *hpkecompact.Suite
|
||||
keyID []byte
|
||||
publicKey []byte
|
||||
}
|
||||
|
||||
func encodeLengthValue(b []byte) []byte {
|
||||
lengthBuffer := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(lengthBuffer, uint16(len(b)))
|
||||
return append(lengthBuffer, b...)
|
||||
}
|
||||
|
||||
func parseODoHTargetConfig(config []byte) (ODoHTarget, error) {
|
||||
if len(config) < 8 {
|
||||
return ODoHTarget{}, fmt.Errorf("Malformed config")
|
||||
}
|
||||
kemID := binary.BigEndian.Uint16(config[0:2])
|
||||
kdfID := binary.BigEndian.Uint16(config[2:4])
|
||||
aeadID := binary.BigEndian.Uint16(config[4:6])
|
||||
publicKeyLength := binary.BigEndian.Uint16(config[6:8])
|
||||
if len(config[8:]) != int(publicKeyLength) {
|
||||
return ODoHTarget{}, fmt.Errorf("Malformed config")
|
||||
}
|
||||
|
||||
suite, err := hpkecompact.NewSuite(hpkecompact.KemID(kemID), hpkecompact.KdfID(kdfID), hpkecompact.AeadID(aeadID))
|
||||
if err != nil {
|
||||
return ODoHTarget{}, err
|
||||
}
|
||||
|
||||
publicKey := config[8:]
|
||||
_, _, err = suite.NewClientContext(publicKey, []byte("odoh query"), nil)
|
||||
if err != nil {
|
||||
return ODoHTarget{}, err
|
||||
}
|
||||
|
||||
keyID, err := suite.Expand(suite.Extract(config, nil), []byte("odoh key id"), uint16(suite.Hash().Size()))
|
||||
if err != nil {
|
||||
return ODoHTarget{}, err
|
||||
}
|
||||
|
||||
return ODoHTarget{
|
||||
suite: suite,
|
||||
publicKey: publicKey,
|
||||
keyID: encodeLengthValue(keyID),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseODoHTargetConfigs(configs []byte) ([]ODoHTarget, error) {
|
||||
length := binary.BigEndian.Uint16(configs)
|
||||
if len(configs) != int(length)+2 {
|
||||
return nil, fmt.Errorf("Malformed configs")
|
||||
}
|
||||
|
||||
targets := make([]ODoHTarget, 0)
|
||||
offset := 2
|
||||
for {
|
||||
if offset+4 > len(configs) {
|
||||
return targets, nil
|
||||
}
|
||||
configVersion := binary.BigEndian.Uint16(configs[offset : offset+2])
|
||||
configLength := binary.BigEndian.Uint16(configs[offset+2 : offset+4])
|
||||
if configVersion == odohVersion {
|
||||
target, err := parseODoHTargetConfig(configs[offset+4 : offset+4+int(configLength)])
|
||||
if err == nil {
|
||||
targets = append(targets, target)
|
||||
}
|
||||
}
|
||||
|
||||
offset = offset + int(configLength) + 4
|
||||
}
|
||||
}
|
||||
|
||||
type ODoHQuery struct {
|
||||
suite *hpkecompact.Suite
|
||||
ctx hpkecompact.ClientContext
|
||||
odohPlaintext []byte
|
||||
odohMessage []byte
|
||||
}
|
||||
|
||||
func (t ODoHTarget) encryptQuery(query []byte) (ODoHQuery, error) {
|
||||
clientCtx, encryptedSharedSecret, err := t.suite.NewClientContext(t.publicKey, []byte("odoh query"), nil)
|
||||
if err != nil {
|
||||
return ODoHQuery{}, err
|
||||
}
|
||||
|
||||
odohPlaintext := make([]byte, 4+len(query))
|
||||
binary.BigEndian.PutUint16(odohPlaintext[0:2], uint16(len(query)))
|
||||
copy(odohPlaintext[2:], query)
|
||||
|
||||
aad := append([]byte{0x01}, t.keyID...)
|
||||
ciphertext, err := clientCtx.EncryptToServer(odohPlaintext, aad)
|
||||
|
||||
encryptedMessage := encodeLengthValue(append(encryptedSharedSecret, ciphertext...))
|
||||
odohMessage := append(append([]byte{0x01}, t.keyID...), encryptedMessage...)
|
||||
|
||||
return ODoHQuery{
|
||||
suite: t.suite,
|
||||
odohPlaintext: odohPlaintext,
|
||||
odohMessage: odohMessage,
|
||||
ctx: clientCtx,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q ODoHQuery) decryptResponse(response []byte) ([]byte, error) {
|
||||
if len(response) < 3 {
|
||||
return nil, fmt.Errorf("Malformed response")
|
||||
}
|
||||
|
||||
messageType := response[0]
|
||||
if messageType != uint8(0x02) {
|
||||
return nil, fmt.Errorf("Malformed response")
|
||||
}
|
||||
|
||||
responseNonceLength := binary.BigEndian.Uint16(response[1:3])
|
||||
if len(response) < 5+int(responseNonceLength) {
|
||||
return nil, fmt.Errorf("Malformed response")
|
||||
}
|
||||
|
||||
responseNonceEnc := response[1 : 3+responseNonceLength]
|
||||
|
||||
secret, err := q.ctx.Export([]byte("odoh response"), q.suite.KeyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
salt := append(q.odohPlaintext, responseNonceEnc...)
|
||||
prk := q.suite.Extract(secret, salt)
|
||||
key, err := q.suite.Expand(prk, []byte("odoh key"), q.suite.KeyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nonce, err := q.suite.Expand(prk, []byte("odoh nonce"), q.suite.NonceBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aesgcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctLength := binary.BigEndian.Uint16(response[3+int(responseNonceLength) : 5+int(responseNonceLength)])
|
||||
if int(ctLength) != len(response[5+int(responseNonceLength):]) {
|
||||
return nil, fmt.Errorf("Malformed response")
|
||||
}
|
||||
|
||||
ct := response[5+int(responseNonceLength):]
|
||||
aad := response[0 : 3+int(responseNonceLength)]
|
||||
|
||||
responsePlaintext, err := aesgcm.Open(nil, nonce, ct, aad)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
responseLength := binary.BigEndian.Uint16(responsePlaintext[0:2])
|
||||
valid := 1
|
||||
for i := 4 + int(responseLength); i < len(responsePlaintext); i++ {
|
||||
valid = valid & subtle.ConstantTimeByteEq(response[i], 0x00)
|
||||
}
|
||||
if valid != 1 {
|
||||
return nil, fmt.Errorf("Malformed response")
|
||||
}
|
||||
|
||||
return responsePlaintext[2 : 2+int(responseLength)], nil
|
||||
}
|
|
@ -658,7 +658,7 @@ func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string,
|
|||
tid := TransactionID(query)
|
||||
SetTransactionID(query, 0)
|
||||
serverInfo.noticeBegin(proxy)
|
||||
serverResponse, tls, _, err := proxy.xTransport.DoHQuery(serverInfo.useGet, serverInfo.URL, query, proxy.timeout)
|
||||
serverResponse, _, tls, _, err := proxy.xTransport.DoHQuery(serverInfo.useGet, serverInfo.URL, query, proxy.timeout)
|
||||
SetTransactionID(query, tid)
|
||||
if err == nil || tls == nil || !tls.HandshakeComplete {
|
||||
response = nil
|
||||
|
@ -678,6 +678,42 @@ func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string,
|
|||
if len(response) >= MinDNSPacketSize {
|
||||
SetTransactionID(response, tid)
|
||||
}
|
||||
} else if serverInfo.Proto == stamps.StampProtoTypeODoHTarget {
|
||||
tid := TransactionID(query)
|
||||
target := serverInfo.odohTargets[0]
|
||||
odohQuery, err := target.encryptQuery(query)
|
||||
if err != nil {
|
||||
dlog.Error("Failed to encrypt query")
|
||||
response = nil
|
||||
} else {
|
||||
targetURL := serverInfo.URL
|
||||
if serverInfo.Relay != nil && serverInfo.Relay.ODoH != nil {
|
||||
targetURL = serverInfo.Relay.ODoH.url
|
||||
}
|
||||
responseBody, responseCode, _, _, err := proxy.xTransport.ObliviousDoHQuery(targetURL, odohQuery.odohMessage, proxy.timeout)
|
||||
if err == nil && len(responseBody) > 0 && responseCode == 200 {
|
||||
response, err = odohQuery.decryptResponse(responseBody)
|
||||
if err != nil {
|
||||
dlog.Error("Failed to decrypt response")
|
||||
response = nil
|
||||
}
|
||||
} else if responseCode == 401 {
|
||||
dlog.Notice("Forcing key update")
|
||||
go proxy.serversInfo.refresh(proxy)
|
||||
response = nil
|
||||
} else {
|
||||
dlog.Error("Failed to receive successful response")
|
||||
}
|
||||
}
|
||||
|
||||
if len(response) >= MinDNSPacketSize {
|
||||
SetTransactionID(response, tid)
|
||||
} else if response == nil {
|
||||
pluginsState.returnCode = PluginsReturnCodeNetworkError
|
||||
pluginsState.ApplyLoggingPlugins(&proxy.pluginsGlobals)
|
||||
serverInfo.noticeFailure(proxy)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
dlog.Fatal("Unsupported protocol")
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/bits"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -61,6 +63,7 @@ type ServerInfo struct {
|
|||
knownBugs ServerBugs
|
||||
Proto stamps.StampProtoType
|
||||
useGet bool
|
||||
odohTargets []ODoHTarget
|
||||
}
|
||||
|
||||
type LBStrategy interface {
|
||||
|
@ -104,7 +107,9 @@ type DNSCryptRelay struct {
|
|||
RelayTCPAddr *net.TCPAddr
|
||||
}
|
||||
|
||||
type ODoHRelay struct{}
|
||||
type ODoHRelay struct {
|
||||
url *url.URL
|
||||
}
|
||||
|
||||
type Relay struct {
|
||||
Proto stamps.StampProtoType
|
||||
|
@ -277,6 +282,8 @@ func fetchServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew
|
|||
return fetchDNSCryptServerInfo(proxy, name, stamp, isNew)
|
||||
} else if stamp.Proto == stamps.StampProtoTypeDoH {
|
||||
return fetchDoHServerInfo(proxy, name, stamp, isNew)
|
||||
} else if stamp.Proto == stamps.StampProtoTypeODoHTarget {
|
||||
return fetchODoHTargetInfo(proxy, name, stamp, isNew)
|
||||
}
|
||||
return ServerInfo{}, fmt.Errorf("Unsupported protocol for [%s]: [%s]", name, stamp.Proto.String())
|
||||
}
|
||||
|
@ -412,7 +419,26 @@ func route(proxy *Proxy, name string) (*Relay, error) {
|
|||
dlog.Noticef("Anonymizing queries for [%v] via [%v]", name, relayName)
|
||||
return &Relay{Proto: stamps.StampProtoTypeDNSCryptRelay, Dnscrypt: &DNSCryptRelay{RelayUDPAddr: relayUDPAddr, RelayTCPAddr: relayTCPAddr}}, nil
|
||||
case stamps.StampProtoTypeODoHRelay:
|
||||
return &Relay{Proto: stamps.StampProtoTypeODoHRelay, ODoH: &ODoHRelay{}}, nil
|
||||
target, err := url.Parse("https://" + relayCandidateStamp.ProviderName + "/" + relayCandidateStamp.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, server := range proxy.registeredServers {
|
||||
if server.name == name && server.stamp.Proto == stamps.StampProtoTypeODoHTarget {
|
||||
qs := target.Query()
|
||||
qs.Add("targethost", server.stamp.ProviderName)
|
||||
qs.Add("targetpath", server.stamp.Path)
|
||||
target2 := *target
|
||||
target2.RawQuery = qs.Encode()
|
||||
target = &target2
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return &Relay{Proto: stamps.StampProtoTypeODoHRelay, ODoH: &ODoHRelay{
|
||||
url: target,
|
||||
}}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Invalid relay set for server [%v]", name)
|
||||
}
|
||||
|
@ -550,15 +576,15 @@ func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isN
|
|||
proxy.xTransport.rebuildTransport()
|
||||
}
|
||||
useGet := false
|
||||
if _, _, _, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout); err != nil {
|
||||
if _, _, _, _, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout); err != nil {
|
||||
useGet = true
|
||||
if _, _, _, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout); err != nil {
|
||||
if _, _, _, _, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout); err != nil {
|
||||
return ServerInfo{}, err
|
||||
}
|
||||
dlog.Debugf("Server [%s] doesn't appear to support POST; falling back to GET requests", name)
|
||||
}
|
||||
body = dohNXTestPacket(0xcafe)
|
||||
serverResponse, tls, rtt, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout)
|
||||
serverResponse, _, tls, rtt, err := proxy.xTransport.DoHQuery(useGet, url, body, proxy.timeout)
|
||||
if err != nil {
|
||||
dlog.Infof("[%s] [%s]: %v", name, url, err)
|
||||
return ServerInfo{}, err
|
||||
|
@ -632,6 +658,62 @@ func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isN
|
|||
}, nil
|
||||
}
|
||||
|
||||
func fetchTargetConfigsFromWellKnown(url string) ([]ODoHTarget, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parseODoHTargetConfigs(bodyBytes)
|
||||
}
|
||||
|
||||
func fetchODoHTargetInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew bool) (ServerInfo, error) {
|
||||
odohTargets, err := fetchTargetConfigsFromWellKnown("https://" + stamp.ProviderName + "/.well-known/odohconfigs")
|
||||
if err != nil || len(odohTargets) == 0 {
|
||||
return ServerInfo{}, fmt.Errorf("[%s] does not have an Oblivious DoH configuration", name)
|
||||
}
|
||||
|
||||
relay, err := route(proxy, name)
|
||||
if err != nil {
|
||||
return ServerInfo{}, err
|
||||
}
|
||||
if relay == nil || relay.ODoH == nil {
|
||||
relay = nil
|
||||
}
|
||||
|
||||
if relay == nil {
|
||||
dlog.Notice("Relay is empty for " + name)
|
||||
}
|
||||
|
||||
url := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: stamp.ProviderName,
|
||||
Path: stamp.Path,
|
||||
}
|
||||
|
||||
return ServerInfo{
|
||||
Proto: stamps.StampProtoTypeODoHTarget,
|
||||
Name: name,
|
||||
Timeout: proxy.timeout,
|
||||
URL: url,
|
||||
HostName: stamp.ProviderName,
|
||||
useGet: false,
|
||||
odohTargets: odohTargets,
|
||||
Relay: relay,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (serverInfo *ServerInfo) noticeFailure(proxy *Proxy) {
|
||||
proxy.serversInfo.Lock()
|
||||
serverInfo.rtt.Add(float64(proxy.timeout.Nanoseconds() / 1000000))
|
||||
|
|
|
@ -132,7 +132,7 @@ func (source *Source) parseURLs(urls []string) {
|
|||
}
|
||||
|
||||
func fetchFromURL(xTransport *XTransport, u *url.URL) (bin []byte, err error) {
|
||||
bin, _, _, err = xTransport.Get(u, "", DefaultTimeout)
|
||||
bin, _, _, _, err = xTransport.Get(u, "", DefaultTimeout)
|
||||
return bin, err
|
||||
}
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string, contentType string, body *[]byte, timeout time.Duration) ([]byte, *tls.ConnectionState, time.Duration, error) {
|
||||
func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string, contentType string, body *[]byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||
if timeout <= 0 {
|
||||
timeout = xTransport.timeout
|
||||
}
|
||||
|
@ -361,11 +361,11 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
|
|||
}
|
||||
host, _ := ExtractHostAndPort(url.Host, 0)
|
||||
if xTransport.proxyDialer == nil && strings.HasSuffix(host, ".onion") {
|
||||
return nil, nil, 0, errors.New("Onion service is not reachable without Tor")
|
||||
return nil, 0, nil, 0, errors.New("Onion service is not reachable without Tor")
|
||||
}
|
||||
if err := xTransport.resolveAndUpdateCache(host); err != nil {
|
||||
dlog.Errorf("Unable to resolve [%v] - Make sure that the system resolver works, or that `bootstrap_resolvers` has been set to resolvers that can be reached", host)
|
||||
return nil, nil, 0, err
|
||||
return nil, 0, nil, 0, err
|
||||
}
|
||||
req := &http.Request{
|
||||
Method: method,
|
||||
|
@ -396,26 +396,26 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
|
|||
xTransport.tlsCipherSuite = nil
|
||||
xTransport.rebuildTransport()
|
||||
}
|
||||
return nil, nil, 0, err
|
||||
return nil, 0, nil, 0, err
|
||||
}
|
||||
tls := resp.TLS
|
||||
bin, err := ioutil.ReadAll(io.LimitReader(resp.Body, MaxHTTPBodyLength))
|
||||
if err != nil {
|
||||
return nil, tls, 0, err
|
||||
return nil, resp.StatusCode, tls, 0, err
|
||||
}
|
||||
resp.Body.Close()
|
||||
return bin, tls, rtt, err
|
||||
return bin, resp.StatusCode, tls, rtt, err
|
||||
}
|
||||
|
||||
func (xTransport *XTransport) Get(url *url.URL, accept string, timeout time.Duration) ([]byte, *tls.ConnectionState, time.Duration, error) {
|
||||
func (xTransport *XTransport) Get(url *url.URL, accept string, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||
return xTransport.Fetch("GET", url, accept, "", nil, timeout)
|
||||
}
|
||||
|
||||
func (xTransport *XTransport) Post(url *url.URL, accept string, contentType string, body *[]byte, timeout time.Duration) ([]byte, *tls.ConnectionState, time.Duration, error) {
|
||||
func (xTransport *XTransport) Post(url *url.URL, accept string, contentType string, body *[]byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||
return xTransport.Fetch("POST", url, accept, contentType, body, timeout)
|
||||
}
|
||||
|
||||
func (xTransport *XTransport) DoHQuery(useGet bool, url *url.URL, body []byte, timeout time.Duration) ([]byte, *tls.ConnectionState, time.Duration, error) {
|
||||
func (xTransport *XTransport) DoHQuery(useGet bool, url *url.URL, body []byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||
dataType := "application/dns-message"
|
||||
if useGet {
|
||||
qs := url.Query()
|
||||
|
@ -427,3 +427,8 @@ func (xTransport *XTransport) DoHQuery(useGet bool, url *url.URL, body []byte, t
|
|||
}
|
||||
return xTransport.Post(url, dataType, dataType, &body, timeout)
|
||||
}
|
||||
|
||||
func (xTransport *XTransport) ObliviousDoHQuery(url *url.URL, body []byte, timeout time.Duration) ([]byte, int, *tls.ConnectionState, time.Duration, error) {
|
||||
dataType := "application/oblivious-dns-message"
|
||||
return xTransport.Post(url, dataType, dataType, &body, timeout)
|
||||
}
|
||||
|
|
3
go.mod
3
go.mod
|
@ -5,6 +5,8 @@ go 1.16
|
|||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/VividCortex/ewma v1.1.1
|
||||
github.com/cisco/go-hpke v0.0.0-20210215210317-01c430f1f302 // indirect
|
||||
github.com/cloudflare/odoh-go v0.1.6 // indirect
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0
|
||||
|
@ -13,6 +15,7 @@ require (
|
|||
github.com/jedisct1/dlog v0.0.0-20210101122416-354ffe815216
|
||||
github.com/jedisct1/go-clocksmith v0.0.0-20210101121932-da382b963868
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20210101121956-16fbdadcf8f5
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20210329192501-7ceabaabca65
|
||||
github.com/jedisct1/go-minisign v0.0.0-20210106175330-e54e81d562c7
|
||||
github.com/jedisct1/xsecretbox v0.0.0-20210102102453-4ecb2081017a
|
||||
github.com/k-sone/critbitgo v1.4.0
|
||||
|
|
24
go.sum
24
go.sum
|
@ -1,4 +1,6 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
git.schwanenlied.me/yawning/x448.git v0.0.0-20170617130356-01b048fb03d6 h1:w8IZgCntCe0RuBJp+dENSMwEBl/k8saTgJ5hPca5IWw=
|
||||
git.schwanenlied.me/yawning/x448.git v0.0.0-20170617130356-01b048fb03d6/go.mod h1:wQaGCqEu44ykB17jZHCevrgSVl3KJnwQBObUtrKU4uU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
|
@ -8,9 +10,18 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSi
|
|||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cisco/go-hpke v0.0.0-20210215210317-01c430f1f302 h1:unAbn7dpE8eeUfWRaOPl1qTfffhIcCNuKQuECGNGWtk=
|
||||
github.com/cisco/go-hpke v0.0.0-20210215210317-01c430f1f302/go.mod h1:RSsoIHRMBe69FbF/fIbmWYa3rrC6vuPyC0MbNUpel3Q=
|
||||
github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b h1:Ves2turKTX7zruivAcUOQg155xggcbv3suVdbKCBQNM=
|
||||
github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b/go.mod h1:0AZAV7lYvynZQ5ErHlGMKH+4QYMyNCFd+AiL9MlrCYA=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.0.0 h1:64b6pyfCFbYm623ncIkYGNZaOcmIbyd+CjyMi2L9vdI=
|
||||
github.com/cloudflare/circl v1.0.0/go.mod h1:MhjB3NEEhJbTOdLLq964NIUisXDxaE1WkQPUxtgZXiY=
|
||||
github.com/cloudflare/odoh-go v0.1.6 h1:siTTv/pBXztJORDgVNDAYKdTboenwWFMDD1B9YQHkag=
|
||||
github.com/cloudflare/odoh-go v0.1.6/go.mod h1:J3Doz827YDYvz4hEmJU6q45hRFOqxUBL6NRUuEfjMxA=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185 h1:3T8ZyTDp5QxTx3NU48JVb2u+75xc040fofcBaN+6jPA=
|
||||
|
@ -54,6 +65,10 @@ github.com/jedisct1/go-clocksmith v0.0.0-20210101121932-da382b963868 h1:QZ79mRbN
|
|||
github.com/jedisct1/go-clocksmith v0.0.0-20210101121932-da382b963868/go.mod h1:SAINchklztk2jcLWJ4bpNF4KnwDUSUTX+cJbspWC2Rw=
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20210101121956-16fbdadcf8f5 h1:FnAupK0Gm6PJZDhI5sGkbNZQ7DT4+tG8opjmoXfBu/o=
|
||||
github.com/jedisct1/go-dnsstamps v0.0.0-20210101121956-16fbdadcf8f5/go.mod h1:t35n6rsPE3nD3RXbc5hI5Ax1ci/SSYTpx0BdMXh/1aE=
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20210216141532-42fe67ec23b2 h1:5pGP8stsRZ3SHicLH189p/RroaZ43+m8P4+CBu3maRE=
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20210216141532-42fe67ec23b2/go.mod h1:Sc4df3OZCQgMxgbCVYLnIA16SRDKrGcSFcUqeu67MGs=
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20210329192501-7ceabaabca65 h1:qxey1Jfre+udaWyQI+lS3qPGuJDzmkBaHDIhmL9qef8=
|
||||
github.com/jedisct1/go-hpke-compact v0.0.0-20210329192501-7ceabaabca65/go.mod h1:fFxJHJ4XTptLoMkie7bC9zjyKSKC8yycljJtKXGaAAI=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20210106175330-e54e81d562c7 h1:qrPDNqqT76vs8oWL6Z1/D6hKvbXULvlD7FdNVTIUI8A=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20210106175330-e54e81d562c7/go.mod h1:oPTyITpvr7hPx/9w76gWrgbZwbb+7gZ9/On8hFc+LNE=
|
||||
github.com/jedisct1/xsecretbox v0.0.0-20210102102453-4ecb2081017a h1:ptZ+a2DzulAgKEfMuqH2Ckfv6oio5BX14fRG5aShvXw=
|
||||
|
@ -70,6 +85,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/powerman/check v1.3.0/go.mod h1:k/8NCUQwepaKJKctBBKjQo84jvGEvKiumD9pDl87RB0=
|
||||
github.com/powerman/check v1.3.1 h1:86xiEjMNn0K4b3bhQsLfrLqJb0DWLXHBK3wBd5PoJH4=
|
||||
github.com/powerman/check v1.3.1/go.mod h1:k/8NCUQwepaKJKctBBKjQo84jvGEvKiumD9pDl87RB0=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
|
@ -78,8 +94,12 @@ github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHei
|
|||
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -102,12 +122,15 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
|
|||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
|
||||
|
@ -149,5 +172,6 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXL
|
|||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
2
vendor/github.com/jedisct1/go-hpke-compact/.gitignore
generated
vendored
Normal file
2
vendor/github.com/jedisct1/go-hpke-compact/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*~
|
||||
go.sum
|
18
vendor/github.com/jedisct1/go-hpke-compact/LICENSE
generated
vendored
Normal file
18
vendor/github.com/jedisct1/go-hpke-compact/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* ISC License
|
||||
*
|
||||
* Copyright (c) 2020-2021
|
||||
* Frank Denis <j at pureftpd dot org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
129
vendor/github.com/jedisct1/go-hpke-compact/README.md
generated
vendored
Normal file
129
vendor/github.com/jedisct1/go-hpke-compact/README.md
generated
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
[](https://github.com/jedisct1/go-hpke-compact/actions)
|
||||
[](https://pkg.go.dev/github.com/jedisct1/go-hpke-compact)
|
||||
|
||||
# 
|
||||
|
||||
# A compact HPKE implemention for Go
|
||||
|
||||
`hpkecompact` is a small implementation of the [Hybrid Public Key Encryption](https://cfrg.github.io/draft-irtf-cfrg-hpke/draft-irtf-cfrg-hpke.html) (HPKE) draft.
|
||||
|
||||
It fits in a single file and only uses the Go standard library and `x/crypto`.
|
||||
|
||||
Suites are currently limited to `X25519-HKDF-SHA256` / `HKDF-SHA-256` / `{AES-{128,256}-GCM, CHACHA20-POLY1305}`; these are very likely to be the most commonly deployed ones for a forseable future.
|
||||
|
||||
## Usage
|
||||
|
||||
### Suite instantiation
|
||||
|
||||
```go
|
||||
suite, err := NewSuite(KemX25519HkdfSha256, KdfHkdfSha256, AeadAes128Gcm)
|
||||
```
|
||||
|
||||
### Key pair creation
|
||||
|
||||
```go
|
||||
serverKp, err := ctx.GenerateKeyPair()
|
||||
```
|
||||
|
||||
### Client: creation and encapsulation of the shared secret
|
||||
|
||||
A _client_ initiates a connexion by sending an encrypted secret; a _server_ accepts an encrypted secret from a client, and decrypts it, so that both parties can eventually agree on a shared secret.
|
||||
|
||||
```go
|
||||
clientCtx, encryptedSharedSecret, err :=
|
||||
suite.NewClientContext(serverKp.PublicKey, []byte("application name"), nil)
|
||||
```
|
||||
|
||||
* `encryptedSharedSecret` needs to be sent to the server.
|
||||
* `clientCtx` can be used to encrypt/decrypt messages exchanged with the server.
|
||||
* The last parameter is an optional pre-shared key (`Psk` type).
|
||||
|
||||
To improve misuse resistance, this implementation uses distinct types for the client and the server context: `ClientContext` for the client, and `ServerContext` for the server.
|
||||
|
||||
### Server: decapsulation of the shared secret
|
||||
|
||||
```go
|
||||
serverCtx, err := suite.NewServerContext(encryptedSharedSecret,
|
||||
serverKp, []byte("application name"), nil)
|
||||
```
|
||||
|
||||
* `serverCtx` can be used to encrypt/decrypt messages exchanged with the client
|
||||
* The last parameter is an optional pre-shared key (`Psk` type).
|
||||
|
||||
### Encryption of a message from the client to the server
|
||||
|
||||
A message can be encrypted by the client for the server:
|
||||
|
||||
```go
|
||||
ciphertext, err := clientCtx.EncryptToServer([]byte("message"), nil)
|
||||
```
|
||||
|
||||
Nonces are automatically incremented, so it is safe to call this function multiple times within the same context.
|
||||
|
||||
Second parameter is optional associated data.
|
||||
|
||||
### Decryption of a ciphertext received by the server
|
||||
|
||||
The server can decrypt a ciphertext sent by the client:
|
||||
|
||||
```go
|
||||
decrypted, err := serverCtx.DecryptFromClient(ciphertext, nil)
|
||||
```
|
||||
|
||||
Second parameter is optional associated data.
|
||||
|
||||
### Encryption of a message from the server to the client
|
||||
|
||||
A message can also be encrypted by the server for the client:
|
||||
|
||||
```go
|
||||
ciphertext, err := clientCtx.EncryptToClient([]byte("response"), nil)
|
||||
```
|
||||
|
||||
Nonces are automatically incremented, so it is safe to call this function multiple times within the same context.
|
||||
|
||||
Second parameter is optional associated data.
|
||||
|
||||
### Decryption of a ciphertext received by the client
|
||||
|
||||
The client can decrypt a ciphertext sent by the server:
|
||||
|
||||
```go
|
||||
decrypted, err := serverCtx.DecryptFromServer(ciphertext, nil)
|
||||
```
|
||||
|
||||
Second parameter is optional associated data.
|
||||
|
||||
## Authenticated modes
|
||||
|
||||
Authenticated modes, with or without a PSK are supported.
|
||||
|
||||
Just replace `NewClientContext()` with `NewAuthenticatedClientContext()` and `NewServerContext()` with `NewAuthenticatedServerContext()` for authentication.
|
||||
|
||||
```go
|
||||
clientKp, err := suite.GenerateKeyPair()
|
||||
serverKp, err := suite.GenerateKeyPair()
|
||||
|
||||
clientCtx, encryptedSharedSecret, err := suite.NewAuthenticatedClientContext(
|
||||
clientKp, serverKp.PublicKey, []byte("app"), psk)
|
||||
|
||||
serverCtx, err := suite.NewAuthenticatedServerContext(
|
||||
clientKp.PublicKey, encryptedSharedSecret, serverKp, []byte("app"), psk)
|
||||
```
|
||||
|
||||
### Exporter secret
|
||||
|
||||
The exporter secret can be obtained with the `ExportedSecret()` function available both in the `ServerContext` and `ClientContext` structures:
|
||||
|
||||
```go
|
||||
exporter := serverCtx.ExporterSecret()
|
||||
```
|
||||
|
||||
### Key derivation
|
||||
|
||||
```go
|
||||
secret1, err := clientCtx.Export("description 1")
|
||||
secret2, err := serverCtx.Export("description 2");
|
||||
```
|
||||
|
||||
## That's it!
|
8
vendor/github.com/jedisct1/go-hpke-compact/go.mod
generated
vendored
Normal file
8
vendor/github.com/jedisct1/go-hpke-compact/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
module github.com/jedisct1/go-hpke-compact
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/powerman/check v1.3.1
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
)
|
656
vendor/github.com/jedisct1/go-hpke-compact/hpke.go
generated
vendored
Normal file
656
vendor/github.com/jedisct1/go-hpke-compact/hpke.go
generated
vendored
Normal file
|
@ -0,0 +1,656 @@
|
|||
package hpkecompact
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
crypto_rand "crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
var hpkeVersion = [7]byte{'H', 'P', 'K', 'E', '-', 'v', '1'}
|
||||
|
||||
// Mode - Mode
|
||||
type Mode byte
|
||||
|
||||
const (
|
||||
// ModeBase - Base mode
|
||||
ModeBase Mode = 0x00
|
||||
// ModePsk - PSK mode
|
||||
ModePsk Mode = 0x01
|
||||
// ModeAuth - Auth mode
|
||||
ModeAuth Mode = 0x02
|
||||
// ModeAuthPsk - PSK Auth mode
|
||||
ModeAuthPsk Mode = 0x03
|
||||
)
|
||||
|
||||
// KemID - KEM ID
|
||||
type KemID uint16
|
||||
|
||||
const (
|
||||
// KemX25519HkdfSha256 - X25519 with HKDF-SHA256
|
||||
KemX25519HkdfSha256 KemID = 0x0020
|
||||
)
|
||||
|
||||
// KdfID - KDF ID
|
||||
type KdfID uint16
|
||||
|
||||
const (
|
||||
// KdfHkdfSha256 - HKDF-SHA256
|
||||
KdfHkdfSha256 KdfID = 0x0001
|
||||
)
|
||||
|
||||
// AeadID - AEAD ID
|
||||
type AeadID uint16
|
||||
|
||||
const (
|
||||
// AeadAes128Gcm - AES128-GCM
|
||||
AeadAes128Gcm AeadID = 0x0001
|
||||
// AeadAes256Gcm - AES256-GCM
|
||||
AeadAes256Gcm AeadID = 0x0002
|
||||
// AeadChaCha20Poly1305 - ChaCha20-Poly1305
|
||||
AeadChaCha20Poly1305 AeadID = 0x0003
|
||||
// AeadExportOnly - Don't use the HPKE encryption API
|
||||
AeadExportOnly AeadID = 0xffff
|
||||
)
|
||||
|
||||
// Psk - Pre-shared key and key ID
|
||||
type Psk struct {
|
||||
Key []byte
|
||||
ID []byte
|
||||
}
|
||||
|
||||
// KeyPair - A key pair (packed as a byte string)
|
||||
type KeyPair struct {
|
||||
// PublicKey - Public key
|
||||
PublicKey []byte
|
||||
// SecretKey - Secret key
|
||||
SecretKey []byte
|
||||
}
|
||||
|
||||
type aeadState struct {
|
||||
aead aeadImpl
|
||||
baseNonce []byte
|
||||
counter []byte
|
||||
}
|
||||
|
||||
// Suite - HPKE suite
|
||||
type Suite struct {
|
||||
SuiteIDContext [10]byte
|
||||
SuiteIDKEM [5]byte
|
||||
Hash func() hash.Hash
|
||||
PrkBytes uint16
|
||||
KeyBytes uint16
|
||||
NonceBytes uint16
|
||||
KemHashBytes uint16
|
||||
AeadID AeadID
|
||||
}
|
||||
|
||||
// NewSuite - Create a new suite from its components
|
||||
func NewSuite(kemID KemID, kdfID KdfID, aeadID AeadID) (*Suite, error) {
|
||||
if kemID != KemX25519HkdfSha256 || kdfID != KdfHkdfSha256 {
|
||||
return nil, errors.New("unimplemented suite")
|
||||
}
|
||||
hash := sha256.New
|
||||
nonceBytes := uint16(12)
|
||||
var keyBytes uint16
|
||||
switch aeadID {
|
||||
case AeadAes128Gcm:
|
||||
keyBytes = 16
|
||||
case AeadAes256Gcm:
|
||||
keyBytes = 32
|
||||
case AeadChaCha20Poly1305:
|
||||
keyBytes = 32
|
||||
case AeadExportOnly:
|
||||
keyBytes = 0
|
||||
nonceBytes = 0
|
||||
default:
|
||||
return nil, errors.New("unimplemented suite")
|
||||
}
|
||||
var prkBytes uint16
|
||||
switch kdfID {
|
||||
case KdfHkdfSha256:
|
||||
prkBytes = 32
|
||||
default:
|
||||
return nil, errors.New("unimplemented suite")
|
||||
}
|
||||
var kemHashBytes uint16
|
||||
switch kemID {
|
||||
case KemX25519HkdfSha256:
|
||||
kemHashBytes = 32
|
||||
default:
|
||||
return nil, errors.New("unimplemented suite")
|
||||
}
|
||||
suite := Suite{
|
||||
SuiteIDContext: getSuiteIDContext(kemID, kdfID, aeadID),
|
||||
SuiteIDKEM: getSuiteIDKEM(kemID),
|
||||
Hash: hash,
|
||||
KeyBytes: keyBytes,
|
||||
PrkBytes: prkBytes,
|
||||
NonceBytes: nonceBytes,
|
||||
KemHashBytes: kemHashBytes,
|
||||
AeadID: aeadID,
|
||||
}
|
||||
return &suite, nil
|
||||
}
|
||||
|
||||
func getSuiteIDContext(kemID KemID, kdfID KdfID, aeadID AeadID) [10]byte {
|
||||
suiteIDContext := [10]byte{'H', 'P', 'K', 'E', 0, 0, 0, 0, 0, 0}
|
||||
binary.BigEndian.PutUint16(suiteIDContext[4:6], uint16(kemID))
|
||||
binary.BigEndian.PutUint16(suiteIDContext[6:8], uint16(kdfID))
|
||||
binary.BigEndian.PutUint16(suiteIDContext[8:10], uint16(aeadID))
|
||||
return suiteIDContext
|
||||
}
|
||||
|
||||
func getSuiteIDKEM(kemID KemID) [5]byte {
|
||||
suiteIDKEM := [5]byte{'K', 'E', 'M', 0, 0}
|
||||
binary.BigEndian.PutUint16(suiteIDKEM[3:5], uint16(kemID))
|
||||
return suiteIDKEM
|
||||
}
|
||||
|
||||
// Extract - KDF-Extract
|
||||
func (suite *Suite) Extract(secret []byte, salt []byte) []byte {
|
||||
return hkdf.Extract(suite.Hash, secret, salt)
|
||||
}
|
||||
|
||||
// Expand - KDF-Expand
|
||||
func (suite *Suite) Expand(prk []byte, info []byte, length uint16) ([]byte, error) {
|
||||
reader := hkdf.Expand(suite.Hash, prk, info)
|
||||
out := make([]byte, length)
|
||||
if readNb, err := reader.Read(out); err != nil {
|
||||
return nil, err
|
||||
} else if readNb != int(length) {
|
||||
return nil, errors.New("unable to expand")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) labeledExtract(suiteID []byte, salt []byte, label string, ikm []byte) []byte {
|
||||
secret := append(hpkeVersion[:], suiteID...)
|
||||
secret = append(secret, []byte(label)...)
|
||||
secret = append(secret, ikm...)
|
||||
return suite.Extract(secret, salt)
|
||||
}
|
||||
|
||||
func (suite *Suite) labeledExpand(suiteID []byte, prk []byte, label string, info []byte, length uint16) ([]byte, error) {
|
||||
labeledInfo := []byte{0, 0}
|
||||
binary.BigEndian.PutUint16(labeledInfo, length)
|
||||
labeledInfo = append(labeledInfo, hpkeVersion[:]...)
|
||||
labeledInfo = append(labeledInfo, suiteID...)
|
||||
labeledInfo = append(labeledInfo, []byte(label)...)
|
||||
labeledInfo = append(labeledInfo, info...)
|
||||
return suite.Expand(prk, labeledInfo, length)
|
||||
}
|
||||
|
||||
func (suite *Suite) newAeadState(key []uint8, baseNonce []uint8) (*aeadState, error) {
|
||||
var aead aeadImpl
|
||||
var err error
|
||||
switch suite.AeadID {
|
||||
case AeadAes128Gcm, AeadAes256Gcm:
|
||||
aead, err = newAesAead(key)
|
||||
case AeadChaCha20Poly1305:
|
||||
aead, err = newChaChaPolyAead(key)
|
||||
default:
|
||||
return nil, errors.New("unimplemented AEAD")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &aeadState{aead: aead, baseNonce: baseNonce, counter: make([]byte, suite.NonceBytes)}, nil
|
||||
}
|
||||
|
||||
func verifyPskInputs(mode Mode, psk *Psk) error {
|
||||
if psk != nil && ((len(psk.Key) == 0) != (len(psk.ID) == 0)) {
|
||||
return errors.New("a PSK and a PSK ID need both to be set")
|
||||
}
|
||||
if psk != nil {
|
||||
if mode == ModeBase || mode == ModeAuth {
|
||||
return errors.New("PSK input provided when not needed")
|
||||
}
|
||||
} else if mode == ModePsk || mode == ModeAuthPsk {
|
||||
return errors.New("PSK required for that mode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// innerContext - An AEAD context
|
||||
type innerContext struct {
|
||||
suite *Suite
|
||||
exporterSecret []byte
|
||||
outboundState *aeadState
|
||||
inboundState *aeadState
|
||||
}
|
||||
|
||||
func (inner *innerContext) export(exporterContext []byte, length uint16) ([]byte, error) {
|
||||
return inner.suite.labeledExpand(inner.suite.SuiteIDContext[:], inner.exporterSecret, "sec", exporterContext, length)
|
||||
}
|
||||
|
||||
// ClientContext - A client encryption context
|
||||
type ClientContext struct {
|
||||
inner innerContext
|
||||
}
|
||||
|
||||
// ServerContext - A server encryption context
|
||||
type ServerContext struct {
|
||||
inner innerContext
|
||||
}
|
||||
|
||||
func (suite *Suite) keySchedule(mode Mode, dhSecret []byte, info []byte, psk *Psk) (innerContext, error) {
|
||||
if err := verifyPskInputs(mode, psk); err != nil {
|
||||
return innerContext{}, err
|
||||
}
|
||||
if psk == nil {
|
||||
psk = &Psk{}
|
||||
}
|
||||
pskIDHash := suite.labeledExtract(suite.SuiteIDContext[:], nil, "psk_id_hash", psk.ID)
|
||||
infoHash := suite.labeledExtract(suite.SuiteIDContext[:], nil, "info_hash", info)
|
||||
keyScheduleContext := []byte{byte(mode)}
|
||||
keyScheduleContext = append(keyScheduleContext, pskIDHash...)
|
||||
keyScheduleContext = append(keyScheduleContext, infoHash...)
|
||||
secret := suite.labeledExtract(suite.SuiteIDContext[:], dhSecret, "secret", psk.Key)
|
||||
|
||||
exporterSecret, err := suite.labeledExpand(suite.SuiteIDContext[:], secret, "exp", keyScheduleContext, suite.PrkBytes)
|
||||
if err != nil {
|
||||
return innerContext{}, err
|
||||
}
|
||||
|
||||
var outboundState *aeadState
|
||||
if suite.AeadID != AeadExportOnly {
|
||||
outboundKey, err := suite.labeledExpand(suite.SuiteIDContext[:], secret, "key", keyScheduleContext, suite.KeyBytes)
|
||||
if err != nil {
|
||||
return innerContext{}, err
|
||||
}
|
||||
outboundBaseNonce, err := suite.labeledExpand(suite.SuiteIDContext[:], secret, "base_nonce", keyScheduleContext, suite.NonceBytes)
|
||||
if err != nil {
|
||||
return innerContext{}, err
|
||||
}
|
||||
outboundState, err = suite.newAeadState(outboundKey, outboundBaseNonce)
|
||||
if err != nil {
|
||||
return innerContext{}, err
|
||||
}
|
||||
}
|
||||
return innerContext{
|
||||
suite: suite,
|
||||
exporterSecret: exporterSecret,
|
||||
outboundState: outboundState,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateKeyPair - Generate a random key pair
|
||||
func (suite *Suite) GenerateKeyPair() (KeyPair, error) {
|
||||
var pk, sk [32]byte
|
||||
if _, err := crypto_rand.Read(sk[:]); err != nil {
|
||||
return KeyPair{}, err
|
||||
}
|
||||
curve25519.ScalarBaseMult(&pk, &sk)
|
||||
return KeyPair{PublicKey: pk[:], SecretKey: sk[:]}, nil
|
||||
}
|
||||
|
||||
// DeterministicKeyPair - Derive a deterministic key pair from a seed
|
||||
func (suite *Suite) DeterministicKeyPair(seed []byte) (KeyPair, error) {
|
||||
var pk, sk [32]byte
|
||||
prk := suite.labeledExtract(suite.SuiteIDKEM[:], nil, "dkp_prk", seed)
|
||||
xsk, err := suite.labeledExpand(suite.SuiteIDKEM[:], prk, "sk", nil, 32)
|
||||
if err != nil {
|
||||
return KeyPair{}, err
|
||||
}
|
||||
copy(sk[:], xsk)
|
||||
curve25519.ScalarBaseMult(&pk, &sk)
|
||||
return KeyPair{PublicKey: pk[:], SecretKey: sk[:]}, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) dh(pk []byte, sk []byte) ([]byte, error) {
|
||||
dhSecret, err := curve25519.X25519(sk, pk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dhSecret, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) extractAndExpandDH(dh []byte, kemContext []byte) ([]byte, error) {
|
||||
prk := suite.labeledExtract(suite.SuiteIDKEM[:], nil, "eae_prk", dh)
|
||||
dhSecret, err := suite.labeledExpand(suite.SuiteIDKEM[:], prk, "shared_secret", kemContext, suite.KemHashBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dhSecret, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) encap(serverPk []byte, seed []byte) ([]byte, []byte, error) {
|
||||
var ephKp KeyPair
|
||||
var err error
|
||||
if len(seed) > 0 {
|
||||
ephKp, err = suite.DeterministicKeyPair(seed)
|
||||
} else {
|
||||
ephKp, err = suite.GenerateKeyPair()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
dh, err := suite.dh(serverPk, ephKp.SecretKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
kemContext := append(ephKp.PublicKey, serverPk...)
|
||||
dhSecret, err := suite.extractAndExpandDH(dh, kemContext)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return dhSecret, ephKp.PublicKey, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) decap(ephPk []byte, serverKp KeyPair) ([]byte, error) {
|
||||
dh, err := suite.dh(ephPk, serverKp.SecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kemContext := append(ephPk, serverKp.PublicKey...)
|
||||
dhSecret, err := suite.extractAndExpandDH(dh, kemContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dhSecret, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) authEncap(serverPk []byte, clientKp KeyPair, seed []byte) ([]byte, []byte, error) {
|
||||
var ephKp KeyPair
|
||||
var err error
|
||||
if len(seed) > 0 {
|
||||
ephKp, err = suite.DeterministicKeyPair(seed)
|
||||
} else {
|
||||
ephKp, err = suite.GenerateKeyPair()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
dh1, err := suite.dh(serverPk, ephKp.SecretKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
dh2, err := suite.dh(serverPk, clientKp.SecretKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
dh := append(dh1, dh2...)
|
||||
kemContext := append(ephKp.PublicKey, serverPk...)
|
||||
kemContext = append(kemContext, clientKp.PublicKey...)
|
||||
dhSecret, err := suite.extractAndExpandDH(dh, kemContext)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return dhSecret, ephKp.PublicKey, nil
|
||||
}
|
||||
|
||||
func (suite *Suite) authDecap(ephPk []byte, serverKp KeyPair, clientPk []byte) ([]byte, error) {
|
||||
dh1, err := suite.dh(ephPk, serverKp.SecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dh2, err := suite.dh(clientPk, serverKp.SecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dh := append(dh1, dh2...)
|
||||
kemContext := append(ephPk, serverKp.PublicKey...)
|
||||
kemContext = append(kemContext, clientPk...)
|
||||
dhSecret, err := suite.extractAndExpandDH(dh, kemContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dhSecret, nil
|
||||
}
|
||||
|
||||
// NewClientContext - Create a new context for a client (aka "sender")
|
||||
func (suite *Suite) NewClientContext(serverPk []byte, info []byte, psk *Psk) (ClientContext, []byte, error) {
|
||||
dhSecret, enc, err := suite.encap(serverPk, nil)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
mode := ModeBase
|
||||
if psk != nil {
|
||||
mode = ModePsk
|
||||
}
|
||||
context, err := suite.keySchedule(mode, dhSecret, info, psk)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
return ClientContext{inner: context}, enc, nil
|
||||
}
|
||||
|
||||
// NewClientDeterministicContext - Create a new deterministic context for a client - Should only be used for testing purposes
|
||||
func (suite *Suite) NewClientDeterministicContext(serverPk []byte, info []byte, psk *Psk, seed []byte) (ClientContext, []byte, error) {
|
||||
dhSecret, enc, err := suite.encap(serverPk, seed)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
mode := ModeBase
|
||||
if psk != nil {
|
||||
mode = ModePsk
|
||||
}
|
||||
context, err := suite.keySchedule(mode, dhSecret, info, psk)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
return ClientContext{inner: context}, enc, nil
|
||||
}
|
||||
|
||||
// NewServerContext - Create a new context for a server (aka "recipient")
|
||||
func (suite *Suite) NewServerContext(enc []byte, serverKp KeyPair, info []byte, psk *Psk) (ServerContext, error) {
|
||||
dhSecret, err := suite.decap(enc, serverKp)
|
||||
if err != nil {
|
||||
return ServerContext{}, err
|
||||
}
|
||||
mode := ModeBase
|
||||
if psk != nil {
|
||||
mode = ModePsk
|
||||
}
|
||||
context, err := suite.keySchedule(mode, dhSecret, info, psk)
|
||||
if err != nil {
|
||||
return ServerContext{}, err
|
||||
}
|
||||
return ServerContext{inner: context}, nil
|
||||
}
|
||||
|
||||
// NewAuthenticatedClientContext - Create a new context for a client (aka "sender"), with authentication
|
||||
func (suite *Suite) NewAuthenticatedClientContext(clientKp KeyPair, serverPk []byte, info []byte, psk *Psk) (ClientContext, []byte, error) {
|
||||
dhSecret, enc, err := suite.authEncap(serverPk, clientKp, nil)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
mode := ModeAuth
|
||||
if psk != nil {
|
||||
mode = ModeAuthPsk
|
||||
}
|
||||
context, err := suite.keySchedule(mode, dhSecret, info, psk)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
return ClientContext{inner: context}, enc, nil
|
||||
}
|
||||
|
||||
// NewAuthenticatedClientDeterministicContext - Create a new deterministic context for a client, with authentication - Should only be used for testing purposes
|
||||
func (suite *Suite) NewAuthenticatedClientDeterministicContext(clientKp KeyPair, serverPk []byte, info []byte, psk *Psk, seed []byte) (ClientContext, []byte, error) {
|
||||
dhSecret, enc, err := suite.authEncap(serverPk, clientKp, seed)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
mode := ModeAuth
|
||||
if psk != nil {
|
||||
mode = ModeAuthPsk
|
||||
}
|
||||
context, err := suite.keySchedule(mode, dhSecret, info, psk)
|
||||
if err != nil {
|
||||
return ClientContext{}, nil, err
|
||||
}
|
||||
return ClientContext{inner: context}, enc, nil
|
||||
}
|
||||
|
||||
// NewAuthenticatedServerContext - Create a new context for a server (aka "recipient"), with authentication
|
||||
func (suite *Suite) NewAuthenticatedServerContext(clientPk []byte, enc []byte, serverKp KeyPair, info []byte, psk *Psk) (ServerContext, error) {
|
||||
dhSecret, err := suite.authDecap(enc, serverKp, clientPk)
|
||||
if err != nil {
|
||||
return ServerContext{}, err
|
||||
}
|
||||
mode := ModeAuth
|
||||
if psk != nil {
|
||||
mode = ModeAuthPsk
|
||||
}
|
||||
context, err := suite.keySchedule(mode, dhSecret, info, psk)
|
||||
if err != nil {
|
||||
return ServerContext{}, err
|
||||
}
|
||||
return ServerContext{inner: context}, nil
|
||||
}
|
||||
|
||||
func (state *aeadState) incrementCounter() error {
|
||||
carry := uint16(1)
|
||||
for i := len(state.counter); ; {
|
||||
i--
|
||||
x := uint16(state.counter[i]) + carry
|
||||
state.counter[i] = byte(x & 0xff)
|
||||
carry = x >> 8
|
||||
if i == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if carry != 0 {
|
||||
return errors.New("Overflow")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextNonce - Get the next nonce to encrypt/decrypt a message with an AEAD
|
||||
// Note: this is not thread-safe.
|
||||
func (state *aeadState) NextNonce() []byte {
|
||||
if len(state.counter) != len(state.baseNonce) {
|
||||
panic("Inconsistent nonce length")
|
||||
}
|
||||
nonce := append(state.baseNonce[:0:0], state.baseNonce...)
|
||||
for i := 0; i < len(nonce); i++ {
|
||||
nonce[i] ^= state.counter[i]
|
||||
}
|
||||
state.incrementCounter()
|
||||
return nonce
|
||||
}
|
||||
|
||||
// EncryptToServer - Encrypt and authenticate a message for the server, with optional associated data
|
||||
func (context *ClientContext) EncryptToServer(message []byte, ad []byte) ([]byte, error) {
|
||||
state := context.inner.outboundState
|
||||
nonce := state.NextNonce()
|
||||
return state.aead.internal().Seal(nil, nonce, message, ad), nil
|
||||
}
|
||||
|
||||
// DecryptFromClient - Verify and decrypt a ciphertext received from the client, with optional associated data
|
||||
func (context *ServerContext) DecryptFromClient(ciphertext []byte, ad []byte) ([]byte, error) {
|
||||
state := context.inner.outboundState
|
||||
nonce := state.NextNonce()
|
||||
return state.aead.internal().Open(nil, nonce, ciphertext, ad)
|
||||
}
|
||||
|
||||
func (inner *innerContext) responseState() (*aeadState, error) {
|
||||
key, err := inner.export([]byte("response key"), inner.suite.KeyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseNonce, err := inner.export([]byte("response nonce"), inner.suite.NonceBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inner.suite.newAeadState(key, baseNonce)
|
||||
}
|
||||
|
||||
// EncryptToClient - Encrypt and authenticate a message for the client, with optional associated data
|
||||
func (context *ServerContext) EncryptToClient(message []byte, ad []byte) ([]byte, error) {
|
||||
if context.inner.inboundState == nil {
|
||||
var err error
|
||||
context.inner.inboundState, err = context.inner.responseState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
state := context.inner.inboundState
|
||||
nonce := state.NextNonce()
|
||||
return state.aead.internal().Seal(nil, nonce, message, ad), nil
|
||||
}
|
||||
|
||||
// DecryptFromServer - Verify and decrypt a ciphertext received from the server, with optional associated data
|
||||
func (context *ClientContext) DecryptFromServer(ciphertext []byte, ad []byte) ([]byte, error) {
|
||||
if context.inner.inboundState == nil {
|
||||
var err error
|
||||
context.inner.inboundState, err = context.inner.responseState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
state := context.inner.inboundState
|
||||
nonce := state.NextNonce()
|
||||
return state.aead.internal().Open(nil, nonce, ciphertext, ad)
|
||||
}
|
||||
|
||||
// ExporterSecret - Return the exporter secret
|
||||
func (context *ClientContext) ExporterSecret() []byte {
|
||||
return context.inner.exporterSecret
|
||||
}
|
||||
|
||||
// ExporterSecret - Return the exporter secret
|
||||
func (context *ServerContext) ExporterSecret() []byte {
|
||||
return context.inner.exporterSecret
|
||||
}
|
||||
|
||||
// Export - Return the exporter secret
|
||||
func (context *ClientContext) Export(exporterContext []byte, length uint16) ([]byte, error) {
|
||||
return context.inner.export(exporterContext, length)
|
||||
}
|
||||
|
||||
// Export - Return the exporter secret
|
||||
func (context *ServerContext) Export(exporterContext []byte, length uint16) ([]byte, error) {
|
||||
return context.inner.export(exporterContext, length)
|
||||
}
|
||||
|
||||
type aeadImpl interface {
|
||||
internal() cipher.AEAD
|
||||
}
|
||||
|
||||
type aeadAesImpl struct {
|
||||
impl cipher.AEAD
|
||||
}
|
||||
|
||||
func newAesAead(key []byte) (aeadAesImpl, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return aeadAesImpl{}, nil
|
||||
}
|
||||
aesGcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return aeadAesImpl{}, nil
|
||||
}
|
||||
aead := aeadAesImpl{impl: aesGcm}
|
||||
return aead, nil
|
||||
}
|
||||
|
||||
func (aead aeadAesImpl) internal() cipher.AEAD {
|
||||
return aead.impl
|
||||
}
|
||||
|
||||
type aeadChaChaPolyImpl struct {
|
||||
impl cipher.AEAD
|
||||
}
|
||||
|
||||
func newChaChaPolyAead(key []byte) (aeadChaChaPolyImpl, error) {
|
||||
impl, err := chacha20poly1305.New(key)
|
||||
if err != nil {
|
||||
return aeadChaChaPolyImpl{}, nil
|
||||
}
|
||||
aead := aeadChaChaPolyImpl{impl: impl}
|
||||
return aead, nil
|
||||
}
|
||||
|
||||
func (aead aeadChaChaPolyImpl) internal() cipher.AEAD {
|
||||
return aead.impl
|
||||
}
|
17
vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
generated
vendored
Normal file
17
vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.11 && gc && !purego
|
||||
// +build go1.11,gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
const bufSize = 256
|
||||
|
||||
//go:noescape
|
||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||
|
||||
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
|
||||
}
|
307
vendor/golang.org/x/crypto/chacha20/chacha_arm64.s
generated
vendored
Normal file
307
vendor/golang.org/x/crypto/chacha20/chacha_arm64.s
generated
vendored
Normal file
|
@ -0,0 +1,307 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.11,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
#define NUM_ROUNDS 10
|
||||
|
||||
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
||||
MOVD dst+0(FP), R1
|
||||
MOVD src+24(FP), R2
|
||||
MOVD src_len+32(FP), R3
|
||||
MOVD key+48(FP), R4
|
||||
MOVD nonce+56(FP), R6
|
||||
MOVD counter+64(FP), R7
|
||||
|
||||
MOVD $·constants(SB), R10
|
||||
MOVD $·incRotMatrix(SB), R11
|
||||
|
||||
MOVW (R7), R20
|
||||
|
||||
AND $~255, R3, R13
|
||||
ADD R2, R13, R12 // R12 for block end
|
||||
AND $255, R3, R13
|
||||
loop:
|
||||
MOVD $NUM_ROUNDS, R21
|
||||
VLD1 (R11), [V30.S4, V31.S4]
|
||||
|
||||
// load contants
|
||||
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
|
||||
WORD $0x4D60E940
|
||||
|
||||
// load keys
|
||||
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4]
|
||||
WORD $0x4DFFE884
|
||||
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4]
|
||||
WORD $0x4DFFE888
|
||||
SUB $32, R4
|
||||
|
||||
// load counter + nonce
|
||||
// VLD1R (R7), [V12.S4]
|
||||
WORD $0x4D40C8EC
|
||||
|
||||
// VLD3R (R6), [V13.S4, V14.S4, V15.S4]
|
||||
WORD $0x4D40E8CD
|
||||
|
||||
// update counter
|
||||
VADD V30.S4, V12.S4, V12.S4
|
||||
|
||||
chacha:
|
||||
// V0..V3 += V4..V7
|
||||
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16)
|
||||
VADD V0.S4, V4.S4, V0.S4
|
||||
VADD V1.S4, V5.S4, V1.S4
|
||||
VADD V2.S4, V6.S4, V2.S4
|
||||
VADD V3.S4, V7.S4, V3.S4
|
||||
VEOR V12.B16, V0.B16, V12.B16
|
||||
VEOR V13.B16, V1.B16, V13.B16
|
||||
VEOR V14.B16, V2.B16, V14.B16
|
||||
VEOR V15.B16, V3.B16, V15.B16
|
||||
VREV32 V12.H8, V12.H8
|
||||
VREV32 V13.H8, V13.H8
|
||||
VREV32 V14.H8, V14.H8
|
||||
VREV32 V15.H8, V15.H8
|
||||
// V8..V11 += V12..V15
|
||||
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12)
|
||||
VADD V8.S4, V12.S4, V8.S4
|
||||
VADD V9.S4, V13.S4, V9.S4
|
||||
VADD V10.S4, V14.S4, V10.S4
|
||||
VADD V11.S4, V15.S4, V11.S4
|
||||
VEOR V8.B16, V4.B16, V16.B16
|
||||
VEOR V9.B16, V5.B16, V17.B16
|
||||
VEOR V10.B16, V6.B16, V18.B16
|
||||
VEOR V11.B16, V7.B16, V19.B16
|
||||
VSHL $12, V16.S4, V4.S4
|
||||
VSHL $12, V17.S4, V5.S4
|
||||
VSHL $12, V18.S4, V6.S4
|
||||
VSHL $12, V19.S4, V7.S4
|
||||
VSRI $20, V16.S4, V4.S4
|
||||
VSRI $20, V17.S4, V5.S4
|
||||
VSRI $20, V18.S4, V6.S4
|
||||
VSRI $20, V19.S4, V7.S4
|
||||
|
||||
// V0..V3 += V4..V7
|
||||
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8)
|
||||
VADD V0.S4, V4.S4, V0.S4
|
||||
VADD V1.S4, V5.S4, V1.S4
|
||||
VADD V2.S4, V6.S4, V2.S4
|
||||
VADD V3.S4, V7.S4, V3.S4
|
||||
VEOR V12.B16, V0.B16, V12.B16
|
||||
VEOR V13.B16, V1.B16, V13.B16
|
||||
VEOR V14.B16, V2.B16, V14.B16
|
||||
VEOR V15.B16, V3.B16, V15.B16
|
||||
VTBL V31.B16, [V12.B16], V12.B16
|
||||
VTBL V31.B16, [V13.B16], V13.B16
|
||||
VTBL V31.B16, [V14.B16], V14.B16
|
||||
VTBL V31.B16, [V15.B16], V15.B16
|
||||
|
||||
// V8..V11 += V12..V15
|
||||
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7)
|
||||
VADD V12.S4, V8.S4, V8.S4
|
||||
VADD V13.S4, V9.S4, V9.S4
|
||||
VADD V14.S4, V10.S4, V10.S4
|
||||
VADD V15.S4, V11.S4, V11.S4
|
||||
VEOR V8.B16, V4.B16, V16.B16
|
||||
VEOR V9.B16, V5.B16, V17.B16
|
||||
VEOR V10.B16, V6.B16, V18.B16
|
||||
VEOR V11.B16, V7.B16, V19.B16
|
||||
VSHL $7, V16.S4, V4.S4
|
||||
VSHL $7, V17.S4, V5.S4
|
||||
VSHL $7, V18.S4, V6.S4
|
||||
VSHL $7, V19.S4, V7.S4
|
||||
VSRI $25, V16.S4, V4.S4
|
||||
VSRI $25, V17.S4, V5.S4
|
||||
VSRI $25, V18.S4, V6.S4
|
||||
VSRI $25, V19.S4, V7.S4
|
||||
|
||||
// V0..V3 += V5..V7, V4
|
||||
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16)
|
||||
VADD V0.S4, V5.S4, V0.S4
|
||||
VADD V1.S4, V6.S4, V1.S4
|
||||
VADD V2.S4, V7.S4, V2.S4
|
||||
VADD V3.S4, V4.S4, V3.S4
|
||||
VEOR V15.B16, V0.B16, V15.B16
|
||||
VEOR V12.B16, V1.B16, V12.B16
|
||||
VEOR V13.B16, V2.B16, V13.B16
|
||||
VEOR V14.B16, V3.B16, V14.B16
|
||||
VREV32 V12.H8, V12.H8
|
||||
VREV32 V13.H8, V13.H8
|
||||
VREV32 V14.H8, V14.H8
|
||||
VREV32 V15.H8, V15.H8
|
||||
|
||||
// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
|
||||
// ...
|
||||
VADD V15.S4, V10.S4, V10.S4
|
||||
VADD V12.S4, V11.S4, V11.S4
|
||||
VADD V13.S4, V8.S4, V8.S4
|
||||
VADD V14.S4, V9.S4, V9.S4
|
||||
VEOR V10.B16, V5.B16, V16.B16
|
||||
VEOR V11.B16, V6.B16, V17.B16
|
||||
VEOR V8.B16, V7.B16, V18.B16
|
||||
VEOR V9.B16, V4.B16, V19.B16
|
||||
VSHL $12, V16.S4, V5.S4
|
||||
VSHL $12, V17.S4, V6.S4
|
||||
VSHL $12, V18.S4, V7.S4
|
||||
VSHL $12, V19.S4, V4.S4
|
||||
VSRI $20, V16.S4, V5.S4
|
||||
VSRI $20, V17.S4, V6.S4
|
||||
VSRI $20, V18.S4, V7.S4
|
||||
VSRI $20, V19.S4, V4.S4
|
||||
|
||||
// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
|
||||
// ...
|
||||
VADD V5.S4, V0.S4, V0.S4
|
||||
VADD V6.S4, V1.S4, V1.S4
|
||||
VADD V7.S4, V2.S4, V2.S4
|
||||
VADD V4.S4, V3.S4, V3.S4
|
||||
VEOR V0.B16, V15.B16, V15.B16
|
||||
VEOR V1.B16, V12.B16, V12.B16
|
||||
VEOR V2.B16, V13.B16, V13.B16
|
||||
VEOR V3.B16, V14.B16, V14.B16
|
||||
VTBL V31.B16, [V12.B16], V12.B16
|
||||
VTBL V31.B16, [V13.B16], V13.B16
|
||||
VTBL V31.B16, [V14.B16], V14.B16
|
||||
VTBL V31.B16, [V15.B16], V15.B16
|
||||
|
||||
// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
|
||||
// ...
|
||||
VADD V15.S4, V10.S4, V10.S4
|
||||
VADD V12.S4, V11.S4, V11.S4
|
||||
VADD V13.S4, V8.S4, V8.S4
|
||||
VADD V14.S4, V9.S4, V9.S4
|
||||
VEOR V10.B16, V5.B16, V16.B16
|
||||
VEOR V11.B16, V6.B16, V17.B16
|
||||
VEOR V8.B16, V7.B16, V18.B16
|
||||
VEOR V9.B16, V4.B16, V19.B16
|
||||
VSHL $7, V16.S4, V5.S4
|
||||
VSHL $7, V17.S4, V6.S4
|
||||
VSHL $7, V18.S4, V7.S4
|
||||
VSHL $7, V19.S4, V4.S4
|
||||
VSRI $25, V16.S4, V5.S4
|
||||
VSRI $25, V17.S4, V6.S4
|
||||
VSRI $25, V18.S4, V7.S4
|
||||
VSRI $25, V19.S4, V4.S4
|
||||
|
||||
SUB $1, R21
|
||||
CBNZ R21, chacha
|
||||
|
||||
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4]
|
||||
WORD $0x4D60E950
|
||||
|
||||
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4]
|
||||
WORD $0x4DFFE894
|
||||
VADD V30.S4, V12.S4, V12.S4
|
||||
VADD V16.S4, V0.S4, V0.S4
|
||||
VADD V17.S4, V1.S4, V1.S4
|
||||
VADD V18.S4, V2.S4, V2.S4
|
||||
VADD V19.S4, V3.S4, V3.S4
|
||||
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4]
|
||||
WORD $0x4DFFE898
|
||||
// restore R4
|
||||
SUB $32, R4
|
||||
|
||||
// load counter + nonce
|
||||
// VLD1R (R7), [V28.S4]
|
||||
WORD $0x4D40C8FC
|
||||
// VLD3R (R6), [V29.S4, V30.S4, V31.S4]
|
||||
WORD $0x4D40E8DD
|
||||
|
||||
VADD V20.S4, V4.S4, V4.S4
|
||||
VADD V21.S4, V5.S4, V5.S4
|
||||
VADD V22.S4, V6.S4, V6.S4
|
||||
VADD V23.S4, V7.S4, V7.S4
|
||||
VADD V24.S4, V8.S4, V8.S4
|
||||
VADD V25.S4, V9.S4, V9.S4
|
||||
VADD V26.S4, V10.S4, V10.S4
|
||||
VADD V27.S4, V11.S4, V11.S4
|
||||
VADD V28.S4, V12.S4, V12.S4
|
||||
VADD V29.S4, V13.S4, V13.S4
|
||||
VADD V30.S4, V14.S4, V14.S4
|
||||
VADD V31.S4, V15.S4, V15.S4
|
||||
|
||||
VZIP1 V1.S4, V0.S4, V16.S4
|
||||
VZIP2 V1.S4, V0.S4, V17.S4
|
||||
VZIP1 V3.S4, V2.S4, V18.S4
|
||||
VZIP2 V3.S4, V2.S4, V19.S4
|
||||
VZIP1 V5.S4, V4.S4, V20.S4
|
||||
VZIP2 V5.S4, V4.S4, V21.S4
|
||||
VZIP1 V7.S4, V6.S4, V22.S4
|
||||
VZIP2 V7.S4, V6.S4, V23.S4
|
||||
VZIP1 V9.S4, V8.S4, V24.S4
|
||||
VZIP2 V9.S4, V8.S4, V25.S4
|
||||
VZIP1 V11.S4, V10.S4, V26.S4
|
||||
VZIP2 V11.S4, V10.S4, V27.S4
|
||||
VZIP1 V13.S4, V12.S4, V28.S4
|
||||
VZIP2 V13.S4, V12.S4, V29.S4
|
||||
VZIP1 V15.S4, V14.S4, V30.S4
|
||||
VZIP2 V15.S4, V14.S4, V31.S4
|
||||
VZIP1 V18.D2, V16.D2, V0.D2
|
||||
VZIP2 V18.D2, V16.D2, V4.D2
|
||||
VZIP1 V19.D2, V17.D2, V8.D2
|
||||
VZIP2 V19.D2, V17.D2, V12.D2
|
||||
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16]
|
||||
|
||||
VZIP1 V22.D2, V20.D2, V1.D2
|
||||
VZIP2 V22.D2, V20.D2, V5.D2
|
||||
VZIP1 V23.D2, V21.D2, V9.D2
|
||||
VZIP2 V23.D2, V21.D2, V13.D2
|
||||
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16]
|
||||
VZIP1 V26.D2, V24.D2, V2.D2
|
||||
VZIP2 V26.D2, V24.D2, V6.D2
|
||||
VZIP1 V27.D2, V25.D2, V10.D2
|
||||
VZIP2 V27.D2, V25.D2, V14.D2
|
||||
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16]
|
||||
VZIP1 V30.D2, V28.D2, V3.D2
|
||||
VZIP2 V30.D2, V28.D2, V7.D2
|
||||
VZIP1 V31.D2, V29.D2, V11.D2
|
||||
VZIP2 V31.D2, V29.D2, V15.D2
|
||||
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16]
|
||||
VEOR V0.B16, V16.B16, V16.B16
|
||||
VEOR V1.B16, V17.B16, V17.B16
|
||||
VEOR V2.B16, V18.B16, V18.B16
|
||||
VEOR V3.B16, V19.B16, V19.B16
|
||||
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1)
|
||||
VEOR V4.B16, V20.B16, V20.B16
|
||||
VEOR V5.B16, V21.B16, V21.B16
|
||||
VEOR V6.B16, V22.B16, V22.B16
|
||||
VEOR V7.B16, V23.B16, V23.B16
|
||||
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1)
|
||||
VEOR V8.B16, V24.B16, V24.B16
|
||||
VEOR V9.B16, V25.B16, V25.B16
|
||||
VEOR V10.B16, V26.B16, V26.B16
|
||||
VEOR V11.B16, V27.B16, V27.B16
|
||||
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1)
|
||||
VEOR V12.B16, V28.B16, V28.B16
|
||||
VEOR V13.B16, V29.B16, V29.B16
|
||||
VEOR V14.B16, V30.B16, V30.B16
|
||||
VEOR V15.B16, V31.B16, V31.B16
|
||||
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1)
|
||||
|
||||
ADD $4, R20
|
||||
MOVW R20, (R7) // update counter
|
||||
|
||||
CMP R2, R12
|
||||
BGT loop
|
||||
|
||||
RET
|
||||
|
||||
|
||||
DATA ·constants+0x00(SB)/4, $0x61707865
|
||||
DATA ·constants+0x04(SB)/4, $0x3320646e
|
||||
DATA ·constants+0x08(SB)/4, $0x79622d32
|
||||
DATA ·constants+0x0c(SB)/4, $0x6b206574
|
||||
GLOBL ·constants(SB), NOPTR|RODATA, $32
|
||||
|
||||
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000
|
||||
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001
|
||||
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002
|
||||
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003
|
||||
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003
|
||||
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407
|
||||
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B
|
||||
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F
|
||||
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32
|
398
vendor/golang.org/x/crypto/chacha20/chacha_generic.go
generated
vendored
Normal file
398
vendor/golang.org/x/crypto/chacha20/chacha_generic.go
generated
vendored
Normal file
|
@ -0,0 +1,398 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms
|
||||
// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01.
|
||||
package chacha20
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math/bits"
|
||||
|
||||
"golang.org/x/crypto/internal/subtle"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeySize is the size of the key used by this cipher, in bytes.
|
||||
KeySize = 32
|
||||
|
||||
// NonceSize is the size of the nonce used with the standard variant of this
|
||||
// cipher, in bytes.
|
||||
//
|
||||
// Note that this is too short to be safely generated at random if the same
|
||||
// key is reused more than 2³² times.
|
||||
NonceSize = 12
|
||||
|
||||
// NonceSizeX is the size of the nonce used with the XChaCha20 variant of
|
||||
// this cipher, in bytes.
|
||||
NonceSizeX = 24
|
||||
)
|
||||
|
||||
// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key
|
||||
// and nonce. A *Cipher implements the cipher.Stream interface.
|
||||
type Cipher struct {
|
||||
// The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter
|
||||
// (incremented after each block), and 3 of nonce.
|
||||
key [8]uint32
|
||||
counter uint32
|
||||
nonce [3]uint32
|
||||
|
||||
// The last len bytes of buf are leftover key stream bytes from the previous
|
||||
// XORKeyStream invocation. The size of buf depends on how many blocks are
|
||||
// computed at a time by xorKeyStreamBlocks.
|
||||
buf [bufSize]byte
|
||||
len int
|
||||
|
||||
// overflow is set when the counter overflowed, no more blocks can be
|
||||
// generated, and the next XORKeyStream call should panic.
|
||||
overflow bool
|
||||
|
||||
// The counter-independent results of the first round are cached after they
|
||||
// are computed the first time.
|
||||
precompDone bool
|
||||
p1, p5, p9, p13 uint32
|
||||
p2, p6, p10, p14 uint32
|
||||
p3, p7, p11, p15 uint32
|
||||
}
|
||||
|
||||
var _ cipher.Stream = (*Cipher)(nil)
|
||||
|
||||
// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given
|
||||
// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided,
|
||||
// the XChaCha20 construction will be used. It returns an error if key or nonce
|
||||
// have any other length.
|
||||
//
|
||||
// Note that ChaCha20, like all stream ciphers, is not authenticated and allows
|
||||
// attackers to silently tamper with the plaintext. For this reason, it is more
|
||||
// appropriate as a building block than as a standalone encryption mechanism.
|
||||
// Instead, consider using package golang.org/x/crypto/chacha20poly1305.
|
||||
func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
|
||||
// This function is split into a wrapper so that the Cipher allocation will
|
||||
// be inlined, and depending on how the caller uses the return value, won't
|
||||
// escape to the heap.
|
||||
c := &Cipher{}
|
||||
return newUnauthenticatedCipher(c, key, nonce)
|
||||
}
|
||||
|
||||
func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
|
||||
if len(key) != KeySize {
|
||||
return nil, errors.New("chacha20: wrong key size")
|
||||
}
|
||||
if len(nonce) == NonceSizeX {
|
||||
// XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a
|
||||
// derived key, allowing it to operate on a nonce of 24 bytes. See
|
||||
// draft-irtf-cfrg-xchacha-01, Section 2.3.
|
||||
key, _ = HChaCha20(key, nonce[0:16])
|
||||
cNonce := make([]byte, NonceSize)
|
||||
copy(cNonce[4:12], nonce[16:24])
|
||||
nonce = cNonce
|
||||
} else if len(nonce) != NonceSize {
|
||||
return nil, errors.New("chacha20: wrong nonce size")
|
||||
}
|
||||
|
||||
key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint
|
||||
c.key = [8]uint32{
|
||||
binary.LittleEndian.Uint32(key[0:4]),
|
||||
binary.LittleEndian.Uint32(key[4:8]),
|
||||
binary.LittleEndian.Uint32(key[8:12]),
|
||||
binary.LittleEndian.Uint32(key[12:16]),
|
||||
binary.LittleEndian.Uint32(key[16:20]),
|
||||
binary.LittleEndian.Uint32(key[20:24]),
|
||||
binary.LittleEndian.Uint32(key[24:28]),
|
||||
binary.LittleEndian.Uint32(key[28:32]),
|
||||
}
|
||||
c.nonce = [3]uint32{
|
||||
binary.LittleEndian.Uint32(nonce[0:4]),
|
||||
binary.LittleEndian.Uint32(nonce[4:8]),
|
||||
binary.LittleEndian.Uint32(nonce[8:12]),
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// The constant first 4 words of the ChaCha20 state.
|
||||
const (
|
||||
j0 uint32 = 0x61707865 // expa
|
||||
j1 uint32 = 0x3320646e // nd 3
|
||||
j2 uint32 = 0x79622d32 // 2-by
|
||||
j3 uint32 = 0x6b206574 // te k
|
||||
)
|
||||
|
||||
const blockSize = 64
|
||||
|
||||
// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words.
|
||||
// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16
|
||||
// words each round, in columnar or diagonal groups of 4 at a time.
|
||||
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
|
||||
a += b
|
||||
d ^= a
|
||||
d = bits.RotateLeft32(d, 16)
|
||||
c += d
|
||||
b ^= c
|
||||
b = bits.RotateLeft32(b, 12)
|
||||
a += b
|
||||
d ^= a
|
||||
d = bits.RotateLeft32(d, 8)
|
||||
c += d
|
||||
b ^= c
|
||||
b = bits.RotateLeft32(b, 7)
|
||||
return a, b, c, d
|
||||
}
|
||||
|
||||
// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
|
||||
// behave as if (64 * counter) bytes had been encrypted so far.
|
||||
//
|
||||
// To prevent accidental counter reuse, SetCounter panics if counter is less
|
||||
// than the current value.
|
||||
//
|
||||
// Note that the execution time of XORKeyStream is not independent of the
|
||||
// counter value.
|
||||
func (s *Cipher) SetCounter(counter uint32) {
|
||||
// Internally, s may buffer multiple blocks, which complicates this
|
||||
// implementation slightly. When checking whether the counter has rolled
|
||||
// back, we must use both s.counter and s.len to determine how many blocks
|
||||
// we have already output.
|
||||
outputCounter := s.counter - uint32(s.len)/blockSize
|
||||
if s.overflow || counter < outputCounter {
|
||||
panic("chacha20: SetCounter attempted to rollback counter")
|
||||
}
|
||||
|
||||
// In the general case, we set the new counter value and reset s.len to 0,
|
||||
// causing the next call to XORKeyStream to refill the buffer. However, if
|
||||
// we're advancing within the existing buffer, we can save work by simply
|
||||
// setting s.len.
|
||||
if counter < s.counter {
|
||||
s.len = int(s.counter-counter) * blockSize
|
||||
} else {
|
||||
s.counter = counter
|
||||
s.len = 0
|
||||
}
|
||||
}
|
||||
|
||||
// XORKeyStream XORs each byte in the given slice with a byte from the
|
||||
// cipher's key stream. Dst and src must overlap entirely or not at all.
|
||||
//
|
||||
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
|
||||
// to pass a dst bigger than src, and in that case, XORKeyStream will
|
||||
// only update dst[:len(src)] and will not touch the rest of dst.
|
||||
//
|
||||
// Multiple calls to XORKeyStream behave as if the concatenation of
|
||||
// the src buffers was passed in a single run. That is, Cipher
|
||||
// maintains state and does not reset at each XORKeyStream call.
|
||||
func (s *Cipher) XORKeyStream(dst, src []byte) {
|
||||
if len(src) == 0 {
|
||||
return
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("chacha20: output smaller than input")
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
if subtle.InexactOverlap(dst, src) {
|
||||
panic("chacha20: invalid buffer overlap")
|
||||
}
|
||||
|
||||
// First, drain any remaining key stream from a previous XORKeyStream.
|
||||
if s.len != 0 {
|
||||
keyStream := s.buf[bufSize-s.len:]
|
||||
if len(src) < len(keyStream) {
|
||||
keyStream = keyStream[:len(src)]
|
||||
}
|
||||
_ = src[len(keyStream)-1] // bounds check elimination hint
|
||||
for i, b := range keyStream {
|
||||
dst[i] = src[i] ^ b
|
||||
}
|
||||
s.len -= len(keyStream)
|
||||
dst, src = dst[len(keyStream):], src[len(keyStream):]
|
||||
}
|
||||
if len(src) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// If we'd need to let the counter overflow and keep generating output,
|
||||
// panic immediately. If instead we'd only reach the last block, remember
|
||||
// not to generate any more output after the buffer is drained.
|
||||
numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize
|
||||
if s.overflow || uint64(s.counter)+numBlocks > 1<<32 {
|
||||
panic("chacha20: counter overflow")
|
||||
} else if uint64(s.counter)+numBlocks == 1<<32 {
|
||||
s.overflow = true
|
||||
}
|
||||
|
||||
// xorKeyStreamBlocks implementations expect input lengths that are a
|
||||
// multiple of bufSize. Platform-specific ones process multiple blocks at a
|
||||
// time, so have bufSizes that are a multiple of blockSize.
|
||||
|
||||
full := len(src) - len(src)%bufSize
|
||||
if full > 0 {
|
||||
s.xorKeyStreamBlocks(dst[:full], src[:full])
|
||||
}
|
||||
dst, src = dst[full:], src[full:]
|
||||
|
||||
// If using a multi-block xorKeyStreamBlocks would overflow, use the generic
|
||||
// one that does one block at a time.
|
||||
const blocksPerBuf = bufSize / blockSize
|
||||
if uint64(s.counter)+blocksPerBuf > 1<<32 {
|
||||
s.buf = [bufSize]byte{}
|
||||
numBlocks := (len(src) + blockSize - 1) / blockSize
|
||||
buf := s.buf[bufSize-numBlocks*blockSize:]
|
||||
copy(buf, src)
|
||||
s.xorKeyStreamBlocksGeneric(buf, buf)
|
||||
s.len = len(buf) - copy(dst, buf)
|
||||
return
|
||||
}
|
||||
|
||||
// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
|
||||
// keep the leftover keystream for the next XORKeyStream invocation.
|
||||
if len(src) > 0 {
|
||||
s.buf = [bufSize]byte{}
|
||||
copy(s.buf[:], src)
|
||||
s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
|
||||
s.len = bufSize - copy(dst, s.buf[:])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
|
||||
if len(dst) != len(src) || len(dst)%blockSize != 0 {
|
||||
panic("chacha20: internal error: wrong dst and/or src length")
|
||||
}
|
||||
|
||||
// To generate each block of key stream, the initial cipher state
|
||||
// (represented below) is passed through 20 rounds of shuffling,
|
||||
// alternatively applying quarterRounds by columns (like 1, 5, 9, 13)
|
||||
// or by diagonals (like 1, 6, 11, 12).
|
||||
//
|
||||
// 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc
|
||||
// 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk
|
||||
// 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk
|
||||
// 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn
|
||||
//
|
||||
// c=constant k=key b=blockcount n=nonce
|
||||
var (
|
||||
c0, c1, c2, c3 = j0, j1, j2, j3
|
||||
c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3]
|
||||
c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7]
|
||||
_, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2]
|
||||
)
|
||||
|
||||
// Three quarters of the first round don't depend on the counter, so we can
|
||||
// calculate them here, and reuse them for multiple blocks in the loop, and
|
||||
// for future XORKeyStream invocations.
|
||||
if !s.precompDone {
|
||||
s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13)
|
||||
s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14)
|
||||
s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15)
|
||||
s.precompDone = true
|
||||
}
|
||||
|
||||
// A condition of len(src) > 0 would be sufficient, but this also
|
||||
// acts as a bounds check elimination hint.
|
||||
for len(src) >= 64 && len(dst) >= 64 {
|
||||
// The remainder of the first column round.
|
||||
fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
|
||||
|
||||
// The second diagonal round.
|
||||
x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15)
|
||||
x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12)
|
||||
x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13)
|
||||
x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14)
|
||||
|
||||
// The remaining 18 rounds.
|
||||
for i := 0; i < 9; i++ {
|
||||
// Column round.
|
||||
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
|
||||
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
|
||||
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
|
||||
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
|
||||
|
||||
// Diagonal round.
|
||||
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
|
||||
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
|
||||
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
|
||||
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
|
||||
}
|
||||
|
||||
// Add back the initial state to generate the key stream, then
|
||||
// XOR the key stream with the source and write out the result.
|
||||
addXor(dst[0:4], src[0:4], x0, c0)
|
||||
addXor(dst[4:8], src[4:8], x1, c1)
|
||||
addXor(dst[8:12], src[8:12], x2, c2)
|
||||
addXor(dst[12:16], src[12:16], x3, c3)
|
||||
addXor(dst[16:20], src[16:20], x4, c4)
|
||||
addXor(dst[20:24], src[20:24], x5, c5)
|
||||
addXor(dst[24:28], src[24:28], x6, c6)
|
||||
addXor(dst[28:32], src[28:32], x7, c7)
|
||||
addXor(dst[32:36], src[32:36], x8, c8)
|
||||
addXor(dst[36:40], src[36:40], x9, c9)
|
||||
addXor(dst[40:44], src[40:44], x10, c10)
|
||||
addXor(dst[44:48], src[44:48], x11, c11)
|
||||
addXor(dst[48:52], src[48:52], x12, s.counter)
|
||||
addXor(dst[52:56], src[52:56], x13, c13)
|
||||
addXor(dst[56:60], src[56:60], x14, c14)
|
||||
addXor(dst[60:64], src[60:64], x15, c15)
|
||||
|
||||
s.counter += 1
|
||||
|
||||
src, dst = src[blockSize:], dst[blockSize:]
|
||||
}
|
||||
}
|
||||
|
||||
// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes
|
||||
// key and a 16 bytes nonce. It returns an error if key or nonce have any other
|
||||
// length. It is used as part of the XChaCha20 construction.
|
||||
func HChaCha20(key, nonce []byte) ([]byte, error) {
|
||||
// This function is split into a wrapper so that the slice allocation will
|
||||
// be inlined, and depending on how the caller uses the return value, won't
|
||||
// escape to the heap.
|
||||
out := make([]byte, 32)
|
||||
return hChaCha20(out, key, nonce)
|
||||
}
|
||||
|
||||
func hChaCha20(out, key, nonce []byte) ([]byte, error) {
|
||||
if len(key) != KeySize {
|
||||
return nil, errors.New("chacha20: wrong HChaCha20 key size")
|
||||
}
|
||||
if len(nonce) != 16 {
|
||||
return nil, errors.New("chacha20: wrong HChaCha20 nonce size")
|
||||
}
|
||||
|
||||
x0, x1, x2, x3 := j0, j1, j2, j3
|
||||
x4 := binary.LittleEndian.Uint32(key[0:4])
|
||||
x5 := binary.LittleEndian.Uint32(key[4:8])
|
||||
x6 := binary.LittleEndian.Uint32(key[8:12])
|
||||
x7 := binary.LittleEndian.Uint32(key[12:16])
|
||||
x8 := binary.LittleEndian.Uint32(key[16:20])
|
||||
x9 := binary.LittleEndian.Uint32(key[20:24])
|
||||
x10 := binary.LittleEndian.Uint32(key[24:28])
|
||||
x11 := binary.LittleEndian.Uint32(key[28:32])
|
||||
x12 := binary.LittleEndian.Uint32(nonce[0:4])
|
||||
x13 := binary.LittleEndian.Uint32(nonce[4:8])
|
||||
x14 := binary.LittleEndian.Uint32(nonce[8:12])
|
||||
x15 := binary.LittleEndian.Uint32(nonce[12:16])
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
// Diagonal round.
|
||||
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
|
||||
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
|
||||
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
|
||||
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
|
||||
|
||||
// Column round.
|
||||
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
|
||||
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
|
||||
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
|
||||
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
|
||||
}
|
||||
|
||||
_ = out[31] // bounds check elimination hint
|
||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], x12)
|
||||
binary.LittleEndian.PutUint32(out[20:24], x13)
|
||||
binary.LittleEndian.PutUint32(out[24:28], x14)
|
||||
binary.LittleEndian.PutUint32(out[28:32], x15)
|
||||
return out, nil
|
||||
}
|
14
vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
generated
vendored
Normal file
14
vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego
|
||||
// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego
|
||||
|
||||
package chacha20
|
||||
|
||||
const bufSize = blockSize
|
||||
|
||||
func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||
s.xorKeyStreamBlocksGeneric(dst, src)
|
||||
}
|
17
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
generated
vendored
Normal file
17
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
const bufSize = 256
|
||||
|
||||
//go:noescape
|
||||
func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||
|
||||
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||
chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
|
||||
}
|
449
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
generated
vendored
Normal file
449
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
generated
vendored
Normal file
|
@ -0,0 +1,449 @@
|
|||
// 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/.
|
||||
// # ====================================================================
|
||||
|
||||
// Code for the perl script that generates the ppc64 assembler
|
||||
// can be found in the cryptogams repository at the link below. It is based on
|
||||
// the original from openssl.
|
||||
|
||||
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91
|
||||
|
||||
// The differences in this and the original implementation are
|
||||
// due to the calling conventions and initialization of constants.
|
||||
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
#define OUT R3
|
||||
#define INP R4
|
||||
#define LEN R5
|
||||
#define KEY R6
|
||||
#define CNT R7
|
||||
#define TMP R15
|
||||
|
||||
#define CONSTBASE R16
|
||||
#define BLOCKS R17
|
||||
|
||||
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
|
||||
DATA consts<>+0x50(SB)/8, $0x6170786561707865
|
||||
DATA consts<>+0x58(SB)/8, $0x6170786561707865
|
||||
DATA consts<>+0x60(SB)/8, $0x3320646e3320646e
|
||||
DATA consts<>+0x68(SB)/8, $0x3320646e3320646e
|
||||
DATA consts<>+0x70(SB)/8, $0x79622d3279622d32
|
||||
DATA consts<>+0x78(SB)/8, $0x79622d3279622d32
|
||||
DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
|
||||
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
|
||||
DATA consts<>+0x90(SB)/8, $0x0000000100000000
|
||||
DATA consts<>+0x98(SB)/8, $0x0000000300000002
|
||||
GLOBL consts<>(SB), RODATA, $0xa0
|
||||
|
||||
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||
MOVD out+0(FP), OUT
|
||||
MOVD inp+8(FP), INP
|
||||
MOVD len+16(FP), LEN
|
||||
MOVD key+24(FP), KEY
|
||||
MOVD counter+32(FP), CNT
|
||||
|
||||
// Addressing for constants
|
||||
MOVD $consts<>+0x00(SB), CONSTBASE
|
||||
MOVD $16, R8
|
||||
MOVD $32, R9
|
||||
MOVD $48, R10
|
||||
MOVD $64, R11
|
||||
SRD $6, LEN, BLOCKS
|
||||
// V16
|
||||
LXVW4X (CONSTBASE)(R0), VS48
|
||||
ADD $80,CONSTBASE
|
||||
|
||||
// Load key into V17,V18
|
||||
LXVW4X (KEY)(R0), VS49
|
||||
LXVW4X (KEY)(R8), VS50
|
||||
|
||||
// Load CNT, NONCE into V19
|
||||
LXVW4X (CNT)(R0), VS51
|
||||
|
||||
// Clear V27
|
||||
VXOR V27, V27, V27
|
||||
|
||||
// V28
|
||||
LXVW4X (CONSTBASE)(R11), VS60
|
||||
|
||||
// splat slot from V19 -> V26
|
||||
VSPLTW $0, V19, V26
|
||||
|
||||
VSLDOI $4, V19, V27, V19
|
||||
VSLDOI $12, V27, V19, V19
|
||||
|
||||
VADDUWM V26, V28, V26
|
||||
|
||||
MOVD $10, R14
|
||||
MOVD R14, CTR
|
||||
|
||||
loop_outer_vsx:
|
||||
// V0, V1, V2, V3
|
||||
LXVW4X (R0)(CONSTBASE), VS32
|
||||
LXVW4X (R8)(CONSTBASE), VS33
|
||||
LXVW4X (R9)(CONSTBASE), VS34
|
||||
LXVW4X (R10)(CONSTBASE), VS35
|
||||
|
||||
// splat values from V17, V18 into V4-V11
|
||||
VSPLTW $0, V17, V4
|
||||
VSPLTW $1, V17, V5
|
||||
VSPLTW $2, V17, V6
|
||||
VSPLTW $3, V17, V7
|
||||
VSPLTW $0, V18, V8
|
||||
VSPLTW $1, V18, V9
|
||||
VSPLTW $2, V18, V10
|
||||
VSPLTW $3, V18, V11
|
||||
|
||||
// VOR
|
||||
VOR V26, V26, V12
|
||||
|
||||
// splat values from V19 -> V13, V14, V15
|
||||
VSPLTW $1, V19, V13
|
||||
VSPLTW $2, V19, V14
|
||||
VSPLTW $3, V19, V15
|
||||
|
||||
// splat const values
|
||||
VSPLTISW $-16, V27
|
||||
VSPLTISW $12, V28
|
||||
VSPLTISW $8, V29
|
||||
VSPLTISW $7, V30
|
||||
|
||||
loop_vsx:
|
||||
VADDUWM V0, V4, V0
|
||||
VADDUWM V1, V5, V1
|
||||
VADDUWM V2, V6, V2
|
||||
VADDUWM V3, V7, V3
|
||||
|
||||
VXOR V12, V0, V12
|
||||
VXOR V13, V1, V13
|
||||
VXOR V14, V2, V14
|
||||
VXOR V15, V3, V15
|
||||
|
||||
VRLW V12, V27, V12
|
||||
VRLW V13, V27, V13
|
||||
VRLW V14, V27, V14
|
||||
VRLW V15, V27, V15
|
||||
|
||||
VADDUWM V8, V12, V8
|
||||
VADDUWM V9, V13, V9
|
||||
VADDUWM V10, V14, V10
|
||||
VADDUWM V11, V15, V11
|
||||
|
||||
VXOR V4, V8, V4
|
||||
VXOR V5, V9, V5
|
||||
VXOR V6, V10, V6
|
||||
VXOR V7, V11, V7
|
||||
|
||||
VRLW V4, V28, V4
|
||||
VRLW V5, V28, V5
|
||||
VRLW V6, V28, V6
|
||||
VRLW V7, V28, V7
|
||||
|
||||
VADDUWM V0, V4, V0
|
||||
VADDUWM V1, V5, V1
|
||||
VADDUWM V2, V6, V2
|
||||
VADDUWM V3, V7, V3
|
||||
|
||||
VXOR V12, V0, V12
|
||||
VXOR V13, V1, V13
|
||||
VXOR V14, V2, V14
|
||||
VXOR V15, V3, V15
|
||||
|
||||
VRLW V12, V29, V12
|
||||
VRLW V13, V29, V13
|
||||
VRLW V14, V29, V14
|
||||
VRLW V15, V29, V15
|
||||
|
||||
VADDUWM V8, V12, V8
|
||||
VADDUWM V9, V13, V9
|
||||
VADDUWM V10, V14, V10
|
||||
VADDUWM V11, V15, V11
|
||||
|
||||
VXOR V4, V8, V4
|
||||
VXOR V5, V9, V5
|
||||
VXOR V6, V10, V6
|
||||
VXOR V7, V11, V7
|
||||
|
||||
VRLW V4, V30, V4
|
||||
VRLW V5, V30, V5
|
||||
VRLW V6, V30, V6
|
||||
VRLW V7, V30, V7
|
||||
|
||||
VADDUWM V0, V5, V0
|
||||
VADDUWM V1, V6, V1
|
||||
VADDUWM V2, V7, V2
|
||||
VADDUWM V3, V4, V3
|
||||
|
||||
VXOR V15, V0, V15
|
||||
VXOR V12, V1, V12
|
||||
VXOR V13, V2, V13
|
||||
VXOR V14, V3, V14
|
||||
|
||||
VRLW V15, V27, V15
|
||||
VRLW V12, V27, V12
|
||||
VRLW V13, V27, V13
|
||||
VRLW V14, V27, V14
|
||||
|
||||
VADDUWM V10, V15, V10
|
||||
VADDUWM V11, V12, V11
|
||||
VADDUWM V8, V13, V8
|
||||
VADDUWM V9, V14, V9
|
||||
|
||||
VXOR V5, V10, V5
|
||||
VXOR V6, V11, V6
|
||||
VXOR V7, V8, V7
|
||||
VXOR V4, V9, V4
|
||||
|
||||
VRLW V5, V28, V5
|
||||
VRLW V6, V28, V6
|
||||
VRLW V7, V28, V7
|
||||
VRLW V4, V28, V4
|
||||
|
||||
VADDUWM V0, V5, V0
|
||||
VADDUWM V1, V6, V1
|
||||
VADDUWM V2, V7, V2
|
||||
VADDUWM V3, V4, V3
|
||||
|
||||
VXOR V15, V0, V15
|
||||
VXOR V12, V1, V12
|
||||
VXOR V13, V2, V13
|
||||
VXOR V14, V3, V14
|
||||
|
||||
VRLW V15, V29, V15
|
||||
VRLW V12, V29, V12
|
||||
VRLW V13, V29, V13
|
||||
VRLW V14, V29, V14
|
||||
|
||||
VADDUWM V10, V15, V10
|
||||
VADDUWM V11, V12, V11
|
||||
VADDUWM V8, V13, V8
|
||||
VADDUWM V9, V14, V9
|
||||
|
||||
VXOR V5, V10, V5
|
||||
VXOR V6, V11, V6
|
||||
VXOR V7, V8, V7
|
||||
VXOR V4, V9, V4
|
||||
|
||||
VRLW V5, V30, V5
|
||||
VRLW V6, V30, V6
|
||||
VRLW V7, V30, V7
|
||||
VRLW V4, V30, V4
|
||||
BC 16, LT, loop_vsx
|
||||
|
||||
VADDUWM V12, V26, V12
|
||||
|
||||
WORD $0x13600F8C // VMRGEW V0, V1, V27
|
||||
WORD $0x13821F8C // VMRGEW V2, V3, V28
|
||||
|
||||
WORD $0x10000E8C // VMRGOW V0, V1, V0
|
||||
WORD $0x10421E8C // VMRGOW V2, V3, V2
|
||||
|
||||
WORD $0x13A42F8C // VMRGEW V4, V5, V29
|
||||
WORD $0x13C63F8C // VMRGEW V6, V7, V30
|
||||
|
||||
XXPERMDI VS32, VS34, $0, VS33
|
||||
XXPERMDI VS32, VS34, $3, VS35
|
||||
XXPERMDI VS59, VS60, $0, VS32
|
||||
XXPERMDI VS59, VS60, $3, VS34
|
||||
|
||||
WORD $0x10842E8C // VMRGOW V4, V5, V4
|
||||
WORD $0x10C63E8C // VMRGOW V6, V7, V6
|
||||
|
||||
WORD $0x13684F8C // VMRGEW V8, V9, V27
|
||||
WORD $0x138A5F8C // VMRGEW V10, V11, V28
|
||||
|
||||
XXPERMDI VS36, VS38, $0, VS37
|
||||
XXPERMDI VS36, VS38, $3, VS39
|
||||
XXPERMDI VS61, VS62, $0, VS36
|
||||
XXPERMDI VS61, VS62, $3, VS38
|
||||
|
||||
WORD $0x11084E8C // VMRGOW V8, V9, V8
|
||||
WORD $0x114A5E8C // VMRGOW V10, V11, V10
|
||||
|
||||
WORD $0x13AC6F8C // VMRGEW V12, V13, V29
|
||||
WORD $0x13CE7F8C // VMRGEW V14, V15, V30
|
||||
|
||||
XXPERMDI VS40, VS42, $0, VS41
|
||||
XXPERMDI VS40, VS42, $3, VS43
|
||||
XXPERMDI VS59, VS60, $0, VS40
|
||||
XXPERMDI VS59, VS60, $3, VS42
|
||||
|
||||
WORD $0x118C6E8C // VMRGOW V12, V13, V12
|
||||
WORD $0x11CE7E8C // VMRGOW V14, V15, V14
|
||||
|
||||
VSPLTISW $4, V27
|
||||
VADDUWM V26, V27, V26
|
||||
|
||||
XXPERMDI VS44, VS46, $0, VS45
|
||||
XXPERMDI VS44, VS46, $3, VS47
|
||||
XXPERMDI VS61, VS62, $0, VS44
|
||||
XXPERMDI VS61, VS62, $3, VS46
|
||||
|
||||
VADDUWM V0, V16, V0
|
||||
VADDUWM V4, V17, V4
|
||||
VADDUWM V8, V18, V8
|
||||
VADDUWM V12, V19, V12
|
||||
|
||||
CMPU LEN, $64
|
||||
BLT tail_vsx
|
||||
|
||||
// Bottom of loop
|
||||
LXVW4X (INP)(R0), VS59
|
||||
LXVW4X (INP)(R8), VS60
|
||||
LXVW4X (INP)(R9), VS61
|
||||
LXVW4X (INP)(R10), VS62
|
||||
|
||||
VXOR V27, V0, V27
|
||||
VXOR V28, V4, V28
|
||||
VXOR V29, V8, V29
|
||||
VXOR V30, V12, V30
|
||||
|
||||
STXVW4X VS59, (OUT)(R0)
|
||||
STXVW4X VS60, (OUT)(R8)
|
||||
ADD $64, INP
|
||||
STXVW4X VS61, (OUT)(R9)
|
||||
ADD $-64, LEN
|
||||
STXVW4X VS62, (OUT)(R10)
|
||||
ADD $64, OUT
|
||||
BEQ done_vsx
|
||||
|
||||
VADDUWM V1, V16, V0
|
||||
VADDUWM V5, V17, V4
|
||||
VADDUWM V9, V18, V8
|
||||
VADDUWM V13, V19, V12
|
||||
|
||||
CMPU LEN, $64
|
||||
BLT tail_vsx
|
||||
|
||||
LXVW4X (INP)(R0), VS59
|
||||
LXVW4X (INP)(R8), VS60
|
||||
LXVW4X (INP)(R9), VS61
|
||||
LXVW4X (INP)(R10), VS62
|
||||
VXOR V27, V0, V27
|
||||
|
||||
VXOR V28, V4, V28
|
||||
VXOR V29, V8, V29
|
||||
VXOR V30, V12, V30
|
||||
|
||||
STXVW4X VS59, (OUT)(R0)
|
||||
STXVW4X VS60, (OUT)(R8)
|
||||
ADD $64, INP
|
||||
STXVW4X VS61, (OUT)(R9)
|
||||
ADD $-64, LEN
|
||||
STXVW4X VS62, (OUT)(V10)
|
||||
ADD $64, OUT
|
||||
BEQ done_vsx
|
||||
|
||||
VADDUWM V2, V16, V0
|
||||
VADDUWM V6, V17, V4
|
||||
VADDUWM V10, V18, V8
|
||||
VADDUWM V14, V19, V12
|
||||
|
||||
CMPU LEN, $64
|
||||
BLT tail_vsx
|
||||
|
||||
LXVW4X (INP)(R0), VS59
|
||||
LXVW4X (INP)(R8), VS60
|
||||
LXVW4X (INP)(R9), VS61
|
||||
LXVW4X (INP)(R10), VS62
|
||||
|
||||
VXOR V27, V0, V27
|
||||
VXOR V28, V4, V28
|
||||
VXOR V29, V8, V29
|
||||
VXOR V30, V12, V30
|
||||
|
||||
STXVW4X VS59, (OUT)(R0)
|
||||
STXVW4X VS60, (OUT)(R8)
|
||||
ADD $64, INP
|
||||
STXVW4X VS61, (OUT)(R9)
|
||||
ADD $-64, LEN
|
||||
STXVW4X VS62, (OUT)(R10)
|
||||
ADD $64, OUT
|
||||
BEQ done_vsx
|
||||
|
||||
VADDUWM V3, V16, V0
|
||||
VADDUWM V7, V17, V4
|
||||
VADDUWM V11, V18, V8
|
||||
VADDUWM V15, V19, V12
|
||||
|
||||
CMPU LEN, $64
|
||||
BLT tail_vsx
|
||||
|
||||
LXVW4X (INP)(R0), VS59
|
||||
LXVW4X (INP)(R8), VS60
|
||||
LXVW4X (INP)(R9), VS61
|
||||
LXVW4X (INP)(R10), VS62
|
||||
|
||||
VXOR V27, V0, V27
|
||||
VXOR V28, V4, V28
|
||||
VXOR V29, V8, V29
|
||||
VXOR V30, V12, V30
|
||||
|
||||
STXVW4X VS59, (OUT)(R0)
|
||||
STXVW4X VS60, (OUT)(R8)
|
||||
ADD $64, INP
|
||||
STXVW4X VS61, (OUT)(R9)
|
||||
ADD $-64, LEN
|
||||
STXVW4X VS62, (OUT)(R10)
|
||||
ADD $64, OUT
|
||||
|
||||
MOVD $10, R14
|
||||
MOVD R14, CTR
|
||||
BNE loop_outer_vsx
|
||||
|
||||
done_vsx:
|
||||
// Increment counter by number of 64 byte blocks
|
||||
MOVD (CNT), R14
|
||||
ADD BLOCKS, R14
|
||||
MOVD R14, (CNT)
|
||||
RET
|
||||
|
||||
tail_vsx:
|
||||
ADD $32, R1, R11
|
||||
MOVD LEN, CTR
|
||||
|
||||
// Save values on stack to copy from
|
||||
STXVW4X VS32, (R11)(R0)
|
||||
STXVW4X VS36, (R11)(R8)
|
||||
STXVW4X VS40, (R11)(R9)
|
||||
STXVW4X VS44, (R11)(R10)
|
||||
ADD $-1, R11, R12
|
||||
ADD $-1, INP
|
||||
ADD $-1, OUT
|
||||
|
||||
looptail_vsx:
|
||||
// Copying the result to OUT
|
||||
// in bytes.
|
||||
MOVBZU 1(R12), KEY
|
||||
MOVBZU 1(INP), TMP
|
||||
XOR KEY, TMP, KEY
|
||||
MOVBU KEY, 1(OUT)
|
||||
BC 16, LT, looptail_vsx
|
||||
|
||||
// Clear the stack values
|
||||
STXVW4X VS48, (R11)(R0)
|
||||
STXVW4X VS48, (R11)(R8)
|
||||
STXVW4X VS48, (R11)(R9)
|
||||
STXVW4X VS48, (R11)(R10)
|
||||
BR done_vsx
|
27
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
Normal file
27
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
var haveAsm = cpu.S390X.HasVX
|
||||
|
||||
const bufSize = 256
|
||||
|
||||
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
|
||||
// be called when the vector facility is available. Implementation in asm_s390x.s.
|
||||
//go:noescape
|
||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||
|
||||
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
|
||||
if cpu.S390X.HasVX {
|
||||
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
|
||||
} else {
|
||||
c.xorKeyStreamBlocksGeneric(dst, src)
|
||||
}
|
||||
}
|
224
vendor/golang.org/x/crypto/chacha20/chacha_s390x.s
generated
vendored
Normal file
224
vendor/golang.org/x/crypto/chacha20/chacha_s390x.s
generated
vendored
Normal file
|
@ -0,0 +1,224 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build gc,!purego
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// This is an implementation of the ChaCha20 encryption algorithm as
|
||||
// specified in RFC 7539. It uses vector instructions to compute
|
||||
// 4 keystream blocks in parallel (256 bytes) which are then XORed
|
||||
// with the bytes in the input slice.
|
||||
|
||||
GLOBL ·constants<>(SB), RODATA|NOPTR, $32
|
||||
// BSWAP: swap bytes in each 4-byte element
|
||||
DATA ·constants<>+0x00(SB)/4, $0x03020100
|
||||
DATA ·constants<>+0x04(SB)/4, $0x07060504
|
||||
DATA ·constants<>+0x08(SB)/4, $0x0b0a0908
|
||||
DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c
|
||||
// J0: [j0, j1, j2, j3]
|
||||
DATA ·constants<>+0x10(SB)/4, $0x61707865
|
||||
DATA ·constants<>+0x14(SB)/4, $0x3320646e
|
||||
DATA ·constants<>+0x18(SB)/4, $0x79622d32
|
||||
DATA ·constants<>+0x1c(SB)/4, $0x6b206574
|
||||
|
||||
#define BSWAP V5
|
||||
#define J0 V6
|
||||
#define KEY0 V7
|
||||
#define KEY1 V8
|
||||
#define NONCE V9
|
||||
#define CTR V10
|
||||
#define M0 V11
|
||||
#define M1 V12
|
||||
#define M2 V13
|
||||
#define M3 V14
|
||||
#define INC V15
|
||||
#define X0 V16
|
||||
#define X1 V17
|
||||
#define X2 V18
|
||||
#define X3 V19
|
||||
#define X4 V20
|
||||
#define X5 V21
|
||||
#define X6 V22
|
||||
#define X7 V23
|
||||
#define X8 V24
|
||||
#define X9 V25
|
||||
#define X10 V26
|
||||
#define X11 V27
|
||||
#define X12 V28
|
||||
#define X13 V29
|
||||
#define X14 V30
|
||||
#define X15 V31
|
||||
|
||||
#define NUM_ROUNDS 20
|
||||
|
||||
#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \
|
||||
VAF a1, a0, a0 \
|
||||
VAF b1, b0, b0 \
|
||||
VAF c1, c0, c0 \
|
||||
VAF d1, d0, d0 \
|
||||
VX a0, a2, a2 \
|
||||
VX b0, b2, b2 \
|
||||
VX c0, c2, c2 \
|
||||
VX d0, d2, d2 \
|
||||
VERLLF $16, a2, a2 \
|
||||
VERLLF $16, b2, b2 \
|
||||
VERLLF $16, c2, c2 \
|
||||
VERLLF $16, d2, d2 \
|
||||
VAF a2, a3, a3 \
|
||||
VAF b2, b3, b3 \
|
||||
VAF c2, c3, c3 \
|
||||
VAF d2, d3, d3 \
|
||||
VX a3, a1, a1 \
|
||||
VX b3, b1, b1 \
|
||||
VX c3, c1, c1 \
|
||||
VX d3, d1, d1 \
|
||||
VERLLF $12, a1, a1 \
|
||||
VERLLF $12, b1, b1 \
|
||||
VERLLF $12, c1, c1 \
|
||||
VERLLF $12, d1, d1 \
|
||||
VAF a1, a0, a0 \
|
||||
VAF b1, b0, b0 \
|
||||
VAF c1, c0, c0 \
|
||||
VAF d1, d0, d0 \
|
||||
VX a0, a2, a2 \
|
||||
VX b0, b2, b2 \
|
||||
VX c0, c2, c2 \
|
||||
VX d0, d2, d2 \
|
||||
VERLLF $8, a2, a2 \
|
||||
VERLLF $8, b2, b2 \
|
||||
VERLLF $8, c2, c2 \
|
||||
VERLLF $8, d2, d2 \
|
||||
VAF a2, a3, a3 \
|
||||
VAF b2, b3, b3 \
|
||||
VAF c2, c3, c3 \
|
||||
VAF d2, d3, d3 \
|
||||
VX a3, a1, a1 \
|
||||
VX b3, b1, b1 \
|
||||
VX c3, c1, c1 \
|
||||
VX d3, d1, d1 \
|
||||
VERLLF $7, a1, a1 \
|
||||
VERLLF $7, b1, b1 \
|
||||
VERLLF $7, c1, c1 \
|
||||
VERLLF $7, d1, d1
|
||||
|
||||
#define PERMUTE(mask, v0, v1, v2, v3) \
|
||||
VPERM v0, v0, mask, v0 \
|
||||
VPERM v1, v1, mask, v1 \
|
||||
VPERM v2, v2, mask, v2 \
|
||||
VPERM v3, v3, mask, v3
|
||||
|
||||
#define ADDV(x, v0, v1, v2, v3) \
|
||||
VAF x, v0, v0 \
|
||||
VAF x, v1, v1 \
|
||||
VAF x, v2, v2 \
|
||||
VAF x, v3, v3
|
||||
|
||||
#define XORV(off, dst, src, v0, v1, v2, v3) \
|
||||
VLM off(src), M0, M3 \
|
||||
PERMUTE(BSWAP, v0, v1, v2, v3) \
|
||||
VX v0, M0, M0 \
|
||||
VX v1, M1, M1 \
|
||||
VX v2, M2, M2 \
|
||||
VX v3, M3, M3 \
|
||||
VSTM M0, M3, off(dst)
|
||||
|
||||
#define SHUFFLE(a, b, c, d, t, u, v, w) \
|
||||
VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]}
|
||||
VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]}
|
||||
VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]}
|
||||
VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]}
|
||||
VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]}
|
||||
VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]}
|
||||
VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
|
||||
VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
|
||||
|
||||
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
|
||||
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
||||
MOVD $·constants<>(SB), R1
|
||||
MOVD dst+0(FP), R2 // R2=&dst[0]
|
||||
LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src)
|
||||
MOVD key+48(FP), R5 // R5=key
|
||||
MOVD nonce+56(FP), R6 // R6=nonce
|
||||
MOVD counter+64(FP), R7 // R7=counter
|
||||
|
||||
// load BSWAP and J0
|
||||
VLM (R1), BSWAP, J0
|
||||
|
||||
// setup
|
||||
MOVD $95, R0
|
||||
VLM (R5), KEY0, KEY1
|
||||
VLL R0, (R6), NONCE
|
||||
VZERO M0
|
||||
VLEIB $7, $32, M0
|
||||
VSRLB M0, NONCE, NONCE
|
||||
|
||||
// initialize counter values
|
||||
VLREPF (R7), CTR
|
||||
VZERO INC
|
||||
VLEIF $1, $1, INC
|
||||
VLEIF $2, $2, INC
|
||||
VLEIF $3, $3, INC
|
||||
VAF INC, CTR, CTR
|
||||
VREPIF $4, INC
|
||||
|
||||
chacha:
|
||||
VREPF $0, J0, X0
|
||||
VREPF $1, J0, X1
|
||||
VREPF $2, J0, X2
|
||||
VREPF $3, J0, X3
|
||||
VREPF $0, KEY0, X4
|
||||
VREPF $1, KEY0, X5
|
||||
VREPF $2, KEY0, X6
|
||||
VREPF $3, KEY0, X7
|
||||
VREPF $0, KEY1, X8
|
||||
VREPF $1, KEY1, X9
|
||||
VREPF $2, KEY1, X10
|
||||
VREPF $3, KEY1, X11
|
||||
VLR CTR, X12
|
||||
VREPF $1, NONCE, X13
|
||||
VREPF $2, NONCE, X14
|
||||
VREPF $3, NONCE, X15
|
||||
|
||||
MOVD $(NUM_ROUNDS/2), R1
|
||||
|
||||
loop:
|
||||
ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11)
|
||||
ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9)
|
||||
|
||||
ADD $-1, R1
|
||||
BNE loop
|
||||
|
||||
// decrement length
|
||||
ADD $-256, R4
|
||||
|
||||
// rearrange vectors
|
||||
SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
|
||||
ADDV(J0, X0, X1, X2, X3)
|
||||
SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3)
|
||||
ADDV(KEY0, X4, X5, X6, X7)
|
||||
SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3)
|
||||
ADDV(KEY1, X8, X9, X10, X11)
|
||||
VAF CTR, X12, X12
|
||||
SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3)
|
||||
ADDV(NONCE, X12, X13, X14, X15)
|
||||
|
||||
// increment counters
|
||||
VAF INC, CTR, CTR
|
||||
|
||||
// xor keystream with plaintext
|
||||
XORV(0*64, R2, R3, X0, X4, X8, X12)
|
||||
XORV(1*64, R2, R3, X1, X5, X9, X13)
|
||||
XORV(2*64, R2, R3, X2, X6, X10, X14)
|
||||
XORV(3*64, R2, R3, X3, X7, X11, X15)
|
||||
|
||||
// increment pointers
|
||||
MOVD $256(R2), R2
|
||||
MOVD $256(R3), R3
|
||||
|
||||
CMPBNE R4, $0, chacha
|
||||
|
||||
VSTEF $0, CTR, (R7)
|
||||
RET
|
42
vendor/golang.org/x/crypto/chacha20/xor.go
generated
vendored
Normal file
42
vendor/golang.org/x/crypto/chacha20/xor.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found src the LICENSE file.
|
||||
|
||||
package chacha20
|
||||
|
||||
import "runtime"
|
||||
|
||||
// Platforms that have fast unaligned 32-bit little endian accesses.
|
||||
const unaligned = runtime.GOARCH == "386" ||
|
||||
runtime.GOARCH == "amd64" ||
|
||||
runtime.GOARCH == "arm64" ||
|
||||
runtime.GOARCH == "ppc64le" ||
|
||||
runtime.GOARCH == "s390x"
|
||||
|
||||
// addXor reads a little endian uint32 from src, XORs it with (a + b) and
|
||||
// places the result in little endian byte order in dst.
|
||||
func addXor(dst, src []byte, a, b uint32) {
|
||||
_, _ = src[3], dst[3] // bounds check elimination hint
|
||||
if unaligned {
|
||||
// The compiler should optimize this code into
|
||||
// 32-bit unaligned little endian loads and stores.
|
||||
// TODO: delete once the compiler does a reliably
|
||||
// good job with the generic code below.
|
||||
// See issue #25111 for more details.
|
||||
v := uint32(src[0])
|
||||
v |= uint32(src[1]) << 8
|
||||
v |= uint32(src[2]) << 16
|
||||
v |= uint32(src[3]) << 24
|
||||
v ^= a + b
|
||||
dst[0] = byte(v)
|
||||
dst[1] = byte(v >> 8)
|
||||
dst[2] = byte(v >> 16)
|
||||
dst[3] = byte(v >> 24)
|
||||
} else {
|
||||
a += b
|
||||
dst[0] = src[0] ^ byte(a)
|
||||
dst[1] = src[1] ^ byte(a>>8)
|
||||
dst[2] = src[2] ^ byte(a>>16)
|
||||
dst[3] = src[3] ^ byte(a>>24)
|
||||
}
|
||||
}
|
94
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
generated
vendored
Normal file
94
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its
|
||||
// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and
|
||||
// draft-irtf-cfrg-xchacha-01.
|
||||
package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeySize is the size of the key used by this AEAD, in bytes.
|
||||
KeySize = 32
|
||||
|
||||
// NonceSize is the size of the nonce used with the standard variant of this
|
||||
// AEAD, in bytes.
|
||||
//
|
||||
// Note that this is too short to be safely generated at random if the same
|
||||
// key is reused more than 2³² times.
|
||||
NonceSize = 12
|
||||
|
||||
// NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305
|
||||
// variant of this AEAD, in bytes.
|
||||
NonceSizeX = 24
|
||||
)
|
||||
|
||||
type chacha20poly1305 struct {
|
||||
key [KeySize]byte
|
||||
}
|
||||
|
||||
// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key.
|
||||
func New(key []byte) (cipher.AEAD, error) {
|
||||
if len(key) != KeySize {
|
||||
return nil, errors.New("chacha20poly1305: bad key length")
|
||||
}
|
||||
ret := new(chacha20poly1305)
|
||||
copy(ret.key[:], key)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) NonceSize() int {
|
||||
return NonceSize
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) Overhead() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if len(nonce) != NonceSize {
|
||||
panic("chacha20poly1305: bad nonce length passed to Seal")
|
||||
}
|
||||
|
||||
if uint64(len(plaintext)) > (1<<38)-64 {
|
||||
panic("chacha20poly1305: plaintext too large")
|
||||
}
|
||||
|
||||
return c.seal(dst, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
var errOpen = errors.New("chacha20poly1305: message authentication failed")
|
||||
|
||||
func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if len(nonce) != NonceSize {
|
||||
panic("chacha20poly1305: bad nonce length passed to Open")
|
||||
}
|
||||
if len(ciphertext) < 16 {
|
||||
return nil, errOpen
|
||||
}
|
||||
if uint64(len(ciphertext)) > (1<<38)-48 {
|
||||
panic("chacha20poly1305: ciphertext too large")
|
||||
}
|
||||
|
||||
return c.open(dst, nonce, ciphertext, additionalData)
|
||||
}
|
||||
|
||||
// sliceForAppend takes a slice and a requested number of bytes. It returns a
|
||||
// slice with the contents of the given slice followed by that many bytes and a
|
||||
// second slice that aliases into it and contains only the extra bytes. If the
|
||||
// original slice has sufficient capacity then no allocation is performed.
|
||||
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
if total := len(in) + n; cap(in) >= total {
|
||||
head = in[:total]
|
||||
} else {
|
||||
head = make([]byte, total)
|
||||
copy(head, in)
|
||||
}
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
87
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
generated
vendored
Normal file
87
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/crypto/internal/subtle"
|
||||
"golang.org/x/sys/cpu"
|
||||
)
|
||||
|
||||
//go:noescape
|
||||
func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
|
||||
|
||||
//go:noescape
|
||||
func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
|
||||
|
||||
var (
|
||||
useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
|
||||
)
|
||||
|
||||
// setupState writes a ChaCha20 input matrix to state. See
|
||||
// https://tools.ietf.org/html/rfc7539#section-2.3.
|
||||
func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
|
||||
state[0] = 0x61707865
|
||||
state[1] = 0x3320646e
|
||||
state[2] = 0x79622d32
|
||||
state[3] = 0x6b206574
|
||||
|
||||
state[4] = binary.LittleEndian.Uint32(key[0:4])
|
||||
state[5] = binary.LittleEndian.Uint32(key[4:8])
|
||||
state[6] = binary.LittleEndian.Uint32(key[8:12])
|
||||
state[7] = binary.LittleEndian.Uint32(key[12:16])
|
||||
state[8] = binary.LittleEndian.Uint32(key[16:20])
|
||||
state[9] = binary.LittleEndian.Uint32(key[20:24])
|
||||
state[10] = binary.LittleEndian.Uint32(key[24:28])
|
||||
state[11] = binary.LittleEndian.Uint32(key[28:32])
|
||||
|
||||
state[12] = 0
|
||||
state[13] = binary.LittleEndian.Uint32(nonce[0:4])
|
||||
state[14] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||
state[15] = binary.LittleEndian.Uint32(nonce[8:12])
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if !cpu.X86.HasSSSE3 {
|
||||
return c.sealGeneric(dst, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
var state [16]uint32
|
||||
setupState(&state, &c.key, nonce)
|
||||
|
||||
ret, out := sliceForAppend(dst, len(plaintext)+16)
|
||||
if subtle.InexactOverlap(out, plaintext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
}
|
||||
chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if !cpu.X86.HasSSSE3 {
|
||||
return c.openGeneric(dst, nonce, ciphertext, additionalData)
|
||||
}
|
||||
|
||||
var state [16]uint32
|
||||
setupState(&state, &c.key, nonce)
|
||||
|
||||
ciphertext = ciphertext[:len(ciphertext)-16]
|
||||
ret, out := sliceForAppend(dst, len(ciphertext))
|
||||
if subtle.InexactOverlap(out, ciphertext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
}
|
||||
if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
return nil, errOpen
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
2695
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
generated
vendored
Normal file
2695
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
81
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
generated
vendored
Normal file
81
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/crypto/chacha20"
|
||||
"golang.org/x/crypto/internal/subtle"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
)
|
||||
|
||||
func writeWithPadding(p *poly1305.MAC, b []byte) {
|
||||
p.Write(b)
|
||||
if rem := len(b) % 16; rem != 0 {
|
||||
var buf [16]byte
|
||||
padLen := 16 - rem
|
||||
p.Write(buf[:padLen])
|
||||
}
|
||||
}
|
||||
|
||||
func writeUint64(p *poly1305.MAC, n int) {
|
||||
var buf [8]byte
|
||||
binary.LittleEndian.PutUint64(buf[:], uint64(n))
|
||||
p.Write(buf[:])
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
|
||||
ciphertext, tag := out[:len(plaintext)], out[len(plaintext):]
|
||||
if subtle.InexactOverlap(out, plaintext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
}
|
||||
|
||||
var polyKey [32]byte
|
||||
s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
|
||||
s.XORKeyStream(polyKey[:], polyKey[:])
|
||||
s.SetCounter(1) // set the counter to 1, skipping 32 bytes
|
||||
s.XORKeyStream(ciphertext, plaintext)
|
||||
|
||||
p := poly1305.New(&polyKey)
|
||||
writeWithPadding(p, additionalData)
|
||||
writeWithPadding(p, ciphertext)
|
||||
writeUint64(p, len(additionalData))
|
||||
writeUint64(p, len(plaintext))
|
||||
p.Sum(tag[:0])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
tag := ciphertext[len(ciphertext)-16:]
|
||||
ciphertext = ciphertext[:len(ciphertext)-16]
|
||||
|
||||
var polyKey [32]byte
|
||||
s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
|
||||
s.XORKeyStream(polyKey[:], polyKey[:])
|
||||
s.SetCounter(1) // set the counter to 1, skipping 32 bytes
|
||||
|
||||
p := poly1305.New(&polyKey)
|
||||
writeWithPadding(p, additionalData)
|
||||
writeWithPadding(p, ciphertext)
|
||||
writeUint64(p, len(additionalData))
|
||||
writeUint64(p, len(ciphertext))
|
||||
|
||||
ret, out := sliceForAppend(dst, len(ciphertext))
|
||||
if subtle.InexactOverlap(out, ciphertext) {
|
||||
panic("chacha20poly1305: invalid buffer overlap")
|
||||
}
|
||||
if !p.Verify(tag) {
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
return nil, errOpen
|
||||
}
|
||||
|
||||
s.XORKeyStream(out, ciphertext)
|
||||
return ret, nil
|
||||
}
|
16
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
generated
vendored
Normal file
16
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || !gc || purego
|
||||
// +build !amd64 !gc purego
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
return c.sealGeneric(dst, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
return c.openGeneric(dst, nonce, ciphertext, additionalData)
|
||||
}
|
86
vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go
generated
vendored
Normal file
86
vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
|
||||
"golang.org/x/crypto/chacha20"
|
||||
)
|
||||
|
||||
type xchacha20poly1305 struct {
|
||||
key [KeySize]byte
|
||||
}
|
||||
|
||||
// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key.
|
||||
//
|
||||
// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce,
|
||||
// suitable to be generated randomly without risk of collisions. It should be
|
||||
// preferred when nonce uniqueness cannot be trivially ensured, or whenever
|
||||
// nonces are randomly generated.
|
||||
func NewX(key []byte) (cipher.AEAD, error) {
|
||||
if len(key) != KeySize {
|
||||
return nil, errors.New("chacha20poly1305: bad key length")
|
||||
}
|
||||
ret := new(xchacha20poly1305)
|
||||
copy(ret.key[:], key)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (*xchacha20poly1305) NonceSize() int {
|
||||
return NonceSizeX
|
||||
}
|
||||
|
||||
func (*xchacha20poly1305) Overhead() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if len(nonce) != NonceSizeX {
|
||||
panic("chacha20poly1305: bad nonce length passed to Seal")
|
||||
}
|
||||
|
||||
// XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no
|
||||
// size limit. However, since we reuse the ChaCha20-Poly1305 implementation,
|
||||
// the second half of the counter is not available. This is unlikely to be
|
||||
// an issue because the cipher.AEAD API requires the entire message to be in
|
||||
// memory, and the counter overflows at 256 GB.
|
||||
if uint64(len(plaintext)) > (1<<38)-64 {
|
||||
panic("chacha20poly1305: plaintext too large")
|
||||
}
|
||||
|
||||
c := new(chacha20poly1305)
|
||||
hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16])
|
||||
copy(c.key[:], hKey)
|
||||
|
||||
// The first 4 bytes of the final nonce are unused counter space.
|
||||
cNonce := make([]byte, NonceSize)
|
||||
copy(cNonce[4:12], nonce[16:24])
|
||||
|
||||
return c.seal(dst, cNonce[:], plaintext, additionalData)
|
||||
}
|
||||
|
||||
func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if len(nonce) != NonceSizeX {
|
||||
panic("chacha20poly1305: bad nonce length passed to Open")
|
||||
}
|
||||
if len(ciphertext) < 16 {
|
||||
return nil, errOpen
|
||||
}
|
||||
if uint64(len(ciphertext)) > (1<<38)-48 {
|
||||
panic("chacha20poly1305: ciphertext too large")
|
||||
}
|
||||
|
||||
c := new(chacha20poly1305)
|
||||
hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16])
|
||||
copy(c.key[:], hKey)
|
||||
|
||||
// The first 4 bytes of the final nonce are unused counter space.
|
||||
cNonce := make([]byte, NonceSize)
|
||||
copy(cNonce[4:12], nonce[16:24])
|
||||
|
||||
return c.open(dst, cNonce[:], ciphertext, additionalData)
|
||||
}
|
93
vendor/golang.org/x/crypto/hkdf/hkdf.go
generated
vendored
Normal file
93
vendor/golang.org/x/crypto/hkdf/hkdf.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation
|
||||
// Function (HKDF) as defined in RFC 5869.
|
||||
//
|
||||
// HKDF is a cryptographic key derivation function (KDF) with the goal of
|
||||
// expanding limited input keying material into one or more cryptographically
|
||||
// strong secret keys.
|
||||
package hkdf // import "golang.org/x/crypto/hkdf"
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Extract generates a pseudorandom key for use with Expand from an input secret
|
||||
// and an optional independent salt.
|
||||
//
|
||||
// Only use this function if you need to reuse the extracted key with multiple
|
||||
// Expand invocations and different context values. Most common scenarios,
|
||||
// including the generation of multiple keys, should use New instead.
|
||||
func Extract(hash func() hash.Hash, secret, salt []byte) []byte {
|
||||
if salt == nil {
|
||||
salt = make([]byte, hash().Size())
|
||||
}
|
||||
extractor := hmac.New(hash, salt)
|
||||
extractor.Write(secret)
|
||||
return extractor.Sum(nil)
|
||||
}
|
||||
|
||||
type hkdf struct {
|
||||
expander hash.Hash
|
||||
size int
|
||||
|
||||
info []byte
|
||||
counter byte
|
||||
|
||||
prev []byte
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (f *hkdf) Read(p []byte) (int, error) {
|
||||
// Check whether enough data can be generated
|
||||
need := len(p)
|
||||
remains := len(f.buf) + int(255-f.counter+1)*f.size
|
||||
if remains < need {
|
||||
return 0, errors.New("hkdf: entropy limit reached")
|
||||
}
|
||||
// Read any leftover from the buffer
|
||||
n := copy(p, f.buf)
|
||||
p = p[n:]
|
||||
|
||||
// Fill the rest of the buffer
|
||||
for len(p) > 0 {
|
||||
f.expander.Reset()
|
||||
f.expander.Write(f.prev)
|
||||
f.expander.Write(f.info)
|
||||
f.expander.Write([]byte{f.counter})
|
||||
f.prev = f.expander.Sum(f.prev[:0])
|
||||
f.counter++
|
||||
|
||||
// Copy the new batch into p
|
||||
f.buf = f.prev
|
||||
n = copy(p, f.buf)
|
||||
p = p[n:]
|
||||
}
|
||||
// Save leftovers for next run
|
||||
f.buf = f.buf[n:]
|
||||
|
||||
return need, nil
|
||||
}
|
||||
|
||||
// Expand returns a Reader, from which keys can be read, using the given
|
||||
// pseudorandom key and optional context info, skipping the extraction step.
|
||||
//
|
||||
// The pseudorandomKey should have been generated by Extract, or be a uniformly
|
||||
// random or pseudorandom cryptographically strong key. See RFC 5869, Section
|
||||
// 3.3. Most common scenarios will want to use New instead.
|
||||
func Expand(hash func() hash.Hash, pseudorandomKey, info []byte) io.Reader {
|
||||
expander := hmac.New(hash, pseudorandomKey)
|
||||
return &hkdf{expander, expander.Size(), info, 1, nil, nil}
|
||||
}
|
||||
|
||||
// New returns a Reader, from which keys can be read, using the given hash,
|
||||
// secret, salt and context info. Salt and info can be nil.
|
||||
func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader {
|
||||
prk := Extract(hash, secret, salt)
|
||||
return Expand(hash, prk, info)
|
||||
}
|
10
vendor/modules.txt
vendored
10
vendor/modules.txt
vendored
|
@ -8,6 +8,10 @@ github.com/VividCortex/ewma
|
|||
github.com/aead/chacha20/chacha
|
||||
# github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635
|
||||
github.com/aead/poly1305
|
||||
# github.com/cisco/go-hpke v0.0.0-20210215210317-01c430f1f302
|
||||
## explicit
|
||||
# github.com/cloudflare/odoh-go v0.1.6
|
||||
## explicit
|
||||
# github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
## explicit
|
||||
github.com/coreos/go-systemd/activation
|
||||
|
@ -45,6 +49,9 @@ github.com/jedisct1/go-clocksmith
|
|||
# github.com/jedisct1/go-dnsstamps v0.0.0-20210101121956-16fbdadcf8f5
|
||||
## explicit
|
||||
github.com/jedisct1/go-dnsstamps
|
||||
# github.com/jedisct1/go-hpke-compact v0.0.0-20210329192501-7ceabaabca65
|
||||
## explicit
|
||||
github.com/jedisct1/go-hpke-compact
|
||||
# github.com/jedisct1/go-minisign v0.0.0-20210106175330-e54e81d562c7
|
||||
## explicit
|
||||
github.com/jedisct1/go-minisign
|
||||
|
@ -73,9 +80,12 @@ github.com/smartystreets/goconvey/convey/reporting
|
|||
# golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
## explicit
|
||||
golang.org/x/crypto/blake2b
|
||||
golang.org/x/crypto/chacha20
|
||||
golang.org/x/crypto/chacha20poly1305
|
||||
golang.org/x/crypto/curve25519
|
||||
golang.org/x/crypto/ed25519
|
||||
golang.org/x/crypto/ed25519/internal/edwards25519
|
||||
golang.org/x/crypto/hkdf
|
||||
golang.org/x/crypto/internal/subtle
|
||||
golang.org/x/crypto/nacl/box
|
||||
golang.org/x/crypto/nacl/secretbox
|
||||
|
|
Loading…
Add table
Reference in a new issue