Add Oblivious DoH support

This commit is contained in:
Tanya Verma 2020-12-07 02:52:41 -08:00
parent 65e70650dc
commit e3b1f5b7d0
95 changed files with 20544 additions and 198 deletions

View File

@ -262,7 +262,11 @@ func StartServer(
wg.Add(1)
go func() {
defer wg.Done()
errC <- runDNSProxyServer(c, dnsReadySignal, shutdownC, generalLogger)
if c.IsSet("proxy-dns-odoh") {
errC <- runDNSProxyServer(c, dnsReadySignal, shutdownC, generalLogger, true)
} else {
errC <- runDNSProxyServer(c, dnsReadySignal, shutdownC, generalLogger, false)
}
}()
} else {
close(dnsReadySignal)
@ -1015,6 +1019,30 @@ func configureProxyDNSFlags(shouldHide bool) []cli.Flag {
EnvVars: []string{"TUNNEL_DNS_BOOTSTRAP"},
Hidden: shouldHide,
}),
altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "proxy-dns-odoh",
Usage: "Runs an Oblivious DNS over HTTPS client.",
EnvVars: []string{"TUNNEL_DNS_ODOH"},
Hidden: shouldHide,
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: "proxy-dns-odoh-target",
Usage: "ODoH target URL",
Value: "https://1.1.1.1/dns-query",
EnvVars: []string{"TUNNEL_DNS_ODOH_TARGET"},
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: "proxy-dns-odoh-proxy",
Usage: "ODoH proxy URL",
Value: "https://odoh1.surfdomeinen.nl/proxy",
EnvVars: []string{"TUNNEL_DNS_ODOH_PROXY"},
}),
altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "proxy-dns-odoh-useproxy",
Usage: "Set flag to enable proxy usage",
Value: false,
EnvVars: []string{"TUNNEL_DNS_ODOH_USE_PROXY"},
}),
}
}

View File

@ -9,22 +9,56 @@ import (
"github.com/pkg/errors"
)
func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{}, logger logger.Service) error {
func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{}, logger logger.Service, odoh bool) error {
port := c.Int("proxy-dns-port")
if port <= 0 || port > 65535 {
return errors.New("The 'proxy-dns-port' must be a valid port number in <1, 65535> range.")
}
listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(port), c.StringSlice("proxy-dns-upstream"), c.StringSlice("proxy-dns-bootstrap"), logger)
var listener *tunneldns.Listener
var err error
if odoh {
listener, err = tunneldns.CreateObliviousDNSListener(
c.String("proxy-dns-address"),
uint16(port),
c.String("proxy-dns-odoh-target"),
c.String("proxy-dns-odoh-proxy"),
c.Bool("proxy-dns-odoh-useproxy"),
logger,
)
} else {
listener, err = tunneldns.CreateListener(
c.String("proxy-dns-address"),
uint16(port),
c.StringSlice("proxy-dns-upstream"),
c.StringSlice("proxy-dns-bootstrap"),
logger,
)
}
// Update odohconfig
go listener.UpdateOdohConfig()
if err != nil {
close(dnsReadySignal)
listener.Stop()
return errors.Wrap(err, "Cannot create the DNS over HTTPS proxy server")
if odoh {
return errors.Wrap(err, "Cannot create the Oblivious DNS over HTTPS proxy server")
} else {
return errors.Wrap(err, "Cannot create the DNS over HTTPS proxy server")
}
}
err = listener.Start(dnsReadySignal)
if err != nil {
return errors.Wrap(err, "Cannot start the DNS over HTTPS proxy server")
if odoh {
if err != nil {
return errors.Wrap(err, "Cannot start the Oblivious DNS over HTTPS proxy server")
}
} else {
if err != nil {
return errors.Wrap(err, "Cannot start the DNS over HTTPS proxy server")
}
}
<-shutdownC
listener.Stop()
return nil

7
go.mod
View File

@ -11,11 +11,11 @@ require (
github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect
github.com/cloudflare/brotli-go v0.0.0-20191101163834-d34379f7ff93
github.com/cloudflare/golibs v0.0.0-20170913112048-333127dbecfc
github.com/cloudflare/odoh-go v0.1.3
github.com/coredns/coredns v1.7.0
github.com/coreos/go-oidc v0.0.0-20171002155002-a93f71fdfe73
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0
github.com/equinox-io/equinox v1.2.0 // indirect
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect
github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9 // indirect
github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434
@ -42,7 +42,7 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/lib/pq v1.2.0
github.com/mattn/go-sqlite3 v1.11.0
github.com/miekg/dns v1.1.31
github.com/miekg/dns v1.1.32
github.com/mitchellh/go-homedir v1.1.0
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
@ -51,9 +51,8 @@ require (
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v1.7.1
github.com/prometheus/common v0.13.0 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect
github.com/rivo/tview v0.0.0-20200712113419-c65badfc3d92
github.com/stretchr/testify v1.6.0
github.com/stretchr/testify v1.6.1
github.com/urfave/cli/v2 v2.2.0
github.com/xo/dburl v0.0.0-20191005012637-293c3298d6c0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a

87
go.sum
View File

@ -12,6 +12,7 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
@ -32,38 +33,50 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
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/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v40.6.0+incompatible h1:ULjp/a/UsBfnZcl45jjywhcBKex/k/A1cG9s9NapLFw=
github.com/Azure/azure-sdk-for-go v40.6.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
github.com/Azure/go-autorest/autorest v0.10.2 h1:NuSF3gXetiHyUbVdneJMEVyPUYAe5wh+aN08JYAf1tI=
github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0=
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U=
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U=
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/autorest/to v0.2.0 h1:nQOZzFCudTh+TvquAtCRjM01VEYx85e9qbwt5ncW4L8=
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DataDog/datadog-go v3.5.0+incompatible h1:AShr9cqkF+taHjyQgcBcQUt/ZNK+iPq4ROaZwSX5c/U=
github.com/DataDog/datadog-go v3.5.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
@ -109,12 +122,15 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/caddyserver/caddy v1.0.5 h1:5B1Hs0UF2x2tggr2X9jL2qOZtDXbIWQb9YLbmlxHSuM=
github.com/caddyserver/caddy v1.0.5/go.mod h1:AnFHB+/MrgRC+mJAvuAgQ38ePzw+wKeW0wzENpdQQKY=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v4 v4.0.2 h1:JIufpQLbh4DkbQoii76ItQIUFzevQSqOLZca4eamEDs=
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -126,15 +142,23 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cisco/go-hpke v0.0.0-20201023221920-2866d2aa0603 h1:dszdCFyug261XPbbU9YQA+8CnpPJm1svHDeCHd8vhRI=
github.com/cisco/go-hpke v0.0.0-20201023221920-2866d2aa0603/go.mod h1:AyK7f6CWiLAvOFmAyCEF5xDN51zS6PIZgj3Qq7hla1Y=
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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/brotli-go v0.0.0-20191101163834-d34379f7ff93 h1:QrGfkZDnMxcWHaYDdB7CmqS9i26OAnUj/xcus/abYkY=
github.com/cloudflare/brotli-go v0.0.0-20191101163834-d34379f7ff93/go.mod h1:QiTe66jFdP7cUKMCCf/WrvDyYdtdmdZfVcdoLbzaKVY=
github.com/cloudflare/circl v1.0.0 h1:64b6pyfCFbYm623ncIkYGNZaOcmIbyd+CjyMi2L9vdI=
github.com/cloudflare/circl v1.0.0/go.mod h1:MhjB3NEEhJbTOdLLq964NIUisXDxaE1WkQPUxtgZXiY=
github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY=
github.com/cloudflare/golibs v0.0.0-20170913112048-333127dbecfc h1:Dvk3ySBsOm5EviLx6VCyILnafPcQinXGP5jbTdHUJgE=
github.com/cloudflare/golibs v0.0.0-20170913112048-333127dbecfc/go.mod h1:HlgKKR8V5a1wroIDDIz3/A+T+9Janfq+7n1P5sEFdi0=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/cloudflare/odoh-go v0.1.3 h1:kI0ANqbcLfKZHZOJ6myyEMWReQTy6ZOybSBFpg2yTsM=
github.com/cloudflare/odoh-go v0.1.3/go.mod h1:+8PrCWF56ioFtPx7VyhT8fL/IM6cJtPNh9IecQ1EIxg=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
@ -146,6 +170,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
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/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/license-bill-of-materials v0.0.0-20190913234955-13baff47494e/go.mod h1:4xMOusJ7xxc84WclVxKT8+lNfGYDwojOUC2OQNCwcj4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
@ -160,10 +185,13 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g=
github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0 h1:epsH3lb7KVbXHYk7LYGN5EiE0MxcevHU85CKITJ0wUY=
github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
github.com/dnstap/golang-dnstap v0.2.0 h1:+NrmP4mkaTeKYV7xJ5FXpUxRn0RpcgoQcsOCTS8WQPk=
github.com/dnstap/golang-dnstap v0.2.0/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@ -179,16 +207,19 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/equinox-io/equinox v1.2.0 h1:bBS7Ou+Y7Jwgmy8TWSYxEh85WctuFn7FPlgbUzX4DBA=
github.com/equinox-io/equinox v1.2.0/go.mod h1:6s3HJB0PYUNgs0mxmI8fHdfVl3TQ25ieA/PVfr+eyVo=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9 h1:wWke/RUCl7VRjQhwPlR/v0glZXNYzBHdNUzf/Am2Nmg=
github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9/go.mod h1:uPmAp6Sws4L7+Q/OokbWDAK1ibXYhB3PXFP1kol5hPg=
github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434 h1:mOp33BLbcbJ8fvTAmZacbBiOASfxN+MLcLxymZCIrGE=
github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434/go.mod h1:KigFdumBXUPSwzLDbeuzyt0elrL7+CP7TKuhrhT4bcU=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y=
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/farsightsec/golang-framestream v0.0.0-20190425193708-fa4b164d59b8 h1:/iPdQppoAsTfML+yqFSq2EBChiEMnRkh5WvhFgtWwcU=
github.com/farsightsec/golang-framestream v0.0.0-20190425193708-fa4b164d59b8/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
@ -196,6 +227,7 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
@ -245,6 +277,7 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
@ -255,6 +288,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -289,9 +323,11 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -308,11 +344,14 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.9.0 h1:eJHQQFguQRv2FatH2d2VXH2ueTe2XzjgjwFjFS7SGcs=
github.com/gophercloud/gophercloud v0.9.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
@ -348,6 +387,7 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
@ -358,9 +398,11 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062 h1:d3VSuNcgTCn21dNMm8g412Fck/XWFmMj4nJhhHT7ZZ0=
github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062/go.mod h1:PcNJqIlcX/dj3DTG/+QQnRvSgTMG6CLpRMjWcv4+J6w=
github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@ -392,13 +434,16 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kshvakov/clickhouse v1.3.11 h1:dtzTJY0fCA+MWkLyuKZaNPkmSwdX4gh8+Klic9NB1Lw=
github.com/kshvakov/clickhouse v1.3.11/go.mod h1:/SVBAcqF3u7rxQ9sTWCZwf8jzzvxiZGeQvtmSF2BBEc=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
@ -435,8 +480,8 @@ github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaR
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo=
github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.32 h1:MDaYYzWOYscpvDOEgPMT1c1mebCZmIdxZI/J161OdJU=
github.com/miekg/dns v1.1.32/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@ -468,6 +513,7 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
@ -484,6 +530,7 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@ -491,9 +538,11 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5/go.mod h1:uVHyebswE1cCXr2A73cRM2frx5ld1RJUCJkFNZ90ZiI=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
@ -502,9 +551,11 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -543,7 +594,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
@ -551,7 +601,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/prometheus v2.5.0+incompatible/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/rivo/tview v0.0.0-20200712113419-c65badfc3d92 h1:rqaqSUdaW+OBbjnsrOoiaJv43mSRARuvsAuirmdxu7E=
github.com/rivo/tview v0.0.0-20200712113419-c65badfc3d92/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
@ -582,6 +631,7 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@ -592,10 +642,10 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ=
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY=
@ -617,6 +667,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200306183522-221f0cc107cb h1:TcJ8iNja1CH/h/3QcsydKL5krb0MIPjMJLYgzClNaSQ=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200306183522-221f0cc107cb/go.mod h1:VZB9Yx4s43MHItytoe8jcvaEFEgF2QzHDZGfQ/XQjvQ=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -624,17 +675,21 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -765,6 +820,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -811,6 +867,7 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -865,6 +922,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@ -883,6 +941,7 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -956,11 +1015,13 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/DataDog/dd-trace-go.v1 v1.24.1 h1:CGQIcKZxAsFtMTUiXw0TxBWwj+l+b2bS2V8l1bIsfk4=
gopkg.in/DataDog/dd-trace-go.v1 v1.24.1/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/coreos/go-oidc.v2 v2.1.0 h1:E8PjVFdj/SLDKB0hvb70KTbMbYVHjqztiQdSkIg8E+I=
@ -969,6 +1030,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@ -1002,21 +1064,28 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0=
k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk=
k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k=
k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
zombiezen.com/go/capnproto2 v2.18.0+incompatible h1:mwfXZniffG5mXokQGHUJWGnqIBggoPfT/CEwon9Yess=

View File

@ -12,30 +12,47 @@ import (
"time"
"github.com/cloudflare/cloudflared/logger"
odoh "github.com/cloudflare/odoh-go"
"github.com/miekg/dns"
"github.com/pkg/errors"
"golang.org/x/net/http2"
)
const (
defaultTimeout = 5 * time.Second
defaultTimeout = 10 * time.Second
odohConfigDuration = 3600 * time.Second
targetHostname = "odoh.cloudflare-dns.com."
)
// ObliviousDoHCtx maintains info needed for the ODoH service
type ObliviousDoHCtx struct {
useproxy bool
target *url.URL
queryCtx *odoh.QueryContext
}
// UpstreamHTTPS is the upstream implementation for DNS over HTTPS service
type UpstreamHTTPS struct {
client *http.Client
endpoint *url.URL
bootstraps []string
odoh *ObliviousDoHCtx
logger logger.Service
}
// NewUpstreamHTTPS creates a new DNS over HTTPS upstream from endpoint
func NewUpstreamHTTPS(endpoint string, bootstraps []string, logger logger.Service) (Upstream, error) {
func NewUpstreamHTTPS(endpoint string, bootstraps []string, odohCtx *ObliviousDoHCtx, logger logger.Service) (Upstream, error) {
u, err := url.Parse(endpoint)
if err != nil {
return nil, err
}
return &UpstreamHTTPS{client: configureClient(u.Hostname()), endpoint: u, bootstraps: bootstraps, logger: logger}, nil
return &UpstreamHTTPS{
client: configureClient(u.Hostname()),
endpoint: u,
bootstraps: bootstraps,
odoh: odohCtx,
logger: logger,
}, nil
}
// Exchange provides an implementation for the Upstream interface
@ -45,35 +62,95 @@ func (u *UpstreamHTTPS) Exchange(ctx context.Context, query *dns.Msg) (*dns.Msg,
return nil, errors.Wrap(err, "failed to pack DNS query")
}
if len(query.Question) > 0 && query.Question[0].Name == fmt.Sprintf("%s.", u.endpoint.Hostname()) {
for _, bootstrap := range u.bootstraps {
endpoint, client, err := configureBootstrap(bootstrap)
if err != nil {
u.logger.Errorf("failed to configure boostrap upstream %s: %s", bootstrap, err)
continue
if u.odoh == nil {
if len(query.Question) > 0 && query.Question[0].Name == fmt.Sprintf("%s.", u.endpoint.Hostname()) {
for _, bootstrap := range u.bootstraps {
endpoint, client, err := configureBootstrap(bootstrap)
if err != nil {
u.logger.Errorf("failed to configure boostrap upstream %s: %s", bootstrap, err)
continue
}
msg, err := exchange(queryBuf, query.Id, endpoint, client, u.odoh, u.logger)
if err != nil {
u.logger.Errorf("failed to connect to a boostrap upstream %s: %s", bootstrap, err)
continue
}
return msg, nil
}
msg, err := exchange(queryBuf, query.Id, endpoint, client, u.logger)
if err != nil {
u.logger.Errorf("failed to connect to a boostrap upstream %s: %s", bootstrap, err)
continue
}
return msg, nil
return nil, fmt.Errorf("failed to reach any bootstrap upstream: %v", u.bootstraps)
}
return nil, fmt.Errorf("failed to reach any bootstrap upstream: %v", u.bootstraps)
} else {
odohQuery, queryCtx, err := createOdohQuery(queryBuf, OdohConfig)
if err != nil {
u.logger.Errorf("failed to create oblivious query: %s", err)
}
queryBuf = odohQuery
u.odoh.queryCtx = &queryCtx
}
return exchange(queryBuf, query.Id, u.endpoint, u.client, u.odoh, u.logger)
return exchange(queryBuf, query.Id, u.endpoint, u.client, u.logger)
}
func exchange(msg []byte, queryID uint16, endpoint *url.URL, client *http.Client, logger logger.Service) (*dns.Msg, error) {
func createOdohQuery(dnsMessage []byte, publicKey odoh.ObliviousDoHConfigContents) ([]byte, odoh.QueryContext, error) {
odohQuery := odoh.CreateObliviousDNSQuery(dnsMessage, 0)
encryptedMessage, queryContext, err := publicKey.EncryptQuery(odohQuery)
if err != nil {
return nil, odoh.QueryContext{}, err
}
return encryptedMessage.Marshal(), queryContext, nil
}
// FetchObliviousDoHConfig fetches `odohconfig` by querying the target server for HTTPS records.
func FetchObliviousDoHConfig(client *http.Client, msg []byte, dohResolver *url.URL) (*odoh.ObliviousDoHConfigs, error) {
buf, err := exchangeWireformat(msg, dohResolver, client, nil)
if err != nil {
return nil, err
}
response := &dns.Msg{}
if err := response.Unpack(buf); err != nil {
return nil, errors.Wrap(err, "failed to unpack HTTPS DNS response from body")
}
// extracts `odohconfig` from the https record
for _, answer := range response.Answer {
httpsResponse, ok := answer.(*dns.HTTPS)
if ok {
for _, value := range httpsResponse.Value {
if value.Key() == 32769 {
parameter, ok := value.(*dns.SVCBLocal)
if ok {
odohConfigs, err := odoh.UnmarshalObliviousDoHConfigs(parameter.Data)
if err == nil {
return &odohConfigs, nil
}
}
}
}
}
}
return nil, nil
}
func exchange(msg []byte, queryID uint16, endpoint *url.URL, client *http.Client, odohCtx *ObliviousDoHCtx, logger logger.Service) (*dns.Msg, error) {
// No content negotiation for now, use DNS wire format
buf, backendErr := exchangeWireformat(msg, endpoint, client)
buf, backendErr := exchangeWireformat(msg, endpoint, client, odohCtx)
if backendErr == nil {
response := &dns.Msg{}
if odohCtx != nil {
odohQueryResponse, err := odoh.UnmarshalDNSMessage(buf)
if err != nil {
return nil, errors.Wrap(err, "failed to deserialize ObliviousDoHMessage from response")
}
buf, err = odohCtx.queryCtx.OpenAnswer(odohQueryResponse)
if err != nil {
return nil, errors.Wrap(err, "failed to decrypt encrypted response")
}
}
if err := response.Unpack(buf); err != nil {
return nil, errors.Wrap(err, "failed to unpack DNS response from body")
}
response.Id = queryID
return response, nil
}
@ -83,16 +160,28 @@ func exchange(msg []byte, queryID uint16, endpoint *url.URL, client *http.Client
}
// Perform message exchange with the default UDP wireformat defined in current draft
// https://datatracker.ietf.org/doc/draft-ietf-doh-dns-over-https
func exchangeWireformat(msg []byte, endpoint *url.URL, client *http.Client) ([]byte, error) {
// https://datatracker.ietf.org/doc/draft-ietf-doh-dns-over-https for DoH and
// https://tools.ietf.org/html/draft-pauly-dprive-oblivious-doh-03 for ODoH
func exchangeWireformat(msg []byte, endpoint *url.URL, client *http.Client, odoh *ObliviousDoHCtx) ([]byte, error) {
req, err := http.NewRequest("POST", endpoint.String(), bytes.NewBuffer(msg))
if err != nil {
return nil, errors.Wrap(err, "failed to create an HTTPS request")
}
req.Header.Add("Content-Type", "application/dns-message")
if odoh != nil {
req.Header.Add("Content-Type", "application/oblivious-dns-message")
req.Header.Add("Accept", "application/oblivious-dns-message")
req.Header.Add("Cache-Control", "no-cache, no-store")
if odoh.useproxy {
queries := req.URL.Query()
queries.Add("targethost", odoh.target.Hostname())
queries.Add("targetpath", "/dns-query")
req.URL.RawQuery = queries.Encode()
}
} else {
req.Header.Add("Content-Type", "application/dns-message")
}
req.Host = endpoint.Host
resp, err := client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "failed to perform an HTTPS request")

View File

@ -2,15 +2,20 @@ package tunneldns
import (
"net"
"net/http"
"net/url"
"os"
"os/signal"
"strconv"
"sync"
"syscall"
"time"
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
"github.com/cloudflare/cloudflared/logger"
"github.com/cloudflare/cloudflared/metrics"
odoh "github.com/cloudflare/odoh-go"
"github.com/miekg/dns"
"github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/plugin"
@ -26,6 +31,12 @@ type Listener struct {
logger logger.Service
}
const (
dohResolver = "https://1.1.1.1/dns-query"
)
var OdohConfig odoh.ObliviousDoHConfigContents
func Command(hidden bool) *cli.Command {
return &cli.Command{
Name: "proxy-dns",
@ -63,6 +74,33 @@ func Command(hidden bool) *cli.Command {
EnvVars: []string{"TUNNEL_DNS_BOOTSTRAP"},
},
},
Subcommands: []*cli.Command{
{
Name: "odoh",
Action: cliutil.ErrorHandler(RunOdoh),
Usage: "Runs an Oblivious DNS over HTTPS client.",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "target",
Usage: "ODoH target URL",
Value: "https://1.1.1.1/dns-query",
EnvVars: []string{"TUNNEL_DNS_ODOH_TARGET"},
},
&cli.StringFlag{
Name: "proxy",
Usage: "ODoH proxy URL",
Value: "https://odoh1.surfdomeinen.nl/proxy",
EnvVars: []string{"TUNNEL_DNS_ODOH_PROXY"},
},
&cli.BoolFlag{
Name: "useproxy",
Usage: "Set flag to enable proxy usage",
Value: false,
EnvVars: []string{"TUNNEL_DNS_ODOH_USE_PROXY"},
},
},
},
},
ArgsUsage: " ", // can't be the empty string or we get the default output
Hidden: hidden,
}
@ -82,7 +120,13 @@ func Run(c *cli.Context) error {
go metrics.ServeMetrics(metricsListener, nil, nil, logger)
listener, err := CreateListener(c.String("address"), uint16(c.Uint("port")), c.StringSlice("upstream"), c.StringSlice("bootstrap"), logger)
listener, err := CreateListener(
c.String("address"),
uint16(c.Uint("port")),
c.StringSlice("upstream"),
c.StringSlice("bootstrap"),
logger,
)
if err != nil {
logger.Errorf("Failed to create the listeners: %s", err)
return err
@ -111,6 +155,59 @@ func Run(c *cli.Context) error {
return err
}
// RunOdoh implements a foreground runner
func RunOdoh(c *cli.Context) error {
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
if err != nil {
return cliutil.PrintLoggerSetupError("error setting up logger", err)
}
metricsListener, err := net.Listen("tcp", c.String("metrics"))
if err != nil {
logger.Fatalf("Failed to open the metrics listener: %s", err)
}
go metrics.ServeMetrics(metricsListener, nil, nil, logger)
listener, err := CreateObliviousDNSListener(
c.String("address"),
uint16(c.Uint("port")),
c.String("target"),
c.String("proxy"),
c.Bool("useproxy"),
logger,
)
if err != nil {
logger.Errorf("Failed to create the listeners: %s", err)
return err
}
// Update odohconfig
go listener.UpdateOdohConfig()
// Try to start the server
readySignal := make(chan struct{})
err = listener.Start(readySignal)
if err != nil {
logger.Errorf("Failed to start the listeners: %s", err)
return listener.Stop()
}
<-readySignal
// Wait for signal
signals := make(chan os.Signal, 10)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
defer signal.Stop(signals)
<-signals
// Shut down server
err = listener.Stop()
if err != nil {
logger.Errorf("failed to stop: %s", err)
}
return err
}
// Create a CoreDNS server plugin from configuration
func createConfig(address string, port uint16, p plugin.Handler) *dnsserver.Config {
c := &dnsserver.Config{
@ -127,7 +224,8 @@ func createConfig(address string, port uint16, p plugin.Handler) *dnsserver.Conf
// Start blocks for serving requests
func (l *Listener) Start(readySignal chan struct{}) error {
defer close(readySignal)
l.logger.Infof("Starting DNS over HTTPS proxy server on: %s", l.server.Address())
l.logger.Infof("Starting DNS proxy server on: %s", l.server.Address())
// Start UDP listener
if udp, err := l.server.ListenPacket(); err == nil {
@ -153,6 +251,26 @@ func (l *Listener) Start(readySignal chan struct{}) error {
return errors.Wrap(err, "failed to create a TCP listener")
}
// UpdateOdohConfig periodically updates odoh configs
// Currently supports `odoh.cloudflare-dns.com.`.
func (l *Listener) UpdateOdohConfig() {
l.logger.Infof("Starting Oblivious DoH key updates")
dohResolver, _ := url.Parse(dohResolver)
client := http.Client{}
dnsQuery := new(dns.Msg)
dnsQuery.SetQuestion(targetHostname, dns.TypeHTTPS)
dnsQuery.RecursionDesired = true
packedDNSQuery, _ := dnsQuery.Pack()
for {
configs, err := FetchObliviousDoHConfig(&client, packedDNSQuery, dohResolver)
if err != nil {
l.logger.Errorf("odoh config not updated with err ", err)
}
OdohConfig = configs.Configs[0].Contents
time.Sleep(odohConfigDuration)
}
}
// Stop signals server shutdown and blocks until completed
func (l *Listener) Stop() error {
if err := l.server.Stop(); err != nil {
@ -169,17 +287,48 @@ func CreateListener(address string, port uint16, upstreams []string, bootstraps
upstreamList := make([]Upstream, 0)
for _, url := range upstreams {
logger.Infof("Adding DNS upstream - url: %s", url)
upstream, err := NewUpstreamHTTPS(url, bootstraps, logger)
upstream, err := NewUpstreamHTTPS(url, bootstraps, nil, logger)
if err != nil {
return nil, errors.Wrap(err, "failed to create HTTPS upstream")
}
upstreamList = append(upstreamList, upstream)
}
return buildListenerFromUpstream(upstreamList, address, port, logger)
}
// CreateObliviousDNSListener configures the server and bound sockets
func CreateObliviousDNSListener(address string, port uint16, target string, proxy string, useproxy bool, logger logger.Service) (*Listener, error) {
logger.Infof("Adding Oblivious DoH target - url: %s", target)
var upstream Upstream
var err error
targetURL, err := url.Parse(target)
if err != nil {
return nil, err
}
odohCtx := ObliviousDoHCtx{
useproxy: useproxy,
target: targetURL,
}
if useproxy {
logger.Infof("Adding Oblivious DoH proxy - url: %s", proxy)
upstream, err = NewUpstreamHTTPS(proxy, nil, &odohCtx, logger)
} else {
logger.Infof("No Oblivious DoH proxy is set")
upstream, err = NewUpstreamHTTPS(target, nil, &odohCtx, logger)
}
if err != nil {
return nil, errors.Wrap(err, "failed to create HTTPS upstream")
}
return buildListenerFromUpstream([]Upstream{upstream}, address, port, logger)
}
func buildListenerFromUpstream(upstreams []Upstream, address string, port uint16, logger logger.Service) (*Listener, error) {
// Create a local cache with HTTPS proxy plugin
chain := cache.New()
chain.Next = ProxyPlugin{
Upstreams: upstreamList,
Upstreams: upstreams,
}
// Format an endpoint

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2014-2015 Cryptography Research, Inc.
Copyright (c) 2015 Yawning Angel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

13
vendor/git.schwanenlied.me/yawning/x448.git/README.md generated vendored Normal file
View File

@ -0,0 +1,13 @@
### x448 - curve448 ECDH
#### Yawning Angel (yawning at schwanenlied dot me)
A straight forward port of Michael Hamburg's x448 code to Go lang.
See: https://www.rfc-editor.org/rfc/rfc7748.txt
If you're familiar with how to use golang.org/x/crypto/curve25519, you will be
right at home with using x448, since the functions are the same. Generate a
random secret key, ScalarBaseMult() to get the public key, etc etc etc.
Both routines return 0 on success, -1 on failure which MUST be checked, and
the handshake aborted on failure.

114
vendor/git.schwanenlied.me/yawning/x448.git/x448.go generated vendored Normal file
View File

@ -0,0 +1,114 @@
// The MIT License (MIT)
//
// Copyright (c) 2014-2015 Cryptography Research, Inc.
// Copyright (c) 2015 Yawning Angel.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Package x448 provides an implementation of scalar multiplication on the
// elliptic curve known as curve448.
//
// See https://tools.ietf.org/html/draft-irtf-cfrg-curves-11
package x448 // import "git.schwanenlied.me/yawning/x448.git"
const (
x448Bytes = 56
edwardsD = -39081
)
var basePoint = [56]byte{
5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
func ScalarMult(out, scalar, base *[56]byte) int {
var x1, x2, z2, x3, z3, t1, t2 gf
x1.deser(base)
x2.cpy(&one)
z2.cpy(&zero)
x3.cpy(&x1)
z3.cpy(&one)
var swap limbUint
for t := int(448 - 1); t >= 0; t-- {
sb := scalar[t/8]
// Scalar conditioning.
if t/8 == 0 {
sb &= 0xFC
} else if t/8 == x448Bytes-1 {
sb |= 0x80
}
kT := (limbUint)((sb >> ((uint)(t) % 8)) & 1)
kT = -kT // Set to all 0s or all 1s
swap ^= kT
x2.condSwap(&x3, swap)
z2.condSwap(&z3, swap)
swap = kT
t1.add(&x2, &z2) // A = x2 + z2
t2.sub(&x2, &z2) // B = x2 - z2
z2.sub(&x3, &z3) // D = x3 - z3
x2.mul(&t1, &z2) // DA
z2.add(&z3, &x3) // C = x3 + z3
x3.mul(&t2, &z2) // CB
z3.sub(&x2, &x3) // DA-CB
z2.sqr(&z3) // (DA-CB)^2
z3.mul(&x1, &z2) // z3 = x1(DA-CB)^2
z2.add(&x2, &x3) // (DA+CB)
x3.sqr(&z2) // x3 = (DA+CB)^2
z2.sqr(&t1) // AA = A^2
t1.sqr(&t2) // BB = B^2
x2.mul(&z2, &t1) // x2 = AA*BB
t2.sub(&z2, &t1) // E = AA-BB
t1.mlw(&t2, -edwardsD) // E*-d = a24*E
t1.add(&t1, &z2) // AA + a24*E
z2.mul(&t2, &t1) // z2 = E(AA+a24*E)
}
// Finish
x2.condSwap(&x3, swap)
z2.condSwap(&x3, swap)
z2.inv(&z2)
x1.mul(&x2, &z2)
x1.ser(out)
// As with X25519, both sides MUST check, without leaking extra
// information about the value of K, whether the resulting shared K is
// the all-zero value and abort if so.
var nz limbSint
for _, v := range out {
nz |= (limbSint)(v)
}
nz = (nz - 1) >> 8 // 0 = succ, -1 = fail
// return value: 0 = succ, -1 = fail
return (int)(nz)
}
func ScalarBaseMult(out, scalar *[56]byte) int {
return ScalarMult(out, scalar, &basePoint)
}

778
vendor/git.schwanenlied.me/yawning/x448.git/x448_ref.go generated vendored Normal file
View File

@ -0,0 +1,778 @@
// The MIT License (MIT)
//
// Copyright (c) 2014-2015 Cryptography Research, Inc.
// Copyright (c) 2015 Yawning Angel.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package x448
// This should really use 64 bit limbs, but Go is fucking retarded and doesn't
// have __(u)int128_t, so the 32 bit code it is, at a hefty performance
// penalty. Fuck my life, I'm going to have to bust out PeachPy to get this
// to go fast aren't I.
const (
wBits = 32
lBits = (wBits * 7 / 8)
x448Limbs = (448 / lBits)
lMask = (1 << lBits) - 1
)
type limbUint uint32
type limbSint int32
type gf struct {
limb [x448Limbs]uint32
}
var zero = gf{[x448Limbs]uint32{0}}
var one = gf{[x448Limbs]uint32{1}}
var p = gf{[x448Limbs]uint32{
lMask, lMask, lMask, lMask, lMask, lMask, lMask, lMask,
lMask - 1, lMask, lMask, lMask, lMask, lMask, lMask, lMask,
}}
// cpy copies x = y.
func (x *gf) cpy(y *gf) {
// for i, v := range y.limb {
// x.limb[i] = v
// }
copy(x.limb[:], y.limb[:])
}
// mul multiplies c = a * b. (PERF)
func (c *gf) mul(a, b *gf) {
var aa gf
aa.cpy(a)
//
// This is *by far* the most CPU intesive routine in the code.
//
// var accum [x448Limbs]uint64
// for i, bv := range b.limb {
// for j, aav := range aa.limb {
// accum[(i+j)%x448Limbs] += (uint64)(bv) * (uint64)(aav)
// }
// aa.limb[(x448Limbs-1-i)^(x448Limbs/2)] += aa.limb[x448Limbs-1-i]
// }
// So fucking stupid that this is actually a fairly massive gain.
var accum0, accum1, accum2, accum3, accum4, accum5, accum6, accum7, accum8, accum9, accum10, accum11, accum12, accum13, accum14, accum15 uint64
var bv uint64
bv = (uint64)(b.limb[0])
accum0 += bv * (uint64)(aa.limb[0])
accum1 += bv * (uint64)(aa.limb[1])
accum2 += bv * (uint64)(aa.limb[2])
accum3 += bv * (uint64)(aa.limb[3])
accum4 += bv * (uint64)(aa.limb[4])
accum5 += bv * (uint64)(aa.limb[5])
accum6 += bv * (uint64)(aa.limb[6])
accum7 += bv * (uint64)(aa.limb[7])
accum8 += bv * (uint64)(aa.limb[8])
accum9 += bv * (uint64)(aa.limb[9])
accum10 += bv * (uint64)(aa.limb[10])
accum11 += bv * (uint64)(aa.limb[11])
accum12 += bv * (uint64)(aa.limb[12])
accum13 += bv * (uint64)(aa.limb[13])
accum14 += bv * (uint64)(aa.limb[14])
accum15 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-0)^(x448Limbs/2)] += aa.limb[x448Limbs-1-0]
bv = (uint64)(b.limb[1])
accum1 += bv * (uint64)(aa.limb[0])
accum2 += bv * (uint64)(aa.limb[1])
accum3 += bv * (uint64)(aa.limb[2])
accum4 += bv * (uint64)(aa.limb[3])
accum5 += bv * (uint64)(aa.limb[4])
accum6 += bv * (uint64)(aa.limb[5])
accum7 += bv * (uint64)(aa.limb[6])
accum8 += bv * (uint64)(aa.limb[7])
accum9 += bv * (uint64)(aa.limb[8])
accum10 += bv * (uint64)(aa.limb[9])
accum11 += bv * (uint64)(aa.limb[10])
accum12 += bv * (uint64)(aa.limb[11])
accum13 += bv * (uint64)(aa.limb[12])
accum14 += bv * (uint64)(aa.limb[13])
accum15 += bv * (uint64)(aa.limb[14])
accum0 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-1)^(x448Limbs/2)] += aa.limb[x448Limbs-1-1]
bv = (uint64)(b.limb[2])
accum2 += bv * (uint64)(aa.limb[0])
accum3 += bv * (uint64)(aa.limb[1])
accum4 += bv * (uint64)(aa.limb[2])
accum5 += bv * (uint64)(aa.limb[3])
accum6 += bv * (uint64)(aa.limb[4])
accum7 += bv * (uint64)(aa.limb[5])
accum8 += bv * (uint64)(aa.limb[6])
accum9 += bv * (uint64)(aa.limb[7])
accum10 += bv * (uint64)(aa.limb[8])
accum11 += bv * (uint64)(aa.limb[9])
accum12 += bv * (uint64)(aa.limb[10])
accum13 += bv * (uint64)(aa.limb[11])
accum14 += bv * (uint64)(aa.limb[12])
accum15 += bv * (uint64)(aa.limb[13])
accum0 += bv * (uint64)(aa.limb[14])
accum1 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-2)^(x448Limbs/2)] += aa.limb[x448Limbs-1-2]
bv = (uint64)(b.limb[3])
accum3 += bv * (uint64)(aa.limb[0])
accum4 += bv * (uint64)(aa.limb[1])
accum5 += bv * (uint64)(aa.limb[2])
accum6 += bv * (uint64)(aa.limb[3])
accum7 += bv * (uint64)(aa.limb[4])
accum8 += bv * (uint64)(aa.limb[5])
accum9 += bv * (uint64)(aa.limb[6])
accum10 += bv * (uint64)(aa.limb[7])
accum11 += bv * (uint64)(aa.limb[8])
accum12 += bv * (uint64)(aa.limb[9])
accum13 += bv * (uint64)(aa.limb[10])
accum14 += bv * (uint64)(aa.limb[11])
accum15 += bv * (uint64)(aa.limb[12])
accum0 += bv * (uint64)(aa.limb[13])
accum1 += bv * (uint64)(aa.limb[14])
accum2 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-3)^(x448Limbs/2)] += aa.limb[x448Limbs-1-3]
bv = (uint64)(b.limb[4])
accum4 += bv * (uint64)(aa.limb[0])
accum5 += bv * (uint64)(aa.limb[1])
accum6 += bv * (uint64)(aa.limb[2])
accum7 += bv * (uint64)(aa.limb[3])
accum8 += bv * (uint64)(aa.limb[4])
accum9 += bv * (uint64)(aa.limb[5])
accum10 += bv * (uint64)(aa.limb[6])
accum11 += bv * (uint64)(aa.limb[7])
accum12 += bv * (uint64)(aa.limb[8])
accum13 += bv * (uint64)(aa.limb[9])
accum14 += bv * (uint64)(aa.limb[10])
accum15 += bv * (uint64)(aa.limb[11])
accum0 += bv * (uint64)(aa.limb[12])
accum1 += bv * (uint64)(aa.limb[13])
accum2 += bv * (uint64)(aa.limb[14])
accum3 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-4)^(x448Limbs/2)] += aa.limb[x448Limbs-1-4]
bv = (uint64)(b.limb[5])
accum5 += bv * (uint64)(aa.limb[0])
accum6 += bv * (uint64)(aa.limb[1])
accum7 += bv * (uint64)(aa.limb[2])
accum8 += bv * (uint64)(aa.limb[3])
accum9 += bv * (uint64)(aa.limb[4])
accum10 += bv * (uint64)(aa.limb[5])
accum11 += bv * (uint64)(aa.limb[6])
accum12 += bv * (uint64)(aa.limb[7])
accum13 += bv * (uint64)(aa.limb[8])
accum14 += bv * (uint64)(aa.limb[9])
accum15 += bv * (uint64)(aa.limb[10])
accum0 += bv * (uint64)(aa.limb[11])
accum1 += bv * (uint64)(aa.limb[12])
accum2 += bv * (uint64)(aa.limb[13])
accum3 += bv * (uint64)(aa.limb[14])
accum4 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-5)^(x448Limbs/2)] += aa.limb[x448Limbs-1-5]
bv = (uint64)(b.limb[6])
accum6 += bv * (uint64)(aa.limb[0])
accum7 += bv * (uint64)(aa.limb[1])
accum8 += bv * (uint64)(aa.limb[2])
accum9 += bv * (uint64)(aa.limb[3])
accum10 += bv * (uint64)(aa.limb[4])
accum11 += bv * (uint64)(aa.limb[5])
accum12 += bv * (uint64)(aa.limb[6])
accum13 += bv * (uint64)(aa.limb[7])
accum14 += bv * (uint64)(aa.limb[8])
accum15 += bv * (uint64)(aa.limb[9])
accum0 += bv * (uint64)(aa.limb[10])
accum1 += bv * (uint64)(aa.limb[11])
accum2 += bv * (uint64)(aa.limb[12])
accum3 += bv * (uint64)(aa.limb[13])
accum4 += bv * (uint64)(aa.limb[14])
accum5 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-6)^(x448Limbs/2)] += aa.limb[x448Limbs-1-6]
bv = (uint64)(b.limb[7])
accum7 += bv * (uint64)(aa.limb[0])
accum8 += bv * (uint64)(aa.limb[1])
accum9 += bv * (uint64)(aa.limb[2])
accum10 += bv * (uint64)(aa.limb[3])
accum11 += bv * (uint64)(aa.limb[4])
accum12 += bv * (uint64)(aa.limb[5])
accum13 += bv * (uint64)(aa.limb[6])
accum14 += bv * (uint64)(aa.limb[7])
accum15 += bv * (uint64)(aa.limb[8])
accum0 += bv * (uint64)(aa.limb[9])
accum1 += bv * (uint64)(aa.limb[10])
accum2 += bv * (uint64)(aa.limb[11])
accum3 += bv * (uint64)(aa.limb[12])
accum4 += bv * (uint64)(aa.limb[13])
accum5 += bv * (uint64)(aa.limb[14])
accum6 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-7)^(x448Limbs/2)] += aa.limb[x448Limbs-1-7]
bv = (uint64)(b.limb[8])
accum8 += bv * (uint64)(aa.limb[0])
accum9 += bv * (uint64)(aa.limb[1])
accum10 += bv * (uint64)(aa.limb[2])
accum11 += bv * (uint64)(aa.limb[3])
accum12 += bv * (uint64)(aa.limb[4])
accum13 += bv * (uint64)(aa.limb[5])
accum14 += bv * (uint64)(aa.limb[6])
accum15 += bv * (uint64)(aa.limb[7])
accum0 += bv * (uint64)(aa.limb[8])
accum1 += bv * (uint64)(aa.limb[9])
accum2 += bv * (uint64)(aa.limb[10])
accum3 += bv * (uint64)(aa.limb[11])
accum4 += bv * (uint64)(aa.limb[12])
accum5 += bv * (uint64)(aa.limb[13])
accum6 += bv * (uint64)(aa.limb[14])
accum7 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-8)^(x448Limbs/2)] += aa.limb[x448Limbs-1-8]
bv = (uint64)(b.limb[9])
accum9 += bv * (uint64)(aa.limb[0])
accum10 += bv * (uint64)(aa.limb[1])
accum11 += bv * (uint64)(aa.limb[2])
accum12 += bv * (uint64)(aa.limb[3])
accum13 += bv * (uint64)(aa.limb[4])
accum14 += bv * (uint64)(aa.limb[5])
accum15 += bv * (uint64)(aa.limb[6])
accum0 += bv * (uint64)(aa.limb[7])
accum1 += bv * (uint64)(aa.limb[8])
accum2 += bv * (uint64)(aa.limb[9])
accum3 += bv * (uint64)(aa.limb[10])
accum4 += bv * (uint64)(aa.limb[11])
accum5 += bv * (uint64)(aa.limb[12])
accum6 += bv * (uint64)(aa.limb[13])
accum7 += bv * (uint64)(aa.limb[14])
accum8 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-9)^(x448Limbs/2)] += aa.limb[x448Limbs-1-9]
bv = (uint64)(b.limb[10])
accum10 += bv * (uint64)(aa.limb[0])
accum11 += bv * (uint64)(aa.limb[1])
accum12 += bv * (uint64)(aa.limb[2])
accum13 += bv * (uint64)(aa.limb[3])
accum14 += bv * (uint64)(aa.limb[4])
accum15 += bv * (uint64)(aa.limb[5])
accum0 += bv * (uint64)(aa.limb[6])
accum1 += bv * (uint64)(aa.limb[7])
accum2 += bv * (uint64)(aa.limb[8])
accum3 += bv * (uint64)(aa.limb[9])
accum4 += bv * (uint64)(aa.limb[10])
accum5 += bv * (uint64)(aa.limb[11])
accum6 += bv * (uint64)(aa.limb[12])
accum7 += bv * (uint64)(aa.limb[13])
accum8 += bv * (uint64)(aa.limb[14])
accum9 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-10)^(x448Limbs/2)] += aa.limb[x448Limbs-1-10]
bv = (uint64)(b.limb[11])
accum11 += bv * (uint64)(aa.limb[0])
accum12 += bv * (uint64)(aa.limb[1])
accum13 += bv * (uint64)(aa.limb[2])
accum14 += bv * (uint64)(aa.limb[3])
accum15 += bv * (uint64)(aa.limb[4])
accum0 += bv * (uint64)(aa.limb[5])
accum1 += bv * (uint64)(aa.limb[6])
accum2 += bv * (uint64)(aa.limb[7])
accum3 += bv * (uint64)(aa.limb[8])
accum4 += bv * (uint64)(aa.limb[9])
accum5 += bv * (uint64)(aa.limb[10])
accum6 += bv * (uint64)(aa.limb[11])
accum7 += bv * (uint64)(aa.limb[12])
accum8 += bv * (uint64)(aa.limb[13])
accum9 += bv * (uint64)(aa.limb[14])
accum10 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-11)^(x448Limbs/2)] += aa.limb[x448Limbs-1-11]
bv = (uint64)(b.limb[12])
accum12 += bv * (uint64)(aa.limb[0])
accum13 += bv * (uint64)(aa.limb[1])
accum14 += bv * (uint64)(aa.limb[2])
accum15 += bv * (uint64)(aa.limb[3])
accum0 += bv * (uint64)(aa.limb[4])
accum1 += bv * (uint64)(aa.limb[5])
accum2 += bv * (uint64)(aa.limb[6])
accum3 += bv * (uint64)(aa.limb[7])
accum4 += bv * (uint64)(aa.limb[8])
accum5 += bv * (uint64)(aa.limb[9])
accum6 += bv * (uint64)(aa.limb[10])
accum7 += bv * (uint64)(aa.limb[11])
accum8 += bv * (uint64)(aa.limb[12])
accum9 += bv * (uint64)(aa.limb[13])
accum10 += bv * (uint64)(aa.limb[14])
accum11 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-12)^(x448Limbs/2)] += aa.limb[x448Limbs-1-12]
bv = (uint64)(b.limb[13])
accum13 += bv * (uint64)(aa.limb[0])
accum14 += bv * (uint64)(aa.limb[1])
accum15 += bv * (uint64)(aa.limb[2])
accum0 += bv * (uint64)(aa.limb[3])
accum1 += bv * (uint64)(aa.limb[4])
accum2 += bv * (uint64)(aa.limb[5])
accum3 += bv * (uint64)(aa.limb[6])
accum4 += bv * (uint64)(aa.limb[7])
accum5 += bv * (uint64)(aa.limb[8])
accum6 += bv * (uint64)(aa.limb[9])
accum7 += bv * (uint64)(aa.limb[10])
accum8 += bv * (uint64)(aa.limb[11])
accum9 += bv * (uint64)(aa.limb[12])
accum10 += bv * (uint64)(aa.limb[13])
accum11 += bv * (uint64)(aa.limb[14])
accum12 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-13)^(x448Limbs/2)] += aa.limb[x448Limbs-1-13]
bv = (uint64)(b.limb[14])
accum14 += bv * (uint64)(aa.limb[0])
accum15 += bv * (uint64)(aa.limb[1])
accum0 += bv * (uint64)(aa.limb[2])
accum1 += bv * (uint64)(aa.limb[3])
accum2 += bv * (uint64)(aa.limb[4])
accum3 += bv * (uint64)(aa.limb[5])
accum4 += bv * (uint64)(aa.limb[6])
accum5 += bv * (uint64)(aa.limb[7])
accum6 += bv * (uint64)(aa.limb[8])
accum7 += bv * (uint64)(aa.limb[9])
accum8 += bv * (uint64)(aa.limb[10])
accum9 += bv * (uint64)(aa.limb[11])
accum10 += bv * (uint64)(aa.limb[12])
accum11 += bv * (uint64)(aa.limb[13])
accum12 += bv * (uint64)(aa.limb[14])
accum13 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-14)^(x448Limbs/2)] += aa.limb[x448Limbs-1-14]
bv = (uint64)(b.limb[15])
accum15 += bv * (uint64)(aa.limb[0])
accum0 += bv * (uint64)(aa.limb[1])
accum1 += bv * (uint64)(aa.limb[2])
accum2 += bv * (uint64)(aa.limb[3])
accum3 += bv * (uint64)(aa.limb[4])
accum4 += bv * (uint64)(aa.limb[5])
accum5 += bv * (uint64)(aa.limb[6])
accum6 += bv * (uint64)(aa.limb[7])
accum7 += bv * (uint64)(aa.limb[8])
accum8 += bv * (uint64)(aa.limb[9])
accum9 += bv * (uint64)(aa.limb[10])
accum10 += bv * (uint64)(aa.limb[11])
accum11 += bv * (uint64)(aa.limb[12])
accum12 += bv * (uint64)(aa.limb[13])
accum13 += bv * (uint64)(aa.limb[14])
accum14 += bv * (uint64)(aa.limb[15])
aa.limb[(x448Limbs-1-15)^(x448Limbs/2)] += aa.limb[x448Limbs-1-15]
// accum[x448Limbs-1] += accum[x448Limbs-2] >> lBits
// accum[x448Limbs-2] &= lMask
// accum[x448Limbs/2] += accum[x448Limbs-1] >> lBits
accum15 += accum14 >> lBits
accum14 &= lMask
accum8 += accum15 >> lBits
// for j := uint(0); j < x448Limbs; j++ {
// accum[j] += accum[(j-1)%x448Limbs] >> lBits
// accum[(j-1)%x448Limbs] &= lMask
// }
accum0 += accum15 >> lBits
accum15 &= lMask
accum1 += accum0 >> lBits
accum0 &= lMask
accum2 += accum1 >> lBits
accum1 &= lMask
accum3 += accum2 >> lBits
accum2 &= lMask
accum4 += accum3 >> lBits
accum3 &= lMask
accum5 += accum4 >> lBits
accum4 &= lMask
accum6 += accum5 >> lBits
accum5 &= lMask
accum7 += accum6 >> lBits
accum6 &= lMask
accum8 += accum7 >> lBits
accum7 &= lMask
accum9 += accum8 >> lBits
accum8 &= lMask
accum10 += accum9 >> lBits
accum9 &= lMask
accum11 += accum10 >> lBits
accum10 &= lMask
accum12 += accum11 >> lBits
accum11 &= lMask
accum13 += accum12 >> lBits
accum12 &= lMask
accum14 += accum13 >> lBits
accum13 &= lMask
accum15 += accum14 >> lBits
accum14 &= lMask
// for j, accv := range accum {
// c.limb[j] = (uint32)(accv)
// }
c.limb[0] = (uint32)(accum0)
c.limb[1] = (uint32)(accum1)
c.limb[2] = (uint32)(accum2)
c.limb[3] = (uint32)(accum3)
c.limb[4] = (uint32)(accum4)
c.limb[5] = (uint32)(accum5)
c.limb[6] = (uint32)(accum6)
c.limb[7] = (uint32)(accum7)
c.limb[8] = (uint32)(accum8)
c.limb[9] = (uint32)(accum9)
c.limb[10] = (uint32)(accum10)
c.limb[11] = (uint32)(accum11)
c.limb[12] = (uint32)(accum12)
c.limb[13] = (uint32)(accum13)
c.limb[14] = (uint32)(accum14)
c.limb[15] = (uint32)(accum15)
}
// sqr squares (c = x * x). Just calls multiply. (PERF)
func (c *gf) sqr(x *gf) {
c.mul(x, x)
}
// isqrt inverse square roots (y = 1/sqrt(x)), using an addition chain.
func (y *gf) isqrt(x *gf) {
var a, b, c gf
c.sqr(x)
// XXX/Yawning, could unroll, but this is called only once.
// STEP(b,x,1);
b.mul(x, &c)
c.cpy(&b)
for i := 0; i < 1; i++ {
c.sqr(&c)
}
// STEP(b,x,3);
b.mul(x, &c)
c.cpy(&b)
for i := 0; i < 3; i++ {
c.sqr(&c)
}
//STEP(a,b,3);
a.mul(&b, &c)
c.cpy(&a)
for i := 0; i < 3; i++ {
c.sqr(&c)
}
// STEP(a,b,9);
a.mul(&b, &c)
c.cpy(&a)
for i := 0; i < 9; i++ {
c.sqr(&c)
}
// STEP(b,a,1);
b.mul(&a, &c)
c.cpy(&b)
for i := 0; i < 1; i++ {
c.sqr(&c)
}
// STEP(a,x,18);
a.mul(x, &c)
c.cpy(&a)
for i := 0; i < 18; i++ {
c.sqr(&c)
}
// STEP(a,b,37);
a.mul(&b, &c)
c.cpy(&a)
for i := 0; i < 37; i++ {
c.sqr(&c)
}
// STEP(b,a,37);
b.mul(&a, &c)
c.cpy(&b)
for i := 0; i < 37; i++ {
c.sqr(&c)
}
// STEP(b,a,111);
b.mul(&a, &c)
c.cpy(&b)
for i := 0; i < 111; i++ {
c.sqr(&c)
}
// STEP(a,b,1);
a.mul(&b, &c)
c.cpy(&a)
for i := 0; i < 1; i++ {
c.sqr(&c)
}
// STEP(b,x,223);
b.mul(x, &c)
c.cpy(&b)
for i := 0; i < 223; i++ {
c.sqr(&c)
}
y.mul(&a, &c)
}
// inv inverses (y = 1/x).
func (y *gf) inv(x *gf) {
var z, w gf
z.sqr(x) // x^2
w.isqrt(&z) // +- 1/sqrt(x^2) = +- 1/x
z.sqr(&w) // 1/x^2
w.mul(x, &z) // 1/x
y.cpy(&w)
}
// reduce weakly reduces mod p
func (x *gf) reduce() {
x.limb[x448Limbs/2] += x.limb[x448Limbs-1] >> lBits
// for j := uint(0); j < x448Limbs; j++ {
// x.limb[j] += x.limb[(j-1)%x448Limbs] >> lBits
// x.limb[(j-1)%x448Limbs] &= lMask
// }
x.limb[0] += x.limb[15] >> lBits
x.limb[15] &= lMask
x.limb[1] += x.limb[0] >> lBits
x.limb[0] &= lMask
x.limb[2] += x.limb[1] >> lBits
x.limb[1] &= lMask
x.limb[3] += x.limb[2] >> lBits
x.limb[2] &= lMask
x.limb[4] += x.limb[3] >> lBits
x.limb[3] &= lMask
x.limb[5] += x.limb[4] >> lBits
x.limb[4] &= lMask
x.limb[6] += x.limb[5] >> lBits
x.limb[5] &= lMask
x.limb[7] += x.limb[6] >> lBits
x.limb[6] &= lMask
x.limb[8] += x.limb[7] >> lBits
x.limb[7] &= lMask
x.limb[9] += x.limb[8] >> lBits
x.limb[8] &= lMask
x.limb[10] += x.limb[9] >> lBits
x.limb[9] &= lMask
x.limb[11] += x.limb[10] >> lBits
x.limb[10] &= lMask
x.limb[12] += x.limb[11] >> lBits
x.limb[11] &= lMask
x.limb[13] += x.limb[12] >> lBits
x.limb[12] &= lMask
x.limb[14] += x.limb[13] >> lBits
x.limb[13] &= lMask
x.limb[15] += x.limb[14] >> lBits
x.limb[14] &= lMask
}
// add adds mod p. Conservatively always weak-reduces. (PERF)
func (x *gf) add(y, z *gf) {
// for i, yv := range y.limb {
// x.limb[i] = yv + z.limb[i]
// }
x.limb[0] = y.limb[0] + z.limb[0]
x.limb[1] = y.limb[1] + z.limb[1]
x.limb[2] = y.limb[2] + z.limb[2]
x.limb[3] = y.limb[3] + z.limb[3]
x.limb[4] = y.limb[4] + z.limb[4]
x.limb[5] = y.limb[5] + z.limb[5]
x.limb[6] = y.limb[6] + z.limb[6]
x.limb[7] = y.limb[7] + z.limb[7]
x.limb[8] = y.limb[8] + z.limb[8]
x.limb[9] = y.limb[9] + z.limb[9]
x.limb[10] = y.limb[10] + z.limb[10]
x.limb[11] = y.limb[11] + z.limb[11]
x.limb[12] = y.limb[12] + z.limb[12]
x.limb[13] = y.limb[13] + z.limb[13]
x.limb[14] = y.limb[14] + z.limb[14]
x.limb[15] = y.limb[15] + z.limb[15]
x.reduce()
}
// sub subtracts mod p. Conservatively always weak-reduces. (PERF)
func (x *gf) sub(y, z *gf) {
// for i, yv := range y.limb {
// x.limb[i] = yv - z.limb[i] + 2*p.limb[i]
// }
x.limb[0] = y.limb[0] - z.limb[0] + 2*lMask
x.limb[1] = y.limb[1] - z.limb[1] + 2*lMask
x.limb[2] = y.limb[2] - z.limb[2] + 2*lMask
x.limb[3] = y.limb[3] - z.limb[3] + 2*lMask
x.limb[4] = y.limb[4] - z.limb[4] + 2*lMask
x.limb[5] = y.limb[5] - z.limb[5] + 2*lMask
x.limb[6] = y.limb[6] - z.limb[6] + 2*lMask
x.limb[7] = y.limb[7] - z.limb[7] + 2*lMask
x.limb[8] = y.limb[8] - z.limb[8] + 2*(lMask-1)
x.limb[9] = y.limb[9] - z.limb[9] + 2*lMask
x.limb[10] = y.limb[10] - z.limb[10] + 2*lMask
x.limb[11] = y.limb[11] - z.limb[11] + 2*lMask
x.limb[12] = y.limb[12] - z.limb[12] + 2*lMask
x.limb[13] = y.limb[13] - z.limb[13] + 2*lMask
x.limb[14] = y.limb[14] - z.limb[14] + 2*lMask
x.limb[15] = y.limb[15] - z.limb[15] + 2*lMask
x.reduce()
}
// condSwap swaps x and y in constant time.
func (x *gf) condSwap(y *gf, swap limbUint) {
// for i, xv := range x.limb {
// s := (xv ^ y.limb[i]) & (uint32)(swap) // Sort of dumb, oh well.
// x.limb[i] ^= s
// y.limb[i] ^= s
// }
var s uint32
s = (x.limb[0] ^ y.limb[0]) & (uint32)(swap)
x.limb[0] ^= s
y.limb[0] ^= s
s = (x.limb[1] ^ y.limb[1]) & (uint32)(swap)
x.limb[1] ^= s
y.limb[1] ^= s
s = (x.limb[2] ^ y.limb[2]) & (uint32)(swap)
x.limb[2] ^= s
y.limb[2] ^= s
s = (x.limb[3] ^ y.limb[3]) & (uint32)(swap)
x.limb[3] ^= s
y.limb[3] ^= s
s = (x.limb[4] ^ y.limb[4]) & (uint32)(swap)
x.limb[4] ^= s
y.limb[4] ^= s
s = (x.limb[5] ^ y.limb[5]) & (uint32)(swap)
x.limb[5] ^= s
y.limb[5] ^= s
s = (x.limb[6] ^ y.limb[6]) & (uint32)(swap)
x.limb[6] ^= s
y.limb[6] ^= s
s = (x.limb[7] ^ y.limb[7]) & (uint32)(swap)
x.limb[7] ^= s
y.limb[7] ^= s
s = (x.limb[8] ^ y.limb[8]) & (uint32)(swap)
x.limb[8] ^= s
y.limb[8] ^= s
s = (x.limb[9] ^ y.limb[9]) & (uint32)(swap)
x.limb[9] ^= s
y.limb[9] ^= s
s = (x.limb[10] ^ y.limb[10]) & (uint32)(swap)
x.limb[10] ^= s
y.limb[10] ^= s
s = (x.limb[11] ^ y.limb[11]) & (uint32)(swap)
x.limb[11] ^= s
y.limb[11] ^= s
s = (x.limb[12] ^ y.limb[12]) & (uint32)(swap)
x.limb[12] ^= s
y.limb[12] ^= s
s = (x.limb[13] ^ y.limb[13]) & (uint32)(swap)
x.limb[13] ^= s
y.limb[13] ^= s
s = (x.limb[14] ^ y.limb[14]) & (uint32)(swap)
x.limb[14] ^= s
y.limb[14] ^= s
s = (x.limb[15] ^ y.limb[15]) & (uint32)(swap)
x.limb[15] ^= s
y.limb[15] ^= s
}
// mlw multiplies by a signed int. NOT CONSTANT TIME wrt the sign of the int,
// but that's ok because it's only ever called with w = -edwardsD. Just uses
// a full multiply. (PERF)
func (a *gf) mlw(b *gf, w int) {
if w > 0 {
ww := gf{[x448Limbs]uint32{(uint32)(w)}}
a.mul(b, &ww)
} else {
// This branch is *NEVER* taken with the current code.
panic("mul called with negative w")
ww := gf{[x448Limbs]uint32{(uint32)(-w)}}
a.mul(b, &ww)
a.sub(&zero, a)
}
}
// canon canonicalizes.
func (a *gf) canon() {
a.reduce()
// Subtract p with borrow.
var carry int64
for i, v := range a.limb {
carry = carry + (int64)(v) - (int64)(p.limb[i])
a.limb[i] = (uint32)(carry & lMask)
carry >>= lBits
}
addback := carry
carry = 0
// Add it back.
for i, v := range a.limb {
carry = carry + (int64)(v) + (int64)(p.limb[i]&(uint32)(addback))
a.limb[i] = uint32(carry & lMask)
carry >>= lBits
}
}
// deser deserializes into the limb representation.
func (s *gf) deser(ser *[x448Bytes]byte) {
var buf uint64
bits := uint(0)
k := 0
for i, v := range ser {
buf |= (uint64)(v) << bits
for bits += 8; (bits >= lBits || i == x448Bytes-1) && k < x448Limbs; bits, buf = bits-lBits, buf>>lBits {
s.limb[k] = (uint32)(buf & lMask)
k++
}
}
}
// ser serializes into byte representation.
func (a *gf) ser(ser *[x448Bytes]byte) {
a.canon()
k := 0
bits := uint(0)
var buf uint64
for i, v := range a.limb {
buf |= (uint64)(v) << bits
for bits += lBits; (bits >= 8 || i == x448Limbs-1) && k < x448Bytes; bits, buf = bits-8, buf>>8 {
ser[k] = (byte)(buf)
k++
}
}
}
func init() {
if x448Limbs != 16 {
panic("x448Limbs != 16, unrolled loops likely broken")
}
}

25
vendor/github.com/cisco/go-hpke/LICENSE generated vendored Normal file
View File

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

21
vendor/github.com/cisco/go-hpke/README.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
# HPKE
[![Coverage Status](https://coveralls.io/repos/github/cisco/go-hpke/badge.svg?branch=ci)](https://coveralls.io/github/cisco/go-hpke?branch=ci)
This repo provides a Go implementation of the HPKE primitive proposed for discussion at CFRG.
https://tools.ietf.org/html/draft-irtf-cfrg-hpke
## Test vector generation
To generate test vectors, run:
```
$ HPKE_TEST_VECTORS_OUT=test-vectors.json go test -v -run TestVectorGenerate
```
To check test vectors, run:
```
$ HPKE_TEST_VECTORS_IN=test-vectors.json go test -v -run TestVectorVerify
```

990
vendor/github.com/cisco/go-hpke/crypto.go generated vendored Normal file
View File

@ -0,0 +1,990 @@
package hpke
import (
"bytes"
"crypto"
"crypto/aes"
"crypto/cipher"
"crypto/elliptic"
"crypto/hmac"
"crypto/rand"
"crypto/subtle"
"encoding/binary"
"fmt"
"io"
"math/big"
mrand "math/rand"
_ "crypto/sha256"
_ "crypto/sha512"
"git.schwanenlied.me/yawning/x448.git"
"github.com/cloudflare/circl/dh/sidh"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/curve25519"
)
////////
// DHKEM
type dhScheme interface {
ID() KEMID
DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error)
Serialize(pk KEMPublicKey) []byte
Deserialize(enc []byte) (KEMPublicKey, error)
DH(priv KEMPrivateKey, pub KEMPublicKey) ([]byte, error)
PublicKeySize() int
PrivateKeySize() int
SerializePrivate(sk KEMPrivateKey) []byte
DeserializePrivate(enc []byte) (KEMPrivateKey, error)
internalKDF() KDFScheme
}
type dhkemScheme struct {
group dhScheme
skE KEMPrivateKey
}
func (s dhkemScheme) ID() KEMID {
return s.group.ID()
}
func (s dhkemScheme) DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error) {
return s.group.DeriveKeyPair(ikm)
}
func (s dhkemScheme) Serialize(pk KEMPublicKey) []byte {
return s.group.Serialize(pk)
}
func (s dhkemScheme) SerializePrivate(sk KEMPrivateKey) []byte {
return s.group.SerializePrivate(sk)
}
func (s dhkemScheme) Deserialize(enc []byte) (KEMPublicKey, error) {
return s.group.Deserialize(enc)
}
func (s dhkemScheme) DeserializePrivate(enc []byte) (KEMPrivateKey, error) {
return s.group.DeserializePrivate(enc)
}
func (s *dhkemScheme) setEphemeralKeyPair(skE KEMPrivateKey) {
s.skE = skE
}
func (s dhkemScheme) getEphemeralKeyPair(rand io.Reader) (KEMPrivateKey, KEMPublicKey, error) {
if s.skE != nil {
return s.skE, s.skE.PublicKey(), nil
}
ikm := make([]byte, s.PrivateKeySize())
rand.Read(ikm)
return s.group.DeriveKeyPair(ikm)
}
func (s dhkemScheme) extractAndExpand(dh []byte, kemContext []byte, Nsecret int) []byte {
suiteID := kemSuiteFromID(s.ID())
eae_prk := s.group.internalKDF().LabeledExtract(nil, suiteID, "eae_prk", dh)
return s.group.internalKDF().LabeledExpand(eae_prk, suiteID, "shared_secret", kemContext, Nsecret)
}
func (s dhkemScheme) Encap(rand io.Reader, pkR KEMPublicKey) ([]byte, []byte, error) {
skE, pkE, err := s.getEphemeralKeyPair(rand)
if err != nil {
return nil, nil, err
}
dh, err := s.group.DH(skE, pkR)
if err != nil {
return nil, nil, err
}
enc := s.group.Serialize(pkE)
pkRm := s.group.Serialize(pkR)
kemContext := make([]byte, len(enc)+len(pkRm))
copy(kemContext, enc)
copy(kemContext[len(enc):], pkRm)
Nsecret := s.group.internalKDF().OutputSize()
sharedSecret := s.extractAndExpand(dh, kemContext, Nsecret)
return sharedSecret, enc, nil
}
func (s dhkemScheme) Decap(enc []byte, skR KEMPrivateKey) ([]byte, error) {
pkE, err := s.group.Deserialize(enc)
if err != nil {
return nil, err
}
dh, err := s.group.DH(skR, pkE)
if err != nil {
return nil, err
}
pkRm := s.group.Serialize(skR.PublicKey())
kemContext := make([]byte, len(enc)+len(pkRm))
copy(kemContext, enc)
copy(kemContext[len(enc):], pkRm)
Nsecret := s.group.internalKDF().OutputSize()
sharedSecret := s.extractAndExpand(dh, kemContext, Nsecret)
return sharedSecret, nil
}
func (s dhkemScheme) AuthEncap(rand io.Reader, pkR KEMPublicKey, skS KEMPrivateKey) ([]byte, []byte, error) {
skE, pkE, err := s.getEphemeralKeyPair(rand)
if err != nil {
return nil, nil, err
}
dhER, err := s.group.DH(skE, pkR)
if err != nil {
return nil, nil, err
}
dhIR, err := s.group.DH(skS, pkR)
if err != nil {
return nil, nil, err
}
dh := append(dhER, dhIR...)
enc := s.group.Serialize(pkE)
pkRm := s.group.Serialize(pkR)
pkSm := s.group.Serialize(skS.PublicKey())
Nenc := len(enc)
Npk := len(pkRm)
Nsk := len(pkSm)
kemContext := make([]byte, Nenc+Npk+Nsk)
copy(kemContext[:Nenc], enc)
copy(kemContext[Nenc:Nenc+Npk], pkRm)
copy(kemContext[Nenc+Npk:], pkSm)
Nsecret := s.group.internalKDF().OutputSize()
sharedSecret := s.extractAndExpand(dh, kemContext, Nsecret)
return sharedSecret, enc, nil
}
func (s dhkemScheme) AuthDecap(enc []byte, skR KEMPrivateKey, pkS KEMPublicKey) ([]byte, error) {
pkE, err := s.group.Deserialize(enc)
if err != nil {
return nil, err
}
dhER, err := s.group.DH(skR, pkE)
if err != nil {
return nil, err
}
dhIR, err := s.group.DH(skR, pkS)
if err != nil {
return nil, err
}
dh := append(dhER, dhIR...)
pkRm := s.group.Serialize(skR.PublicKey())
pkSm := s.group.Serialize(pkS)
Nenc := len(enc)
Npk := len(pkRm)
Nsk := len(pkSm)
kemContext := make([]byte, Nenc+Npk+Nsk)
copy(kemContext[:Nenc], enc)
copy(kemContext[Nenc:Nenc+Npk], pkRm)
copy(kemContext[Nenc+Npk:], pkSm)
Nsecret := s.group.internalKDF().OutputSize()
sharedSecret := s.extractAndExpand(dh, kemContext, Nsecret)
return sharedSecret, nil
}
func (s dhkemScheme) PublicKeySize() int {
return s.group.PublicKeySize()
}
func (s dhkemScheme) PrivateKeySize() int {
return s.group.PrivateKeySize()
}
////////////////////////
// ECDH with NIST curves
type ecdhPrivateKey struct {
curve elliptic.Curve
d []byte
x, y *big.Int
}
func (priv ecdhPrivateKey) PublicKey() KEMPublicKey {
return &ecdhPublicKey{priv.curve, priv.x, priv.y}
}
type ecdhPublicKey struct {
curve elliptic.Curve
x, y *big.Int
}
type ecdhScheme struct {
curve elliptic.Curve
KDF KDFScheme
skE KEMPrivateKey
}
func (s ecdhScheme) internalKDF() KDFScheme {
return s.KDF
}
func (s ecdhScheme) ID() KEMID {
switch s.curve.Params().Name {
case "P-256":
return DHKEM_P256
case "P-521":
return DHKEM_P521
}
panic(fmt.Sprintf("Unsupported curve: %s", s.curve.Params().Name))
}
func (s ecdhScheme) privateKeyBitmask() uint8 {
switch s.curve.Params().Name {
case "P-256":
return 0xFF
case "P-521":
return 0x01
}
panic(fmt.Sprintf("Unsupported curve: %s", s.curve.Params().Name))
}
func (s ecdhScheme) DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error) {
suiteID := kemSuiteFromID(s.ID())
dkp_prk := s.KDF.LabeledExtract(nil, suiteID, "dkp_prk", ikm)
counter := 0
for {
if counter > 255 {
return nil, nil, fmt.Errorf("Error deriving key pair")
}
bytes := s.KDF.LabeledExpand(dkp_prk, suiteID, "candidate", []byte{uint8(counter)}, s.PrivateKeySize())
bytes[0] = bytes[0] & s.privateKeyBitmask()
sk, err := s.DeserializePrivate(bytes)
if err == nil {
return sk, sk.PublicKey(), nil
}
counter = counter + 1
}
return nil, nil, fmt.Errorf("Error deriving key pair")
}
func (s ecdhScheme) Serialize(pk KEMPublicKey) []byte {
if pk == nil {
return nil
}
raw := pk.(*ecdhPublicKey)
return elliptic.Marshal(raw.curve, raw.x, raw.y)
}
func (s ecdhScheme) SerializePrivate(sk KEMPrivateKey) []byte {
if sk == nil {
return nil
}
raw := sk.(*ecdhPrivateKey)
copied := make([]byte, len(raw.d))
copy(copied, raw.d)
return copied
}
func (s ecdhScheme) Deserialize(enc []byte) (KEMPublicKey, error) {
x, y := elliptic.Unmarshal(s.curve, enc)
if x == nil {
return nil, fmt.Errorf("Error deserializing public key")
}
return &ecdhPublicKey{s.curve, x, y}, nil
}
func (s ecdhScheme) DeserializePrivate(enc []byte) (KEMPrivateKey, error) {
if enc == nil {
return nil, fmt.Errorf("Invalid input")
}
x, y := s.curve.Params().ScalarBaseMult(enc)
return &ecdhPrivateKey{s.curve, enc, x, y}, nil
}
func (s ecdhScheme) DH(priv KEMPrivateKey, pub KEMPublicKey) ([]byte, error) {
ecdhPriv, ok := priv.(*ecdhPrivateKey)
if !ok {
return nil, fmt.Errorf("Private key not suitable for ECDH")
}
ecdhPub, ok := pub.(*ecdhPublicKey)
if !ok {
return nil, fmt.Errorf("Public key not suitable for ECDH")
}
x, _ := s.curve.Params().ScalarMult(ecdhPub.x, ecdhPub.y, ecdhPriv.d)
xx := x.Bytes()
size := (s.curve.Params().BitSize + 7) >> 3
pad := make([]byte, size-len(xx))
dh := append(pad, xx...)
return dh, nil
}
func (s ecdhScheme) PublicKeySize() int {
feSize := (s.curve.Params().BitSize + 7) >> 3
return 1 + 2*feSize
}
func (s ecdhScheme) PrivateKeySize() int {
return (s.curve.Params().BitSize + 7) >> 3
}
///////////////////
// ECDH with X25519
type x25519PrivateKey struct {
val [32]byte
}
func (priv x25519PrivateKey) PublicKey() KEMPublicKey {
pub := &x25519PublicKey{}
curve25519.ScalarBaseMult(&pub.val, &priv.val)
return pub
}
type x25519PublicKey struct {
val [32]byte
}
type x25519Scheme struct {
skE KEMPrivateKey
}
func (s x25519Scheme) internalKDF() KDFScheme {
return hkdfScheme{hash: crypto.SHA256}
}
func (s x25519Scheme) ID() KEMID {
return DHKEM_X25519
}
func (s x25519Scheme) DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error) {
suiteID := kemSuiteFromID(s.ID())
dkp_prk := s.internalKDF().LabeledExtract(nil, suiteID, "dkp_prk", ikm)
sk_bytes := s.internalKDF().LabeledExpand(dkp_prk, suiteID, "sk", nil, s.PrivateKeySize())
sk, err := s.DeserializePrivate(sk_bytes)
if err != nil {
return nil, nil, err
} else {
return sk, sk.PublicKey(), nil
}
}
func (s x25519Scheme) Serialize(pk KEMPublicKey) []byte {
if pk == nil {
return nil
}
raw := pk.(*x25519PublicKey)
return raw.val[:]
}
func (s x25519Scheme) SerializePrivate(sk KEMPrivateKey) []byte {
if sk == nil {
return nil
}
raw := sk.(*x25519PrivateKey)
return raw.val[:]
}
func (s x25519Scheme) Deserialize(enc []byte) (KEMPublicKey, error) {
if len(enc) != 32 {
return nil, fmt.Errorf("Error deserializing X25519 public key")
}
pub := &x25519PublicKey{}
copy(pub.val[:], enc)
return pub, nil
}
func (s x25519Scheme) DeserializePrivate(enc []byte) (KEMPrivateKey, error) {
if enc == nil {
return nil, fmt.Errorf("Invalid input")
}
if len(enc) != 32 {
return nil, fmt.Errorf("Error deserializing X25519 private key")
}
key := &x25519PrivateKey{}
copy(key.val[:], enc[0:32])
return key, nil
}
func (s x25519Scheme) DH(priv KEMPrivateKey, pub KEMPublicKey) ([]byte, error) {
xPriv, ok := priv.(*x25519PrivateKey)
if !ok {
return nil, fmt.Errorf("Private key not suitable for X25519: %+v", priv)
}
xPub, ok := pub.(*x25519PublicKey)
if !ok {
return nil, fmt.Errorf("Private key not suitable for X25519")
}
sharedSecret, err := curve25519.X25519(xPriv.val[:], xPub.val[:])
return sharedSecret, err
}
func (s x25519Scheme) PublicKeySize() int {
return 32
}
func (s x25519Scheme) PrivateKeySize() int {
return 32
}
///////////////////
// ECDH with X448
type x448PrivateKey struct {
val [56]byte
}
func (priv x448PrivateKey) PublicKey() KEMPublicKey {
pub := &x448PublicKey{}
x448.ScalarBaseMult(&pub.val, &priv.val)
return pub
}
type x448PublicKey struct {
val [56]byte
}
type x448Scheme struct {
skE KEMPrivateKey
}
func (s x448Scheme) internalKDF() KDFScheme {
return hkdfScheme{hash: crypto.SHA512}
}
func (s x448Scheme) ID() KEMID {
return DHKEM_X448
}
func (s x448Scheme) DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error) {
suiteID := kemSuiteFromID(s.ID())
dkp_prk := s.internalKDF().LabeledExtract(nil, suiteID, "dkp_prk", ikm)
sk_bytes := s.internalKDF().LabeledExpand(dkp_prk, suiteID, "sk", nil, s.PrivateKeySize())
sk, err := s.DeserializePrivate(sk_bytes)
if err != nil {
return nil, nil, err
} else {
return sk, sk.PublicKey(), nil
}
}
func (s x448Scheme) Serialize(pk KEMPublicKey) []byte {
if pk == nil {
return nil
}
raw := pk.(*x448PublicKey)
return raw.val[:]
}
func (s x448Scheme) SerializePrivate(sk KEMPrivateKey) []byte {
if sk == nil {
return nil
}
raw := sk.(*x448PrivateKey)
return raw.val[:]
}
func (s x448Scheme) Deserialize(enc []byte) (KEMPublicKey, error) {
if len(enc) != 56 {
return nil, fmt.Errorf("Error deserializing X448 public key")
}
pub := &x448PublicKey{}
copy(pub.val[:], enc)
return pub, nil
}
func (s x448Scheme) DeserializePrivate(enc []byte) (KEMPrivateKey, error) {
if enc == nil {
return nil, fmt.Errorf("Invalid input")
}
if len(enc) != 56 {
return nil, fmt.Errorf("Error deserializing X448 private key")
}
key := &x448PrivateKey{}
copy(key.val[:], enc[0:56])
return key, nil
}
func (s x448Scheme) DH(priv KEMPrivateKey, pub KEMPublicKey) ([]byte, error) {
xPriv, ok := priv.(*x448PrivateKey)
if !ok {
return nil, fmt.Errorf("Private key not suitable for X448: %+v", priv)
}
xPub, ok := pub.(*x448PublicKey)
if !ok {
return nil, fmt.Errorf("Public key not suitable for X448: %+v", pub)
}
var sharedSecret, zero [56]byte
x448.ScalarMult(&sharedSecret, &xPriv.val, &xPub.val)
if subtle.ConstantTimeCompare(sharedSecret[:], zero[:]) == 1 {
return nil, fmt.Errorf("bad input point: low order point")
}
return sharedSecret[:], nil
}
func (s x448Scheme) PublicKeySize() int {
return 56
}
func (s x448Scheme) PrivateKeySize() int {
return 56
}
///////
// SIKE
type sikePublicKey struct {
field uint8
pub *sidh.PublicKey
}
type sikePrivateKey struct {
field uint8
priv *sidh.PrivateKey
pub *sidh.PublicKey
}
func (priv sikePrivateKey) PublicKey() KEMPublicKey {
return &sikePublicKey{priv.field, priv.pub}
}
type sikeScheme struct {
field uint8
KDF KDFScheme
}
func (s sikeScheme) internalKDF() KDFScheme {
return s.KDF
}
func (s sikeScheme) ID() KEMID {
switch s.field {
case sidh.Fp503:
return KEM_SIKE503
case sidh.Fp751:
return KEM_SIKE751
}
panic(fmt.Sprintf("Unsupported field: %d", s.field))
}
func (s sikeScheme) generateKeyPair(rand io.Reader) (KEMPrivateKey, KEMPublicKey, error) {
rawPriv := sidh.NewPrivateKey(s.field, sidh.KeyVariantSike)
err := rawPriv.Generate(rand)
if err != nil {
return nil, nil, err
}
rawPub := sidh.NewPublicKey(s.field, sidh.KeyVariantSike)
rawPriv.GeneratePublicKey(rawPub)
priv := &sikePrivateKey{s.field, rawPriv, rawPub}
return priv, priv.PublicKey(), nil
}
func (s sikeScheme) DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error) {
// Note: DeriveKeyPair is not specified for SIKE, so we just use IKM to
// seed a DRBG, and then re-use the other APIs for generating key pairs
// from randomness.
var seed int64
ikmReader := bytes.NewReader(ikm)
if err := binary.Read(ikmReader, binary.BigEndian, &seed); err != nil {
return nil, nil, fmt.Errorf("Error deriving key pair")
}
source := mrand.NewSource(seed)
return s.generateKeyPair(mrand.New(source))
}
func (s sikeScheme) Serialize(pk KEMPublicKey) []byte {
if pk == nil {
return nil
}
raw := pk.(*sikePublicKey)
out := make([]byte, raw.pub.Size())
raw.pub.Export(out)
return out
}
func (s sikeScheme) SerializePrivate(sk KEMPrivateKey) []byte {
panic("Not implemented")
return nil
}
func (s sikeScheme) Deserialize(enc []byte) (KEMPublicKey, error) {
rawPub := sidh.NewPublicKey(s.field, sidh.KeyVariantSike)
if len(enc) != rawPub.Size() {
return nil, fmt.Errorf("Invalid public key size: got %d, expected %d", len(enc), rawPub.Size())
}
err := rawPub.Import(enc)
if err != nil {
return nil, err
}
return &sikePublicKey{s.field, rawPub}, nil
}
func (s sikeScheme) DeserializePrivate(enc []byte) (KEMPrivateKey, error) {
panic("Not implemented")
return nil, nil
}
func (s sikeScheme) newKEM(rand io.Reader) (*sidh.KEM, error) {
switch s.field {
case sidh.Fp503:
return sidh.NewSike503(rand), nil
case sidh.Fp751:
return sidh.NewSike751(rand), nil
}
return nil, fmt.Errorf("Invalid field")
}
func (s sikeScheme) Encap(rand io.Reader, pkR KEMPublicKey) ([]byte, []byte, error) {
raw := pkR.(*sikePublicKey)
kem, err := s.newKEM(rand)
if err != nil {
return nil, nil, err
}
enc := make([]byte, kem.CiphertextSize())
sharedSecret := make([]byte, s.KDF.OutputSize())
err = kem.Encapsulate(enc, sharedSecret, raw.pub)
if err != nil {
return nil, nil, err
}
return sharedSecret, enc, nil
}
type panicReader struct{}
func (p panicReader) Read(unused []byte) (int, error) {
panic("Should not read")
}
func (s sikeScheme) Decap(enc []byte, skR KEMPrivateKey) ([]byte, error) {
raw := skR.(*sikePrivateKey)
kem, err := s.newKEM(panicReader{})
if err != nil {
return nil, err
}
sharedSecret := make([]byte, s.KDF.OutputSize())
err = kem.Decapsulate(sharedSecret, raw.priv, raw.pub, enc)
if err != nil {
return nil, err
}
return sharedSecret, nil
}
func (s sikeScheme) PublicKeySize() int {
rawPub := sidh.NewPublicKey(s.field, sidh.KeyVariantSike)
return rawPub.Size()
}
func (s sikeScheme) PrivateKeySize() int {
rawPriv := sidh.NewPrivateKey(s.field, sidh.KeyVariantSike)
err := rawPriv.Generate(rand.Reader)
if err != nil {
panic("PrivateKeySize failed")
}
return rawPriv.Size()
}
func (s sikeScheme) setEphemeralKeyPair(skE KEMPrivateKey) {
panic("SIKE cannot use a pre-set ephemeral key pair")
}
//////////
// AES-GCM
type aesgcmScheme struct {
keySize int
}
func (s aesgcmScheme) ID() AEADID {
switch s.keySize {
case 16:
return AEAD_AESGCM128
case 32:
return AEAD_AESGCM256
}
panic(fmt.Sprintf("Unsupported key size: %d", s.keySize))
}
func (s aesgcmScheme) New(key []byte) (cipher.AEAD, error) {
if len(key) != s.keySize {
return nil, fmt.Errorf("Incorrect key size %d != %d", len(key), s.keySize)
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return cipher.NewGCM(block)
}
func (s aesgcmScheme) KeySize() int {
return s.keySize
}
func (s aesgcmScheme) NonceSize() int {
return 12
}
//////////
// ChaCha20-Poly1305
type chachaPolyScheme struct {
}
func (s chachaPolyScheme) ID() AEADID {
return AEAD_CHACHA20POLY1305
}
func (s chachaPolyScheme) New(key []byte) (cipher.AEAD, error) {
return chacha20poly1305.New(key)
}
func (s chachaPolyScheme) KeySize() int {
return chacha20poly1305.KeySize
}
func (s chachaPolyScheme) NonceSize() int {
return chacha20poly1305.NonceSize
}
///////
// HKDF
type hkdfScheme struct {
hash crypto.Hash
}
func (s hkdfScheme) ID() KDFID {
switch s.hash {
case crypto.SHA256:
return KDF_HKDF_SHA256
case crypto.SHA384:
return KDF_HKDF_SHA384
case crypto.SHA512:
return KDF_HKDF_SHA512
}
panic(fmt.Sprintf("Unsupported hash: %d", s.hash))
}
func (s hkdfScheme) Hash(message []byte) []byte {
h := s.hash.New()
h.Write(message)
return h.Sum(nil)
}
func (s hkdfScheme) Extract(salt, ikm []byte) []byte {
saltOrZero := salt
// if [salt is] not provided, it is set to a string of HashLen zeros
if salt == nil {
saltOrZero = make([]byte, s.hash.Size())
}
h := hmac.New(s.hash.New, saltOrZero)
h.Write(ikm)
return h.Sum(nil)
}
func (s hkdfScheme) Expand(prk, info []byte, outLen int) []byte {
out := []byte{}
T := []byte{}
i := byte(1)
for len(out) < outLen {
block := append(T, info...)
block = append(block, i)
h := hmac.New(s.hash.New, prk)
h.Write(block)
T = h.Sum(nil)
out = append(out, T...)
i++
}
return out[:outLen]
}
func (s hkdfScheme) LabeledExtract(salt []byte, suiteID []byte, label string, ikm []byte) []byte {
labeledIKM := append([]byte(rfcLabel), suiteID...)
labeledIKM = append(labeledIKM, []byte(label)...)
labeledIKM = append(labeledIKM, ikm...)
return s.Extract(salt, labeledIKM)
}
func (s hkdfScheme) LabeledExpand(prk []byte, suiteID []byte, label string, info []byte, L int) []byte {
if L > (1 << 16) {
panic("Expand length cannot be larger than 2^16")
}
lengthBuffer := make([]byte, 2)
binary.BigEndian.PutUint16(lengthBuffer, uint16(L))
labeledLength := append(lengthBuffer, []byte(rfcLabel)...)
labeledInfo := append(labeledLength, suiteID...)
labeledInfo = append(labeledInfo, []byte(label)...)
labeledInfo = append(labeledInfo, info...)
return s.Expand(prk, labeledInfo, L)
}
func (s hkdfScheme) OutputSize() int {
return s.hash.Size()
}
///////////////////////////
// Pre-defined KEM identifiers
type KEMID uint16
const (
DHKEM_P256 KEMID = 0x0010
DHKEM_P521 KEMID = 0x0012
DHKEM_X25519 KEMID = 0x0020
DHKEM_X448 KEMID = 0x0021
KEM_SIKE503 KEMID = 0xFFFE
KEM_SIKE751 KEMID = 0xFFFF
)
var kems = map[KEMID]KEMScheme{
DHKEM_X25519: &dhkemScheme{group: x25519Scheme{}},
DHKEM_X448: &dhkemScheme{group: x448Scheme{}},
DHKEM_P256: &dhkemScheme{group: ecdhScheme{curve: elliptic.P256(), KDF: hkdfScheme{hash: crypto.SHA256}}},
DHKEM_P521: &dhkemScheme{group: ecdhScheme{curve: elliptic.P521(), KDF: hkdfScheme{hash: crypto.SHA512}}},
KEM_SIKE503: &sikeScheme{field: sidh.Fp503, KDF: hkdfScheme{hash: crypto.SHA512}},
KEM_SIKE751: &sikeScheme{field: sidh.Fp751, KDF: hkdfScheme{hash: crypto.SHA512}},
}
func newKEMScheme(kemID KEMID) (KEMScheme, bool) {
switch kemID {
case DHKEM_X25519:
return &dhkemScheme{group: x25519Scheme{}}, true
case DHKEM_X448:
return &dhkemScheme{group: x448Scheme{}}, true
case DHKEM_P256:
return &dhkemScheme{group: ecdhScheme{curve: elliptic.P256(), KDF: hkdfScheme{hash: crypto.SHA256}}}, true
case DHKEM_P521:
return &dhkemScheme{group: ecdhScheme{curve: elliptic.P521(), KDF: hkdfScheme{hash: crypto.SHA512}}}, true
case KEM_SIKE503:
return &sikeScheme{field: sidh.Fp503, KDF: hkdfScheme{hash: crypto.SHA512}}, true
case KEM_SIKE751:
return &sikeScheme{field: sidh.Fp751, KDF: hkdfScheme{hash: crypto.SHA512}}, true
default:
return nil, false
}
}
///////////////////////////
// Pre-defined KDF identifiers
type KDFID uint16
const (
KDF_HKDF_SHA256 KDFID = 0x0001
KDF_HKDF_SHA384 KDFID = 0x0002
KDF_HKDF_SHA512 KDFID = 0x0003
)
var kdfs = map[KDFID]KDFScheme{
KDF_HKDF_SHA256: hkdfScheme{hash: crypto.SHA256},
KDF_HKDF_SHA384: hkdfScheme{hash: crypto.SHA384},
KDF_HKDF_SHA512: hkdfScheme{hash: crypto.SHA512},
}
///////////////////////////
// Pre-defined AEAD identifiers
type AEADID uint16
const (
AEAD_AESGCM128 AEADID = 0x0001
AEAD_AESGCM256 AEADID = 0x0002
AEAD_CHACHA20POLY1305 AEADID = 0x0003
)
var aeads = map[AEADID]AEADScheme{
AEAD_AESGCM128: aesgcmScheme{keySize: 16},
AEAD_AESGCM256: aesgcmScheme{keySize: 32},
AEAD_CHACHA20POLY1305: chachaPolyScheme{},
}
func AssembleCipherSuite(kemID KEMID, kdfID KDFID, aeadID AEADID) (CipherSuite, error) {
kem, ok := newKEMScheme(kemID)
if !ok {
return CipherSuite{}, fmt.Errorf("Unknown KEM id")
}
kdf, ok := kdfs[kdfID]
if !ok {
return CipherSuite{}, fmt.Errorf("Unknown KDF id")
}
aead, ok := aeads[aeadID]
if !ok {
return CipherSuite{}, fmt.Errorf("Unknown AEAD id")
}
return CipherSuite{
KEM: kem,
KDF: kdf,
AEAD: aead,
}, nil
}
//////////
// Helpers
func kemSuiteFromID(id KEMID) []byte {
idBuffer := make([]byte, 2)
binary.BigEndian.PutUint16(idBuffer, uint16(id))
return append([]byte("KEM"), idBuffer...)
}

133
vendor/github.com/cisco/go-hpke/format_vectors.py generated vendored Normal file
View File

@ -0,0 +1,133 @@
import sys
import json
import textwrap
ordered_keys = [
# Mode and ciphersuite parameters
"mode", "kem_id", "kdf_id", "aead_id", "info",
# Private key material
"ikmE", "pkEm", "skEm",
"ikmR", "pkRm", "skRm",
"ikmS", "pkSm", "skSm",
"psk", "psk_id",
# Derived context
"enc", "shared_secret", "key_schedule_context", "secret", "key", "base_nonce", "exporter_secret",
]
ordered_encryption_keys = [
"plaintext", "aad", "nonce", "ciphertext",
]
encryption_count_keys = [
0, 1, 2, 4, 10, 32, 255, 256, 257
]
def entry_kem(entry):
return kemMap[entry["kem_id"]]
def entry_kem_value(entry):
return entry["kem_id"]
def entry_kdf(entry):
return kdfMap[entry["kdf_id"]]
def entry_kdf_value(entry):
return entry["kdf_id"]
def entry_aead(entry):
return aeadMap[entry["aead_id"]]
def entry_aead_value(entry):
return entry["aead_id"]
def entry_mode(entry):
return modeMap[entry["mode"]]
def entry_mode_value(entry):
return entry["mode"]
modeBase = 0x00
modePSK = 0x01
modeAuth = 0x02
modeAuthPSK = 0x03
modeMap = {modeBase: "Base", modePSK: "PSK", modeAuth: "Auth", modeAuthPSK: "AuthPSK"}
kem_idP256 = 0x0010
kem_idP521 = 0x0012
kem_idX25519 = 0x0020
kemMap = {kem_idX25519: "DHKEM(X25519, HKDF-SHA256)", kem_idP256: "DHKEM(P-256, HKDF-SHA256)", kem_idP521: "DHKEM(P-521, HKDF-SHA512)"}
kdf_idSHA256 = 0x0001
kdf_idSHA512 = 0x0003
kdfMap = {kdf_idSHA256: "HKDF-SHA256", kdf_idSHA512: "HKDF-SHA512"}
aead_idAES128GCM = 0x0001
aead_idAES256GCM = 0x0002
aead_idChaCha20Poly1305 = 0x0003
aeadMap = {aead_idAES128GCM: "AES-128-GCM", aead_idAES256GCM: "AES-256-GCM", aead_idChaCha20Poly1305: "ChaCha20Poly1305"}
class CipherSuite(object):
def __init__(self, kem_id, kdf_id, aead_id):
self.kem_id = kem_id
self.kdf_id = kdf_id
self.aead_id = aead_id
def __str__(self):
return kemMap[self.kem_id] + ", " + kdfMap[self.kdf_id] + ", " + aeadMap[self.aead_id]
def __repr__(self):
return str(self)
def matches_vector(self, vector):
return self.kem_id == entry_kem_value(vector) and self.kdf_id == entry_kdf_value(vector) and self.aead_id == entry_aead_value(vector)
testSuites = [
CipherSuite(kem_idX25519, kdf_idSHA256, aead_idAES128GCM),
CipherSuite(kem_idX25519, kdf_idSHA256, aead_idChaCha20Poly1305),
CipherSuite(kem_idP256, kdf_idSHA256, aead_idAES128GCM),
CipherSuite(kem_idP256, kdf_idSHA512, aead_idAES128GCM),
CipherSuite(kem_idP256, kdf_idSHA256, aead_idChaCha20Poly1305),
CipherSuite(kem_idP521, kdf_idSHA512, aead_idAES256GCM),
]
def wrap_line(value):
return textwrap.fill(value, width=72)
def format_encryption(entry, count):
formatted = wrap_line("sequence number: %d" % count) + "\n"
for key in ordered_encryption_keys:
if key in entry:
formatted = formatted + wrap_line(key + ": " + str(entry[key])) + "\n"
return formatted
def format_encryptions(entry, mode):
formatted = "~~~\n"
for seq_number in encryption_count_keys:
for i, encryption in enumerate(entry["encryptions"]):
if i == seq_number:
formatted = formatted + format_encryption(encryption, i)
if i < len(entry["encryptions"]) - 1:
formatted = formatted + "\n"
return formatted + "~~~"
def format_vector(entry, mode):
formatted = "~~~\n"
for key in ordered_keys:
if key in entry:
formatted = formatted + wrap_line(key + ": " + str(entry[key])) + "\n"
return formatted + "~~~\n"
with open(sys.argv[1], "r") as fh:
data = json.load(fh)
for suite in testSuites:
print("## " + str(suite))
print("")
for mode in [modeBase, modePSK, modeAuth, modeAuthPSK]:
for vector in data:
if suite.matches_vector(vector):
if mode == entry_mode_value(vector):
print("### " + modeMap[mode] + " Setup Information")
print(format_vector(vector, mode))
print("#### Encryptions")
print(format_encryptions(vector, mode))
print("")

10
vendor/github.com/cisco/go-hpke/go.mod generated vendored Normal file
View File

@ -0,0 +1,10 @@
module github.com/cisco/go-hpke
go 1.14
require (
git.schwanenlied.me/yawning/x448.git v0.0.0-20170617130356-01b048fb03d6
github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b
github.com/cloudflare/circl v1.0.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
)

26
vendor/github.com/cisco/go-hpke/go.sum generated vendored Normal file
View File

@ -0,0 +1,26 @@
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/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/cloudflare/circl v1.0.0 h1:64b6pyfCFbYm623ncIkYGNZaOcmIbyd+CjyMi2L9vdI=
github.com/cloudflare/circl v1.0.0/go.mod h1:MhjB3NEEhJbTOdLLq964NIUisXDxaE1WkQPUxtgZXiY=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
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 h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed h1:uPxWBzB3+mlnjy9W58qY1j/cjyFjutgw/Vhan2zLy/A=
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

549
vendor/github.com/cisco/go-hpke/hpke.go generated vendored Normal file
View File

@ -0,0 +1,549 @@
package hpke
import (
"bytes"
"crypto/cipher"
"encoding/binary"
"fmt"
"io"
"log"
"github.com/cisco/go-tls-syntax"
)
const (
debug = true
rfcLabel = "HPKE-06"
)
type KEMPrivateKey interface {
PublicKey() KEMPublicKey
}
type KEMPublicKey interface{}
type KEMScheme interface {
ID() KEMID
DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error)
Serialize(pk KEMPublicKey) []byte
Deserialize(enc []byte) (KEMPublicKey, error)
Encap(rand io.Reader, pkR KEMPublicKey) ([]byte, []byte, error)
Decap(enc []byte, skR KEMPrivateKey) ([]byte, error)
PublicKeySize() int
PrivateKeySize() int
SerializePrivate(sk KEMPrivateKey) []byte
DeserializePrivate(enc []byte) (KEMPrivateKey, error)
setEphemeralKeyPair(sk KEMPrivateKey)
}
type AuthKEMScheme interface {
KEMScheme
AuthEncap(rand io.Reader, pkR KEMPublicKey, skS KEMPrivateKey) ([]byte, []byte, error)
AuthDecap(enc []byte, skR KEMPrivateKey, pkS KEMPublicKey) ([]byte, error)
}
type KDFScheme interface {
ID() KDFID
Hash(message []byte) []byte
Extract(salt, ikm []byte) []byte
Expand(prk, info []byte, L int) []byte
LabeledExtract(salt []byte, suiteID []byte, label string, ikm []byte) []byte
LabeledExpand(prk []byte, suiteID []byte, label string, info []byte, L int) []byte
OutputSize() int
}
type AEADScheme interface {
ID() AEADID
New(key []byte) (cipher.AEAD, error)
KeySize() int
NonceSize() int
}
type CipherSuite struct {
KEM KEMScheme
KDF KDFScheme
AEAD AEADScheme
}
func (suite CipherSuite) ID() []byte {
suiteID := make([]byte, 6)
binary.BigEndian.PutUint16(suiteID, uint16(suite.KEM.ID()))
binary.BigEndian.PutUint16(suiteID[2:], uint16(suite.KDF.ID()))
binary.BigEndian.PutUint16(suiteID[4:], uint16(suite.AEAD.ID()))
return append([]byte("HPKE"), suiteID...)
}
type Mode uint8
const (
modeBase Mode = 0x00
modePSK Mode = 0x01
modeAuth Mode = 0x02
modeAuthPSK Mode = 0x03
)
func logString(val string) {
if debug {
log.Printf("%s", val)
}
}
func logVal(name string, value []byte) {
if debug {
log.Printf(" %6s %x", name, value)
}
}
///////
// Core
func defaultPSK(suite CipherSuite) []byte {
return []byte{}
}
func defaultPSKID(suite CipherSuite) []byte {
return []byte{}
}
func verifyPSKInputs(suite CipherSuite, mode Mode, psk, pskID []byte) error {
defaultPSK := defaultPSK(suite)
defaultPSKID := defaultPSKID(suite)
pskMode := map[Mode]bool{modePSK: true, modeAuthPSK: true}
gotPSK := !bytes.Equal(psk, defaultPSK)
gotPSKID := !bytes.Equal(pskID, defaultPSKID)
switch {
case gotPSK != gotPSKID:
return fmt.Errorf("Inconsistent PSK inputs [%d] [%v] [%v]", mode, gotPSK, gotPSKID)
case gotPSK && !pskMode[mode]:
return fmt.Errorf("PSK input provided when not needed [%d]", mode)
case !gotPSK && pskMode[mode]:
return fmt.Errorf("Missing required PSK input [%d]", mode)
}
return nil
}
type hpkeContext struct {
mode Mode
pskIDHash []byte `tls:"head=none"`
infoHash []byte `tls:"head=none"`
}
type contextParameters struct {
suite CipherSuite
keyScheduleContext []byte
secret []byte
}
func (cp contextParameters) aeadKey() []byte {
return cp.suite.KDF.LabeledExpand(cp.secret, cp.suite.ID(), "key", cp.keyScheduleContext, cp.suite.AEAD.KeySize())
}
func (cp contextParameters) exporterSecret() []byte {
return cp.suite.KDF.LabeledExpand(cp.secret, cp.suite.ID(), "exp", cp.keyScheduleContext, cp.suite.KDF.OutputSize())
}
func (cp contextParameters) aeadBaseNonce() []byte {
return cp.suite.KDF.LabeledExpand(cp.secret, cp.suite.ID(), "base_nonce", cp.keyScheduleContext, cp.suite.AEAD.NonceSize())
}
type setupParameters struct {
sharedSecret []byte
enc []byte
}
func keySchedule(suite CipherSuite, mode Mode, sharedSecret, info, psk, pskID []byte) (contextParameters, error) {
err := verifyPSKInputs(suite, mode, psk, pskID)
if err != nil {
return contextParameters{}, err
}
suiteID := suite.ID()
pskIDHash := suite.KDF.LabeledExtract(nil, suiteID, "psk_id_hash", pskID)
infoHash := suite.KDF.LabeledExtract(nil, suiteID, "info_hash", info)
contextStruct := hpkeContext{mode, pskIDHash, infoHash}
keyScheduleContext, err := syntax.Marshal(contextStruct)
if err != nil {
return contextParameters{}, err
}
secret := suite.KDF.LabeledExtract(sharedSecret, suiteID, "secret", psk)
params := contextParameters{
suite: suite,
keyScheduleContext: keyScheduleContext,
secret: secret,
}
return params, nil
}
// contextRole specifies the role of a party in possession of a Context: if
// equal to `contextRoleSender`, then the party is the sender; if equal to
// `contextRoleReceiver`, then the party is the receiver.
type contextRole uint8
const (
contextRoleSender contextRole = 0x00
contextRoleReceiver contextRole = 0x01
)
// context represents an HPKE context encoded on the wire.
type context struct {
// Marshaled fields
Role contextRole
KEMID KEMID
KDFID KDFID
AEADID AEADID
ExporterSecret []byte `tls:"head=1"`
Key []byte `tls:"head=1"`
BaseNonce []byte `tls:"head=1"`
Seq uint64
// Operational structures
aead cipher.AEAD `tls:"omit"`
suite CipherSuite `tls:"omit"`
// Historical record
nonces [][]byte `tls:"omit"`
setupParams setupParameters `tls:"omit"`
contextParams contextParameters `tls:"omit"`
}
func newContext(role contextRole, suite CipherSuite, setupParams setupParameters, contextParams contextParameters) (context, error) {
key := contextParams.aeadKey()
baseNonce := contextParams.aeadBaseNonce()
exporterSecret := contextParams.exporterSecret()
aead, err := suite.AEAD.New(key)
if err != nil {
return context{}, err
}
ctx := context{
Role: role,
KEMID: suite.KEM.ID(),
KDFID: suite.KDF.ID(),
AEADID: suite.AEAD.ID(),
ExporterSecret: exporterSecret,
Key: key,
BaseNonce: baseNonce,
Seq: 0,
aead: aead,
suite: suite,
setupParams: setupParams,
contextParams: contextParams,
}
return ctx, nil
}
func unmarshalContext(role contextRole, opaque []byte) (context, error) {
var ctx context
var err error
if _, err = syntax.Unmarshal(opaque, &ctx); err != nil {
return context{}, err
}
if ctx.Role != role {
return context{}, fmt.Errorf("role mismatch")
}
ctx.suite, err = AssembleCipherSuite(ctx.KEMID, ctx.KDFID, ctx.AEADID)
if err != nil {
return context{}, err
}
// Construct AEAD and validate the key length.
ctx.aead, err = ctx.suite.AEAD.New(ctx.Key)
if err != nil {
return context{}, err
}
// Validate the nonce length.
if len(ctx.BaseNonce) != ctx.aead.NonceSize() {
return context{}, fmt.Errorf("base nonce length: got %d; want %d", len(ctx.BaseNonce), ctx.aead.NonceSize())
}
// Validate the exporter secret length.
if len(ctx.ExporterSecret) != ctx.suite.KDF.OutputSize() {
return context{}, fmt.Errorf("exporter secret length: got %d; want %d", len(ctx.ExporterSecret), ctx.suite.KDF.OutputSize())
}
return ctx, nil
}
func (ctx *context) computeNonce() []byte {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, ctx.Seq)
Nn := len(ctx.BaseNonce)
nonce := make([]byte, Nn)
copy(nonce, ctx.BaseNonce)
for i := range buf {
nonce[Nn-8+i] ^= buf[i]
}
ctx.nonces = append(ctx.nonces, nonce)
return nonce
}
func (ctx *context) incrementSeq() {
ctx.Seq += 1
if ctx.Seq == 0 {
panic("sequence number wrapped")
}
}
func (ctx *context) Export(context []byte, L int) []byte {
return ctx.suite.KDF.LabeledExpand(ctx.ExporterSecret, ctx.suite.ID(), "sec", context, L)
}
func (ctx *context) Marshal() ([]byte, error) {
return syntax.Marshal(ctx)
}
type EncryptContext struct {
context
}
func newEncryptContext(suite CipherSuite, setupParams setupParameters, contextParams contextParameters) (*EncryptContext, error) {
ctx, err := newContext(contextRoleSender, suite, setupParams, contextParams)
if err != nil {
return nil, err
}
return &EncryptContext{ctx}, nil
}
func (ctx *EncryptContext) Seal(aad, pt []byte) []byte {
ct := ctx.aead.Seal(nil, ctx.computeNonce(), pt, aad)
ctx.incrementSeq()
return ct
}
func UnmarshalEncryptContext(opaque []byte) (*EncryptContext, error) {
ctx, err := unmarshalContext(contextRoleSender, opaque)
if err != nil {
return nil, err
}
return &EncryptContext{ctx}, nil
}
type DecryptContext struct {
context
}
func newDecryptContext(suite CipherSuite, setupParams setupParameters, contextParams contextParameters) (*DecryptContext, error) {
ctx, err := newContext(contextRoleReceiver, suite, setupParams, contextParams)
if err != nil {
return nil, err
}
return &DecryptContext{ctx}, nil
}
func (ctx *DecryptContext) Open(aad, ct []byte) ([]byte, error) {
pt, err := ctx.aead.Open(nil, ctx.computeNonce(), ct, aad)
if err != nil {
return nil, err
}
ctx.incrementSeq()
return pt, nil
}
func UnmarshalDecryptContext(opaque []byte) (*DecryptContext, error) {
ctx, err := unmarshalContext(contextRoleReceiver, opaque)
if err != nil {
return nil, err
}
return &DecryptContext{ctx}, nil
}
///////
// Base
func SetupBaseS(suite CipherSuite, rand io.Reader, pkR KEMPublicKey, info []byte) ([]byte, *EncryptContext, error) {
// sharedSecret, enc = Encap(pkR)
sharedSecret, enc, err := suite.KEM.Encap(rand, pkR)
if err != nil {
return nil, nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modeBase, sharedSecret, info, defaultPSK(suite), defaultPSKID(suite))
if err != nil {
return nil, nil, err
}
ctx, err := newEncryptContext(suite, setupParams, params)
return enc, ctx, err
}
func SetupBaseR(suite CipherSuite, skR KEMPrivateKey, enc, info []byte) (*DecryptContext, error) {
// sharedSecret = Decap(enc, skR)
sharedSecret, err := suite.KEM.Decap(enc, skR)
if err != nil {
return nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modeBase, sharedSecret, info, defaultPSK(suite), defaultPSKID(suite))
if err != nil {
return nil, err
}
return newDecryptContext(suite, setupParams, params)
}
//////
// PSK
func SetupPSKS(suite CipherSuite, rand io.Reader, pkR KEMPublicKey, psk, pskID, info []byte) ([]byte, *EncryptContext, error) {
// sharedSecret, enc = Encap(pkR)
sharedSecret, enc, err := suite.KEM.Encap(rand, pkR)
if err != nil {
return nil, nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modePSK, sharedSecret, info, psk, pskID)
if err != nil {
return nil, nil, err
}
ctx, err := newEncryptContext(suite, setupParams, params)
return enc, ctx, err
}
func SetupPSKR(suite CipherSuite, skR KEMPrivateKey, enc, psk, pskID, info []byte) (*DecryptContext, error) {
// sharedSecret = Decap(enc, skR)
sharedSecret, err := suite.KEM.Decap(enc, skR)
if err != nil {
return nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modePSK, sharedSecret, info, psk, pskID)
if err != nil {
return nil, err
}
return newDecryptContext(suite, setupParams, params)
}
///////
// Auth
func SetupAuthS(suite CipherSuite, rand io.Reader, pkR KEMPublicKey, skS KEMPrivateKey, info []byte) ([]byte, *EncryptContext, error) {
// sharedSecret, enc = AuthEncap(pkR, skS)
auth := suite.KEM.(AuthKEMScheme)
sharedSecret, enc, err := auth.AuthEncap(rand, pkR, skS)
if err != nil {
return nil, nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modeAuth, sharedSecret, info, defaultPSK(suite), defaultPSKID(suite))
if err != nil {
return nil, nil, err
}
ctx, err := newEncryptContext(suite, setupParams, params)
return enc, ctx, err
}
func SetupAuthR(suite CipherSuite, skR KEMPrivateKey, pkS KEMPublicKey, enc, info []byte) (*DecryptContext, error) {
// sharedSecret = AuthDecap(enc, skR, pkS)
auth := suite.KEM.(AuthKEMScheme)
sharedSecret, err := auth.AuthDecap(enc, skR, pkS)
if err != nil {
return nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modeAuth, sharedSecret, info, defaultPSK(suite), defaultPSKID(suite))
if err != nil {
return nil, err
}
return newDecryptContext(suite, setupParams, params)
}
/////////////
// PSK + Auth
func SetupAuthPSKS(suite CipherSuite, rand io.Reader, pkR KEMPublicKey, skS KEMPrivateKey, psk, pskID, info []byte) ([]byte, *EncryptContext, error) {
// sharedSecret, enc = AuthEncap(pkR, skS)
auth := suite.KEM.(AuthKEMScheme)
sharedSecret, enc, err := auth.AuthEncap(rand, pkR, skS)
if err != nil {
return nil, nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modeAuthPSK, sharedSecret, info, psk, pskID)
if err != nil {
return nil, nil, err
}
ctx, err := newEncryptContext(suite, setupParams, params)
return enc, ctx, err
}
func SetupAuthPSKR(suite CipherSuite, skR KEMPrivateKey, pkS KEMPublicKey, enc, psk, pskID, info []byte) (*DecryptContext, error) {
// sharedSecret = AuthDecap(enc, skR, pkS)
auth := suite.KEM.(AuthKEMScheme)
sharedSecret, err := auth.AuthDecap(enc, skR, pkS)
if err != nil {
return nil, err
}
setupParams := setupParameters{
sharedSecret: sharedSecret,
enc: enc,
}
params, err := keySchedule(suite, modeAuthPSK, sharedSecret, info, psk, pskID)
if err != nil {
return nil, err
}
return newDecryptContext(suite, setupParams, params)
}

1
vendor/github.com/cisco/go-hpke/test-vectors.json generated vendored Normal file

File diff suppressed because one or more lines are too long

15
vendor/github.com/cisco/go-tls-syntax/.gitignore generated vendored Normal file
View File

@ -0,0 +1,15 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

25
vendor/github.com/cisco/go-tls-syntax/LICENSE generated vendored Normal file
View File

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

105
vendor/github.com/cisco/go-tls-syntax/README.md generated vendored Normal file
View File

@ -0,0 +1,105 @@
[![Coverage Status](https://coveralls.io/repos/github/cisco/go-tls-syntax/badge.svg)](https://coveralls.io/github/cisco/go-tls-syntax)
TLS Syntax
==========
TLS defines [its own syntax](https://tlswg.github.io/tls13-spec/#rfc.section.3)
for describing structures used in that protocol. To facilitate the reuse of
this serialization format in other context, this module maps that syntax to
the Go structure syntax, taking advantage of Go's type annotations to encode
non-type information carried in the TLS presentation format.
For example, in the TLS specification, a ClientHello message has the following
structure:
~~~~~
uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2];
enum { server_name(0), ... (65535)} ExtensionType;
struct {
ExtensionType extension_type;
opaque extension_data<0..2^16-1>;
} Extension;
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id<0..32>;
CipherSuite cipher_suites<2..2^16-2>;
opaque legacy_compression_methods<1..2^8-1>;
Extension extensions<0..2^16-1>;
} ClientHello;
~~~~~
This maps to the following Go type definitions:
~~~~~
type protocolVersion uint16
type random [32]byte
type cipherSuite uint16 // or [2]byte
type ExtensionType uint16
const (
ExtensionTypeServerName ExtensionType = 0
// ...
)
type Extension struct {
ExtensionType ExtensionType
ExtensionData []byte `tls:"head=2"`
}
type ClientHello struct {
LegacyVersion ProtocolVersion
Random Random
LegacySessionID []byte `tls:"head=1,max=32"`
CipherSuites []CipherSuite `tls:"head=2,min=2"`
LegacyCompressionMethods []byte `tls:"head=1,min=1"`
Extensions []Extension `tls:"head=2"`
}
~~~~~
Then you can just declare, marshal, and unmarshal structs just like you would
with, say JSON.
The available annotations are as follows (with supported types noted):
* `omit`: Do not encode/decode this field (for: any)
* `head=n`: Encode the length header as an `n`-byte integer (for: slice)
* `head=varint`: Encode the length header as a [QUIC-style
varint](https://tools.ietf.org/html/draft-ietf-quic-transport-27#section-16)
(for: slice)
* `head=none`: Omit the length header on encode; consume the remainder of the
buffer on decode (for: slice)
* `min`: The minimum length of the vector, in bytes (for: slice)
* `max`: The maximum length of the vector, in bytes (for: slice)
* `varint`: Encode the value as a QUIC-style varint (for:
uint8, uint16, uint32, uint64)
* `optional`: Encode a pointer value as an [MLS-style
optional](https://github.com/mlswg/mls-protocol/blob/master/draft-ietf-mls-protocol.md#tree-hashes)
(for: pointer)
The `Marshaler` and `Unmarshaler` interfaces play the same role as in
`encoding/json`, i.e., they let the type define its own encoding directly. The
`Validator` interface allows a type to define validation rules to be applied
when marshaling or unmarshaling. The latter is especially helpful for `enum`
values.
## Not supported
* The `select()` syntax for creating alternate version of the same struct (see,
e.g., the KeyShare extension)
* The backreference syntax for array lengths or select parameters, as in `opaque
fragment[TLSPlaintext.length]`. Note, however, that in cases where the length
immediately preceds the array, these can be reframed as vectors with
appropriate sizes.
## History
This code was originally part of the [mint](https://github.com/bifurcation/mint)
TLS 1.3 stack, and has been moved to this repository with the agreement of the
contributors. Please see that repo for history before the move.

456
vendor/github.com/cisco/go-tls-syntax/decode.go generated vendored Normal file
View File

@ -0,0 +1,456 @@
package syntax
import (
"bytes"
"fmt"
"reflect"
"runtime"
"sync"
)
func Unmarshal(data []byte, v interface{}) (int, error) {
// Check for well-formedness.
// Avoids filling out half a data structure
// before discovering a JSON syntax error.
d := decodeState{}
d.Write(data)
return d.unmarshal(v)
}
// Unmarshaler is the interface implemented by types that can
// unmarshal a TLS description of themselves. Note that unlike the
// JSON unmarshaler interface, it is not known a priori how much of
// the input data will be consumed. So the Unmarshaler must state
// how much of the input data it consumed.
type Unmarshaler interface {
UnmarshalTLS([]byte) (int, error)
}
type decodeState struct {
bytes.Buffer
}
func (d *decodeState) unmarshal(v interface{}) (read int, err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
if s, ok := r.(string); ok {
panic(s)
}
err = r.(error)
}
}()
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return 0, fmt.Errorf("Invalid unmarshal target (non-pointer or nil)")
}
read = d.value(rv)
return read, nil
}
func (e *decodeState) value(v reflect.Value) int {
return valueDecoder(v)(e, v, fieldOptions{})
}
type decoderFunc func(e *decodeState, v reflect.Value, opts fieldOptions) int
func valueDecoder(v reflect.Value) decoderFunc {
return typeDecoder(v.Type().Elem())
}
var decoderCache sync.Map // map[reflect.Type]decoderFunc
func typeDecoder(t reflect.Type) decoderFunc {
if fi, ok := decoderCache.Load(t); ok {
return fi.(decoderFunc)
}
// XXX(RLB): Wait group based support for recursive types omitted
// Compute the real decoder and replace the indirect func with it.
f := newTypeDecoder(t)
decoderCache.Store(t, f)
return f
}
var (
unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem()
uint8Type = reflect.TypeOf(uint8(0))
)
func newTypeDecoder(t reflect.Type) decoderFunc {
var dec decoderFunc
if t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(unmarshalerType) {
dec = unmarshalerDecoder
} else {
switch t.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
dec = uintDecoder
case reflect.Array:
dec = newArrayDecoder(t)
case reflect.Slice:
dec = newSliceDecoder(t)
case reflect.Map:
dec = newMapDecoder(t)
case reflect.Struct:
dec = newStructDecoder(t)
case reflect.Ptr:
dec = newPointerDecoder(t)
default:
panic(fmt.Errorf("Unsupported type (%s)", t))
}
}
if reflect.PtrTo(t).Implements(validatorType) {
dec = newValidatorDecoder(dec)
}
return dec
}
///// Specific decoders below
func omitDecoder(d *decodeState, v reflect.Value, opts fieldOptions) int {
return 0
}
//////////
func unmarshalerDecoder(d *decodeState, v reflect.Value, opts fieldOptions) int {
um, ok := v.Interface().(Unmarshaler)
if !ok {
panic(fmt.Errorf("Non-Unmarshaler passed to unmarshalerEncoder"))
}
read, err := um.UnmarshalTLS(d.Bytes())
if err != nil {
panic(err)
}
if read > d.Len() {
panic(fmt.Errorf("Invalid return value from UnmarshalTLS"))
}
d.Next(read)
return read
}
//////////
func newValidatorDecoder(raw decoderFunc) decoderFunc {
return func(d *decodeState, v reflect.Value, opts fieldOptions) int {
read := raw(d, v, opts)
val, ok := v.Interface().(Validator)
if !ok {
panic(fmt.Errorf("Non-Validator passed to validatorDecoder"))
}
if err := val.ValidForTLS(); err != nil {
panic(fmt.Errorf("Decoded invalid TLS value: %v", err))
}
return read
}
}
//////////
func uintDecoder(d *decodeState, v reflect.Value, opts fieldOptions) int {
if opts.varint {
return varintDecoder(d, v, opts)
}
uintLen := int(v.Elem().Type().Size())
buf := d.Next(uintLen)
if len(buf) != uintLen {
panic(fmt.Errorf("Insufficient data to read uint"))
}
return setUintFromBuffer(v, buf)
}
func varintDecoder(d *decodeState, v reflect.Value, opts fieldOptions) int {
l, val := readVarint(d)
uintLen := int(v.Elem().Type().Size())
if uintLen < l {
panic(fmt.Errorf("Uint too small to fit varint: %d < %d", uintLen, l))
}
v.Elem().SetUint(val)
return l
}
func readVarint(d *decodeState) (int, uint64) {
// Read the first octet and decide the size of the presented varint
first := d.Next(1)
if len(first) != 1 {
panic(fmt.Errorf("Insufficient data to read varint length"))
}
twoBits := uint(first[0] >> 6)
varintLen := 1 << twoBits
rest := d.Next(varintLen - 1)
if len(rest) != varintLen-1 {
panic(fmt.Errorf("Insufficient data to read varint"))
}
buf := append(first, rest...)
buf[0] &= 0x3f
return len(buf), decodeUintFromBuffer(buf)
}
func decodeUintFromBuffer(buf []byte) uint64 {
val := uint64(0)
for _, b := range buf {
val = (val << 8) + uint64(b)
}
return val
}
func setUintFromBuffer(v reflect.Value, buf []byte) int {
v.Elem().SetUint(decodeUintFromBuffer(buf))
return len(buf)
}
//////////
type arrayDecoder struct {
elemDec decoderFunc
}
func (ad *arrayDecoder) decode(d *decodeState, v reflect.Value, opts fieldOptions) int {
n := v.Elem().Type().Len()
read := 0
for i := 0; i < n; i += 1 {
read += ad.elemDec(d, v.Elem().Index(i).Addr(), opts)
}
return read
}
func newArrayDecoder(t reflect.Type) decoderFunc {
dec := &arrayDecoder{typeDecoder(t.Elem())}
return dec.decode
}
//////////
func decodeLength(d *decodeState, opts fieldOptions) (int, int) {
read := 0
length := 0
switch {
case opts.omitHeader:
read = 0
length = d.Len()
case opts.varintHeader:
var length64 uint64
read, length64 = readVarint(d)
length = int(length64)
case opts.headerSize > 0:
lengthBytes := d.Next(int(opts.headerSize))
if len(lengthBytes) != int(opts.headerSize) {
panic(fmt.Errorf("Not enough data to read header"))
}
read = len(lengthBytes)
length = int(decodeUintFromBuffer(lengthBytes))
default:
panic(fmt.Errorf("Cannot decode a slice without a header length"))
}
// Check that the length is OK
if opts.maxSize > 0 && length > opts.maxSize {
panic(fmt.Errorf("Length of vector exceeds declared max"))
}
if length < opts.minSize {
panic(fmt.Errorf("Length of vector below declared min"))
}
return read, length
}
//////////
type sliceDecoder struct {
elementType reflect.Type
elementDec decoderFunc
}
func (sd *sliceDecoder) decode(d *decodeState, v reflect.Value, opts fieldOptions) int {
// Determine the length of the vector
read, length := decodeLength(d, opts)
// Decode elements
elemData := d.Next(length)
if len(elemData) != length {
panic(fmt.Errorf("Not enough data to read elements"))
}
// For opaque values, we can return a reference instead of making a new slice
if v.Elem().Type().Elem() == uint8Type {
v.Elem().Set(reflect.ValueOf(elemData))
return read + length
}
// For other values, we need to decode the raw data
elemBuf := &decodeState{}
elemBuf.Write(elemData)
elems := []reflect.Value{}
for elemBuf.Len() > 0 {
elem := reflect.New(sd.elementType)
read += sd.elementDec(elemBuf, elem, opts)
elems = append(elems, elem)
}
v.Elem().Set(reflect.MakeSlice(v.Elem().Type(), len(elems), len(elems)))
for i := 0; i < len(elems); i += 1 {
v.Elem().Index(i).Set(elems[i].Elem())
}
return read
}
func newSliceDecoder(t reflect.Type) decoderFunc {
dec := &sliceDecoder{
elementType: t.Elem(),
elementDec: typeDecoder(t.Elem()),
}
return dec.decode
}
//////////
type mapDecoder struct {
keyType reflect.Type
valType reflect.Type
keyDec decoderFunc
valDec decoderFunc
}
func (md mapDecoder) decode(d *decodeState, v reflect.Value, opts fieldOptions) int {
// Determine the length of the data
read, length := decodeLength(d, opts)
// Decode key/value pairs
elemData := d.Next(length)
if len(elemData) != length {
panic(fmt.Errorf("Not enough data to read elements"))
}
mapType := reflect.MapOf(md.keyType, md.valType)
v.Elem().Set(reflect.MakeMap(mapType))
nullOpts := fieldOptions{}
elemBuf := &decodeState{}
elemBuf.Write(elemData)
for elemBuf.Len() > 0 {
key := reflect.New(md.keyType)
read += md.keyDec(elemBuf, key, nullOpts)
val := reflect.New(md.valType)
read += md.valDec(elemBuf, val, nullOpts)
v.Elem().SetMapIndex(key.Elem(), val.Elem())
}
return read
}
func newMapDecoder(t reflect.Type) decoderFunc {
md := mapDecoder{
keyType: t.Key(),
valType: t.Elem(),
keyDec: typeDecoder(t.Key()),
valDec: typeDecoder(t.Elem()),
}
return md.decode
}
//////////
type structDecoder struct {
fieldOpts []fieldOptions
fieldDecs []decoderFunc
}
func (sd *structDecoder) decode(d *decodeState, v reflect.Value, opts fieldOptions) int {
read := 0
for i := range sd.fieldDecs {
read += sd.fieldDecs[i](d, v.Elem().Field(i).Addr(), sd.fieldOpts[i])
}
return read
}
func newStructDecoder(t reflect.Type) decoderFunc {
n := t.NumField()
sd := structDecoder{
fieldOpts: make([]fieldOptions, n),
fieldDecs: make([]decoderFunc, n),
}
for i := 0; i < n; i += 1 {
f := t.Field(i)
tag := f.Tag.Get("tls")
opts := parseTag(tag)
if !opts.ValidForType(f.Type) {
panic(fmt.Errorf("Tags invalid for field type"))
}
sd.fieldOpts[i] = opts
if sd.fieldOpts[i].omit {
sd.fieldDecs[i] = omitDecoder
} else {
sd.fieldDecs[i] = typeDecoder(f.Type)
}
}
return sd.decode
}
//////////
type pointerDecoder struct {
base decoderFunc
}
func (pd *pointerDecoder) decode(d *decodeState, v reflect.Value, opts fieldOptions) int {
readBase := 0
if opts.optional {
readBase = 1
flag := d.Next(1)
switch flag[0] {
case optionalFlagAbsent:
indir := v.Elem()
indir.Set(reflect.Zero(indir.Type()))
return 1
case optionalFlagPresent:
// No action; continue as normal
default:
panic(fmt.Errorf("Invalid flag byte for optional: [%x]", flag))
}
}
v.Elem().Set(reflect.New(v.Elem().Type().Elem()))
return readBase + pd.base(d, v.Elem(), opts)
}
func newPointerDecoder(t reflect.Type) decoderFunc {
baseDecoder := typeDecoder(t.Elem())
pd := pointerDecoder{base: baseDecoder}
return pd.decode
}

411
vendor/github.com/cisco/go-tls-syntax/encode.go generated vendored Normal file
View File

@ -0,0 +1,411 @@
package syntax
import (
"bytes"
"fmt"
"reflect"
"runtime"
"sort"
"sync"
)
func Marshal(v interface{}) ([]byte, error) {
e := &encodeState{}
err := e.marshal(v, fieldOptions{})
if err != nil {
return nil, err
}
return e.Bytes(), nil
}
// Marshaler is the interface implemented by types that
// have a defined TLS encoding.
type Marshaler interface {
MarshalTLS() ([]byte, error)
}
type encodeState struct {
bytes.Buffer
}
func (e *encodeState) marshal(v interface{}, opts fieldOptions) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
if s, ok := r.(string); ok {
panic(s)
}
err = r.(error)
}
}()
e.reflectValue(reflect.ValueOf(v), opts)
return nil
}
func (e *encodeState) reflectValue(v reflect.Value, opts fieldOptions) {
valueEncoder(v)(e, v, opts)
}
type encoderFunc func(e *encodeState, v reflect.Value, opts fieldOptions)
func valueEncoder(v reflect.Value) encoderFunc {
if !v.IsValid() {
panic(fmt.Errorf("Cannot encode an invalid value"))
}
return typeEncoder(v.Type())
}
var encoderCache sync.Map // map[reflect.Type]encoderFunc
func typeEncoder(t reflect.Type) encoderFunc {
if fi, ok := encoderCache.Load(t); ok {
return fi.(encoderFunc)
}
// XXX(RLB): Wait group based support for recursive types omitted
// Compute the real encoder and replace the indirect func with it.
f := newTypeEncoder(t)
encoderCache.Store(t, f)
return f
}
var (
marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
)
func newTypeEncoder(t reflect.Type) encoderFunc {
var enc encoderFunc
if t.Implements(marshalerType) {
enc = marshalerEncoder
} else {
switch t.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
enc = uintEncoder
case reflect.Array:
enc = newArrayEncoder(t)
case reflect.Slice:
enc = newSliceEncoder(t)
case reflect.Struct:
enc = newStructEncoder(t)
case reflect.Map:
enc = newMapEncoder(t)
case reflect.Ptr:
enc = newPointerEncoder(t)
default:
panic(fmt.Errorf("Unsupported type (%s)", t))
}
}
if t.Implements(validatorType) {
enc = newValidatorEncoder(enc)
}
return enc
}
///// Specific encoders below
func omitEncoder(e *encodeState, v reflect.Value, opts fieldOptions) {
// This space intentionally left blank
}
//////////
func marshalerEncoder(e *encodeState, v reflect.Value, opts fieldOptions) {
if v.Kind() == reflect.Ptr && v.IsNil() && !opts.optional {
panic(fmt.Errorf("Cannot encode nil pointer"))
}
if v.Kind() == reflect.Ptr && opts.optional {
if v.IsNil() {
writeUint(e, uint64(optionalFlagAbsent), 1)
return
}
writeUint(e, uint64(optionalFlagPresent), 1)
}
m, ok := v.Interface().(Marshaler)
if !ok {
panic(fmt.Errorf("Non-Marshaler passed to marshalerEncoder"))
}
b, err := m.MarshalTLS()
if err == nil {
_, err = e.Write(b)
}
if err != nil {
panic(err)
}
}
//////////
func newValidatorEncoder(raw encoderFunc) encoderFunc {
return func(e *encodeState, v reflect.Value, opts fieldOptions) {
if v.Kind() == reflect.Ptr && v.IsNil() {
// Cannot validate nil values; just pass through to encoder
raw(e, v, opts)
return
}
val, ok := v.Interface().(Validator)
if !ok {
panic(fmt.Errorf("Non-Validator passed to validatorEncoder"))
}
if err := val.ValidForTLS(); err != nil {
panic(fmt.Errorf("Invalid TLS value: %v", err))
}
raw(e, v, opts)
}
}
//////////
func uintEncoder(e *encodeState, v reflect.Value, opts fieldOptions) {
if opts.varint {
varintEncoder(e, v, opts)
return
}
writeUint(e, v.Uint(), int(v.Type().Size()))
}
func varintEncoder(e *encodeState, v reflect.Value, opts fieldOptions) {
writeVarint(e, v.Uint())
}
func writeVarint(e *encodeState, u uint64) {
if (u >> 62) > 0 {
panic(fmt.Errorf("uint value is too big for varint"))
}
var varintLen int
for _, len := range []uint{1, 2, 4, 8} {
if u < (uint64(1) << (8*len - 2)) {
varintLen = int(len)
break
}
}
twoBits := map[int]uint64{1: 0x00, 2: 0x01, 4: 0x02, 8: 0x03}[varintLen]
shift := uint(8*varintLen - 2)
writeUint(e, u|(twoBits<<shift), varintLen)
}
func writeUint(e *encodeState, u uint64, len int) {
for i := 0; i < len; i += 1 {
e.WriteByte(byte(u >> uint(8*(len-i-1))))
}
}
//////////
type arrayEncoder struct {
elemEnc encoderFunc
}
func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, opts fieldOptions) {
n := v.Len()
for i := 0; i < n; i += 1 {
ae.elemEnc(e, v.Index(i), opts)
}
}
func newArrayEncoder(t reflect.Type) encoderFunc {
enc := &arrayEncoder{typeEncoder(t.Elem())}
return enc.encode
}
//////////
func encodeLength(e *encodeState, n int, opts fieldOptions) {
if opts.maxSize > 0 && n > opts.maxSize {
panic(fmt.Errorf("Encoded length more than max [%d > %d]", n, opts.maxSize))
}
if n < opts.minSize {
panic(fmt.Errorf("Encoded length less than min [%d < %d]", n, opts.minSize))
}
switch {
case opts.omitHeader:
// None.
case opts.varintHeader:
writeVarint(e, uint64(n))
case opts.headerSize > 0:
if n>>uint(8*opts.headerSize) > 0 {
panic(fmt.Errorf("Encoded length too long for header length [%d, %d]", n, opts.headerSize))
}
writeUint(e, uint64(n), int(opts.headerSize))
default:
panic(fmt.Errorf("Cannot encode a slice without a header length"))
}
}
//////////
type sliceEncoder struct {
ae *arrayEncoder
}
func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, opts fieldOptions) {
arrayState := &encodeState{}
se.ae.encode(arrayState, v, opts)
encodeLength(e, arrayState.Len(), opts)
e.Write(arrayState.Bytes())
}
func newSliceEncoder(t reflect.Type) encoderFunc {
enc := &sliceEncoder{&arrayEncoder{typeEncoder(t.Elem())}}
return enc.encode
}
//////////
type structEncoder struct {
fieldOpts []fieldOptions
fieldEncs []encoderFunc
}
func (se *structEncoder) encode(e *encodeState, v reflect.Value, opts fieldOptions) {
for i := range se.fieldEncs {
se.fieldEncs[i](e, v.Field(i), se.fieldOpts[i])
}
}
func newStructEncoder(t reflect.Type) encoderFunc {
n := t.NumField()
se := structEncoder{
fieldOpts: make([]fieldOptions, n),
fieldEncs: make([]encoderFunc, n),
}
for i := 0; i < n; i += 1 {
f := t.Field(i)
tag := f.Tag.Get("tls")
opts := parseTag(tag)
if !opts.ValidForType(f.Type) {
panic(fmt.Errorf("Tags invalid for field type"))
}
se.fieldOpts[i] = opts
if opts.omit {
se.fieldEncs[i] = omitEncoder
} else {
se.fieldEncs[i] = typeEncoder(f.Type)
}
}
return se.encode
}
//////////
type mapEncoder struct {
keyEnc encoderFunc
valEnc encoderFunc
}
type encMap struct {
keyEncs [][]byte
valEncs [][]byte
}
func (em encMap) Len() int { return len(em.keyEncs) }
func (em *encMap) Swap(i, j int) {
em.keyEncs[i], em.keyEncs[j] = em.keyEncs[j], em.keyEncs[i]
em.valEncs[i], em.valEncs[j] = em.valEncs[j], em.valEncs[i]
}
func (em encMap) Less(i, j int) bool {
return bytes.Compare(em.keyEncs[i], em.keyEncs[j]) < 0
}
func (em encMap) Size() int {
size := 0
for i := range em.keyEncs {
size += len(em.keyEncs[i]) + len(em.valEncs[i])
}
return size
}
func (em encMap) Encode(e *encodeState) {
for i := range em.keyEncs {
e.Write(em.keyEncs[i])
e.Write(em.valEncs[i])
}
}
func (me *mapEncoder) encode(e *encodeState, v reflect.Value, opts fieldOptions) {
enc := &encMap{
keyEncs: make([][]byte, v.Len()),
valEncs: make([][]byte, v.Len()),
}
nullOpts := fieldOptions{}
it := v.MapRange()
for i := 0; i < enc.Len() && it.Next(); i++ {
keyState := &encodeState{}
me.keyEnc(keyState, it.Key(), nullOpts)
enc.keyEncs[i] = keyState.Bytes()
valState := &encodeState{}
me.valEnc(valState, it.Value(), nullOpts)
enc.valEncs[i] = valState.Bytes()
}
sort.Sort(enc)
encodeLength(e, enc.Size(), opts)
enc.Encode(e)
}
func newMapEncoder(t reflect.Type) encoderFunc {
me := mapEncoder{
keyEnc: typeEncoder(t.Key()),
valEnc: typeEncoder(t.Elem()),
}
return me.encode
}
//////////
type pointerEncoder struct {
base encoderFunc
}
func (pe pointerEncoder) encode(e *encodeState, v reflect.Value, opts fieldOptions) {
if v.IsNil() && !opts.optional {
panic(fmt.Errorf("Cannot encode nil pointer"))
}
if opts.optional {
if v.IsNil() {
writeUint(e, uint64(optionalFlagAbsent), 1)
return
}
writeUint(e, uint64(optionalFlagPresent), 1)
}
pe.base(e, v.Elem(), opts)
}
func newPointerEncoder(t reflect.Type) encoderFunc {
baseEncoder := typeEncoder(t.Elem())
pe := pointerEncoder{base: baseEncoder}
return pe.encode
}

5
vendor/github.com/cisco/go-tls-syntax/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/cisco/go-tls-syntax
go 1.14
require github.com/stretchr/testify v1.6.1

10
vendor/github.com/cisco/go-tls-syntax/go.sum generated vendored Normal file
View File

@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

37
vendor/github.com/cisco/go-tls-syntax/go.yml generated vendored Normal file
View File

@ -0,0 +1,37 @@
name: Go
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.13
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Get dependencies
run: |
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Build
run: go build -v .
- name: Test
run: go test -v .

76
vendor/github.com/cisco/go-tls-syntax/stream.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
package syntax
///
/// Write Stream
///
type WriteStream struct {
buffer []byte
}
func NewWriteStream() *WriteStream {
return &WriteStream{}
}
func (s *WriteStream) Data() []byte {
return s.buffer
}
func (s *WriteStream) Write(val interface{}) error {
enc, err := Marshal(val)
if err != nil {
return err
}
s.buffer = append(s.buffer, enc...)
return nil
}
func (s *WriteStream) WriteAll(vals ...interface{}) error {
for _, val := range vals {
err := s.Write(val)
if err != nil {
return err
}
}
return nil
}
///
/// ReadStream
///
type ReadStream struct {
buffer []byte
cursor int
}
func NewReadStream(data []byte) *ReadStream {
return &ReadStream{data, 0}
}
func (s *ReadStream) Read(val interface{}) (int, error) {
read, err := Unmarshal(s.buffer[s.cursor:], val)
if err != nil {
return 0, err
}
s.cursor += read
return read, nil
}
func (s *ReadStream) ReadAll(vals ...interface{}) (int, error) {
read := 0
for _, val := range vals {
readHere, err := s.Read(val)
if err != nil {
return 0, err
}
read += readHere
}
return read, nil
}
func (s *ReadStream) Position() int {
return s.cursor
}

173
vendor/github.com/cisco/go-tls-syntax/tags.go generated vendored Normal file
View File

@ -0,0 +1,173 @@
package syntax
import (
"fmt"
"reflect"
"strconv"
"strings"
)
// Allow types to mark themselves as valid for TLS to marshal/unmarshal
type Validator interface {
ValidForTLS() error
}
var (
validatorType = reflect.TypeOf(new(Validator)).Elem()
)
// `tls:"head=2,min=2,max=255,varint"`
type fieldOptions struct {
omitHeader bool // whether to omit the slice header
varintHeader bool // whether to encode the header length as a varint
headerSize int // length of length in bytes
minSize int // minimum vector size in bytes
maxSize int // maximum vector size in bytes
varint bool // whether to encode as a varint
optional bool // whether to encode pointer as optional
omit bool // whether to skip a field
}
func mutuallyExclusive(vals []bool) bool {
set := 0
for _, val := range vals {
if val {
set += 1
}
}
return set <= 1
}
func (opts fieldOptions) Consistent() bool {
// No more than one of the header options must be set
headerPaths := []bool{opts.omitHeader, opts.varintHeader, opts.headerSize > 1}
if !mutuallyExclusive(headerPaths) {
return false
}
// Max must be greater than min
if opts.maxSize > 0 && opts.minSize > opts.maxSize {
return false
}
// varint and optional are mutually exclusive with each other, and with the slice options
headerOpts := (opts.omitHeader || opts.varintHeader || opts.headerSize > 1 || opts.maxSize > 0 || opts.minSize > 0)
encodePaths := []bool{headerOpts, opts.varint, opts.optional}
if !mutuallyExclusive(encodePaths) {
return false
}
// Omit is mutually exclusive with everything else
otherThanOmit := (headerOpts || opts.varint || opts.optional)
if !mutuallyExclusive([]bool{opts.omit, otherThanOmit}) {
return false
}
return true
}
func (opts fieldOptions) ValidForType(t reflect.Type) bool {
headerType := t.Kind() == reflect.Slice || t.Kind() == reflect.Map
headerTags := opts.omitHeader || opts.varintHeader || (opts.headerSize != 0) ||
(opts.minSize != 0) || (opts.maxSize != 0)
if headerTags && !headerType {
return false
}
uintRequired := opts.varint
if uintRequired {
switch t.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
default:
return false
}
}
ptrRequired := opts.optional
if ptrRequired && t.Kind() != reflect.Ptr {
return false
}
return true
}
var (
varintOption = "varint"
optionalOption = "optional"
omitOption = "omit"
headOptionNone = "none"
headOptionVarint = "varint"
headValueNoHead = uint(255)
headValueVarint = uint(254)
optionalFlagAbsent uint8 = 0
optionalFlagPresent uint8 = 1
)
func atoi(a string) int {
i, err := strconv.Atoi(a)
if err != nil {
panic(fmt.Errorf("Invalid header size: %v", err))
}
return i
}
// parseTag parses a struct field's "tls" tag as a comma-separated list of
// name=value pairs, where the values MUST be unsigned integers, or in
// the special case of head, "none" or "varint"
func parseTag(tag string) fieldOptions {
opts := fieldOptions{}
for _, token := range strings.Split(tag, ",") {
parts := strings.Split(token, "=")
// Handle name-only entries
if len(parts) == 1 {
switch parts[0] {
case varintOption:
opts.varint = true
case optionalOption:
opts.optional = true
case omitOption:
opts.omit = true
default:
// XXX(rlb): Ignoring unknown fields
}
continue
}
if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
panic(fmt.Errorf("Malformed tag"))
}
// Handle name=value entries
switch parts[0] {
case "head":
switch {
case parts[1] == headOptionNone:
opts.omitHeader = true
case parts[1] == headOptionVarint:
opts.varintHeader = true
default:
opts.headerSize = atoi(parts[1])
}
case "min":
opts.minSize = atoi(parts[1])
case "max":
opts.maxSize = atoi(parts[1])
default:
// XXX(rlb): Ignoring unknown fields
}
}
if !opts.Consistent() {
panic(fmt.Errorf("Inconsistent options"))
}
return opts
}

57
vendor/github.com/cloudflare/circl/LICENSE generated vendored Normal file
View File

@ -0,0 +1,57 @@
Copyright (c) 2019 Cloudflare. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Cloudflare nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
========================================================================
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

30
vendor/github.com/cloudflare/circl/dh/sidh/doc.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Package sidh provides implementation of experimental post-quantum
// Supersingular Isogeny Diffie-Hellman (SIDH) as well as Supersingular
// Isogeny Key Encapsulation (SIKE).
//
// It comes with implementations of 2 different field arithmetic
// implementations sidh.Fp503 and sidh.Fp751.
//
// | Algoirthm | Public Key Size | Shared Secret Size | Ciphertext Size |
// |-----------|-----------------|--------------------|-----------------|
// | SIDH/p503 | 376 | 126 | N/A |
// | SIDH/p751 | 564 | 188 | N/A |
// | SIKE/p503 | 376 | 16 | 402 |
// | SIKE/p751 | 564 | 24 | 596 |
//
// In order to instantiate SIKE/p751 KEM one needs to create a KEM object
// and allocate internal structures. This can be done with NewSike751 helper.
// After that kem can be used multiple times.
//
// var kem = sike.NewSike751(rand.Reader)
// kem.Encapsulate(ciphertext, sharedSecret, publicBob)
// kem.Decapsulate(sharedSecret, privateBob, PublicBob, ciphertext)
//
// Code is optimized for AMD64 and aarch64. Generic implementation
// is provided for other architectures.
//
// References:
// - [SIDH] https://eprint.iacr.org/2011/506
// - [SIKE] http://www.sike.org/files/SIDH-spec.pdf
//
package sidh

View File

@ -0,0 +1,2 @@
// Package common provides types, variables, constants and functions commonly used in SIDH or SIKE.
package common

View File

@ -0,0 +1,24 @@
package common
import "fmt"
// Keeps mapping: SIDH prime field ID to domain parameters
var sidhParams = make(map[uint8]SidhParams)
// Params returns domain parameters corresponding to finite field and identified by
// `id` provieded by the caller. Function panics in case `id` wasn't registered earlier.
func Params(id uint8) *SidhParams {
if val, ok := sidhParams[id]; ok {
return &val
}
panic("sidh: SIDH Params ID unregistered")
}
// Registers SIDH parameters for particular field.
func Register(id uint8, p *SidhParams) {
if _, ok := sidhParams[id]; ok {
msg := fmt.Sprintf("sidh: Field with id %d already registered", id)
panic(msg)
}
sidhParams[id] = *p
}

View File

@ -0,0 +1,103 @@
package common
const (
// corresponds to words in P751
FpMaxWords = 12
// corresponds to byte size of P751 SIDH private key for B
MaxSidhPrivateKeyBsz = 48
// corresponds to byte size of P751 SIKE private key for B
MaxSikePrivateKeyBsz = MaxSidhPrivateKeyBsz + MaxMsgBsz
// corresponds to SIKE max length of 'n' (see 1.4 of SIKE spec in NIST PQC round 1)
MaxMsgBsz = 40
// corresponds to byte size of shared secret generated by SIKEp751
MaxSharedSecretBsz = 188
// correponds to by size of the P751 public key
MaxPublicKeySz = 3 * FpMaxWords * 64
// correponds to by size of the ciphertext produced by SIKE/P751
MaxCiphertextBsz = MaxMsgBsz + MaxPublicKeySz
)
// Id's correspond to bitlength of the prime field characteristic
// Currently Fp751 is the only one supported by this implementation
const (
Fp503 uint8 = iota
Fp751
)
// Representation of an element of the base field F_p.
//
// No particular meaning is assigned to the representation -- it could represent
// an element in Montgomery form, or not. Tracking the meaning of the field
// element is left to higher types.
type Fp [FpMaxWords]uint64
// Represents an intermediate product of two elements of the base field F_p.
type FpX2 [2 * FpMaxWords]uint64
// Represents an element of the extended field Fp^2 = Fp(x+i)
type Fp2 struct {
A Fp
B Fp
}
type DomainParams struct {
// P, Q and R=P-Q base points
AffineP, AffineQ, AffineR Fp2
// Size of a compuatation strategy for x-torsion group
IsogenyStrategy []uint32
// Max size of secret key for x-torsion group
SecretBitLen uint
// Max size of secret key for x-torsion group
SecretByteLen uint
}
type SidhParams struct {
ID uint8
// Bytelen of P
Bytelen int
// The public key size, in bytes.
PublicKeySize int
// The shared secret size, in bytes.
SharedSecretSize int
// 2- and 3-torsion group parameter definitions
A, B DomainParams
// Precomputed identity element in the Fp2 in Montgomery domain
OneFp2 Fp2
// Precomputed 1/2 in the Fp2 in Montgomery domain
HalfFp2 Fp2
// Length of SIKE secret message. Must be one of {24,32,40},
// depending on size of prime field used (see [SIKE], 1.4 and 5.1)
MsgLen int
// Length of SIKE ephemeral KEM key (see [SIKE], 1.4 and 5.1)
KemSize int
// Byte size of ciphertext that KEM produces
CiphertextSize int
}
// Stores curve projective parameters equivalent to A/C. Meaning of the
// values depends on the context. When working with isogenies over
// subgroup that are powers of:
// * three then (A:C) ~ (A+2C:A-2C)
// * four then (A:C) ~ (A+2C: 4C)
// See Appendix A of SIKE for more details
type CurveCoefficientsEquiv struct {
A Fp2
C Fp2
}
// A point on the projective line P^1(F_{p^2}).
//
// This represents a point on the Kummer line of a Montgomery curve. The
// curve is specified by a ProjectiveCurveParameters struct.
type ProjectivePoint struct {
X Fp2
Z Fp2
}
// A point on the projective line P^1(F_{p^2}).
//
// This is used to work projectively with the curve coefficients.
type ProjectiveCurveParameters struct {
A Fp2
C Fp2
}

View File

@ -0,0 +1,46 @@
package common
// Constant time select.
// if pick == 1 (out = in1)
// if pick == 0 (out = in2)
// else out is undefined
func Cpick(pick int, out, in1, in2 []byte) {
var which = byte((int8(pick << 7)) >> 7)
for i := range out {
out[i] = (in1[i] & which) | (in2[i] & ^which)
}
}
// Read 2*bytelen(p) bytes into the given ExtensionFieldElement.
//
// It is an error to call this function if the input byte slice is less than 2*bytelen(p) bytes long.
func BytesToFp2(fp2 *Fp2, input []byte, bytelen int) {
if len(input) < 2*bytelen {
panic("input byte slice too short")
}
for i := 0; i < bytelen; i++ {
j := i / 8
k := uint64(i % 8)
fp2.A[j] |= uint64(input[i]) << (8 * k)
fp2.B[j] |= uint64(input[i+bytelen]) << (8 * k)
}
}
// Convert the input to wire format.
//
// The output byte slice must be at least 2*bytelen(p) bytes long.
func Fp2ToBytes(output []byte, fp2 *Fp2, bytelen int) {
if len(output) < 2*bytelen {
panic("output byte slice too short")
}
// convert to bytes in little endian form
for i := 0; i < bytelen; i++ {
// set i = j*8 + k
tmp := i / 8
k := uint64(i % 8)
output[i] = byte(fp2.A[tmp] >> (8 * k))
output[i+bytelen] = byte(fp2.B[tmp] >> (8 * k))
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,769 @@
// +build arm64,!noasm
#include "textflag.h"
TEXT ·cswapP503(SB), NOSPLIT, $0-17
MOVD x+0(FP), R0
MOVD y+8(FP), R1
MOVB choice+16(FP), R2
// Set flags
// If choice is not 0 or 1, this implementation will swap completely
CMP $0, R2
LDP 0(R0), (R3, R4)
LDP 0(R1), (R5, R6)
CSEL EQ, R3, R5, R7
CSEL EQ, R4, R6, R8
STP (R7, R8), 0(R0)
CSEL NE, R3, R5, R9
CSEL NE, R4, R6, R10
STP (R9, R10), 0(R1)
LDP 16(R0), (R3, R4)
LDP 16(R1), (R5, R6)
CSEL EQ, R3, R5, R7
CSEL EQ, R4, R6, R8
STP (R7, R8), 16(R0)
CSEL NE, R3, R5, R9
CSEL NE, R4, R6, R10
STP (R9, R10), 16(R1)
LDP 32(R0), (R3, R4)
LDP 32(R1), (R5, R6)
CSEL EQ, R3, R5, R7
CSEL EQ, R4, R6, R8
STP (R7, R8), 32(R0)
CSEL NE, R3, R5, R9
CSEL NE, R4, R6, R10
STP (R9, R10), 32(R1)
LDP 48(R0), (R3, R4)
LDP 48(R1), (R5, R6)
CSEL EQ, R3, R5, R7
CSEL EQ, R4, R6, R8
STP (R7, R8), 48(R0)
CSEL NE, R3, R5, R9
CSEL NE, R4, R6, R10
STP (R9, R10), 48(R1)
RET
TEXT ·addP503(SB), NOSPLIT, $0-24
MOVD z+0(FP), R2
MOVD x+8(FP), R0
MOVD y+16(FP), R1
// Load first summand into R3-R10
// Add first summand and second summand and store result in R3-R10
LDP 0(R0), (R3, R4)
LDP 0(R1), (R11, R12)
LDP 16(R0), (R5, R6)
LDP 16(R1), (R13, R14)
ADDS R11, R3
ADCS R12, R4
ADCS R13, R5
ADCS R14, R6
LDP 32(R0), (R7, R8)
LDP 32(R1), (R11, R12)
LDP 48(R0), (R9, R10)
LDP 48(R1), (R13, R14)
ADCS R11, R7
ADCS R12, R8
ADCS R13, R9
ADC R14, R10
// Subtract 2 * p503 in R11-R17 from the result in R3-R10
LDP ·P503x2+0(SB), (R11, R12)
LDP ·P503x2+24(SB), (R13, R14)
SUBS R11, R3
SBCS R12, R4
LDP ·P503x2+40(SB), (R15, R16)
SBCS R12, R5
SBCS R13, R6
MOVD ·P503x2+56(SB), R17
SBCS R14, R7
SBCS R15, R8
SBCS R16, R9
SBCS R17, R10
SBC ZR, ZR, R19
// If x + y - 2 * p503 < 0, R19 is 1 and 2 * p503 should be added
AND R19, R11
AND R19, R12
AND R19, R13
AND R19, R14
AND R19, R15
AND R19, R16
AND R19, R17
ADDS R11, R3
ADCS R12, R4
STP (R3, R4), 0(R2)
ADCS R12, R5
ADCS R13, R6
STP (R5, R6), 16(R2)
ADCS R14, R7
ADCS R15, R8
STP (R7, R8), 32(R2)
ADCS R16, R9
ADC R17, R10
STP (R9, R10), 48(R2)
RET
TEXT ·subP503(SB), NOSPLIT, $0-24
MOVD z+0(FP), R2
MOVD x+8(FP), R0
MOVD y+16(FP), R1
// Load x into R3-R10
// Subtract y from x and store result in R3-R10
LDP 0(R0), (R3, R4)
LDP 0(R1), (R11, R12)
LDP 16(R0), (R5, R6)
LDP 16(R1), (R13, R14)
SUBS R11, R3
SBCS R12, R4
SBCS R13, R5
SBCS R14, R6
LDP 32(R0), (R7, R8)
LDP 32(R1), (R11, R12)
LDP 48(R0), (R9, R10)
LDP 48(R1), (R13, R14)
SBCS R11, R7
SBCS R12, R8
SBCS R13, R9
SBCS R14, R10
SBC ZR, ZR, R19
// If x - y < 0, R19 is 1 and 2 * p503 should be added
LDP ·P503x2+0(SB), (R11, R12)
LDP ·P503x2+24(SB), (R13, R14)
AND R19, R11
AND R19, R12
LDP ·P503x2+40(SB), (R15, R16)
AND R19, R13
AND R19, R14
MOVD ·P503x2+56(SB), R17
AND R19, R15
AND R19, R16
AND R19, R17
ADDS R11, R3
ADCS R12, R4
STP (R3, R4), 0(R2)
ADCS R12, R5
ADCS R13, R6
STP (R5, R6), 16(R2)
ADCS R14, R7
ADCS R15, R8
STP (R7, R8), 32(R2)
ADCS R16, R9
ADC R17, R10
STP (R9, R10), 48(R2)
RET
TEXT ·adlP503(SB), NOSPLIT, $0-24
MOVD z+0(FP), R2
MOVD x+8(FP), R0
MOVD y+16(FP), R1
LDP 0(R0), (R3, R4)
LDP 0(R1), (R11, R12)
LDP 16(R0), (R5, R6)
LDP 16(R1), (R13, R14)
ADDS R11, R3
ADCS R12, R4
STP (R3, R4), 0(R2)
ADCS R13, R5
ADCS R14, R6
STP (R5, R6), 16(R2)
LDP 32(R0), (R7, R8)
LDP 32(R1), (R11, R12)
LDP 48(R0), (R9, R10)
LDP 48(R1), (R13, R14)
ADCS R11, R7
ADCS R12, R8
STP (R7, R8), 32(R2)
ADCS R13, R9
ADCS R14, R10
STP (R9, R10), 48(R2)
LDP 64(R0), (R3, R4)
LDP 64(R1), (R11, R12)
LDP 80(R0), (R5, R6)
LDP 80(R1), (R13, R14)
ADCS R11, R3
ADCS R12, R4
STP (R3, R4), 64(R2)
ADCS R13, R5
ADCS R14, R6
STP (R5, R6), 80(R2)
LDP 96(R0), (R7, R8)
LDP 96(R1), (R11, R12)
LDP 112(R0), (R9, R10)
LDP 112(R1), (R13, R14)
ADCS R11, R7
ADCS R12, R8
STP (R7, R8), 96(R2)
ADCS R13, R9
ADC R14, R10
STP (R9, R10), 112(R2)
RET
TEXT ·sulP503(SB), NOSPLIT, $0-24
MOVD z+0(FP), R2
MOVD x+8(FP), R0
MOVD y+16(FP), R1
LDP 0(R0), (R3, R4)
LDP 0(R1), (R11, R12)
LDP 16(R0), (R5, R6)
LDP 16(R1), (R13, R14)
SUBS R11, R3
SBCS R12, R4
STP (R3, R4), 0(R2)
SBCS R13, R5
SBCS R14, R6
STP (R5, R6), 16(R2)
LDP 32(R0), (R7, R8)
LDP 32(R1), (R11, R12)
LDP 48(R0), (R9, R10)
LDP 48(R1), (R13, R14)
SBCS R11, R7
SBCS R12, R8
STP (R7, R8), 32(R2)
SBCS R13, R9
SBCS R14, R10
STP (R9, R10), 48(R2)
LDP 64(R0), (R3, R4)
LDP 64(R1), (R11, R12)
LDP 80(R0), (R5, R6)
LDP 80(R1), (R13, R14)
SBCS R11, R3
SBCS R12, R4
SBCS R13, R5
SBCS R14, R6
LDP 96(R0), (R7, R8)
LDP 96(R1), (R11, R12)
LDP 112(R0), (R9, R10)
LDP 112(R1), (R13, R14)
SBCS R11, R7
SBCS R12, R8
SBCS R13, R9
SBCS R14, R10
SBC ZR, ZR, R15
// If x - y < 0, R15 is 1 and p503 should be added
LDP ·P503+16(SB), (R16, R17)
LDP ·P503+32(SB), (R19, R20)
AND R15, R16
AND R15, R17
LDP ·P503+48(SB), (R21, R22)
AND R15, R19
AND R15, R20
AND R15, R21
AND R15, R22
ADDS R16, R3
ADCS R16, R4
STP (R3, R4), 64(R2)
ADCS R16, R5
ADCS R17, R6
STP (R5, R6), 80(R2)
ADCS R19, R7
ADCS R20, R8
STP (R7, R8), 96(R2)
ADCS R21, R9
ADC R22, R10
STP (R9, R10), 112(R2)
RET
// Expects that X0*Y0 is already in Z0(low),Z3(high) and X0*Y1 in Z1(low),Z2(high)
// Z0 is not actually touched
// Result of (X0-X1) * (Y0-Y1) will be in Z0-Z3
// Inputs get overwritten, except for X1
#define mul128x128comba(X0, X1, Y0, Y1, Z0, Z1, Z2, Z3, T0) \
MUL X1, Y0, X0 \
UMULH X1, Y0, Y0 \
ADDS Z3, Z1 \
ADC ZR, Z2 \
\
MUL Y1, X1, T0 \
UMULH Y1, X1, Y1 \
ADDS X0, Z1 \
ADCS Y0, Z2 \
ADC ZR, ZR, Z3 \
\
ADDS T0, Z2 \
ADC Y1, Z3
// Expects that X points to (X0-X1)
// Result of (X0-X3) * (Y0-Y3) will be in Z0-Z7
// Inputs get overwritten, except X2-X3 and Y2-Y3
#define mul256x256karatsuba(X, X0, X1, X2, X3, Y0, Y1, Y2, Y3, Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7, T0, T1)\
ADDS X2, X0 \ // xH + xL, destroys xL
ADCS X3, X1 \
ADCS ZR, ZR, T0 \
\
ADDS Y2, Y0, Z6 \ // yH + yL
ADCS Y3, Y1, T1 \
ADC ZR, ZR, Z7 \
\
SUB T0, ZR, Z2 \
SUB Z7, ZR, Z3 \
AND Z7, T0 \ // combined carry
\
AND Z2, Z6, Z0 \ // masked(yH + yL)
AND Z2, T1, Z1 \
\
AND Z3, X0, Z4 \ // masked(xH + xL)
AND Z3, X1, Z5 \
\
MUL Z6, X0, Z2 \
MUL T1, X0, Z3 \
\
ADDS Z4, Z0 \
UMULH T1, X0, Z4 \
ADCS Z5, Z1 \
UMULH Z6, X0, Z5 \
ADC ZR, T0 \
\ // (xH + xL) * (yH + yL)
mul128x128comba(X0, X1, Z6, T1, Z2, Z3, Z4, Z5, Z7)\
\
LDP 0+X, (X0, X1) \
\
ADDS Z0, Z4 \
UMULH Y0, X0, Z7 \
UMULH Y1, X0, T1 \
ADCS Z1, Z5 \
MUL Y0, X0, Z0 \
MUL Y1, X0, Z1 \
ADC ZR, T0 \
\ // xL * yL
mul128x128comba(X0, X1, Y0, Y1, Z0, Z1, T1, Z7, Z6)\
\
MUL Y2, X2, X0 \
UMULH Y2, X2, Y0 \
SUBS Z0, Z2 \ // (xH + xL) * (yH + yL) - xL * yL
SBCS Z1, Z3 \
SBCS T1, Z4 \
MUL Y3, X2, X1 \
UMULH Y3, X2, Z6 \
SBCS Z7, Z5 \
SBCS ZR, T0 \
\ // xH * yH
mul128x128comba(X2, X3, Y2, Y3, X0, X1, Z6, Y0, Y1)\
\
SUBS X0, Z2 \ // (xH + xL) * (yH + yL) - xL * yL - xH * yH
SBCS X1, Z3 \
SBCS Z6, Z4 \
SBCS Y0, Z5 \
SBCS ZR, T0 \
\
ADDS T1, Z2 \ // (xH * yH) * 2^256 + ((xH + xL) * (yH + yL) - xL * yL - xH * yH) * 2^128 + xL * yL
ADCS Z7, Z3 \
ADCS X0, Z4 \
ADCS X1, Z5 \
ADCS T0, Z6 \
ADC Y0, ZR, Z7
// This implements two-level Karatsuba with a 128x128 Comba multiplier
// at the bottom
TEXT ·mulP503(SB), NOSPLIT, $0-24
MOVD z+0(FP), R2
MOVD x+8(FP), R0
MOVD y+16(FP), R1
// Load xL in R3-R6, xH in R7-R10
// (xH + xL) in R25-R29
LDP 0(R0), (R3, R4)
LDP 32(R0), (R7, R8)
ADDS R3, R7, R25
ADCS R4, R8, R26
LDP 16(R0), (R5, R6)
LDP 48(R0), (R9, R10)
ADCS R5, R9, R27
ADCS R6, R10, R29
ADC ZR, ZR, R7
// Load yL in R11-R14, yH in R15-19
// (yH + yL) in R11-R14, destroys yL
LDP 0(R1), (R11, R12)
LDP 32(R1), (R15, R16)
ADDS R15, R11
ADCS R16, R12
LDP 16(R1), (R13, R14)
LDP 48(R1), (R17, R19)
ADCS R17, R13
ADCS R19, R14
ADC ZR, ZR, R8
// Compute maskes and combined carry
SUB R7, ZR, R9
SUB R8, ZR, R10
AND R8, R7
// masked(yH + yL)
AND R9, R11, R15
AND R9, R12, R16
AND R9, R13, R17
AND R9, R14, R19
// masked(xH + xL)
AND R10, R25, R20
AND R10, R26, R21
AND R10, R27, R22
AND R10, R29, R23
// masked(xH + xL) + masked(yH + yL) in R15-R19
ADDS R20, R15
ADCS R21, R16
ADCS R22, R17
ADCS R23, R19
ADC ZR, R7
// Use z as temporary storage
STP (R25, R26), 0(R2)
// (xH + xL) * (yH + yL)
mul256x256karatsuba(0(R2), R25, R26, R27, R29, R11, R12, R13, R14, R8, R9, R10, R20, R21, R22, R23, R24, R0, R1)
MOVD x+8(FP), R0
MOVD y+16(FP), R1
ADDS R21, R15
ADCS R22, R16
ADCS R23, R17
ADCS R24, R19
ADC ZR, R7
// Load yL in R11-R14
LDP 0(R1), (R11, R12)
LDP 16(R1), (R13, R14)
// xL * yL
mul256x256karatsuba(0(R0), R3, R4, R5, R6, R11, R12, R13, R14, R21, R22, R23, R24, R25, R26, R27, R29, R1, R2)
MOVD z+0(FP), R2
MOVD y+16(FP), R1
// (xH + xL) * (yH + yL) - xL * yL
SUBS R21, R8
SBCS R22, R9
STP (R21, R22), 0(R2)
SBCS R23, R10
SBCS R24, R20
STP (R23, R24), 16(R2)
SBCS R25, R15
SBCS R26, R16
SBCS R27, R17
SBCS R29, R19
SBC ZR, R7
// Load xH in R3-R6, yH in R11-R14
LDP 32(R0), (R3, R4)
LDP 48(R0), (R5, R6)
LDP 32(R1), (R11, R12)
LDP 48(R1), (R13, R14)
ADDS R25, R8
ADCS R26, R9
ADCS R27, R10
ADCS R29, R20
ADC ZR, ZR, R1
MOVD R20, 32(R2)
// xH * yH
mul256x256karatsuba(32(R0), R3, R4, R5, R6, R11, R12, R13, R14, R21, R22, R23, R24, R25, R26, R27, R29, R2, R20)
NEG R1, R1
MOVD z+0(FP), R2
MOVD 32(R2), R20
// (xH + xL) * (yH + yL) - xL * yL - xH * yH in R8-R10,R20,R15-R19
// Store lower half in z, that's done
SUBS R21, R8
SBCS R22, R9
STP (R8, R9), 32(R2)
SBCS R23, R10
SBCS R24, R20
STP (R10, R20), 48(R2)
SBCS R25, R15
SBCS R26, R16
SBCS R27, R17
SBCS R29, R19
SBC ZR, R7
// (xH * yH) * 2^512 + ((xH + xL) * (yH + yL) - xL * yL - xH * yH) * 2^256 + xL * yL
// Store remaining limbs in z
ADDS $1, R1
ADCS R21, R15
ADCS R22, R16
STP (R15, R16), 64(R2)
ADCS R23, R17
ADCS R24, R19
STP (R17, R19), 80(R2)
ADCS R7, R25
ADCS ZR, R26
STP (R25, R26), 96(R2)
ADCS ZR, R27
ADC ZR, R29
STP (R27, R29), 112(R2)
RET
// Expects that X0*Y0 is already in Z0(low),Z3(high) and X0*Y1 in Z1(low),Z2(high)
// Z0 is not actually touched
// Result of (X0-X1) * (Y0-Y3) will be in Z0-Z5
// Inputs remain intact
#define mul128x256comba(X0, X1, Y0, Y1, Y2, Y3, Z0, Z1, Z2, Z3, Z4, Z5, T0, T1, T2, T3)\
MUL X1, Y0, T0 \
UMULH X1, Y0, T1 \
ADDS Z3, Z1 \
ADC ZR, Z2 \
\
MUL X0, Y2, T2 \
UMULH X0, Y2, T3 \
ADDS T0, Z1 \
ADCS T1, Z2 \
ADC ZR, ZR, Z3 \
\
MUL X1, Y1, T0 \
UMULH X1, Y1, T1 \
ADDS T2, Z2 \
ADCS T3, Z3 \
ADC ZR, ZR, Z4 \
\
MUL X0, Y3, T2 \
UMULH X0, Y3, T3 \
ADDS T0, Z2 \
ADCS T1, Z3 \
ADC ZR, Z4 \
\
MUL X1, Y2, T0 \
UMULH X1, Y2, T1 \
ADDS T2, Z3 \
ADCS T3, Z4 \
ADC ZR, ZR, Z5 \
\
MUL X1, Y3, T2 \
UMULH X1, Y3, T3 \
ADDS T0, Z3 \
ADCS T1, Z4 \
ADC ZR, Z5 \
ADDS T2, Z4 \
ADC T3, Z5
// This implements the shifted 2^(B*w) Montgomery reduction from
// https://eprint.iacr.org/2016/986.pdf with B = 4, w = 64
TEXT ·rdcP503(SB), NOSPLIT, $0-16
MOVD x+8(FP), R0
// Load x0-x1
LDP 0(R0), (R2, R3)
// Load the prime constant in R25-R29
LDP ·P503p1s8+32(SB), (R25, R26)
LDP ·P503p1s8+48(SB), (R27, R29)
// [x0,x1] * p503p1s8 to R4-R9
MUL R2, R25, R4 // x0 * p503p1s8[0]
UMULH R2, R25, R7
MUL R2, R26, R5 // x0 * p503p1s8[1]
UMULH R2, R26, R6
mul128x256comba(R2, R3, R25, R26, R27, R29, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13)
LDP 16(R0), (R3, R11) // x2
LDP 32(R0), (R12, R13)
LDP 48(R0), (R14, R15)
// Left-shift result in R4-R9 by 56 to R4-R10
ORR R9>>8, ZR, R10
LSL $56, R9
ORR R8>>8, R9
LSL $56, R8
ORR R7>>8, R8
LSL $56, R7
ORR R6>>8, R7
LSL $56, R6
ORR R5>>8, R6
LSL $56, R5
ORR R4>>8, R5
LSL $56, R4
ADDS R4, R11 // x3
ADCS R5, R12 // x4
ADCS R6, R13
ADCS R7, R14
ADCS R8, R15
LDP 64(R0), (R16, R17)
LDP 80(R0), (R19, R20)
MUL R3, R25, R4 // x2 * p503p1s8[0]
UMULH R3, R25, R7
ADCS R9, R16
ADCS R10, R17
ADCS ZR, R19
ADCS ZR, R20
LDP 96(R0), (R21, R22)
LDP 112(R0), (R23, R24)
MUL R3, R26, R5 // x2 * p503p1s8[1]
UMULH R3, R26, R6
ADCS ZR, R21
ADCS ZR, R22
ADCS ZR, R23
ADC ZR, R24
// [x2,x3] * p503p1s8 to R4-R9
mul128x256comba(R3, R11, R25, R26, R27, R29, R4, R5, R6, R7, R8, R9, R10, R0, R1, R2)
ORR R9>>8, ZR, R10
LSL $56, R9
ORR R8>>8, R9
LSL $56, R8
ORR R7>>8, R8
LSL $56, R7
ORR R6>>8, R7
LSL $56, R6
ORR R5>>8, R6
LSL $56, R5
ORR R4>>8, R5
LSL $56, R4
ADDS R4, R13 // x5
ADCS R5, R14 // x6
ADCS R6, R15
ADCS R7, R16
MUL R12, R25, R4 // x4 * p503p1s8[0]
UMULH R12, R25, R7
ADCS R8, R17
ADCS R9, R19
ADCS R10, R20
ADCS ZR, R21
MUL R12, R26, R5 // x4 * p503p1s8[1]
UMULH R12, R26, R6
ADCS ZR, R22
ADCS ZR, R23
ADC ZR, R24
// [x4,x5] * p503p1s8 to R4-R9
mul128x256comba(R12, R13, R25, R26, R27, R29, R4, R5, R6, R7, R8, R9, R10, R0, R1, R2)
ORR R9>>8, ZR, R10
LSL $56, R9
ORR R8>>8, R9
LSL $56, R8
ORR R7>>8, R8
LSL $56, R7
ORR R6>>8, R7
LSL $56, R6
ORR R5>>8, R6
LSL $56, R5
ORR R4>>8, R5
LSL $56, R4
ADDS R4, R15 // x7
ADCS R5, R16 // x8
ADCS R6, R17
ADCS R7, R19
MUL R14, R25, R4 // x6 * p503p1s8[0]
UMULH R14, R25, R7
ADCS R8, R20
ADCS R9, R21
ADCS R10, R22
MUL R14, R26, R5 // x6 * p503p1s8[1]
UMULH R14, R26, R6
ADCS ZR, R23
ADC ZR, R24
// [x6,x7] * p503p1s8 to R4-R9
mul128x256comba(R14, R15, R25, R26, R27, R29, R4, R5, R6, R7, R8, R9, R10, R0, R1, R2)
ORR R9>>8, ZR, R10
LSL $56, R9
ORR R8>>8, R9
LSL $56, R8
ORR R7>>8, R8
LSL $56, R7
ORR R6>>8, R7
LSL $56, R6
ORR R5>>8, R6
LSL $56, R5
ORR R4>>8, R5
LSL $56, R4
MOVD z+0(FP), R0
ADDS R4, R17
ADCS R5, R19
STP (R16, R17), 0(R0) // Store final result to z
ADCS R6, R20
ADCS R7, R21
STP (R19, R20), 16(R0)
ADCS R8, R22
ADCS R9, R23
STP (R21, R22), 32(R0)
ADC R10, R24
STP (R23, R24), 48(R0)
RET
TEXT ·modP503(SB), NOSPLIT, $0-8
MOVD x+0(FP), R0
// Keep x in R1-R8, p503 in R9-R14, subtract to R1-R8
LDP ·P503+16(SB), (R9, R10)
LDP 0(R0), (R1, R2)
LDP 16(R0), (R3, R4)
SUBS R9, R1
SBCS R9, R2
LDP 32(R0), (R5, R6)
LDP ·P503+32(SB), (R11, R12)
SBCS R9, R3
SBCS R10, R4
LDP 48(R0), (R7, R8)
LDP ·P503+48(SB), (R13, R14)
SBCS R11, R5
SBCS R12, R6
SBCS R13, R7
SBCS R14, R8
SBC ZR, ZR, R15
// Mask with the borrow and add p503
AND R15, R9
AND R15, R10
AND R15, R11
AND R15, R12
AND R15, R13
AND R15, R14
ADDS R9, R1
ADCS R9, R2
STP (R1, R2), 0(R0)
ADCS R9, R3
ADCS R10, R4
STP (R3, R4), 16(R0)
ADCS R11, R5
ADCS R12, R6
STP (R5, R6), 32(R0)
ADCS R13, R7
ADCS R14, R8
STP (R7, R8), 48(R0)
RET

View File

@ -0,0 +1,45 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
// +build amd64,!noasm arm64,!noasm
package p503
import (
. "github.com/cloudflare/circl/dh/sidh/internal/common"
)
// If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x.
// If choice is neither 0 nor 1 then behaviour is undefined.
// This function executes in constant time.
//go:noescape
func cswapP503(x, y *Fp, choice uint8)
// Compute z = x + y (mod p).
//go:noescape
func addP503(z, x, y *Fp)
// Compute z = x - y (mod p).
//go:noescape
func subP503(z, x, y *Fp)
// Compute z = x + y, without reducing mod p.
//go:noescape
func adlP503(z, x, y *FpX2)
// Compute z = x - y, without reducing mod p.
//go:noescape
func sulP503(z, x, y *FpX2)
// Reduce a field element in [0, 2*p) to one in [0,p).
//go:noescape
func modP503(x *Fp)
// Computes z = x * y.
//go:noescape
func mulP503(z *FpX2, x, y *Fp)
// Computes the Montgomery reduction z = x R^{-1} (mod 2*p). On return value
// of x may be changed. z=x not allowed.
//go:noescape
func rdcP503(z *Fp, x *FpX2)

View File

@ -0,0 +1,192 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
// +build noasm !amd64,!arm64
package p503
import (
"math/bits"
"github.com/cloudflare/circl/dh/sidh/internal/common"
)
// Compute z = x + y (mod p).
func addP503(z, x, y *common.Fp) {
var carry uint64
// z=x+y % P503
for i := 0; i < FpWords; i++ {
z[i], carry = bits.Add64(x[i], y[i], carry)
}
// z = z - P503x2
carry = 0
for i := 0; i < FpWords; i++ {
z[i], carry = bits.Sub64(z[i], P503x2[i], carry)
}
// if z<0 add P503x2 back
mask := uint64(0 - carry)
carry = 0
for i := 0; i < FpWords; i++ {
z[i], carry = bits.Add64(z[i], P503x2[i]&mask, carry)
}
}
// Compute z = x - y (mod p).
func subP503(z, x, y *common.Fp) {
var borrow uint64
for i := 0; i < FpWords; i++ {
z[i], borrow = bits.Sub64(x[i], y[i], borrow)
}
mask := uint64(0 - borrow)
borrow = 0
for i := 0; i < FpWords; i++ {
z[i], borrow = bits.Add64(z[i], P503x2[i]&mask, borrow)
}
}
// Conditionally swaps bits in x and y in constant time.
// mask indicates bits to be swapped (set bits are swapped)
// For details see "Hackers Delight, 2.20"
//
// Implementation doesn't actually depend on a prime field.
func cswapP503(x, y *common.Fp, mask uint8) {
var tmp, mask64 uint64
mask64 = 0 - uint64(mask)
for i := 0; i < FpWords; i++ {
tmp = mask64 & (x[i] ^ y[i])
x[i] = tmp ^ x[i]
y[i] = tmp ^ y[i]
}
}
// Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
// with R=2^(FpWords*64). Destroys the input value.
func rdcP503(z *common.Fp, x *common.FpX2) {
var carry, t, u, v uint64
var hi, lo uint64
var count int
count = P503p1Zeros
for i := 0; i < FpWords; i++ {
for j := 0; j < i; j++ {
if j < (i - count + 1) {
hi, lo = bits.Mul64(z[j], P503p1[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
}
v, carry = bits.Add64(v, x[i], 0)
u, carry = bits.Add64(u, 0, carry)
t += carry
z[i] = v
v = u
u = t
t = 0
}
for i := FpWords; i < 2*FpWords-1; i++ {
if count > 0 {
count--
}
for j := i - FpWords + 1; j < FpWords; j++ {
if j < (FpWords - count) {
hi, lo = bits.Mul64(z[j], P503p1[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
}
v, carry = bits.Add64(v, x[i], 0)
u, carry = bits.Add64(u, 0, carry)
t += carry
z[i-FpWords] = v
v = u
u = t
t = 0
}
v, carry = bits.Add64(v, x[2*FpWords-1], 0)
z[FpWords-1] = v
}
// Compute z = x * y.
func mulP503(z *common.FpX2, x, y *common.Fp) {
var u, v, t uint64
var hi, lo uint64
var carry uint64
for i := uint64(0); i < FpWords; i++ {
for j := uint64(0); j <= i; j++ {
hi, lo = bits.Mul64(x[j], y[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
z[i] = v
v = u
u = t
t = 0
}
for i := FpWords; i < (2*FpWords)-1; i++ {
for j := i - FpWords + 1; j < FpWords; j++ {
hi, lo = bits.Mul64(x[j], y[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
z[i] = v
v = u
u = t
t = 0
}
z[2*FpWords-1] = v
}
// Compute z = x + y, without reducing mod p.
func adlP503(z, x, y *common.FpX2) {
var carry uint64
for i := 0; i < 2*FpWords; i++ {
z[i], carry = bits.Add64(x[i], y[i], carry)
}
}
// Reduce a field element in [0, 2*p) to one in [0,p).
func modP503(x *common.Fp) {
var borrow, mask uint64
for i := 0; i < FpWords; i++ {
x[i], borrow = bits.Sub64(x[i], P503[i], borrow)
}
// Sets all bits if borrow = 1
mask = 0 - borrow
borrow = 0
for i := 0; i < FpWords; i++ {
x[i], borrow = bits.Add64(x[i], P503[i]&mask, borrow)
}
}
// Compute z = x - y, without reducing mod p.
func sulP503(z, x, y *common.FpX2) {
var borrow, mask uint64
for i := 0; i < 2*FpWords; i++ {
z[i], borrow = bits.Sub64(x[i], y[i], borrow)
}
// Sets all bits if borrow = 1
mask = 0 - borrow
borrow = 0
for i := FpWords; i < 2*FpWords; i++ {
z[i], borrow = bits.Add64(z[i], P503[i-FpWords]&mask, borrow)
}
}

View File

@ -0,0 +1,294 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
package p503
import (
. "github.com/cloudflare/circl/dh/sidh/internal/common"
)
// -----------------------------------------------------------------------------
// Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
//
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreePublicKeyA(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny4
cparam := CalcCurveParamsEquiv4(curve)
strat := params.A.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow2k(xR, &cparam, 2*k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
*phiP = phi.EvaluatePoint(phiP)
*phiQ = phi.EvaluatePoint(phiQ)
*phiR = phi.EvaluatePoint(phiR)
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR needed
// for public key generation.
func traverseTreeSharedKeyA(curve *ProjectiveCurveParameters, xR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny4
cparam := CalcCurveParamsEquiv4(curve)
strat := params.A.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow2k(xR, &cparam, 2*k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreePublicKeyB(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny3
cparam := CalcCurveParamsEquiv3(curve)
strat := params.B.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow3k(xR, &cparam, k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
*phiP = phi.EvaluatePoint(phiP)
*phiQ = phi.EvaluatePoint(phiQ)
*phiR = phi.EvaluatePoint(phiR)
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny3
cparam := CalcCurveParamsEquiv3(curve)
strat := params.B.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow3k(xR, &cparam, k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Generate a public key in the 2-torsion group. Public key is a set
// of three x-coordinates: xP,xQ,x(P-Q), where P,Q are points on E_a(Fp2)
func PublicKeyGenA(pub3Pt *[3]Fp2, prvBytes []byte) {
var xPA, xQA, xRA ProjectivePoint
var xPB, xQB, xRB, xR ProjectivePoint
var invZP, invZQ, invZR Fp2
var tmp ProjectiveCurveParameters
var phi isogeny4
// Load points for A
xPA = ProjectivePoint{X: params.A.AffineP, Z: params.OneFp2}
xQA = ProjectivePoint{X: params.A.AffineQ, Z: params.OneFp2}
xRA = ProjectivePoint{X: params.A.AffineR, Z: params.OneFp2}
// Load points for B
xRB = ProjectivePoint{X: params.B.AffineR, Z: params.OneFp2}
xQB = ProjectivePoint{X: params.B.AffineQ, Z: params.OneFp2}
xPB = ProjectivePoint{X: params.B.AffineP, Z: params.OneFp2}
// Find isogeny kernel
tmp.C = params.OneFp2
xR = ScalarMul3Pt(&tmp, &xPA, &xQA, &xRA, params.A.SecretBitLen, prvBytes)
// Reset params object and travers isogeny tree
tmp.C = params.OneFp2
tmp.A = Fp2{}
traverseTreePublicKeyA(&tmp, &xR, &xPB, &xQB, &xRB)
// Secret isogeny
phi.GenerateCurve(&xR)
xPA = phi.EvaluatePoint(&xPB)
xQA = phi.EvaluatePoint(&xQB)
xRA = phi.EvaluatePoint(&xRB)
Fp2Batch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
mul(&pub3Pt[0], &xPA.X, &invZP)
mul(&pub3Pt[1], &xQA.X, &invZQ)
mul(&pub3Pt[2], &xRA.X, &invZR)
}
// Generate a public key in the 2-torsion group. Public key is a set
// of three x-coordinates: xP,xQ,x(P-Q), where P,Q are points on E_a(Fp2)
func PublicKeyGenB(pub3Pt *[3]Fp2, prvBytes []byte) {
var xPB, xQB, xRB, xR ProjectivePoint
var xPA, xQA, xRA ProjectivePoint
var invZP, invZQ, invZR Fp2
var tmp ProjectiveCurveParameters
var phi isogeny3
// Load points for B
xRB = ProjectivePoint{X: params.B.AffineR, Z: params.OneFp2}
xQB = ProjectivePoint{X: params.B.AffineQ, Z: params.OneFp2}
xPB = ProjectivePoint{X: params.B.AffineP, Z: params.OneFp2}
// Load points for A
xPA = ProjectivePoint{X: params.A.AffineP, Z: params.OneFp2}
xQA = ProjectivePoint{X: params.A.AffineQ, Z: params.OneFp2}
xRA = ProjectivePoint{X: params.A.AffineR, Z: params.OneFp2}
tmp.C = params.OneFp2
xR = ScalarMul3Pt(&tmp, &xPB, &xQB, &xRB, params.B.SecretBitLen, prvBytes)
tmp.C = params.OneFp2
tmp.A = Fp2{}
traverseTreePublicKeyB(&tmp, &xR, &xPA, &xQA, &xRA)
phi.GenerateCurve(&xR)
xPB = phi.EvaluatePoint(&xPA)
xQB = phi.EvaluatePoint(&xQA)
xRB = phi.EvaluatePoint(&xRA)
Fp2Batch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
mul(&pub3Pt[0], &xPB.X, &invZP)
mul(&pub3Pt[1], &xQB.X, &invZQ)
mul(&pub3Pt[2], &xRB.X, &invZR)
}
// -----------------------------------------------------------------------------
// Key agreement functions
//
// Establishing shared keys in in 2-torsion group
func DeriveSecretA(ss, prv []byte, pub3Pt *[3]Fp2) {
var cparam ProjectiveCurveParameters
var xP, xQ, xQmP ProjectivePoint
var xR ProjectivePoint
var phi isogeny4
var jInv Fp2
// Recover curve coefficients
cparam.C = params.OneFp2
RecoverCoordinateA(&cparam, &pub3Pt[0], &pub3Pt[1], &pub3Pt[2])
// Find kernel of the morphism
xP = ProjectivePoint{X: pub3Pt[0], Z: params.OneFp2}
xQ = ProjectivePoint{X: pub3Pt[1], Z: params.OneFp2}
xQmP = ProjectivePoint{X: pub3Pt[2], Z: params.OneFp2}
xR = ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, params.A.SecretBitLen, prv)
// Traverse isogeny tree
traverseTreeSharedKeyA(&cparam, &xR)
// Calculate j-invariant on isogeneus curve
c := phi.GenerateCurve(&xR)
RecoverCurveCoefficients4(&cparam, &c)
Jinvariant(&cparam, &jInv)
FromMontgomery(&jInv, &jInv)
Fp2ToBytes(ss, &jInv, params.Bytelen)
}
// Establishing shared keys in in 3-torsion group
func DeriveSecretB(ss, prv []byte, pub3Pt *[3]Fp2) {
var xP, xQ, xQmP ProjectivePoint
var xR ProjectivePoint
var cparam ProjectiveCurveParameters
var phi isogeny3
var jInv Fp2
// Recover curve coefficients
cparam.C = params.OneFp2
RecoverCoordinateA(&cparam, &pub3Pt[0], &pub3Pt[1], &pub3Pt[2])
// Find kernel of the morphism
xP = ProjectivePoint{X: pub3Pt[0], Z: params.OneFp2}
xQ = ProjectivePoint{X: pub3Pt[1], Z: params.OneFp2}
xQmP = ProjectivePoint{X: pub3Pt[2], Z: params.OneFp2}
xR = ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, params.B.SecretBitLen, prv)
// Traverse isogeny tree
traverseTreeSharedKeyB(&cparam, &xR)
// Calculate j-invariant on isogeneus curve
c := phi.GenerateCurve(&xR)
RecoverCurveCoefficients3(&cparam, &c)
Jinvariant(&cparam, &jInv)
FromMontgomery(&jInv, &jInv)
Fp2ToBytes(ss, &jInv, params.Bytelen)
}

View File

@ -0,0 +1,362 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
package p503
import (
. "github.com/cloudflare/circl/dh/sidh/internal/common"
)
// Stores isogeny 3 curve constants
type isogeny3 struct {
K1 Fp2
K2 Fp2
}
// Stores isogeny 4 curve constants
type isogeny4 struct {
isogeny3
K3 Fp2
}
// Computes j-invariant for a curve y2=x3+A/Cx+x with A,C in F_(p^2). Result
// is returned in jBytes buffer, encoded in little-endian format. Caller
// provided jBytes buffer has to be big enough to j-invariant value. In case
// of SIDH, buffer size must be at least size of shared secret.
// Implementation corresponds to Algorithm 9 from SIKE.
func Jinvariant(cparams *ProjectiveCurveParameters, j *Fp2) {
var t0, t1 Fp2
sqr(j, &cparams.A) // j = A^2
sqr(&t1, &cparams.C) // t1 = C^2
add(&t0, &t1, &t1) // t0 = t1 + t1
sub(&t0, j, &t0) // t0 = j - t0
sub(&t0, &t0, &t1) // t0 = t0 - t1
sub(j, &t0, &t1) // t0 = t0 - t1
sqr(&t1, &t1) // t1 = t1^2
mul(j, j, &t1) // j = j * t1
add(&t0, &t0, &t0) // t0 = t0 + t0
add(&t0, &t0, &t0) // t0 = t0 + t0
sqr(&t1, &t0) // t1 = t0^2
mul(&t0, &t0, &t1) // t0 = t0 * t1
add(&t0, &t0, &t0) // t0 = t0 + t0
add(&t0, &t0, &t0) // t0 = t0 + t0
inv(j, j) // j = 1/j
mul(j, &t0, j) // j = t0 * j
}
// Given affine points x(P), x(Q) and x(Q-P) in a extension field F_{p^2}, function
// recorvers projective coordinate A of a curve. This is Algorithm 10 from SIKE.
func RecoverCoordinateA(curve *ProjectiveCurveParameters, xp, xq, xr *Fp2) {
var t0, t1 Fp2
add(&t1, xp, xq) // t1 = Xp + Xq
mul(&t0, xp, xq) // t0 = Xp * Xq
mul(&curve.A, xr, &t1) // A = X(q-p) * t1
add(&curve.A, &curve.A, &t0) // A = A + t0
mul(&t0, &t0, xr) // t0 = t0 * X(q-p)
sub(&curve.A, &curve.A, &params.OneFp2) // A = A - 1
add(&t0, &t0, &t0) // t0 = t0 + t0
add(&t1, &t1, xr) // t1 = t1 + X(q-p)
add(&t0, &t0, &t0) // t0 = t0 + t0
sqr(&curve.A, &curve.A) // A = A^2
inv(&t0, &t0) // t0 = 1/t0
mul(&curve.A, &curve.A, &t0) // A = A * t0
sub(&curve.A, &curve.A, &t1) // A = A - t1
}
// Computes equivalence (A:C) ~ (A+2C : A-2C)
func CalcCurveParamsEquiv3(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv {
var coef CurveCoefficientsEquiv
var c2 Fp2
add(&c2, &cparams.C, &cparams.C)
// A24p = A+2*C
add(&coef.A, &cparams.A, &c2)
// A24m = A-2*C
sub(&coef.C, &cparams.A, &c2)
return coef
}
// Computes equivalence (A:C) ~ (A+2C : 4C)
func CalcCurveParamsEquiv4(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv {
var coefEq CurveCoefficientsEquiv
add(&coefEq.C, &cparams.C, &cparams.C)
// A24p = A+2C
add(&coefEq.A, &cparams.A, &coefEq.C)
// C24 = 4*C
add(&coefEq.C, &coefEq.C, &coefEq.C)
return coefEq
}
// Helper function for RightToLeftLadder(). Returns A+2C / 4.
func CalcAplus2Over4(cparams *ProjectiveCurveParameters) (ret Fp2) {
var tmp Fp2
// 2C
add(&tmp, &cparams.C, &cparams.C)
// A+2C
add(&ret, &cparams.A, &tmp)
// 1/4C
add(&tmp, &tmp, &tmp)
inv(&tmp, &tmp)
// A+2C/4C
mul(&ret, &ret, &tmp)
return
}
// Recovers (A:C) curve parameters from projectively equivalent (A+2C:A-2C).
func RecoverCurveCoefficients3(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) {
add(&cparams.A, &coefEq.A, &coefEq.C)
// cparams.A = 2*(A+2C+A-2C) = 4A
add(&cparams.A, &cparams.A, &cparams.A)
// cparams.C = (A+2C-A+2C) = 4C
sub(&cparams.C, &coefEq.A, &coefEq.C)
return
}
// Recovers (A:C) curve parameters from projectively equivalent (A+2C:4C).
func RecoverCurveCoefficients4(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) {
// cparams.C = (4C)*1/2=2C
mul(&cparams.C, &coefEq.C, &params.HalfFp2)
// cparams.A = A+2C - 2C = A
sub(&cparams.A, &coefEq.A, &cparams.C)
// cparams.C = 2C * 1/2 = C
mul(&cparams.C, &cparams.C, &params.HalfFp2)
}
// Combined coordinate doubling and differential addition. Takes projective points
// P,Q,Q-P and (A+2C)/4C curve E coefficient. Returns 2*P and P+Q calculated on E.
// Function is used only by RightToLeftLadder. Corresponds to Algorithm 5 of SIKE
func xDbladd(P, Q, QmP *ProjectivePoint, a24 *Fp2) (dblP, PaQ ProjectivePoint) {
var t0, t1, t2 Fp2
xQmP, zQmP := &QmP.X, &QmP.Z
xPaQ, zPaQ := &PaQ.X, &PaQ.Z
x2P, z2P := &dblP.X, &dblP.Z
xP, zP := &P.X, &P.Z
xQ, zQ := &Q.X, &Q.Z
add(&t0, xP, zP) // t0 = Xp+Zp
sub(&t1, xP, zP) // t1 = Xp-Zp
sqr(x2P, &t0) // 2P.X = t0^2
sub(&t2, xQ, zQ) // t2 = Xq-Zq
add(xPaQ, xQ, zQ) // Xp+q = Xq+Zq
mul(&t0, &t0, &t2) // t0 = t0 * t2
mul(z2P, &t1, &t1) // 2P.Z = t1 * t1
mul(&t1, &t1, xPaQ) // t1 = t1 * Xp+q
sub(&t2, x2P, z2P) // t2 = 2P.X - 2P.Z
mul(x2P, x2P, z2P) // 2P.X = 2P.X * 2P.Z
mul(xPaQ, a24, &t2) // Xp+q = A24 * t2
sub(zPaQ, &t0, &t1) // Zp+q = t0 - t1
add(z2P, xPaQ, z2P) // 2P.Z = Xp+q + 2P.Z
add(xPaQ, &t0, &t1) // Xp+q = t0 + t1
mul(z2P, z2P, &t2) // 2P.Z = 2P.Z * t2
sqr(zPaQ, zPaQ) // Zp+q = Zp+q ^ 2
sqr(xPaQ, xPaQ) // Xp+q = Xp+q ^ 2
mul(zPaQ, xQmP, zPaQ) // Zp+q = Xq-p * Zp+q
mul(xPaQ, zQmP, xPaQ) // Xp+q = Zq-p * Xp+q
return
}
// Given the curve parameters, xP = x(P), computes xP = x([2^k]P)
// Safe to overlap xP, x2P.
func Pow2k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) {
var t0, t1 Fp2
x, z := &xP.X, &xP.Z
for i := uint32(0); i < k; i++ {
sub(&t0, x, z) // t0 = Xp - Zp
add(&t1, x, z) // t1 = Xp + Zp
sqr(&t0, &t0) // t0 = t0 ^ 2
sqr(&t1, &t1) // t1 = t1 ^ 2
mul(z, &params.C, &t0) // Z2p = C24 * t0
mul(x, z, &t1) // X2p = Z2p * t1
sub(&t1, &t1, &t0) // t1 = t1 - t0
mul(&t0, &params.A, &t1) // t0 = A24+ * t1
add(z, z, &t0) // Z2p = Z2p + t0
mul(z, z, &t1) // Zp = Z2p * t1
}
}
// Given the curve parameters, xP = x(P), and k >= 0, compute xP = x([3^k]P).
//
// Safe to overlap xP, xR.
func Pow3k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) {
var t0, t1, t2, t3, t4, t5, t6 Fp2
x, z := &xP.X, &xP.Z
for i := uint32(0); i < k; i++ {
sub(&t0, x, z) // t0 = Xp - Zp
sqr(&t2, &t0) // t2 = t0^2
add(&t1, x, z) // t1 = Xp + Zp
sqr(&t3, &t1) // t3 = t1^2
add(&t4, &t1, &t0) // t4 = t1 + t0
sub(&t0, &t1, &t0) // t0 = t1 - t0
sqr(&t1, &t4) // t1 = t4^2
sub(&t1, &t1, &t3) // t1 = t1 - t3
sub(&t1, &t1, &t2) // t1 = t1 - t2
mul(&t5, &t3, &params.A) // t5 = t3 * A24+
mul(&t3, &t3, &t5) // t3 = t5 * t3
mul(&t6, &t2, &params.C) // t6 = t2 * A24-
mul(&t2, &t2, &t6) // t2 = t2 * t6
sub(&t3, &t2, &t3) // t3 = t2 - t3
sub(&t2, &t5, &t6) // t2 = t5 - t6
mul(&t1, &t2, &t1) // t1 = t2 * t1
add(&t2, &t3, &t1) // t2 = t3 + t1
sqr(&t2, &t2) // t2 = t2^2
mul(x, &t2, &t4) // X3p = t2 * t4
sub(&t1, &t3, &t1) // t1 = t3 - t1
sqr(&t1, &t1) // t1 = t1^2
mul(z, &t1, &t0) // Z3p = t1 * t0
}
}
// Set (y1, y2, y3) = (1/x1, 1/x2, 1/x3).
//
// All xi, yi must be distinct.
func Fp2Batch3Inv(x1, x2, x3, y1, y2, y3 *Fp2) {
var x1x2, t Fp2
mul(&x1x2, x1, x2) // x1*x2
mul(&t, &x1x2, x3) // 1/(x1*x2*x3)
inv(&t, &t)
mul(y1, &t, x2) // 1/x1
mul(y1, y1, x3)
mul(y2, &t, x1) // 1/x2
mul(y2, y2, x3)
mul(y3, &t, &x1x2) // 1/x3
}
// Scalarmul3Pt is a right-to-left point multiplication that given the
// x-coordinate of P, Q and P-Q calculates the x-coordinate of R=Q+[scalar]P.
// nbits must be smaller or equal to len(scalar).
func ScalarMul3Pt(cparams *ProjectiveCurveParameters, P, Q, PmQ *ProjectivePoint, nbits uint, scalar []uint8) ProjectivePoint {
var R0, R2, R1 ProjectivePoint
aPlus2Over4 := CalcAplus2Over4(cparams)
R1 = *P
R2 = *PmQ
R0 = *Q
// Iterate over the bits of the scalar, bottom to top
prevBit := uint8(0)
for i := uint(0); i < nbits; i++ {
bit := (scalar[i>>3] >> (i & 7) & 1)
swap := prevBit ^ bit
prevBit = bit
cswap(&R1.X, &R1.Z, &R2.X, &R2.Z, swap)
R0, R2 = xDbladd(&R0, &R2, &R1, &aPlus2Over4)
}
cswap(&R1.X, &R1.Z, &R2.X, &R2.Z, prevBit)
return R1
}
// Given a three-torsion point p = x(PB) on the curve E_(A:C), construct the
// three-isogeny phi : E_(A:C) -> E_(A:C)/<P_3> = E_(A':C').
//
// Input: (XP_3: ZP_3), where P_3 has exact order 3 on E_A/C
// Output: * Curve coordinates (A' + 2C', A' - 2C') corresponding to E_A'/C' = A_E/C/<P3>
// * Isogeny phi with constants in F_p^2
func (phi *isogeny3) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv {
var t0, t1, t2, t3, t4 Fp2
var coefEq CurveCoefficientsEquiv
var K1, K2 = &phi.K1, &phi.K2
sub(K1, &p.X, &p.Z) // K1 = XP3 - ZP3
sqr(&t0, K1) // t0 = K1^2
add(K2, &p.X, &p.Z) // K2 = XP3 + ZP3
sqr(&t1, K2) // t1 = K2^2
add(&t2, &t0, &t1) // t2 = t0 + t1
add(&t3, K1, K2) // t3 = K1 + K2
sqr(&t3, &t3) // t3 = t3^2
sub(&t3, &t3, &t2) // t3 = t3 - t2
add(&t2, &t1, &t3) // t2 = t1 + t3
add(&t3, &t3, &t0) // t3 = t3 + t0
add(&t4, &t3, &t0) // t4 = t3 + t0
add(&t4, &t4, &t4) // t4 = t4 + t4
add(&t4, &t1, &t4) // t4 = t1 + t4
mul(&coefEq.C, &t2, &t4) // A24m = t2 * t4
add(&t4, &t1, &t2) // t4 = t1 + t2
add(&t4, &t4, &t4) // t4 = t4 + t4
add(&t4, &t0, &t4) // t4 = t0 + t4
mul(&t4, &t3, &t4) // t4 = t3 * t4
sub(&t0, &t4, &coefEq.C) // t0 = t4 - A24m
add(&coefEq.A, &coefEq.C, &t0) // A24p = A24m + t0
return coefEq
}
// Given a 3-isogeny phi and a point pB = x(PB), compute x(QB), the x-coordinate
// of the image QB = phi(PB) of PB under phi : E_(A:C) -> E_(A':C').
//
// The output xQ = x(Q) is then a point on the curve E_(A':C'); the curve
// parameters are returned by the GenerateCurve function used to construct phi.
func (phi *isogeny3) EvaluatePoint(p *ProjectivePoint) ProjectivePoint {
var t0, t1, t2 Fp2
var q ProjectivePoint
var K1, K2 = &phi.K1, &phi.K2
var px, pz = &p.X, &p.Z
add(&t0, px, pz) // t0 = XQ + ZQ
sub(&t1, px, pz) // t1 = XQ - ZQ
mul(&t0, K1, &t0) // t2 = K1 * t0
mul(&t1, K2, &t1) // t1 = K2 * t1
add(&t2, &t0, &t1) // t2 = t0 + t1
sub(&t0, &t1, &t0) // t0 = t1 - t0
sqr(&t2, &t2) // t2 = t2 ^ 2
sqr(&t0, &t0) // t0 = t0 ^ 2
mul(&q.X, px, &t2) // XQ'= XQ * t2
mul(&q.Z, pz, &t0) // ZQ'= ZQ * t0
return q
}
// Given a four-torsion point p = x(PB) on the curve E_(A:C), construct the
// four-isogeny phi : E_(A:C) -> E_(A:C)/<P_4> = E_(A':C').
//
// Input: (XP_4: ZP_4), where P_4 has exact order 4 on E_A/C
// Output: * Curve coordinates (A' + 2C', 4C') corresponding to E_A'/C' = A_E/C/<P4>
// * Isogeny phi with constants in F_p^2
func (phi *isogeny4) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv {
var coefEq CurveCoefficientsEquiv
var xp4, zp4 = &p.X, &p.Z
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3
sub(K2, xp4, zp4)
add(K3, xp4, zp4)
sqr(K1, zp4)
add(K1, K1, K1)
sqr(&coefEq.C, K1)
add(K1, K1, K1)
sqr(&coefEq.A, xp4)
add(&coefEq.A, &coefEq.A, &coefEq.A)
sqr(&coefEq.A, &coefEq.A)
return coefEq
}
// Given a 4-isogeny phi and a point xP = x(P), compute x(Q), the x-coordinate
// of the image Q = phi(P) of P under phi : E_(A:C) -> E_(A':C').
//
// Input: Isogeny returned by GenerateCurve and point q=(Qx,Qz) from E0_A/C
// Output: Corresponding point q from E1_A'/C', where E1 is 4-isogenous to E0
func (phi *isogeny4) EvaluatePoint(p *ProjectivePoint) ProjectivePoint {
var t0, t1 Fp2
var q = *p
var xq, zq = &q.X, &q.Z
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3
add(&t0, xq, zq)
sub(&t1, xq, zq)
mul(xq, &t0, K2)
mul(zq, &t1, K3)
mul(&t0, &t0, &t1)
mul(&t0, &t0, K1)
add(&t1, xq, zq)
sub(zq, xq, zq)
sqr(&t1, &t1)
sqr(zq, zq)
add(xq, &t0, &t1)
sub(&t0, zq, &t0)
mul(xq, xq, &t1)
mul(zq, zq, &t0)
return q
}

View File

@ -0,0 +1,2 @@
// Package p503 provides implementation of field arithmetic used in SIDH and SIKE.
package p503

View File

@ -0,0 +1,195 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
package p503
import (
"github.com/cloudflare/circl/dh/sidh/internal/common"
)
// Montgomery multiplication. Input values must be already
// in Montgomery domain.
func mulP(dest, lhs, rhs *common.Fp) {
var ab common.FpX2
mulP503(&ab, lhs, rhs) // = a*b*R*R
rdcP503(dest, &ab) // = a*b*R mod p
}
// Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x).
// Uses variation of sliding-window algorithm from with window size
// of 5 and least to most significant bit sliding (left-to-right)
// See HAC 14.85 for general description.
//
// Allowed to overlap x with dest.
// All values in Montgomery domains
// Set dest = x^(2^k), for k >= 1, by repeated squarings.
func p34(dest, x *common.Fp) {
var lookup [16]common.Fp
// This performs sum(powStrategy) + 1 squarings and len(lookup) + len(mulStrategy)
// multiplications.
powStrategy := []uint8{12, 5, 5, 2, 7, 11, 3, 8, 4, 11, 4, 7, 5, 6, 3, 7, 5, 7, 2, 12, 5, 6, 4, 6, 8, 6, 4, 7, 5, 5, 8, 5, 8, 5, 5, 8, 9, 3, 6, 2, 10, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3}
mulStrategy := []uint8{12, 11, 10, 0, 1, 8, 3, 7, 1, 8, 3, 6, 7, 14, 2, 14, 14, 9, 0, 13, 9, 15, 5, 12, 7, 13, 7, 15, 6, 7, 9, 0, 5, 7, 6, 8, 8, 3, 7, 0, 10, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3}
initialMul := uint8(0)
// Precompute lookup table of odd multiples of x for window
// size k=5.
var xx common.Fp
mulP(&xx, x, x)
lookup[0] = *x
for i := 1; i < 16; i++ {
mulP(&lookup[i], &lookup[i-1], &xx)
}
// Now lookup = {x, x^3, x^5, ... }
// so that lookup[i] = x^{2*i + 1}
// so that lookup[k/2] = x^k, for odd k
*dest = lookup[initialMul]
for i := uint8(0); i < uint8(len(powStrategy)); i++ {
mulP(dest, dest, dest)
for j := uint8(1); j < powStrategy[i]; j++ {
mulP(dest, dest, dest)
}
mulP(dest, dest, &lookup[mulStrategy[i]])
}
}
func add(dest, lhs, rhs *common.Fp2) {
addP503(&dest.A, &lhs.A, &rhs.A)
addP503(&dest.B, &lhs.B, &rhs.B)
}
func sub(dest, lhs, rhs *common.Fp2) {
subP503(&dest.A, &lhs.A, &rhs.A)
subP503(&dest.B, &lhs.B, &rhs.B)
}
func mul(dest, lhs, rhs *common.Fp2) {
var bMinA, cMinD common.Fp
var ac, bd common.FpX2
var adPlusBc common.FpX2
var acMinBd common.FpX2
// Let (a,b,c,d) = (lhs.a,lhs.b,rhs.a,rhs.b).
//
// (a + bi)*(c + di) = (a*c - b*d) + (a*d + b*c)i
//
// Use Karatsuba's trick: note that
//
// (b - a)*(c - d) = (b*c + a*d) - a*c - b*d
//
// so (a*d + b*c) = (b-a)*(c-d) + a*c + b*d.
mulP503(&ac, &lhs.A, &rhs.A) // = a*c*R*R
mulP503(&bd, &lhs.B, &rhs.B) // = b*d*R*R
subP503(&bMinA, &lhs.B, &lhs.A) // = (b-a)*R
subP503(&cMinD, &rhs.A, &rhs.B) // = (c-d)*R
mulP503(&adPlusBc, &bMinA, &cMinD) // = (b-a)*(c-d)*R*R
adlP503(&adPlusBc, &adPlusBc, &ac) // = ((b-a)*(c-d) + a*c)*R*R
adlP503(&adPlusBc, &adPlusBc, &bd) // = ((b-a)*(c-d) + a*c + b*d)*R*R
rdcP503(&dest.B, &adPlusBc) // = (a*d + b*c)*R mod p
sulP503(&acMinBd, &ac, &bd) // = (a*c - b*d)*R*R
rdcP503(&dest.A, &acMinBd) // = (a*c - b*d)*R mod p
}
// Set dest = 1/x
//
// Allowed to overlap dest with x.
//
// Returns dest to allow chaining operations.
func inv(dest, x *common.Fp2) {
var e1, e2 common.FpX2
var f1, f2 common.Fp
// We want to compute
//
// 1 1 (a - bi) (a - bi)
// -------- = -------- -------- = -----------
// (a + bi) (a + bi) (a - bi) (a^2 + b^2)
//
// Letting c = 1/(a^2 + b^2), this is
//
// 1/(a+bi) = a*c - b*ci.
mulP503(&e1, &x.A, &x.A) // = a*a*R*R
mulP503(&e2, &x.B, &x.B) // = b*b*R*R
adlP503(&e1, &e1, &e2) // = (a^2 + b^2)*R*R
rdcP503(&f1, &e1) // = (a^2 + b^2)*R mod p
// Now f1 = a^2 + b^2
mulP(&f2, &f1, &f1)
p34(&f2, &f2)
mulP(&f2, &f2, &f2)
mulP(&f2, &f2, &f1)
mulP503(&e1, &x.A, &f2)
rdcP503(&dest.A, &e1)
subP503(&f1, &common.Fp{}, &x.B)
mulP503(&e1, &f1, &f2)
rdcP503(&dest.B, &e1)
}
func sqr(dest, x *common.Fp2) {
var a2, aPlusB, aMinusB common.Fp
var a2MinB2, ab2 common.FpX2
a := &x.A
b := &x.B
// (a + bi)*(a + bi) = (a^2 - b^2) + 2abi.
addP503(&a2, a, a) // = a*R + a*R = 2*a*R
addP503(&aPlusB, a, b) // = a*R + b*R = (a+b)*R
subP503(&aMinusB, a, b) // = a*R - b*R = (a-b)*R
mulP503(&a2MinB2, &aPlusB, &aMinusB) // = (a+b)*(a-b)*R*R = (a^2 - b^2)*R*R
mulP503(&ab2, &a2, b) // = 2*a*b*R*R
rdcP503(&dest.A, &a2MinB2) // = (a^2 - b^2)*R mod p
rdcP503(&dest.B, &ab2) // = 2*a*b*R mod p
}
// In case choice == 1, performs following swap in constant time:
// xPx <-> xQx
// xPz <-> xQz
// Otherwise returns xPx, xPz, xQx, xQz unchanged
func cswap(xPx, xPz, xQx, xQz *common.Fp2, choice uint8) {
cswapP503(&xPx.A, &xQx.A, choice)
cswapP503(&xPx.B, &xQx.B, choice)
cswapP503(&xPz.A, &xQz.A, choice)
cswapP503(&xPz.B, &xQz.B, choice)
}
// Converts in.A and in.B to Montgomery domain and stores
// in 'out'
// out.A = in.A * R mod p
// out.B = in.B * R mod p
// Performs v = v*R^2*R^(-1) mod p, for both in.A and in.B
func ToMontgomery(out, in *common.Fp2) {
var aRR common.FpX2
// a*R*R
mulP503(&aRR, &in.A, &P503R2)
// a*R mod p
rdcP503(&out.A, &aRR)
mulP503(&aRR, &in.B, &P503R2)
rdcP503(&out.B, &aRR)
}
// Converts in.A and in.B from Montgomery domain and stores
// in 'out'
// out.A = in.A mod p
// out.B = in.B mod p
//
// After returning from the call 'in' is not modified.
func FromMontgomery(out, in *common.Fp2) {
var aR common.FpX2
// convert from montgomery domain
copy(aR[:], in.A[:])
rdcP503(&out.A, &aR) // = a mod p in [0, 2p)
modP503(&out.A) // = a mod p in [0, p)
for i := range aR {
aR[i] = 0
}
copy(aR[:], in.B[:])
rdcP503(&out.B, &aR)
modP503(&out.B)
}

View File

@ -0,0 +1,191 @@
package p503
//go:generate go run ../templates/gen.go P503
import (
"github.com/cloudflare/circl/dh/sidh/internal/common"
"golang.org/x/sys/cpu"
)
const (
// Number of uint64 limbs used to store field element
FpWords = 8
)
// P503 is a prime used by field Fp503
var (
// According to https://github.com/golang/go/issues/28230,
// variables referred from the assembly must be in the same package.
// HasBMI2 signals support for MULX which is in BMI2
HasBMI2 = cpu.X86.HasBMI2
// HasADXandBMI2 signals support for ADX and BMI2
HasADXandBMI2 = cpu.X86.HasBMI2 && cpu.X86.HasADX
// P503 is a prime used by field Fp503
P503 = common.Fp{
0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xABFFFFFFFFFFFFFF,
0x13085BDA2211E7A0, 0x1B9BF6C87B7E7DAF, 0x6045C6BDDA77A4D0, 0x004066F541811E1E,
}
// P503x2 = 2*p503 - 1
P503x2 = common.Fp{
0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x57FFFFFFFFFFFFFF,
0x2610B7B44423CF41, 0x3737ED90F6FCFB5E, 0xC08B8D7BB4EF49A0, 0x0080CDEA83023C3C,
}
// P503p1 = p503 + 1
P503p1 = common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0xAC00000000000000,
0x13085BDA2211E7A0, 0x1B9BF6C87B7E7DAF, 0x6045C6BDDA77A4D0, 0x004066F541811E1E,
}
// P503R2 = (2^512)^2 mod p
P503R2 = common.Fp{
0x5289A0CF641D011F, 0x9B88257189FED2B9, 0xA3B365D58DC8F17A, 0x5BC57AB6EFF168EC,
0x9E51998BD84D4423, 0xBF8999CBAC3B5695, 0x46E9127BCE14CDB6, 0x003F6CFCE8B81771,
}
// P503p1s8 = p503 + 1 left-shifted by 8, assuming little endianness
P503p1s8 = common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x085BDA2211E7A0AC, 0x9BF6C87B7E7DAF13, 0x45C6BDDA77A4D01B, 0x4066F541811E1E60,
}
// P503p1Zeros number of 0 digits in the least significant part of P503+1
P503p1Zeros = 3
params common.SidhParams
)
func init() {
params = common.SidhParams{
ID: common.Fp503,
// SIDH public key byte size.
PublicKeySize: 378,
// SIDH shared secret byte size.
SharedSecretSize: 126,
A: common.DomainParams{
// The x-coordinate of PA
AffineP: common.Fp2{
A: common.Fp{
0xE7EF4AA786D855AF, 0xED5758F03EB34D3B, 0x09AE172535A86AA9, 0x237B9CC07D622723,
0xE3A284CBA4E7932D, 0x27481D9176C5E63F, 0x6A323FF55C6E71BF, 0x002ECC31A6FB8773,
},
B: common.Fp{
0x64D02E4E90A620B8, 0xDAB8128537D4B9F1, 0x4BADF77B8A228F98, 0x0F5DBDF9D1FB7D1B,
0xBEC4DB288E1A0DCC, 0xE76A8665E80675DB, 0x6D6F252E12929463, 0x003188BD1463FACC,
},
},
// The x-coordinate of QA
AffineQ: common.Fp2{
A: common.Fp{
0xB79D41025DE85D56, 0x0B867DA9DF169686, 0x740E5368021C827D, 0x20615D72157BF25C,
0xFF1590013C9B9F5B, 0xC884DCADE8C16CEA, 0xEBD05E53BF724E01, 0x0032FEF8FDA5748C,
},
B: common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
},
},
// The x-coordinate of RA = PA-QA
AffineR: common.Fp2{
A: common.Fp{
0x12E2E849AA0A8006, 0x41CF47008635A1E8, 0x9CD720A70798AED7, 0x42A820B42FCF04CF,
0x7BF9BAD32AAE88B1, 0xF619127A54090BBE, 0x1CB10D8F56408EAA, 0x001D6B54C3C0EDEB,
},
B: common.Fp{
0x34DB54931CBAAC36, 0x420A18CB8DD5F0C4, 0x32008C1A48C0F44D, 0x3B3BA772B1CFD44D,
0xA74B058FDAF13515, 0x095FC9CA7EEC17B4, 0x448E829D28F120F8, 0x00261EC3ED16A489,
},
},
// Max size of secret key for 2-torsion group, corresponds to 2^e2 - 1
SecretBitLen: 250,
// SecretBitLen in bytes.
SecretByteLen: uint((250 + 7) / 8),
// 2-torsion group computation strategy
IsogenyStrategy: []uint32{
0x3D, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01,
0x01, 0x02, 0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01,
0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x1D, 0x10, 0x08, 0x04, 0x02, 0x01,
0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x0D, 0x08,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x05, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01},
},
B: common.DomainParams{
// The x-coordinate of PB
AffineP: common.Fp2{
A: common.Fp{
0x7EDE37F4FA0BC727, 0xF7F8EC5C8598941C, 0xD15519B516B5F5C8, 0xF6D5AC9B87A36282,
0x7B19F105B30E952E, 0x13BD8B2025B4EBEE, 0x7B96D27F4EC579A2, 0x00140850CAB7E5DE,
},
B: common.Fp{
0x7764909DAE7B7B2D, 0x578ABB16284911AB, 0x76E2BFD146A6BF4D, 0x4824044B23AA02F0,
0x1105048912A321F3, 0xB8A2E482CF0F10C1, 0x42FF7D0BE2152085, 0x0018E599C5223352,
},
},
// The x-coordinate of QB
AffineQ: common.Fp2{
A: common.Fp{
0x4256C520FB388820, 0x744FD7C3BAAF0A13, 0x4B6A2DDDB12CBCB8, 0xE46826E27F427DF8,
0xFE4A663CD505A61B, 0xD6B3A1BAF025C695, 0x7C3BB62B8FCC00BD, 0x003AFDDE4A35746C,
},
B: common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
},
},
// The x-coordinate of RB = PB - QB
AffineR: common.Fp2{
A: common.Fp{
0x75601CD1E6C0DFCB, 0x1A9007239B58F93E, 0xC1F1BE80C62107AC, 0x7F513B898F29FF08,
0xEA0BEDFF43E1F7B2, 0x2C6D94018CBAE6D0, 0x3A430D31BCD84672, 0x000D26892ECCFE83,
},
B: common.Fp{
0x1119D62AEA3007A1, 0xE3702AA4E04BAE1B, 0x9AB96F7D59F990E7, 0xF58440E8B43319C0,
0xAF8134BEE1489775, 0xE7F7774E905192AA, 0xF54AE09308E98039, 0x001EF7A041A86112,
},
},
// Size of secret key for 3-torsion group, corresponds to log_2(3^e3) - 1.
SecretBitLen: 252,
// SecretBitLen in bytes.
SecretByteLen: uint((252 + 7) / 8),
// 3-torsion group computation strategy
IsogenyStrategy: []uint32{
0x47, 0x26, 0x15, 0x0D, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x05, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02,
0x01, 0x01, 0x01, 0x09, 0x05, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
0x01, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x11, 0x09, 0x05, 0x03, 0x02,
0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02,
0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01,
0x01, 0x02, 0x01, 0x01, 0x21, 0x11, 0x09, 0x05, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x04,
0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01,
0x02, 0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01,
0x01, 0x02, 0x01, 0x01},
},
// 1*R mod p
OneFp2: common.Fp2{
A: common.Fp{
0x00000000000003F9, 0x0000000000000000, 0x0000000000000000, 0xB400000000000000,
0x63CB1A6EA6DED2B4, 0x51689D8D667EB37D, 0x8ACD77C71AB24142, 0x0026FBAEC60F5953},
},
// 1/2 * R mod p
HalfFp2: common.Fp2{
A: common.Fp{
0x00000000000001FC, 0x0000000000000000, 0x0000000000000000, 0xB000000000000000,
0x3B69BB2464785D2A, 0x36824A2AF0FE9896, 0xF5899F427A94F309, 0x0033B15203C83BB8},
},
MsgLen: 24,
// SIKEp503 provides 128 bit of classical security ([SIKE], 5.1)
KemSize: 16,
// ceil(503+7/8)
Bytelen: 63,
CiphertextSize: 16 + 8 + 378,
}
common.Register(common.Fp503, &params)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
// +build amd64,!noasm arm64,!noasm
package p751
import (
. "github.com/cloudflare/circl/dh/sidh/internal/common"
)
// If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x.
// If choice is neither 0 nor 1 then behaviour is undefined.
// This function executes in constant time.
//go:noescape
func cswapP751(x, y *Fp, choice uint8)
// Compute z = x + y (mod p).
//go:noescape
func addP751(z, x, y *Fp)
// Compute z = x - y (mod p).
//go:noescape
func subP751(z, x, y *Fp)
// Compute z = x + y, without reducing mod p.
//go:noescape
func adlP751(z, x, y *FpX2)
// Compute z = x - y, without reducing mod p.
//go:noescape
func sulP751(z, x, y *FpX2)
// Reduce a field element in [0, 2*p) to one in [0,p).
//go:noescape
func modP751(x *Fp)
// Computes z = x * y.
//go:noescape
func mulP751(z *FpX2, x, y *Fp)
// Computes the Montgomery reduction z = x R^{-1} (mod 2*p). On return value
// of x may be changed. z=x not allowed.
//go:noescape
func rdcP751(z *Fp, x *FpX2)

View File

@ -0,0 +1,192 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
// +build noasm !amd64,!arm64
package p751
import (
"math/bits"
"github.com/cloudflare/circl/dh/sidh/internal/common"
)
// Compute z = x + y (mod p).
func addP751(z, x, y *common.Fp) {
var carry uint64
// z=x+y % P751
for i := 0; i < FpWords; i++ {
z[i], carry = bits.Add64(x[i], y[i], carry)
}
// z = z - P751x2
carry = 0
for i := 0; i < FpWords; i++ {
z[i], carry = bits.Sub64(z[i], P751x2[i], carry)
}
// if z<0 add P751x2 back
mask := uint64(0 - carry)
carry = 0
for i := 0; i < FpWords; i++ {
z[i], carry = bits.Add64(z[i], P751x2[i]&mask, carry)
}
}
// Compute z = x - y (mod p).
func subP751(z, x, y *common.Fp) {
var borrow uint64
for i := 0; i < FpWords; i++ {
z[i], borrow = bits.Sub64(x[i], y[i], borrow)
}
mask := uint64(0 - borrow)
borrow = 0
for i := 0; i < FpWords; i++ {
z[i], borrow = bits.Add64(z[i], P751x2[i]&mask, borrow)
}
}
// Conditionally swaps bits in x and y in constant time.
// mask indicates bits to be swapped (set bits are swapped)
// For details see "Hackers Delight, 2.20"
//
// Implementation doesn't actually depend on a prime field.
func cswapP751(x, y *common.Fp, mask uint8) {
var tmp, mask64 uint64
mask64 = 0 - uint64(mask)
for i := 0; i < FpWords; i++ {
tmp = mask64 & (x[i] ^ y[i])
x[i] = tmp ^ x[i]
y[i] = tmp ^ y[i]
}
}
// Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
// with R=2^(FpWords*64). Destroys the input value.
func rdcP751(z *common.Fp, x *common.FpX2) {
var carry, t, u, v uint64
var hi, lo uint64
var count int
count = P751p1Zeros
for i := 0; i < FpWords; i++ {
for j := 0; j < i; j++ {
if j < (i - count + 1) {
hi, lo = bits.Mul64(z[j], P751p1[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
}
v, carry = bits.Add64(v, x[i], 0)
u, carry = bits.Add64(u, 0, carry)
t += carry
z[i] = v
v = u
u = t
t = 0
}
for i := FpWords; i < 2*FpWords-1; i++ {
if count > 0 {
count--
}
for j := i - FpWords + 1; j < FpWords; j++ {
if j < (FpWords - count) {
hi, lo = bits.Mul64(z[j], P751p1[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
}
v, carry = bits.Add64(v, x[i], 0)
u, carry = bits.Add64(u, 0, carry)
t += carry
z[i-FpWords] = v
v = u
u = t
t = 0
}
v, carry = bits.Add64(v, x[2*FpWords-1], 0)
z[FpWords-1] = v
}
// Compute z = x * y.
func mulP751(z *common.FpX2, x, y *common.Fp) {
var u, v, t uint64
var hi, lo uint64
var carry uint64
for i := uint64(0); i < FpWords; i++ {
for j := uint64(0); j <= i; j++ {
hi, lo = bits.Mul64(x[j], y[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
z[i] = v
v = u
u = t
t = 0
}
for i := FpWords; i < (2*FpWords)-1; i++ {
for j := i - FpWords + 1; j < FpWords; j++ {
hi, lo = bits.Mul64(x[j], y[i-j])
v, carry = bits.Add64(lo, v, 0)
u, carry = bits.Add64(hi, u, carry)
t += carry
}
z[i] = v
v = u
u = t
t = 0
}
z[2*FpWords-1] = v
}
// Compute z = x + y, without reducing mod p.
func adlP751(z, x, y *common.FpX2) {
var carry uint64
for i := 0; i < 2*FpWords; i++ {
z[i], carry = bits.Add64(x[i], y[i], carry)
}
}
// Reduce a field element in [0, 2*p) to one in [0,p).
func modP751(x *common.Fp) {
var borrow, mask uint64
for i := 0; i < FpWords; i++ {
x[i], borrow = bits.Sub64(x[i], P751[i], borrow)
}
// Sets all bits if borrow = 1
mask = 0 - borrow
borrow = 0
for i := 0; i < FpWords; i++ {
x[i], borrow = bits.Add64(x[i], P751[i]&mask, borrow)
}
}
// Compute z = x - y, without reducing mod p.
func sulP751(z, x, y *common.FpX2) {
var borrow, mask uint64
for i := 0; i < 2*FpWords; i++ {
z[i], borrow = bits.Sub64(x[i], y[i], borrow)
}
// Sets all bits if borrow = 1
mask = 0 - borrow
borrow = 0
for i := FpWords; i < 2*FpWords; i++ {
z[i], borrow = bits.Add64(z[i], P751[i-FpWords]&mask, borrow)
}
}

View File

@ -0,0 +1,294 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
package p751
import (
. "github.com/cloudflare/circl/dh/sidh/internal/common"
)
// -----------------------------------------------------------------------------
// Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
//
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreePublicKeyA(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny4
cparam := CalcCurveParamsEquiv4(curve)
strat := params.A.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow2k(xR, &cparam, 2*k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
*phiP = phi.EvaluatePoint(phiP)
*phiQ = phi.EvaluatePoint(phiQ)
*phiR = phi.EvaluatePoint(phiR)
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR needed
// for public key generation.
func traverseTreeSharedKeyA(curve *ProjectiveCurveParameters, xR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny4
cparam := CalcCurveParamsEquiv4(curve)
strat := params.A.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow2k(xR, &cparam, 2*k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreePublicKeyB(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny3
cparam := CalcCurveParamsEquiv3(curve)
strat := params.B.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow3k(xR, &cparam, k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
*phiP = phi.EvaluatePoint(phiP)
*phiQ = phi.EvaluatePoint(phiQ)
*phiR = phi.EvaluatePoint(phiR)
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
// for public key generation.
func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoint) {
var points = make([]ProjectivePoint, 0, 8)
var indices = make([]int, 0, 8)
var i, sIdx int
var phi isogeny3
cparam := CalcCurveParamsEquiv3(curve)
strat := params.B.IsogenyStrategy
stratSz := len(strat)
for j := 1; j <= stratSz; j++ {
for i <= stratSz-j {
points = append(points, *xR)
indices = append(indices, i)
k := strat[sIdx]
sIdx++
Pow3k(xR, &cparam, k)
i += int(k)
}
cparam = phi.GenerateCurve(xR)
for k := 0; k < len(points); k++ {
points[k] = phi.EvaluatePoint(&points[k])
}
// pop xR from points
*xR, points = points[len(points)-1], points[:len(points)-1]
i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
}
}
// Generate a public key in the 2-torsion group. Public key is a set
// of three x-coordinates: xP,xQ,x(P-Q), where P,Q are points on E_a(Fp2)
func PublicKeyGenA(pub3Pt *[3]Fp2, prvBytes []byte) {
var xPA, xQA, xRA ProjectivePoint
var xPB, xQB, xRB, xR ProjectivePoint
var invZP, invZQ, invZR Fp2
var tmp ProjectiveCurveParameters
var phi isogeny4
// Load points for A
xPA = ProjectivePoint{X: params.A.AffineP, Z: params.OneFp2}
xQA = ProjectivePoint{X: params.A.AffineQ, Z: params.OneFp2}
xRA = ProjectivePoint{X: params.A.AffineR, Z: params.OneFp2}
// Load points for B
xRB = ProjectivePoint{X: params.B.AffineR, Z: params.OneFp2}
xQB = ProjectivePoint{X: params.B.AffineQ, Z: params.OneFp2}
xPB = ProjectivePoint{X: params.B.AffineP, Z: params.OneFp2}
// Find isogeny kernel
tmp.C = params.OneFp2
xR = ScalarMul3Pt(&tmp, &xPA, &xQA, &xRA, params.A.SecretBitLen, prvBytes)
// Reset params object and travers isogeny tree
tmp.C = params.OneFp2
tmp.A = Fp2{}
traverseTreePublicKeyA(&tmp, &xR, &xPB, &xQB, &xRB)
// Secret isogeny
phi.GenerateCurve(&xR)
xPA = phi.EvaluatePoint(&xPB)
xQA = phi.EvaluatePoint(&xQB)
xRA = phi.EvaluatePoint(&xRB)
Fp2Batch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
mul(&pub3Pt[0], &xPA.X, &invZP)
mul(&pub3Pt[1], &xQA.X, &invZQ)
mul(&pub3Pt[2], &xRA.X, &invZR)
}
// Generate a public key in the 2-torsion group. Public key is a set
// of three x-coordinates: xP,xQ,x(P-Q), where P,Q are points on E_a(Fp2)
func PublicKeyGenB(pub3Pt *[3]Fp2, prvBytes []byte) {
var xPB, xQB, xRB, xR ProjectivePoint
var xPA, xQA, xRA ProjectivePoint
var invZP, invZQ, invZR Fp2
var tmp ProjectiveCurveParameters
var phi isogeny3
// Load points for B
xRB = ProjectivePoint{X: params.B.AffineR, Z: params.OneFp2}
xQB = ProjectivePoint{X: params.B.AffineQ, Z: params.OneFp2}
xPB = ProjectivePoint{X: params.B.AffineP, Z: params.OneFp2}
// Load points for A
xPA = ProjectivePoint{X: params.A.AffineP, Z: params.OneFp2}
xQA = ProjectivePoint{X: params.A.AffineQ, Z: params.OneFp2}
xRA = ProjectivePoint{X: params.A.AffineR, Z: params.OneFp2}
tmp.C = params.OneFp2
xR = ScalarMul3Pt(&tmp, &xPB, &xQB, &xRB, params.B.SecretBitLen, prvBytes)
tmp.C = params.OneFp2
tmp.A = Fp2{}
traverseTreePublicKeyB(&tmp, &xR, &xPA, &xQA, &xRA)
phi.GenerateCurve(&xR)
xPB = phi.EvaluatePoint(&xPA)
xQB = phi.EvaluatePoint(&xQA)
xRB = phi.EvaluatePoint(&xRA)
Fp2Batch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
mul(&pub3Pt[0], &xPB.X, &invZP)
mul(&pub3Pt[1], &xQB.X, &invZQ)
mul(&pub3Pt[2], &xRB.X, &invZR)
}
// -----------------------------------------------------------------------------
// Key agreement functions
//
// Establishing shared keys in in 2-torsion group
func DeriveSecretA(ss, prv []byte, pub3Pt *[3]Fp2) {
var cparam ProjectiveCurveParameters
var xP, xQ, xQmP ProjectivePoint
var xR ProjectivePoint
var phi isogeny4
var jInv Fp2
// Recover curve coefficients
cparam.C = params.OneFp2
RecoverCoordinateA(&cparam, &pub3Pt[0], &pub3Pt[1], &pub3Pt[2])
// Find kernel of the morphism
xP = ProjectivePoint{X: pub3Pt[0], Z: params.OneFp2}
xQ = ProjectivePoint{X: pub3Pt[1], Z: params.OneFp2}
xQmP = ProjectivePoint{X: pub3Pt[2], Z: params.OneFp2}
xR = ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, params.A.SecretBitLen, prv)
// Traverse isogeny tree
traverseTreeSharedKeyA(&cparam, &xR)
// Calculate j-invariant on isogeneus curve
c := phi.GenerateCurve(&xR)
RecoverCurveCoefficients4(&cparam, &c)
Jinvariant(&cparam, &jInv)
FromMontgomery(&jInv, &jInv)
Fp2ToBytes(ss, &jInv, params.Bytelen)
}
// Establishing shared keys in in 3-torsion group
func DeriveSecretB(ss, prv []byte, pub3Pt *[3]Fp2) {
var xP, xQ, xQmP ProjectivePoint
var xR ProjectivePoint
var cparam ProjectiveCurveParameters
var phi isogeny3
var jInv Fp2
// Recover curve coefficients
cparam.C = params.OneFp2
RecoverCoordinateA(&cparam, &pub3Pt[0], &pub3Pt[1], &pub3Pt[2])
// Find kernel of the morphism
xP = ProjectivePoint{X: pub3Pt[0], Z: params.OneFp2}
xQ = ProjectivePoint{X: pub3Pt[1], Z: params.OneFp2}
xQmP = ProjectivePoint{X: pub3Pt[2], Z: params.OneFp2}
xR = ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, params.B.SecretBitLen, prv)
// Traverse isogeny tree
traverseTreeSharedKeyB(&cparam, &xR)
// Calculate j-invariant on isogeneus curve
c := phi.GenerateCurve(&xR)
RecoverCurveCoefficients3(&cparam, &c)
Jinvariant(&cparam, &jInv)
FromMontgomery(&jInv, &jInv)
Fp2ToBytes(ss, &jInv, params.Bytelen)
}

View File

@ -0,0 +1,362 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
package p751
import (
. "github.com/cloudflare/circl/dh/sidh/internal/common"
)
// Stores isogeny 3 curve constants
type isogeny3 struct {
K1 Fp2
K2 Fp2
}
// Stores isogeny 4 curve constants
type isogeny4 struct {
isogeny3
K3 Fp2
}
// Computes j-invariant for a curve y2=x3+A/Cx+x with A,C in F_(p^2). Result
// is returned in jBytes buffer, encoded in little-endian format. Caller
// provided jBytes buffer has to be big enough to j-invariant value. In case
// of SIDH, buffer size must be at least size of shared secret.
// Implementation corresponds to Algorithm 9 from SIKE.
func Jinvariant(cparams *ProjectiveCurveParameters, j *Fp2) {
var t0, t1 Fp2
sqr(j, &cparams.A) // j = A^2
sqr(&t1, &cparams.C) // t1 = C^2
add(&t0, &t1, &t1) // t0 = t1 + t1
sub(&t0, j, &t0) // t0 = j - t0
sub(&t0, &t0, &t1) // t0 = t0 - t1
sub(j, &t0, &t1) // t0 = t0 - t1
sqr(&t1, &t1) // t1 = t1^2
mul(j, j, &t1) // j = j * t1
add(&t0, &t0, &t0) // t0 = t0 + t0
add(&t0, &t0, &t0) // t0 = t0 + t0
sqr(&t1, &t0) // t1 = t0^2
mul(&t0, &t0, &t1) // t0 = t0 * t1
add(&t0, &t0, &t0) // t0 = t0 + t0
add(&t0, &t0, &t0) // t0 = t0 + t0
inv(j, j) // j = 1/j
mul(j, &t0, j) // j = t0 * j
}
// Given affine points x(P), x(Q) and x(Q-P) in a extension field F_{p^2}, function
// recorvers projective coordinate A of a curve. This is Algorithm 10 from SIKE.
func RecoverCoordinateA(curve *ProjectiveCurveParameters, xp, xq, xr *Fp2) {
var t0, t1 Fp2
add(&t1, xp, xq) // t1 = Xp + Xq
mul(&t0, xp, xq) // t0 = Xp * Xq
mul(&curve.A, xr, &t1) // A = X(q-p) * t1
add(&curve.A, &curve.A, &t0) // A = A + t0
mul(&t0, &t0, xr) // t0 = t0 * X(q-p)
sub(&curve.A, &curve.A, &params.OneFp2) // A = A - 1
add(&t0, &t0, &t0) // t0 = t0 + t0
add(&t1, &t1, xr) // t1 = t1 + X(q-p)
add(&t0, &t0, &t0) // t0 = t0 + t0
sqr(&curve.A, &curve.A) // A = A^2
inv(&t0, &t0) // t0 = 1/t0
mul(&curve.A, &curve.A, &t0) // A = A * t0
sub(&curve.A, &curve.A, &t1) // A = A - t1
}
// Computes equivalence (A:C) ~ (A+2C : A-2C)
func CalcCurveParamsEquiv3(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv {
var coef CurveCoefficientsEquiv
var c2 Fp2
add(&c2, &cparams.C, &cparams.C)
// A24p = A+2*C
add(&coef.A, &cparams.A, &c2)
// A24m = A-2*C
sub(&coef.C, &cparams.A, &c2)
return coef
}
// Computes equivalence (A:C) ~ (A+2C : 4C)
func CalcCurveParamsEquiv4(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv {
var coefEq CurveCoefficientsEquiv
add(&coefEq.C, &cparams.C, &cparams.C)
// A24p = A+2C
add(&coefEq.A, &cparams.A, &coefEq.C)
// C24 = 4*C
add(&coefEq.C, &coefEq.C, &coefEq.C)
return coefEq
}
// Helper function for RightToLeftLadder(). Returns A+2C / 4.
func CalcAplus2Over4(cparams *ProjectiveCurveParameters) (ret Fp2) {
var tmp Fp2
// 2C
add(&tmp, &cparams.C, &cparams.C)
// A+2C
add(&ret, &cparams.A, &tmp)
// 1/4C
add(&tmp, &tmp, &tmp)
inv(&tmp, &tmp)
// A+2C/4C
mul(&ret, &ret, &tmp)
return
}
// Recovers (A:C) curve parameters from projectively equivalent (A+2C:A-2C).
func RecoverCurveCoefficients3(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) {
add(&cparams.A, &coefEq.A, &coefEq.C)
// cparams.A = 2*(A+2C+A-2C) = 4A
add(&cparams.A, &cparams.A, &cparams.A)
// cparams.C = (A+2C-A+2C) = 4C
sub(&cparams.C, &coefEq.A, &coefEq.C)
return
}
// Recovers (A:C) curve parameters from projectively equivalent (A+2C:4C).
func RecoverCurveCoefficients4(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) {
// cparams.C = (4C)*1/2=2C
mul(&cparams.C, &coefEq.C, &params.HalfFp2)
// cparams.A = A+2C - 2C = A
sub(&cparams.A, &coefEq.A, &cparams.C)
// cparams.C = 2C * 1/2 = C
mul(&cparams.C, &cparams.C, &params.HalfFp2)
}
// Combined coordinate doubling and differential addition. Takes projective points
// P,Q,Q-P and (A+2C)/4C curve E coefficient. Returns 2*P and P+Q calculated on E.
// Function is used only by RightToLeftLadder. Corresponds to Algorithm 5 of SIKE
func xDbladd(P, Q, QmP *ProjectivePoint, a24 *Fp2) (dblP, PaQ ProjectivePoint) {
var t0, t1, t2 Fp2
xQmP, zQmP := &QmP.X, &QmP.Z
xPaQ, zPaQ := &PaQ.X, &PaQ.Z
x2P, z2P := &dblP.X, &dblP.Z
xP, zP := &P.X, &P.Z
xQ, zQ := &Q.X, &Q.Z
add(&t0, xP, zP) // t0 = Xp+Zp
sub(&t1, xP, zP) // t1 = Xp-Zp
sqr(x2P, &t0) // 2P.X = t0^2
sub(&t2, xQ, zQ) // t2 = Xq-Zq
add(xPaQ, xQ, zQ) // Xp+q = Xq+Zq
mul(&t0, &t0, &t2) // t0 = t0 * t2
mul(z2P, &t1, &t1) // 2P.Z = t1 * t1
mul(&t1, &t1, xPaQ) // t1 = t1 * Xp+q
sub(&t2, x2P, z2P) // t2 = 2P.X - 2P.Z
mul(x2P, x2P, z2P) // 2P.X = 2P.X * 2P.Z
mul(xPaQ, a24, &t2) // Xp+q = A24 * t2
sub(zPaQ, &t0, &t1) // Zp+q = t0 - t1
add(z2P, xPaQ, z2P) // 2P.Z = Xp+q + 2P.Z
add(xPaQ, &t0, &t1) // Xp+q = t0 + t1
mul(z2P, z2P, &t2) // 2P.Z = 2P.Z * t2
sqr(zPaQ, zPaQ) // Zp+q = Zp+q ^ 2
sqr(xPaQ, xPaQ) // Xp+q = Xp+q ^ 2
mul(zPaQ, xQmP, zPaQ) // Zp+q = Xq-p * Zp+q
mul(xPaQ, zQmP, xPaQ) // Xp+q = Zq-p * Xp+q
return
}
// Given the curve parameters, xP = x(P), computes xP = x([2^k]P)
// Safe to overlap xP, x2P.
func Pow2k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) {
var t0, t1 Fp2
x, z := &xP.X, &xP.Z
for i := uint32(0); i < k; i++ {
sub(&t0, x, z) // t0 = Xp - Zp
add(&t1, x, z) // t1 = Xp + Zp
sqr(&t0, &t0) // t0 = t0 ^ 2
sqr(&t1, &t1) // t1 = t1 ^ 2
mul(z, &params.C, &t0) // Z2p = C24 * t0
mul(x, z, &t1) // X2p = Z2p * t1
sub(&t1, &t1, &t0) // t1 = t1 - t0
mul(&t0, &params.A, &t1) // t0 = A24+ * t1
add(z, z, &t0) // Z2p = Z2p + t0
mul(z, z, &t1) // Zp = Z2p * t1
}
}
// Given the curve parameters, xP = x(P), and k >= 0, compute xP = x([3^k]P).
//
// Safe to overlap xP, xR.
func Pow3k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) {
var t0, t1, t2, t3, t4, t5, t6 Fp2
x, z := &xP.X, &xP.Z
for i := uint32(0); i < k; i++ {
sub(&t0, x, z) // t0 = Xp - Zp
sqr(&t2, &t0) // t2 = t0^2
add(&t1, x, z) // t1 = Xp + Zp
sqr(&t3, &t1) // t3 = t1^2
add(&t4, &t1, &t0) // t4 = t1 + t0
sub(&t0, &t1, &t0) // t0 = t1 - t0
sqr(&t1, &t4) // t1 = t4^2
sub(&t1, &t1, &t3) // t1 = t1 - t3
sub(&t1, &t1, &t2) // t1 = t1 - t2
mul(&t5, &t3, &params.A) // t5 = t3 * A24+
mul(&t3, &t3, &t5) // t3 = t5 * t3
mul(&t6, &t2, &params.C) // t6 = t2 * A24-
mul(&t2, &t2, &t6) // t2 = t2 * t6
sub(&t3, &t2, &t3) // t3 = t2 - t3
sub(&t2, &t5, &t6) // t2 = t5 - t6
mul(&t1, &t2, &t1) // t1 = t2 * t1
add(&t2, &t3, &t1) // t2 = t3 + t1
sqr(&t2, &t2) // t2 = t2^2
mul(x, &t2, &t4) // X3p = t2 * t4
sub(&t1, &t3, &t1) // t1 = t3 - t1
sqr(&t1, &t1) // t1 = t1^2
mul(z, &t1, &t0) // Z3p = t1 * t0
}
}
// Set (y1, y2, y3) = (1/x1, 1/x2, 1/x3).
//
// All xi, yi must be distinct.
func Fp2Batch3Inv(x1, x2, x3, y1, y2, y3 *Fp2) {
var x1x2, t Fp2
mul(&x1x2, x1, x2) // x1*x2
mul(&t, &x1x2, x3) // 1/(x1*x2*x3)
inv(&t, &t)
mul(y1, &t, x2) // 1/x1
mul(y1, y1, x3)
mul(y2, &t, x1) // 1/x2
mul(y2, y2, x3)
mul(y3, &t, &x1x2) // 1/x3
}
// Scalarmul3Pt is a right-to-left point multiplication that given the
// x-coordinate of P, Q and P-Q calculates the x-coordinate of R=Q+[scalar]P.
// nbits must be smaller or equal to len(scalar).
func ScalarMul3Pt(cparams *ProjectiveCurveParameters, P, Q, PmQ *ProjectivePoint, nbits uint, scalar []uint8) ProjectivePoint {
var R0, R2, R1 ProjectivePoint
aPlus2Over4 := CalcAplus2Over4(cparams)
R1 = *P
R2 = *PmQ
R0 = *Q
// Iterate over the bits of the scalar, bottom to top
prevBit := uint8(0)
for i := uint(0); i < nbits; i++ {
bit := (scalar[i>>3] >> (i & 7) & 1)
swap := prevBit ^ bit
prevBit = bit
cswap(&R1.X, &R1.Z, &R2.X, &R2.Z, swap)
R0, R2 = xDbladd(&R0, &R2, &R1, &aPlus2Over4)
}
cswap(&R1.X, &R1.Z, &R2.X, &R2.Z, prevBit)
return R1
}
// Given a three-torsion point p = x(PB) on the curve E_(A:C), construct the
// three-isogeny phi : E_(A:C) -> E_(A:C)/<P_3> = E_(A':C').
//
// Input: (XP_3: ZP_3), where P_3 has exact order 3 on E_A/C
// Output: * Curve coordinates (A' + 2C', A' - 2C') corresponding to E_A'/C' = A_E/C/<P3>
// * Isogeny phi with constants in F_p^2
func (phi *isogeny3) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv {
var t0, t1, t2, t3, t4 Fp2
var coefEq CurveCoefficientsEquiv
var K1, K2 = &phi.K1, &phi.K2
sub(K1, &p.X, &p.Z) // K1 = XP3 - ZP3
sqr(&t0, K1) // t0 = K1^2
add(K2, &p.X, &p.Z) // K2 = XP3 + ZP3
sqr(&t1, K2) // t1 = K2^2
add(&t2, &t0, &t1) // t2 = t0 + t1
add(&t3, K1, K2) // t3 = K1 + K2
sqr(&t3, &t3) // t3 = t3^2
sub(&t3, &t3, &t2) // t3 = t3 - t2
add(&t2, &t1, &t3) // t2 = t1 + t3
add(&t3, &t3, &t0) // t3 = t3 + t0
add(&t4, &t3, &t0) // t4 = t3 + t0
add(&t4, &t4, &t4) // t4 = t4 + t4
add(&t4, &t1, &t4) // t4 = t1 + t4
mul(&coefEq.C, &t2, &t4) // A24m = t2 * t4
add(&t4, &t1, &t2) // t4 = t1 + t2
add(&t4, &t4, &t4) // t4 = t4 + t4
add(&t4, &t0, &t4) // t4 = t0 + t4
mul(&t4, &t3, &t4) // t4 = t3 * t4
sub(&t0, &t4, &coefEq.C) // t0 = t4 - A24m
add(&coefEq.A, &coefEq.C, &t0) // A24p = A24m + t0
return coefEq
}
// Given a 3-isogeny phi and a point pB = x(PB), compute x(QB), the x-coordinate
// of the image QB = phi(PB) of PB under phi : E_(A:C) -> E_(A':C').
//
// The output xQ = x(Q) is then a point on the curve E_(A':C'); the curve
// parameters are returned by the GenerateCurve function used to construct phi.
func (phi *isogeny3) EvaluatePoint(p *ProjectivePoint) ProjectivePoint {
var t0, t1, t2 Fp2
var q ProjectivePoint
var K1, K2 = &phi.K1, &phi.K2
var px, pz = &p.X, &p.Z
add(&t0, px, pz) // t0 = XQ + ZQ
sub(&t1, px, pz) // t1 = XQ - ZQ
mul(&t0, K1, &t0) // t2 = K1 * t0
mul(&t1, K2, &t1) // t1 = K2 * t1
add(&t2, &t0, &t1) // t2 = t0 + t1
sub(&t0, &t1, &t0) // t0 = t1 - t0
sqr(&t2, &t2) // t2 = t2 ^ 2
sqr(&t0, &t0) // t0 = t0 ^ 2
mul(&q.X, px, &t2) // XQ'= XQ * t2
mul(&q.Z, pz, &t0) // ZQ'= ZQ * t0
return q
}
// Given a four-torsion point p = x(PB) on the curve E_(A:C), construct the
// four-isogeny phi : E_(A:C) -> E_(A:C)/<P_4> = E_(A':C').
//
// Input: (XP_4: ZP_4), where P_4 has exact order 4 on E_A/C
// Output: * Curve coordinates (A' + 2C', 4C') corresponding to E_A'/C' = A_E/C/<P4>
// * Isogeny phi with constants in F_p^2
func (phi *isogeny4) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv {
var coefEq CurveCoefficientsEquiv
var xp4, zp4 = &p.X, &p.Z
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3
sub(K2, xp4, zp4)
add(K3, xp4, zp4)
sqr(K1, zp4)
add(K1, K1, K1)
sqr(&coefEq.C, K1)
add(K1, K1, K1)
sqr(&coefEq.A, xp4)
add(&coefEq.A, &coefEq.A, &coefEq.A)
sqr(&coefEq.A, &coefEq.A)
return coefEq
}
// Given a 4-isogeny phi and a point xP = x(P), compute x(Q), the x-coordinate
// of the image Q = phi(P) of P under phi : E_(A:C) -> E_(A':C').
//
// Input: Isogeny returned by GenerateCurve and point q=(Qx,Qz) from E0_A/C
// Output: Corresponding point q from E1_A'/C', where E1 is 4-isogenous to E0
func (phi *isogeny4) EvaluatePoint(p *ProjectivePoint) ProjectivePoint {
var t0, t1 Fp2
var q = *p
var xq, zq = &q.X, &q.Z
var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3
add(&t0, xq, zq)
sub(&t1, xq, zq)
mul(xq, &t0, K2)
mul(zq, &t1, K3)
mul(&t0, &t0, &t1)
mul(&t0, &t0, K1)
add(&t1, xq, zq)
sub(zq, xq, zq)
sqr(&t1, &t1)
sqr(zq, zq)
add(xq, &t0, &t1)
sub(&t0, zq, &t0)
mul(xq, xq, &t1)
mul(zq, zq, &t0)
return q
}

View File

@ -0,0 +1,2 @@
// Package p751 provides implementation of field arithmetic used in SIDH and SIKE.
package p751

View File

@ -0,0 +1,195 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots.
package p751
import (
"github.com/cloudflare/circl/dh/sidh/internal/common"
)
// Montgomery multiplication. Input values must be already
// in Montgomery domain.
func mulP(dest, lhs, rhs *common.Fp) {
var ab common.FpX2
mulP751(&ab, lhs, rhs) // = a*b*R*R
rdcP751(dest, &ab) // = a*b*R mod p
}
// Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x).
// Uses variation of sliding-window algorithm from with window size
// of 5 and least to most significant bit sliding (left-to-right)
// See HAC 14.85 for general description.
//
// Allowed to overlap x with dest.
// All values in Montgomery domains
// Set dest = x^(2^k), for k >= 1, by repeated squarings.
func p34(dest, x *common.Fp) {
var lookup [16]common.Fp
// This performs sum(powStrategy) + 1 squarings and len(lookup) + len(mulStrategy)
// multiplications.
powStrategy := []uint8{5, 7, 6, 2, 10, 4, 6, 9, 8, 5, 9, 4, 7, 5, 5, 4, 8, 3, 9, 5, 5, 4, 10, 4, 6, 6, 6, 5, 8, 9, 3, 4, 9, 4, 5, 6, 6, 2, 9, 4, 5, 5, 5, 7, 7, 9, 4, 6, 4, 8, 5, 8, 6, 6, 2, 9, 7, 4, 8, 8, 8, 4, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2}
mulStrategy := []uint8{15, 11, 10, 0, 15, 3, 3, 3, 4, 4, 9, 7, 11, 11, 5, 3, 12, 2, 10, 8, 5, 2, 8, 3, 5, 4, 11, 4, 0, 9, 2, 1, 12, 7, 5, 14, 15, 0, 14, 5, 6, 4, 5, 13, 6, 9, 7, 15, 1, 14, 11, 15, 12, 5, 0, 10, 9, 7, 7, 10, 14, 6, 11, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1}
initialMul := uint8(13)
// Precompute lookup table of odd multiples of x for window
// size k=5.
var xx common.Fp
mulP(&xx, x, x)
lookup[0] = *x
for i := 1; i < 16; i++ {
mulP(&lookup[i], &lookup[i-1], &xx)
}
// Now lookup = {x, x^3, x^5, ... }
// so that lookup[i] = x^{2*i + 1}
// so that lookup[k/2] = x^k, for odd k
*dest = lookup[initialMul]
for i := uint8(0); i < uint8(len(powStrategy)); i++ {
mulP(dest, dest, dest)
for j := uint8(1); j < powStrategy[i]; j++ {
mulP(dest, dest, dest)
}
mulP(dest, dest, &lookup[mulStrategy[i]])
}
}
func add(dest, lhs, rhs *common.Fp2) {
addP751(&dest.A, &lhs.A, &rhs.A)
addP751(&dest.B, &lhs.B, &rhs.B)
}
func sub(dest, lhs, rhs *common.Fp2) {
subP751(&dest.A, &lhs.A, &rhs.A)
subP751(&dest.B, &lhs.B, &rhs.B)
}
func mul(dest, lhs, rhs *common.Fp2) {
var bMinA, cMinD common.Fp
var ac, bd common.FpX2
var adPlusBc common.FpX2
var acMinBd common.FpX2
// Let (a,b,c,d) = (lhs.a,lhs.b,rhs.a,rhs.b).
//
// (a + bi)*(c + di) = (a*c - b*d) + (a*d + b*c)i
//
// Use Karatsuba's trick: note that
//
// (b - a)*(c - d) = (b*c + a*d) - a*c - b*d
//
// so (a*d + b*c) = (b-a)*(c-d) + a*c + b*d.
mulP751(&ac, &lhs.A, &rhs.A) // = a*c*R*R
mulP751(&bd, &lhs.B, &rhs.B) // = b*d*R*R
subP751(&bMinA, &lhs.B, &lhs.A) // = (b-a)*R
subP751(&cMinD, &rhs.A, &rhs.B) // = (c-d)*R
mulP751(&adPlusBc, &bMinA, &cMinD) // = (b-a)*(c-d)*R*R
adlP751(&adPlusBc, &adPlusBc, &ac) // = ((b-a)*(c-d) + a*c)*R*R
adlP751(&adPlusBc, &adPlusBc, &bd) // = ((b-a)*(c-d) + a*c + b*d)*R*R
rdcP751(&dest.B, &adPlusBc) // = (a*d + b*c)*R mod p
sulP751(&acMinBd, &ac, &bd) // = (a*c - b*d)*R*R
rdcP751(&dest.A, &acMinBd) // = (a*c - b*d)*R mod p
}
// Set dest = 1/x
//
// Allowed to overlap dest with x.
//
// Returns dest to allow chaining operations.
func inv(dest, x *common.Fp2) {
var e1, e2 common.FpX2
var f1, f2 common.Fp
// We want to compute
//
// 1 1 (a - bi) (a - bi)
// -------- = -------- -------- = -----------
// (a + bi) (a + bi) (a - bi) (a^2 + b^2)
//
// Letting c = 1/(a^2 + b^2), this is
//
// 1/(a+bi) = a*c - b*ci.
mulP751(&e1, &x.A, &x.A) // = a*a*R*R
mulP751(&e2, &x.B, &x.B) // = b*b*R*R
adlP751(&e1, &e1, &e2) // = (a^2 + b^2)*R*R
rdcP751(&f1, &e1) // = (a^2 + b^2)*R mod p
// Now f1 = a^2 + b^2
mulP(&f2, &f1, &f1)
p34(&f2, &f2)
mulP(&f2, &f2, &f2)
mulP(&f2, &f2, &f1)
mulP751(&e1, &x.A, &f2)
rdcP751(&dest.A, &e1)
subP751(&f1, &common.Fp{}, &x.B)
mulP751(&e1, &f1, &f2)
rdcP751(&dest.B, &e1)
}
func sqr(dest, x *common.Fp2) {
var a2, aPlusB, aMinusB common.Fp
var a2MinB2, ab2 common.FpX2
a := &x.A
b := &x.B
// (a + bi)*(a + bi) = (a^2 - b^2) + 2abi.
addP751(&a2, a, a) // = a*R + a*R = 2*a*R
addP751(&aPlusB, a, b) // = a*R + b*R = (a+b)*R
subP751(&aMinusB, a, b) // = a*R - b*R = (a-b)*R
mulP751(&a2MinB2, &aPlusB, &aMinusB) // = (a+b)*(a-b)*R*R = (a^2 - b^2)*R*R
mulP751(&ab2, &a2, b) // = 2*a*b*R*R
rdcP751(&dest.A, &a2MinB2) // = (a^2 - b^2)*R mod p
rdcP751(&dest.B, &ab2) // = 2*a*b*R mod p
}
// In case choice == 1, performs following swap in constant time:
// xPx <-> xQx
// xPz <-> xQz
// Otherwise returns xPx, xPz, xQx, xQz unchanged
func cswap(xPx, xPz, xQx, xQz *common.Fp2, choice uint8) {
cswapP751(&xPx.A, &xQx.A, choice)
cswapP751(&xPx.B, &xQx.B, choice)
cswapP751(&xPz.A, &xQz.A, choice)
cswapP751(&xPz.B, &xQz.B, choice)
}
// Converts in.A and in.B to Montgomery domain and stores
// in 'out'
// out.A = in.A * R mod p
// out.B = in.B * R mod p
// Performs v = v*R^2*R^(-1) mod p, for both in.A and in.B
func ToMontgomery(out, in *common.Fp2) {
var aRR common.FpX2
// a*R*R
mulP751(&aRR, &in.A, &P751R2)
// a*R mod p
rdcP751(&out.A, &aRR)
mulP751(&aRR, &in.B, &P751R2)
rdcP751(&out.B, &aRR)
}
// Converts in.A and in.B from Montgomery domain and stores
// in 'out'
// out.A = in.A mod p
// out.B = in.B mod p
//
// After returning from the call 'in' is not modified.
func FromMontgomery(out, in *common.Fp2) {
var aR common.FpX2
// convert from montgomery domain
copy(aR[:], in.A[:])
rdcP751(&out.A, &aR) // = a mod p in [0, 2p)
modP751(&out.A) // = a mod p in [0, p)
for i := range aR {
aR[i] = 0
}
copy(aR[:], in.B[:])
rdcP751(&out.B, &aR)
modP751(&out.B)
}

View File

@ -0,0 +1,235 @@
package p751
//go:generate go run ../templates/gen.go P751
import (
"github.com/cloudflare/circl/dh/sidh/internal/common"
"golang.org/x/sys/cpu"
)
const (
// Number of uint64 limbs used to store field element
FpWords = 12
)
var (
// HasBMI2 signals support for MULX which is in BMI2
HasBMI2 = cpu.X86.HasBMI2
// HasADXandBMI2 signals support for ADX and BMI2
HasADXandBMI2 = cpu.X86.HasBMI2 && cpu.X86.HasADX
// P751 is a prime used by field Fp751
P751 = common.Fp{
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff, 0xffffffffffffffff, 0xeeafffffffffffff,
0xe3ec968549f878a8, 0xda959b1a13f7cc76, 0x084e9867d6ebe876,
0x8562b5045cb25748, 0x0e12909f97badc66, 0x00006fe5d541f71c}
// P751x2 = 2*p751 - 1
P751x2 = common.Fp{
0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xDD5FFFFFFFFFFFFF,
0xC7D92D0A93F0F151, 0xB52B363427EF98ED, 0x109D30CFADD7D0ED,
0x0AC56A08B964AE90, 0x1C25213F2F75B8CD, 0x0000DFCBAA83EE38}
// P751p1 = p751 + 1
P751p1 = common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0xeeb0000000000000,
0xe3ec968549f878a8, 0xda959b1a13f7cc76, 0x084e9867d6ebe876,
0x8562b5045cb25748, 0x0e12909f97badc66, 0x00006fe5d541f71c}
// P751R2 = (2^768)^2 mod p
P751R2 = common.Fp{
2535603850726686808, 15780896088201250090, 6788776303855402382,
17585428585582356230, 5274503137951975249, 2266259624764636289,
11695651972693921304, 13072885652150159301, 4908312795585420432,
6229583484603254826, 488927695601805643, 72213483953973}
// P751p1Zeros number of 0 digits in the least significant part of P751+1
P751p1Zeros = 5
params common.SidhParams
)
func init() {
params = common.SidhParams{
ID: common.Fp751,
// SIDH public key byte size.
PublicKeySize: 564,
// SIDH shared secret byte size.
SharedSecretSize: 188,
A: common.DomainParams{
// The x-coordinate of PA
AffineP: common.Fp2{
A: common.Fp{
0xC2FC08CEAB50AD8B, 0x1D7D710F55E457B1, 0xE8738D92953DCD6E,
0xBAA7EBEE8A3418AA, 0xC9A288345F03F46F, 0xC8D18D167CFE2616,
0x02043761F6B1C045, 0xAA1975E13180E7E9, 0x9E13D3FDC6690DE6,
0x3A024640A3A3BB4F, 0x4E5AD44E6ACBBDAE, 0x0000544BEB561DAD,
},
B: common.Fp{
0xE6CC41D21582E411, 0x07C2ECB7C5DF400A, 0xE8E34B521432AEC4,
0x50761E2AB085167D, 0x032CFBCAA6094B3C, 0x6C522F5FDF9DDD71,
0x1319217DC3A1887D, 0xDC4FB25803353A86, 0x362C8D7B63A6AB09,
0x39DCDFBCE47EA488, 0x4C27C99A2C28D409, 0x00003CB0075527C4,
},
},
// The x-coordinate of QA
AffineQ: common.Fp2{
A: common.Fp{
0xD56FE52627914862, 0x1FAD60DC96B5BAEA, 0x01E137D0BF07AB91,
0x404D3E9252161964, 0x3C5385E4CD09A337, 0x4476426769E4AF73,
0x9790C6DB989DFE33, 0xE06E1C04D2AA8B5E, 0x38C08185EDEA73B9,
0xAA41F678A4396CA6, 0x92B9259B2229E9A0, 0x00002F9326818BE0,
},
B: common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
},
},
// The x-coordinate of RA = PA-QA
AffineR: common.Fp2{
A: common.Fp{
0x0BB84441DFFD19B3, 0x84B4DEA99B48C18E, 0x692DE648AD313805,
0xE6D72761B6DFAEE0, 0x223975C672C3058D, 0xA0FDE0C3CBA26FDC,
0xA5326132A922A3CA, 0xCA5E7F5D5EA96FA4, 0x127C7EFE33FFA8C6,
0x4749B1567E2A23C4, 0x2B7DF5B4AF413BFA, 0x0000656595B9623C,
},
B: common.Fp{
0xED78C17F1EC71BE8, 0xF824D6DF753859B1, 0x33A10839B2A8529F,
0xFC03E9E25FDEA796, 0xC4708A8054DF1762, 0x4034F2EC034C6467,
0xABFB70FBF06ECC79, 0xDABE96636EC108B7, 0x49CBCFB090605FD3,
0x20B89711819A45A7, 0xFB8E1590B2B0F63E, 0x0000556A5F964AB2,
},
},
// Max size of secret key for 2-torsion group, corresponds to 2^e2 - 1
SecretBitLen: 372,
// SecretBitLen in bytes.
SecretByteLen: 47,
// 2-torsion group computation strategy
IsogenyStrategy: []uint32{
0x50, 0x30, 0x1B, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02,
0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x07,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01,
0x01, 0x01, 0x01, 0x0C, 0x07, 0x04, 0x02, 0x01, 0x01, 0x02,
0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x05, 0x03,
0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x15,
0x0C, 0x07, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
0x02, 0x01, 0x01, 0x01, 0x01, 0x05, 0x03, 0x02, 0x01, 0x01,
0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x09, 0x05, 0x03, 0x02,
0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x02,
0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x21, 0x14, 0x0C, 0x07,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01,
0x01, 0x01, 0x01, 0x05, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x08, 0x05, 0x03, 0x02, 0x01, 0x01,
0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01,
0x02, 0x01, 0x01, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01},
},
B: common.DomainParams{
// The x-coordinate of PB
AffineP: common.Fp2{
A: common.Fp{
0xCFB6D71EF867AB0B, 0x4A5FDD76E9A45C76, 0x38B1EE69194B1F03,
0xF6E7B18A7761F3F0, 0xFCF01A486A52C84C, 0xCBE2F63F5AA75466,
0x6487BCE837B5E4D6, 0x7747F5A8C622E9B8, 0x4CBFE1E4EE6AEBBA,
0x8A8616A13FA91512, 0x53DB980E1579E0A5, 0x000058FEBFF3BE69,
},
B: common.Fp{
0xA492034E7C075CC3, 0x677BAF00B04AA430, 0x3AAE0C9A755C94C8,
0x1DC4B064E9EBB08B, 0x3684EDD04E826C66, 0x9BAA6CB661F01B22,
0x20285A00AD2EFE35, 0xDCE95ABD0497065F, 0x16C7FBB3778E3794,
0x26B3AC29CEF25AAF, 0xFB3C28A31A30AC1D, 0x000046ED190624EE,
},
},
// The x-coordinate of QB
AffineQ: common.Fp2{
A: common.Fp{
0xF1A8C9ED7B96C4AB, 0x299429DA5178486E, 0xEF4926F20CD5C2F4,
0x683B2E2858B4716A, 0xDDA2FBCC3CAC3EEB, 0xEC055F9F3A600460,
0xD5A5A17A58C3848B, 0x4652D836F42EAED5, 0x2F2E71ED78B3A3B3,
0xA771C057180ADD1D, 0xC780A5D2D835F512, 0x0000114EA3B55AC1,
},
B: common.Fp{
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
},
},
// The x-coordinate of RB = PB - QB
AffineR: common.Fp2{
A: common.Fp{
0x1C0D6733769D0F31, 0xF084C3086E2659D1, 0xE23D5DA27BCBD133,
0xF38EC9A8D5864025, 0x6426DC781B3B645B, 0x4B24E8E3C9FB03EE,
0x6432792F9D2CEA30, 0x7CC8E8B1AE76E857, 0x7F32BFB626BB8963,
0xB9F05995B48D7B74, 0x4D71200A7D67E042, 0x0000228457AF0637,
},
B: common.Fp{
0x4AE37E7D8F72BD95, 0xDD2D504B3E993488, 0x5D14E7FA1ECB3C3E,
0x127610CEB75D6350, 0x255B4B4CAC446B11, 0x9EA12336C1F70CAF,
0x79FA68A2147BC2F8, 0x11E895CFDADBBC49, 0xE4B9D3C4D6356C18,
0x44B25856A67F951C, 0x5851541F61308D0B, 0x00002FFD994F7E4C,
},
},
// Size of secret key for 3-torsion group, corresponds to log_2(3^e3) - 1.
SecretBitLen: 378,
// SecretBitLen in bytes.
SecretByteLen: 48,
// 3-torsion group computation strategy
IsogenyStrategy: []uint32{
0x70, 0x3F, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02,
0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01,
0x01, 0x02, 0x01, 0x01, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01,
0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x1F, 0x10, 0x08, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02,
0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x08, 0x04,
0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01,
0x02, 0x01, 0x01, 0x07, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01,
0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x31, 0x1F, 0x10,
0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02,
0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01,
0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x0F, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04,
0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x07, 0x04, 0x02, 0x01,
0x01, 0x02, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
0x15, 0x0C, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x05, 0x03, 0x02,
0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x09, 0x05,
0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01},
},
// 1*R mod p
OneFp2: common.Fp2{
A: common.Fp{
0x00000000000249ad, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0x8310000000000000,
0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e,
0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x00002d5b24bce5e2},
},
// 1/2 * R mod p
HalfFp2: common.Fp2{
A: common.Fp{
0x00000000000124D6, 0x0000000000000000, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000, 0xB8E0000000000000,
0x9C8A2434C0AA7287, 0xA206996CA9A378A3, 0x6876280D41A41B52,
0xE903B49F175CE04F, 0x0F8511860666D227, 0x00004EA07CFF6E7F},
},
MsgLen: 32,
// SIKEp751 provides 128 bit of classical security ([SIKE], 5.1)
KemSize: 24,
// ceil(751+7/8)
Bytelen: 94,
CiphertextSize: 24 + 8 + 564,
}
common.Register(common.Fp751, &params)
}

View File

@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,7 @@
// Package shake provides implementation of SHA-3 and cSHAKE
// This code has been copied from golang.org/x/crypto/sha3
// and havily modified. This version doesn't use heap when
// computing cSHAKE. It makes it possible to allocate
// heap once when object is created and then reuse heap
// allocated structures in subsequent calls.
package shake

View File

@ -0,0 +1,412 @@
// 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.
// +build !amd64 appengine gccgo
package shake
// rc stores the round constants for use in the ι step.
var rc = [24]uint64{
0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008,
}
// keccakF1600 applies the Keccak permutation to a 1600b-wide
// state represented as a slice of 25 uint64s.
func keccakF1600(a *[25]uint64) {
// Implementation translated from Keccak-inplace.c
// in the keccak reference code.
var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64
for i := 0; i < 24; i += 4 {
// Combines the 5 steps in each round into 2 steps.
// Unrolls 4 rounds per loop and spreads some steps across rounds.
// Round 1
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[6] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[12] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[18] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[24] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i]
a[6] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[16] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[22] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[3] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[10] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[1] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[7] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[19] ^ d4
bc3 = t<<8 | t>>(64-8)
a[20] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[11] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[23] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[4] ^ d4
bc0 = t<<27 | t>>(64-27)
a[5] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[2] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[8] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[14] ^ d4
bc2 = t<<39 | t>>(64-39)
a[15] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
// Round 2
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[16] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[7] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[23] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[14] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1]
a[16] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[11] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[2] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[18] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[20] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[6] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[22] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[4] ^ d4
bc3 = t<<8 | t>>(64-8)
a[15] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[1] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[8] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[24] ^ d4
bc0 = t<<27 | t>>(64-27)
a[10] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[12] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[3] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[19] ^ d4
bc2 = t<<39 | t>>(64-39)
a[5] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
// Round 3
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[11] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[22] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[8] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[19] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2]
a[11] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[1] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[12] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[23] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[15] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[16] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[2] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[24] ^ d4
bc3 = t<<8 | t>>(64-8)
a[5] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[6] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[3] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[14] ^ d4
bc0 = t<<27 | t>>(64-27)
a[20] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[7] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[18] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[4] ^ d4
bc2 = t<<39 | t>>(64-39)
a[10] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
// Round 4
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[1] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[2] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[3] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[4] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3]
a[1] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[6] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[7] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[8] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[5] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[11] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[12] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[14] ^ d4
bc3 = t<<8 | t>>(64-8)
a[10] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[16] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[18] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[19] ^ d4
bc0 = t<<27 | t>>(64-27)
a[15] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[22] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[23] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[24] ^ d4
bc2 = t<<39 | t>>(64-39)
a[20] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
}
}

View File

@ -0,0 +1,13 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64,!appengine,!gccgo
package shake
// This function is implemented in keccakf_amd64.s.
//go:noescape
func keccakF1600(a *[25]uint64)

View File

@ -0,0 +1,390 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64,!appengine,!gccgo
// This code was translated into a form compatible with 6a from the public
// domain sources at https://github.com/gvanas/KeccakCodePackage
// Offsets in state
#define _ba (0*8)
#define _be (1*8)
#define _bi (2*8)
#define _bo (3*8)
#define _bu (4*8)
#define _ga (5*8)
#define _ge (6*8)
#define _gi (7*8)
#define _go (8*8)
#define _gu (9*8)
#define _ka (10*8)
#define _ke (11*8)
#define _ki (12*8)
#define _ko (13*8)
#define _ku (14*8)
#define _ma (15*8)
#define _me (16*8)
#define _mi (17*8)
#define _mo (18*8)
#define _mu (19*8)
#define _sa (20*8)
#define _se (21*8)
#define _si (22*8)
#define _so (23*8)
#define _su (24*8)
// Temporary registers
#define rT1 AX
// Round vars
#define rpState DI
#define rpStack SP
#define rDa BX
#define rDe CX
#define rDi DX
#define rDo R8
#define rDu R9
#define rBa R10
#define rBe R11
#define rBi R12
#define rBo R13
#define rBu R14
#define rCa SI
#define rCe BP
#define rCi rBi
#define rCo rBo
#define rCu R15
#define MOVQ_RBI_RCE MOVQ rBi, rCe
#define XORQ_RT1_RCA XORQ rT1, rCa
#define XORQ_RT1_RCE XORQ rT1, rCe
#define XORQ_RBA_RCU XORQ rBa, rCu
#define XORQ_RBE_RCU XORQ rBe, rCu
#define XORQ_RDU_RCU XORQ rDu, rCu
#define XORQ_RDA_RCA XORQ rDa, rCa
#define XORQ_RDE_RCE XORQ rDe, rCe
#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \
/* Prepare round */ \
MOVQ rCe, rDa; \
ROLQ $1, rDa; \
\
MOVQ _bi(iState), rCi; \
XORQ _gi(iState), rDi; \
XORQ rCu, rDa; \
XORQ _ki(iState), rCi; \
XORQ _mi(iState), rDi; \
XORQ rDi, rCi; \
\
MOVQ rCi, rDe; \
ROLQ $1, rDe; \
\
MOVQ _bo(iState), rCo; \
XORQ _go(iState), rDo; \
XORQ rCa, rDe; \
XORQ _ko(iState), rCo; \
XORQ _mo(iState), rDo; \
XORQ rDo, rCo; \
\
MOVQ rCo, rDi; \
ROLQ $1, rDi; \
\
MOVQ rCu, rDo; \
XORQ rCe, rDi; \
ROLQ $1, rDo; \
\
MOVQ rCa, rDu; \
XORQ rCi, rDo; \
ROLQ $1, rDu; \
\
/* Result b */ \
MOVQ _ba(iState), rBa; \
MOVQ _ge(iState), rBe; \
XORQ rCo, rDu; \
MOVQ _ki(iState), rBi; \
MOVQ _mo(iState), rBo; \
MOVQ _su(iState), rBu; \
XORQ rDe, rBe; \
ROLQ $44, rBe; \
XORQ rDi, rBi; \
XORQ rDa, rBa; \
ROLQ $43, rBi; \
\
MOVQ rBe, rCa; \
MOVQ rc, rT1; \
ORQ rBi, rCa; \
XORQ rBa, rT1; \
XORQ rT1, rCa; \
MOVQ rCa, _ba(oState); \
\
XORQ rDu, rBu; \
ROLQ $14, rBu; \
MOVQ rBa, rCu; \
ANDQ rBe, rCu; \
XORQ rBu, rCu; \
MOVQ rCu, _bu(oState); \
\
XORQ rDo, rBo; \
ROLQ $21, rBo; \
MOVQ rBo, rT1; \
ANDQ rBu, rT1; \
XORQ rBi, rT1; \
MOVQ rT1, _bi(oState); \
\
NOTQ rBi; \
ORQ rBa, rBu; \
ORQ rBo, rBi; \
XORQ rBo, rBu; \
XORQ rBe, rBi; \
MOVQ rBu, _bo(oState); \
MOVQ rBi, _be(oState); \
B_RBI_RCE; \
\
/* Result g */ \
MOVQ _gu(iState), rBe; \
XORQ rDu, rBe; \
MOVQ _ka(iState), rBi; \
ROLQ $20, rBe; \
XORQ rDa, rBi; \
ROLQ $3, rBi; \
MOVQ _bo(iState), rBa; \
MOVQ rBe, rT1; \
ORQ rBi, rT1; \
XORQ rDo, rBa; \
MOVQ _me(iState), rBo; \
MOVQ _si(iState), rBu; \
ROLQ $28, rBa; \
XORQ rBa, rT1; \
MOVQ rT1, _ga(oState); \
G_RT1_RCA; \
\
XORQ rDe, rBo; \
ROLQ $45, rBo; \
MOVQ rBi, rT1; \
ANDQ rBo, rT1; \
XORQ rBe, rT1; \
MOVQ rT1, _ge(oState); \
G_RT1_RCE; \
\
XORQ rDi, rBu; \
ROLQ $61, rBu; \
MOVQ rBu, rT1; \
ORQ rBa, rT1; \
XORQ rBo, rT1; \
MOVQ rT1, _go(oState); \
\
ANDQ rBe, rBa; \
XORQ rBu, rBa; \
MOVQ rBa, _gu(oState); \
NOTQ rBu; \
G_RBA_RCU; \
\
ORQ rBu, rBo; \
XORQ rBi, rBo; \
MOVQ rBo, _gi(oState); \
\
/* Result k */ \
MOVQ _be(iState), rBa; \
MOVQ _gi(iState), rBe; \
MOVQ _ko(iState), rBi; \
MOVQ _mu(iState), rBo; \
MOVQ _sa(iState), rBu; \
XORQ rDi, rBe; \
ROLQ $6, rBe; \
XORQ rDo, rBi; \
ROLQ $25, rBi; \
MOVQ rBe, rT1; \
ORQ rBi, rT1; \
XORQ rDe, rBa; \
ROLQ $1, rBa; \
XORQ rBa, rT1; \
MOVQ rT1, _ka(oState); \
K_RT1_RCA; \
\
XORQ rDu, rBo; \
ROLQ $8, rBo; \
MOVQ rBi, rT1; \
ANDQ rBo, rT1; \
XORQ rBe, rT1; \
MOVQ rT1, _ke(oState); \
K_RT1_RCE; \
\
XORQ rDa, rBu; \
ROLQ $18, rBu; \
NOTQ rBo; \
MOVQ rBo, rT1; \
ANDQ rBu, rT1; \
XORQ rBi, rT1; \
MOVQ rT1, _ki(oState); \
\
MOVQ rBu, rT1; \
ORQ rBa, rT1; \
XORQ rBo, rT1; \
MOVQ rT1, _ko(oState); \
\
ANDQ rBe, rBa; \
XORQ rBu, rBa; \
MOVQ rBa, _ku(oState); \
K_RBA_RCU; \
\
/* Result m */ \
MOVQ _ga(iState), rBe; \
XORQ rDa, rBe; \
MOVQ _ke(iState), rBi; \
ROLQ $36, rBe; \
XORQ rDe, rBi; \
MOVQ _bu(iState), rBa; \
ROLQ $10, rBi; \
MOVQ rBe, rT1; \
MOVQ _mi(iState), rBo; \
ANDQ rBi, rT1; \
XORQ rDu, rBa; \
MOVQ _so(iState), rBu; \
ROLQ $27, rBa; \
XORQ rBa, rT1; \
MOVQ rT1, _ma(oState); \
M_RT1_RCA; \
\
XORQ rDi, rBo; \
ROLQ $15, rBo; \
MOVQ rBi, rT1; \
ORQ rBo, rT1; \
XORQ rBe, rT1; \
MOVQ rT1, _me(oState); \
M_RT1_RCE; \
\
XORQ rDo, rBu; \
ROLQ $56, rBu; \
NOTQ rBo; \
MOVQ rBo, rT1; \
ORQ rBu, rT1; \
XORQ rBi, rT1; \
MOVQ rT1, _mi(oState); \
\
ORQ rBa, rBe; \
XORQ rBu, rBe; \
MOVQ rBe, _mu(oState); \
\
ANDQ rBa, rBu; \
XORQ rBo, rBu; \
MOVQ rBu, _mo(oState); \
M_RBE_RCU; \
\
/* Result s */ \
MOVQ _bi(iState), rBa; \
MOVQ _go(iState), rBe; \
MOVQ _ku(iState), rBi; \
XORQ rDi, rBa; \
MOVQ _ma(iState), rBo; \
ROLQ $62, rBa; \
XORQ rDo, rBe; \
MOVQ _se(iState), rBu; \
ROLQ $55, rBe; \
\
XORQ rDu, rBi; \
MOVQ rBa, rDu; \
XORQ rDe, rBu; \
ROLQ $2, rBu; \
ANDQ rBe, rDu; \
XORQ rBu, rDu; \
MOVQ rDu, _su(oState); \
\
ROLQ $39, rBi; \
S_RDU_RCU; \
NOTQ rBe; \
XORQ rDa, rBo; \
MOVQ rBe, rDa; \
ANDQ rBi, rDa; \
XORQ rBa, rDa; \
MOVQ rDa, _sa(oState); \
S_RDA_RCA; \
\
ROLQ $41, rBo; \
MOVQ rBi, rDe; \
ORQ rBo, rDe; \
XORQ rBe, rDe; \
MOVQ rDe, _se(oState); \
S_RDE_RCE; \
\
MOVQ rBo, rDi; \
MOVQ rBu, rDo; \
ANDQ rBu, rDi; \
ORQ rBa, rDo; \
XORQ rBi, rDi; \
XORQ rBo, rDo; \
MOVQ rDi, _si(oState); \
MOVQ rDo, _so(oState) \
// func keccakF1600(a *[25]uint64)
TEXT ·keccakF1600(SB), 0, $200-8
MOVQ a+0(FP), rpState
// Convert the user state into an internal state
NOTQ _be(rpState)
NOTQ _bi(rpState)
NOTQ _go(rpState)
NOTQ _ki(rpState)
NOTQ _mi(rpState)
NOTQ _sa(rpState)
// Execute the KeccakF permutation
MOVQ _ba(rpState), rCa
MOVQ _be(rpState), rCe
MOVQ _bu(rpState), rCu
XORQ _ga(rpState), rCa
XORQ _ge(rpState), rCe
XORQ _gu(rpState), rCu
XORQ _ka(rpState), rCa
XORQ _ke(rpState), rCe
XORQ _ku(rpState), rCu
XORQ _ma(rpState), rCa
XORQ _me(rpState), rCe
XORQ _mu(rpState), rCu
XORQ _sa(rpState), rCa
XORQ _se(rpState), rCe
MOVQ _si(rpState), rDi
MOVQ _so(rpState), rDo
XORQ _su(rpState), rCu
mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE)
mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP)
// Revert the internal state to the user state
NOTQ _be(rpState)
NOTQ _bi(rpState)
NOTQ _go(rpState)
NOTQ _ki(rpState)
NOTQ _mi(rpState)
NOTQ _sa(rpState)
RET

View File

@ -0,0 +1,199 @@
// 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 shake
import "hash"
// spongeDirection indicates the direction bytes are flowing through the sponge.
type spongeDirection int
const (
// spongeAbsorbing indicates that the sponge is absorbing input.
spongeAbsorbing spongeDirection = iota
// spongeSqueezing indicates that the sponge is being squeezed.
spongeSqueezing
)
const (
// maxRate is the maximum size of the internal buffer. SHAKE-256
// currently needs the largest buffer.
maxRate = 168
)
type state struct {
// Generic sponge components.
a [25]uint64 // main state of the hash
buf []byte // points into storage
rate int // the number of bytes of state to use
// dsbyte contains the "domain separation" bits and the first bit of
// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
// SHA-3 and SHAKE functions by appending bitstrings to the message.
// Using a little-endian bit-ordering convention, these are "01" for SHA-3
// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
// padding rule from section 5.1 is applied to pad the message to a multiple
// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
// giving 00000110b (0x06) and 00011111b (0x1f).
// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
// "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
// Extendable-Output Functions (May 2014)"
dsbyte byte
storage [maxRate]byte
// Specific to SHA-3 and SHAKE.
outputLen int // the default output size in bytes
state spongeDirection // whether the sponge is absorbing or squeezing
}
// BlockSize returns the rate of sponge underlying this hash function.
func (d *state) BlockSize() int { return d.rate }
// Size returns the output size of the hash function in bytes.
func (d *state) Size() int { return d.outputLen }
// Reset clears the internal state by zeroing the sponge state and
// the byte buffer, and setting Sponge.state to absorbing.
func (d *state) Reset() {
// Zero the permutation's state.
for i := range d.a {
d.a[i] = 0
}
d.state = spongeAbsorbing
d.buf = d.storage[:0]
}
func (d *state) clone(ret *state) {
// shallow copy
*ret = *d
// deep copy for a buf
if ret.state == spongeAbsorbing {
ret.buf = ret.storage[:len(d.buf)]
} else {
ret.buf = ret.storage[d.rate-len(d.buf) : d.rate]
}
}
// permute applies the KeccakF-1600 permutation. It handles
// any input-output buffering.
func (d *state) permute() {
switch d.state {
case spongeAbsorbing:
// If we're absorbing, we need to xor the input into the state
// before applying the permutation.
xorIn(d, d.buf)
d.buf = d.storage[:0]
keccakF1600(&d.a)
case spongeSqueezing:
// If we're squeezing, we need to apply the permutatin before
// copying more output.
keccakF1600(&d.a)
d.buf = d.storage[:d.rate]
copyOut(d, d.buf)
}
}
// pads appends the domain separation bits in dsbyte, applies
// the multi-bitrate 10..1 padding rule, and permutes the state.
func (d *state) padAndPermute(dsbyte byte) {
if d.buf == nil {
d.buf = d.storage[:0]
}
// Pad with this instance's domain-separator bits. We know that there's
// at least one byte of space in d.buf because, if it were full,
// permute would have been called to empty it. dsbyte also contains the
// first one bit for the padding. See the comment in the state struct.
d.buf = append(d.buf, dsbyte)
zerosStart := len(d.buf)
d.buf = d.storage[:d.rate]
for i := zerosStart; i < d.rate; i++ {
d.buf[i] = 0
}
// This adds the final one bit for the padding. Because of the way that
// bits are numbered from the LSB upwards, the final bit is the MSB of
// the last byte.
d.buf[d.rate-1] ^= 0x80
// Apply the permutation
d.permute()
d.state = spongeSqueezing
d.buf = d.storage[:d.rate]
copyOut(d, d.buf)
}
// Write absorbs more data into the hash's state. It produces an error
// if more data is written to the ShakeHash after writing
func (d *state) Write(p []byte) (int, error) {
if d.state != spongeAbsorbing {
panic("shake: write to sponge after read")
}
if d.buf == nil {
d.buf = d.storage[:0]
}
written := len(p)
for len(p) > 0 {
if len(d.buf) == 0 && len(p) >= d.rate {
// The fast path; absorb a full "rate" bytes of input and apply the permutation.
xorIn(d, p[:d.rate])
p = p[d.rate:]
keccakF1600(&d.a)
} else {
// The slow path; buffer the input until we can fill the sponge, and then xor it in.
todo := d.rate - len(d.buf)
if todo > len(p) {
todo = len(p)
}
d.buf = append(d.buf, p[:todo]...)
p = p[todo:]
// If the sponge is full, apply the permutation.
if len(d.buf) == d.rate {
d.permute()
}
}
}
return written, nil
}
// Read squeezes an arbitrary number of bytes from the sponge.
func (d *state) Read(out []byte) (n int, err error) {
// If we're still absorbing, pad and apply the permutation.
if d.state == spongeAbsorbing {
d.padAndPermute(d.dsbyte)
}
n = len(out)
// Now, do the squeezing.
for len(out) > 0 {
n := copy(out, d.buf)
d.buf = d.buf[n:]
out = out[n:]
// Apply the permutation if we've squeezed the sponge dry.
if len(d.buf) == 0 {
d.permute()
}
}
return
}
// Sum applies padding to the hash state and then squeezes out the desired
// number of output bytes.
func (d *state) Sum(in []byte) []byte {
// Make a copy of the original hash so that caller can keep writing
// and summing.
var dup state
d.clone(&dup)
hash := make([]byte, dup.outputLen)
dup.Read(hash)
return append(in, hash...)
}
// Only use this function if you require compatibility with an existing cryptosystem
// that uses non-standard padding. All other users should use New256 instead.
func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} }

View File

@ -0,0 +1,134 @@
// 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 shake
// This file defines the CShake struct, and provides
// functions for creating SHAKE and cSHAKE instances, as well as utility
// functions for hashing bytes to arbitrary-length output.
//
//
// SHAKE implementation is based on FIPS PUB 202 [1]
// cSHAKE implementations is based on NIST SP 800-185 [2]
//
// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
// [2] https://doi.org/10.6028/NIST.SP.800-185
import (
"encoding/binary"
)
// cSHAKE specific context
type CShake struct {
state // SHA-3 state context and Read/Write operations
// initBlock is the cSHAKE specific initialization set of bytes. It is initialized
// by newCShake function and stores concatenation of N followed by S, encoded
// by the method specified in 3.3 of [1].
// It is stored here in order for Reset() to be able to put context into
// initial state.
initBlock []byte
}
// Consts for configuring initial SHA-3 state
const (
dsbyteShake = 0x1f
dsbyteCShake = 0x04
rate128 = 168
rate256 = 136
)
func bytepad(input []byte, w int) []byte {
// leftEncode always returns max 9 bytes
buf := make([]byte, 0, 9+len(input)+w)
buf = append(buf, leftEncode(uint64(w))...)
buf = append(buf, input...)
padlen := w - (len(buf) % w)
return append(buf, make([]byte, padlen)...)
}
func leftEncode(value uint64) []byte {
var b [9]byte
binary.BigEndian.PutUint64(b[1:], value)
// Trim all but last leading zero bytes
i := byte(1)
for i < 8 && b[i] == 0 {
i++
}
// Prepend number of encoded bytes
b[i-1] = 9 - i
return b[i-1:]
}
func newCShake(N, S []byte, rate int, dsbyte byte) *CShake {
// leftEncode returns max 9 bytes
initBlock := make([]byte, 0, 9*2+len(N)+len(S))
initBlock = append(initBlock, leftEncode(uint64(len(N)*8))...)
initBlock = append(initBlock, N...)
initBlock = append(initBlock, leftEncode(uint64(len(S)*8))...)
initBlock = append(initBlock, S...)
c := CShake{
state: state{rate: rate, dsbyte: dsbyte},
initBlock: bytepad(initBlock, rate),
}
c.Write(c.initBlock)
return &c
}
// Reset resets the hash to initial state.
func (c *CShake) Reset() {
c.state.Reset()
c.Write(c.initBlock)
}
// Clone returns copy of a cSHAKE context within its current state.
func (c *CShake) Clone() CShake {
var ret CShake
c.clone(&ret.state)
ret.initBlock = make([]byte, len(c.initBlock))
copy(ret.initBlock, c.initBlock)
return ret
}
// NewShake128 creates a new SHAKE128 variable-output-length CShake.
// Its generic security strength is 128 bits against all attacks if at
// least 32 bytes of its output are used.
func NewShake128() *CShake {
return &CShake{state{rate: rate128, dsbyte: dsbyteShake}, nil}
}
// NewShake256 creates a new SHAKE256 variable-output-length CShake.
// Its generic security strength is 256 bits against all attacks if
// at least 64 bytes of its output are used.
func NewShake256() *CShake {
return &CShake{state{rate: rate256, dsbyte: dsbyteShake}, nil}
}
// NewCShake128 creates a new instance of cSHAKE128 variable-output-length CShake,
// a customizable variant of SHAKE128.
// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is
// desired. S is a customization byte string used for domain separation - two cSHAKE
// computations on same input with different S yield unrelated outputs.
// When N and S are both empty, this is equivalent to NewShake128.
func NewCShake128(N, S []byte) *CShake {
if len(N) == 0 && len(S) == 0 {
return NewShake128()
}
return newCShake(N, S, rate128, dsbyteCShake)
}
// NewCShake256 creates a new instance of cSHAKE256 variable-output-length CShake,
// a customizable variant of SHAKE256.
// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is
// desired. S is a customization byte string used for domain separation - two cSHAKE
// computations on same input with different S yield unrelated outputs.
// When N and S are both empty, this is equivalent to NewShake256.
func NewCShake256(N, S []byte) *CShake {
if len(N) == 0 && len(S) == 0 {
return NewShake256()
}
return newCShake(N, S, rate256, dsbyteCShake)
}

View File

@ -0,0 +1,30 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !amd64,!386,!ppc64le
package shake
import "encoding/binary"
// xorInGeneric xors the bytes in buf into the state; it
// makes no non-portable assumptions about memory layout
// or alignment.
func xorIn(d *state, buf []byte) {
n := len(buf) / 8
for i := 0; i < n; i++ {
a := binary.LittleEndian.Uint64(buf)
d.a[i] ^= a
buf = buf[8:]
}
}
// copyOutGeneric copies ulint64s to a byte buffer.
func copyOut(d *state, b []byte) {
for i := 0; len(b) >= 8; i++ {
binary.LittleEndian.PutUint64(b, d.a[i])
b = b[8:]
}
}

View File

@ -0,0 +1,51 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64 386 ppc64le
// +build !appengine
package shake
import "unsafe"
func xorIn(d *state, buf []byte) {
bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))
n := len(buf)
if n >= 72 {
d.a[0] ^= bw[0]
d.a[1] ^= bw[1]
d.a[2] ^= bw[2]
d.a[3] ^= bw[3]
d.a[4] ^= bw[4]
d.a[5] ^= bw[5]
d.a[6] ^= bw[6]
d.a[7] ^= bw[7]
d.a[8] ^= bw[8]
}
if n >= 104 {
d.a[9] ^= bw[9]
d.a[10] ^= bw[10]
d.a[11] ^= bw[11]
d.a[12] ^= bw[12]
}
if n >= 136 {
d.a[13] ^= bw[13]
d.a[14] ^= bw[14]
d.a[15] ^= bw[15]
d.a[16] ^= bw[16]
}
if n >= 144 {
d.a[17] ^= bw[17]
}
if n >= 168 {
d.a[18] ^= bw[18]
d.a[19] ^= bw[19]
d.a[20] ^= bw[20]
}
}
func copyOut(d *state, buf []byte) {
ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0]))
copy(buf, ab[:])
}

267
vendor/github.com/cloudflare/circl/dh/sidh/sidh.go generated vendored Normal file
View File

@ -0,0 +1,267 @@
package sidh
import (
"errors"
"io"
"github.com/cloudflare/circl/dh/sidh/internal/common"
"github.com/cloudflare/circl/dh/sidh/internal/p503"
"github.com/cloudflare/circl/dh/sidh/internal/p751"
)
// I keep it bool in order to be able to apply logical NOT
type KeyVariant uint
// Base type for public and private key. Used mainly to carry domain
// parameters.
type key struct {
// Domain parameters of the algorithm to be used with a key
params *common.SidhParams
// Flag indicates wether corresponds to 2-, 3-torsion group or SIKE
keyVariant KeyVariant
}
// Defines operations on public key
type PublicKey struct {
key
// x-coordinates of P,Q,P-Q in this exact order
affine3Pt [3]common.Fp2
}
// Defines operations on private key
type PrivateKey struct {
key
// Secret key
Scalar []byte
// Used only by KEM
S []byte
}
// Id's correspond to bitlength of the prime field characteristic
// Currently Fp751 is the only one supported by this implementation
const (
Fp503 = common.Fp503
Fp751 = common.Fp751
)
const (
// First 2 bits identify SIDH variant third bit indicates
// wether key is a SIKE variant (set) or SIDH (not set)
// 001 - SIDH: corresponds to 2-torsion group
KeyVariantSidhA KeyVariant = 1 << 0
// 010 - SIDH: corresponds to 3-torsion group
KeyVariantSidhB = 1 << 1
// 110 - SIKE
KeyVariantSike = 1<<2 | KeyVariantSidhB
)
// Accessor to key variant
func (key *key) Variant() KeyVariant {
return key.keyVariant
}
// NewPublicKey initializes public key.
// Usage of this function guarantees that the object is correctly initialized.
func NewPublicKey(id uint8, v KeyVariant) *PublicKey {
return &PublicKey{key: key{params: common.Params(id), keyVariant: v}}
}
// Import clears content of the public key currently stored in the structure
// and imports key stored in the byte string. Returns error in case byte string
// size is wrong. Doesn't perform any validation.
func (pub *PublicKey) Import(input []byte) error {
if len(input) != pub.Size() {
return errors.New("sidh: input to short")
}
ssSz := pub.params.SharedSecretSize
common.BytesToFp2(&pub.affine3Pt[0], input[0:ssSz], pub.params.Bytelen)
common.BytesToFp2(&pub.affine3Pt[1], input[ssSz:2*ssSz], pub.params.Bytelen)
common.BytesToFp2(&pub.affine3Pt[2], input[2*ssSz:3*ssSz], pub.params.Bytelen)
switch pub.params.ID {
case Fp503:
p503.ToMontgomery(&pub.affine3Pt[0], &pub.affine3Pt[0])
p503.ToMontgomery(&pub.affine3Pt[1], &pub.affine3Pt[1])
p503.ToMontgomery(&pub.affine3Pt[2], &pub.affine3Pt[2])
case Fp751:
p751.ToMontgomery(&pub.affine3Pt[0], &pub.affine3Pt[0])
p751.ToMontgomery(&pub.affine3Pt[1], &pub.affine3Pt[1])
p751.ToMontgomery(&pub.affine3Pt[2], &pub.affine3Pt[2])
default:
panic("Unsupported key")
}
return nil
}
// Exports currently stored key. In case structure hasn't been filled with key data
// returned byte string is filled with zeros.
func (pub *PublicKey) Export(out []byte) {
var feTmp [3]common.Fp2
ssSz := pub.params.SharedSecretSize
switch pub.params.ID {
case Fp503:
p503.FromMontgomery(&feTmp[0], &pub.affine3Pt[0])
p503.FromMontgomery(&feTmp[1], &pub.affine3Pt[1])
p503.FromMontgomery(&feTmp[2], &pub.affine3Pt[2])
case Fp751:
p751.FromMontgomery(&feTmp[0], &pub.affine3Pt[0])
p751.FromMontgomery(&feTmp[1], &pub.affine3Pt[1])
p751.FromMontgomery(&feTmp[2], &pub.affine3Pt[2])
default:
panic("Unsupported key")
}
common.Fp2ToBytes(out[0:ssSz], &feTmp[0], pub.params.Bytelen)
common.Fp2ToBytes(out[ssSz:2*ssSz], &feTmp[1], pub.params.Bytelen)
common.Fp2ToBytes(out[2*ssSz:3*ssSz], &feTmp[2], pub.params.Bytelen)
}
// Size returns size of the public key in bytes
func (pub *PublicKey) Size() int {
return pub.params.PublicKeySize
}
// NewPrivateKey initializes private key.
// Usage of this function guarantees that the object is correctly initialized.
func NewPrivateKey(id uint8, v KeyVariant) *PrivateKey {
prv := &PrivateKey{key: key{params: common.Params(id), keyVariant: v}}
if (v & KeyVariantSidhA) == KeyVariantSidhA {
prv.Scalar = make([]byte, prv.params.A.SecretByteLen)
} else {
prv.Scalar = make([]byte, prv.params.B.SecretByteLen)
}
if v == KeyVariantSike {
prv.S = make([]byte, prv.params.MsgLen)
}
return prv
}
// Exports currently stored key. In case structure hasn't been filled with key data
// returned byte string is filled with zeros.
func (prv *PrivateKey) Export(out []byte) {
copy(out, prv.S)
copy(out[len(prv.S):], prv.Scalar)
}
// Size returns size of the private key in bytes
func (prv *PrivateKey) Size() int {
tmp := len(prv.Scalar)
if prv.Variant() == KeyVariantSike {
tmp += prv.params.MsgLen
}
return tmp
}
// Size returns size of the shared secret
func (prv *PrivateKey) SharedSecretSize() int {
return prv.params.SharedSecretSize
}
// Import clears content of the private key currently stored in the structure
// and imports key from octet string. In case of SIKE, the random value 'S'
// must be prepended to the value of actual private key (see SIKE spec for details).
// Function doesn't import public key value to PrivateKey object.
func (prv *PrivateKey) Import(input []byte) error {
if len(input) != prv.Size() {
return errors.New("sidh: input to short")
}
copy(prv.S, input[:len(prv.S)])
copy(prv.Scalar, input[len(prv.S):])
return nil
}
// Generates random private key for SIDH or SIKE. Generated value is
// formed as little-endian integer from key-space <2^(e2-1)..2^e2 - 1>
// for KeyVariant_A or <2^(s-1)..2^s - 1>, where s = floor(log_2(3^e3)),
// for KeyVariant_B.
//
// Returns error in case user provided RNG fails.
func (prv *PrivateKey) Generate(rand io.Reader) error {
var dp *common.DomainParams
if (prv.keyVariant & KeyVariantSidhA) == KeyVariantSidhA {
dp = &prv.params.A
} else {
dp = &prv.params.B
}
if prv.keyVariant == KeyVariantSike {
if _, err := io.ReadFull(rand, prv.S); err != nil {
return err
}
}
// Private key generation takes advantage of the fact that keyspace for secret
// key is (0, 2^x - 1), for some possitivite value of 'x' (see SIKE, 1.3.8).
// It means that all bytes in the secret key, but the last one, can take any
// value between <0x00,0xFF>. Similarly for the last byte, but generation
// needs to chop off some bits, to make sure generated value is an element of
// a key-space.
if _, err := io.ReadFull(rand, prv.Scalar); err != nil {
return err
}
prv.Scalar[len(prv.Scalar)-1] &= (1 << (dp.SecretBitLen % 8)) - 1
// Make sure scalar is SecretBitLen long. SIKE spec says that key
// space starts from 0, but I'm not comfortable with having low
// value scalars used for private keys. It is still secrure as per
// table 5.1 in [SIKE].
prv.Scalar[len(prv.Scalar)-1] |= 1 << ((dp.SecretBitLen % 8) - 1)
return nil
}
// Generates public key.
func (prv *PrivateKey) GeneratePublicKey(pub *PublicKey) {
var isA = (prv.keyVariant & KeyVariantSidhA) == KeyVariantSidhA
if (pub.keyVariant != prv.keyVariant) || (pub.params.ID != prv.params.ID) {
panic("sidh: incompatbile public key")
}
switch prv.params.ID {
case Fp503:
if isA {
p503.PublicKeyGenA(&pub.affine3Pt, prv.Scalar)
} else {
p503.PublicKeyGenB(&pub.affine3Pt, prv.Scalar)
}
case Fp751:
if isA {
p751.PublicKeyGenA(&pub.affine3Pt, prv.Scalar)
} else {
p751.PublicKeyGenB(&pub.affine3Pt, prv.Scalar)
}
default:
panic("Field not supported")
}
}
// Computes a SIDH shared secret. Function requires that pub has different
// KeyVariant than prv. Length of returned output is 2*ceil(log_2 P)/8),
// where P is a prime defining finite field.
//
// Caller must make sure key SIDH key pair is not used more than once.
func (prv *PrivateKey) DeriveSecret(ss []byte, pub *PublicKey) {
var isA = (prv.keyVariant & KeyVariantSidhA) == KeyVariantSidhA
if (pub.keyVariant == prv.keyVariant) || (pub.params.ID != prv.params.ID) {
panic("sidh: public and private are incompatbile")
}
switch prv.params.ID {
case Fp503:
if isA {
p503.DeriveSecretA(ss, prv.Scalar, &pub.affine3Pt)
} else {
p503.DeriveSecretB(ss, prv.Scalar, &pub.affine3Pt)
}
case Fp751:
if isA {
p751.DeriveSecretA(ss, prv.Scalar, &pub.affine3Pt)
} else {
p751.DeriveSecretB(ss, prv.Scalar, &pub.affine3Pt)
}
default:
panic("Field not supported")
}
}

260
vendor/github.com/cloudflare/circl/dh/sidh/sike.go generated vendored Normal file
View File

@ -0,0 +1,260 @@
package sidh
import (
"crypto/subtle"
"errors"
"io"
"github.com/cloudflare/circl/dh/sidh/internal/common"
"github.com/cloudflare/circl/dh/sidh/internal/shake"
)
// SIKE KEM interface
type KEM struct {
allocated bool
rng io.Reader
msg []byte
secretBytes []byte
params *common.SidhParams
cshakeG, cshakeH, cshakeF *shake.CShake
}
// NewSike503 instantiates SIKE/p503 KEM
func NewSike503(rng io.Reader) *KEM {
var c KEM
c.Allocate(Fp503, rng)
return &c
}
// NewSike751 instantiates SIKE/p751 KEM
func NewSike751(rng io.Reader) *KEM {
var c KEM
c.Allocate(Fp751, rng)
return &c
}
// Allocate allocates KEM object for multiple SIKE operations. The rng
// must be cryptographically secure PRNG.
func (c *KEM) Allocate(id uint8, rng io.Reader) {
// Constants used for cSHAKE customization
// Those values are different than in [SIKE] - they are encoded on 16bits. This is
// done in order for implementation to be compatible with [REF] and test vectors.
var G = []byte{0x00, 0x00}
var H = []byte{0x01, 0x00}
var F = []byte{0x02, 0x00}
c.cshakeG = shake.NewCShake256(nil, G)
c.cshakeH = shake.NewCShake256(nil, H)
c.cshakeF = shake.NewCShake256(nil, F)
c.rng = rng
c.params = common.Params(id)
c.msg = make([]byte, c.params.MsgLen)
c.secretBytes = make([]byte, c.params.A.SecretByteLen)
c.allocated = true
}
// Encapsulate receives the public key and generates SIKE ciphertext and shared secret.
// The generated ciphertext is used for authentication.
// Error is returned in case PRNG fails. Function panics in case wrongly formated
// input was provided.
func (c *KEM) Encapsulate(ciphertext, secret []byte, pub *PublicKey) error {
if !c.allocated {
panic("KEM unallocated")
}
if KeyVariantSike != pub.keyVariant {
panic("Wrong type of public key")
}
if len(secret) < c.SharedSecretSize() {
panic("shared secret buffer to small")
}
if len(ciphertext) < c.CiphertextSize() {
panic("ciphertext buffer to small")
}
// Generate ephemeral value
_, err := io.ReadFull(c.rng, c.msg[:])
if err != nil {
return err
}
var buf [3 * common.MaxSharedSecretBsz]byte
var skA = PrivateKey{
key: key{
params: c.params,
keyVariant: KeyVariantSidhA},
Scalar: c.secretBytes}
var pkA = NewPublicKey(c.params.ID, KeyVariantSidhA)
pub.Export(buf[:])
c.cshakeG.Reset()
c.cshakeG.Write(c.msg)
c.cshakeG.Write(buf[:3*c.params.SharedSecretSize])
c.cshakeG.Read(skA.Scalar)
// Ensure bitlength is not bigger then to 2^e2-1
skA.Scalar[len(skA.Scalar)-1] &= (1 << (c.params.A.SecretBitLen % 8)) - 1
skA.GeneratePublicKey(pkA)
c.generateCiphertext(ciphertext, &skA, pkA, pub, c.msg[:])
// K = H(msg||(c0||c1))
c.cshakeH.Reset()
c.cshakeH.Write(c.msg)
c.cshakeH.Write(ciphertext)
c.cshakeH.Read(secret[:c.SharedSecretSize()])
return nil
}
// Decapsulate given the keypair and ciphertext as inputs, Decapsulate outputs a shared
// secret if plaintext verifies correctly, otherwise function outputs random value.
// Decapsulation may panic in case input is wrongly formated, in particular, size of
// the 'ciphertext' must be exactly equal to c.CiphertextSize().
func (c *KEM) Decapsulate(secret []byte, prv *PrivateKey, pub *PublicKey, ciphertext []byte) error {
if !c.allocated {
panic("KEM unallocated")
}
if KeyVariantSike != pub.keyVariant {
panic("Wrong type of public key")
}
if pub.keyVariant != prv.keyVariant {
panic("Public and private key are of different type")
}
if len(secret) < c.SharedSecretSize() {
panic("shared secret buffer to small")
}
if len(ciphertext) != c.CiphertextSize() {
panic("ciphertext buffer to small")
}
var m [common.MaxMsgBsz]byte
var r [common.MaxSidhPrivateKeyBsz]byte
var pkBytes [3 * common.MaxSharedSecretBsz]byte
var skA = PrivateKey{
key: key{
params: c.params,
keyVariant: KeyVariantSidhA},
Scalar: c.secretBytes}
var pkA = NewPublicKey(c.params.ID, KeyVariantSidhA)
c1Len := c.decrypt(m[:], prv, ciphertext)
// r' = G(m'||pub)
pub.Export(pkBytes[:])
c.cshakeG.Reset()
c.cshakeG.Write(m[:c1Len])
c.cshakeG.Write(pkBytes[:3*c.params.SharedSecretSize])
c.cshakeG.Read(r[:c.params.A.SecretByteLen])
// Ensure bitlength is not bigger than 2^e2-1
r[c.params.A.SecretByteLen-1] &= (1 << (c.params.A.SecretBitLen % 8)) - 1
// Never fails
skA.Import(r[:c.params.A.SecretByteLen])
skA.GeneratePublicKey(pkA)
pkA.Export(pkBytes[:])
// S is chosen at random when generating a key and unknown to other party. It is
// important that S is unpredictable to the other party. Without this check, would
// be possible to recover a secret, by providing series of invalid ciphertexts.
//
// See more details in "On the security of supersingular isogeny cryptosystems"
// (S. Galbraith, et al., 2016, ePrint #859).
mask := subtle.ConstantTimeCompare(pkBytes[:c.params.PublicKeySize], ciphertext[:pub.params.PublicKeySize])
common.Cpick(mask, m[:c1Len], m[:c1Len], prv.S)
c.cshakeH.Reset()
c.cshakeH.Write(m[:c1Len])
c.cshakeH.Write(ciphertext)
c.cshakeH.Read(secret[:c.SharedSecretSize()])
return nil
}
// Resets internal state of KEM. Function should be used
// after Allocate and between subsequent calls to Encapsulate
// and/or Decapsulate.
func (c *KEM) Reset() {
for i := range c.msg {
c.msg[i] = 0
}
for i := range c.secretBytes {
c.secretBytes[i] = 0
}
}
// Returns size of resulting ciphertext
func (c *KEM) CiphertextSize() int {
return c.params.CiphertextSize
}
// Returns size of resulting shared secret
func (c *KEM) SharedSecretSize() int {
return c.params.KemSize
}
func (c *KEM) generateCiphertext(ctext []byte, skA *PrivateKey, pkA, pkB *PublicKey, ptext []byte) {
var n [common.MaxMsgBsz]byte
var j [common.MaxSharedSecretBsz]byte
var ptextLen = skA.params.MsgLen
skA.DeriveSecret(j[:], pkB)
c.cshakeF.Reset()
c.cshakeF.Write(j[:skA.params.SharedSecretSize])
c.cshakeF.Read(n[:ptextLen])
for i := range ptext {
n[i] ^= ptext[i]
}
pkA.Export(ctext)
copy(ctext[pkA.Size():], n[:ptextLen])
}
// encrypt uses SIKE public key to encrypt plaintext. Requires cryptographically secure
// PRNG. Returns ciphertext in case encryption succeeds. Returns error in case PRNG fails
// or wrongly formated input was provided.
func (c *KEM) encrypt(ctext []byte, rng io.Reader, pub *PublicKey, ptext []byte) error {
var ptextLen = len(ptext)
// c1 must be security level + 64 bits (see [SIKE] 1.4 and 4.3.3)
if ptextLen != (pub.params.KemSize + 8) {
return errors.New("unsupported message length")
}
skA := NewPrivateKey(pub.params.ID, KeyVariantSidhA)
pkA := NewPublicKey(pub.params.ID, KeyVariantSidhA)
err := skA.Generate(rng)
if err != nil {
return err
}
skA.GeneratePublicKey(pkA)
c.generateCiphertext(ctext, skA, pkA, pub, ptext)
return nil
}
// decrypt uses SIKE private key to decrypt ciphertext. Returns plaintext in case
// decryption succeeds or error in case unexptected input was provided.
// Constant time
func (c *KEM) decrypt(n []byte, prv *PrivateKey, ctext []byte) int {
var c1Len int
var j [common.MaxSharedSecretBsz]byte
var pkLen = prv.params.PublicKeySize
// ctext is a concatenation of (ciphertext = pubkey_A || c1)
// it must be security level + 64 bits (see [SIKE] 1.4 and 4.3.3)
// Lengths has been already checked by Decapsulate()
c1Len = len(ctext) - pkLen
c0 := NewPublicKey(prv.params.ID, KeyVariantSidhA)
// Never fails
c0.Import(ctext[:pkLen])
prv.DeriveSecret(j[:], c0)
c.cshakeF.Reset()
c.cshakeF.Write(j[:prv.params.SharedSecretSize])
c.cshakeF.Read(n[:c1Len])
for i := range n[:c1Len] {
n[i] ^= ctext[pkLen+i]
}
return c1Len
}

21
vendor/github.com/cloudflare/odoh-go/LICENSE.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2019-2020, Cloudflare, Inc. and Apple, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

20
vendor/github.com/cloudflare/odoh-go/README.md generated vendored Normal file
View File

@ -0,0 +1,20 @@
# odoh-go
[![Coverage Status](https://coveralls.io/repos/github/cloudflare/odoh-go/badge.svg?branch=master)](https://coveralls.io/github/cloudflare/odoh-go?branch=master)
[![GoDoc](https://godoc.org/github.com/cloudflare/odoh-go?status.svg)](https://godoc.org/github.com/cloudflare/odoh-go)
This library implements draft -03 of [Oblivious DoH](https://tools.ietf.org/html/draft-pauly-dprive-oblivious-doh-03). It is based on the original implementation [available here](https://github.com/chris-wood/odoh).
## Test vector generation
To generate test vectors, run:
```
$ ODOH_TEST_VECTORS_OUT=test-vectors.json go test -v -run TestVectorGenerate
```
To check test vectors, run:
```
$ ODOH_TEST_VECTORS_IN=test-vectors.json go test -v -run TestVectorVerify
```

47
vendor/github.com/cloudflare/odoh-go/codec.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
// The MIT License
//
// Copyright (c) 2019-2020, Cloudflare, Inc. and Apple, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package odoh
import (
"encoding/binary"
"fmt"
)
func encodeLengthPrefixedSlice(slice []byte) []byte {
result := make([]byte, 2)
binary.BigEndian.PutUint16(result, uint16(len(slice)))
return append(result, slice...)
}
func decodeLengthPrefixedSlice(slice []byte) ([]byte, int, error) {
if len(slice) < 2 {
return nil, 0, fmt.Errorf("Expected at least 2 bytes of length encoded prefix")
}
length := binary.BigEndian.Uint16(slice)
if int(2+length) > len(slice) {
return nil, 0, fmt.Errorf("Insufficient data. Expected %d, got %d", 2+length, len(slice))
}
return slice[2 : 2+length], int(2 + length), nil
}

5
vendor/github.com/cloudflare/odoh-go/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/cloudflare/odoh-go
go 1.14
require github.com/cisco/go-hpke v0.0.0-20201023221920-2866d2aa0603

176
vendor/github.com/cloudflare/odoh-go/messages.go generated vendored Normal file
View File

@ -0,0 +1,176 @@
// The MIT License
//
// Copyright (c) 2019-2020, Cloudflare, Inc. and Apple, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package odoh
import (
"encoding/binary"
"fmt"
)
type ObliviousMessageType uint8
const (
QueryType ObliviousMessageType = 0x01
ResponseType ObliviousMessageType = 0x02
)
//
// struct {
// opaque dns_message<1..2^16-1>;
// opaque padding<0..2^16-1>;
// } ObliviousDoHQueryBody;
//
type ObliviousDNSMessageBody struct {
DnsMessage []byte
Padding []byte
}
func (m ObliviousDNSMessageBody) Marshal() []byte {
return append(encodeLengthPrefixedSlice(m.DnsMessage), encodeLengthPrefixedSlice(m.Padding)...)
}
func UnmarshalMessageBody(data []byte) (ObliviousDNSMessageBody, error) {
messageLength := binary.BigEndian.Uint16(data)
if int(2+messageLength) > len(data) {
return ObliviousDNSMessageBody{}, fmt.Errorf("Invalid DNS message length")
}
message := data[2 : 2+messageLength]
paddingLength := binary.BigEndian.Uint16(data[2+messageLength:])
if int(2+messageLength+2+paddingLength) > len(data) {
return ObliviousDNSMessageBody{}, fmt.Errorf("Invalid DNS padding length")
}
padding := data[2+messageLength+2 : 2+messageLength+2+paddingLength]
return ObliviousDNSMessageBody{
DnsMessage: message,
Padding: padding,
}, nil
}
func (m ObliviousDNSMessageBody) Message() []byte {
return m.DnsMessage
}
type ObliviousDNSQuery struct {
ObliviousDNSMessageBody
}
func CreateObliviousDNSQuery(query []byte, paddingBytes uint16) *ObliviousDNSQuery {
msg := ObliviousDNSMessageBody{
DnsMessage: query,
Padding: make([]byte, int(paddingBytes)),
}
return &ObliviousDNSQuery{
msg,
}
}
func UnmarshalQueryBody(data []byte) (*ObliviousDNSQuery, error) {
msg, err := UnmarshalMessageBody(data)
if err != nil {
return nil, err
}
return &ObliviousDNSQuery{msg}, nil
}
type ObliviousDNSResponse struct {
ObliviousDNSMessageBody
}
func CreateObliviousDNSResponse(response []byte, paddingBytes uint16) *ObliviousDNSResponse {
msg := ObliviousDNSMessageBody{
DnsMessage: response,
Padding: make([]byte, int(paddingBytes)),
}
return &ObliviousDNSResponse{
msg,
}
}
func UnmarshalResponseBody(data []byte) (*ObliviousDNSResponse, error) {
msg, err := UnmarshalMessageBody(data)
if err != nil {
return nil, err
}
return &ObliviousDNSResponse{msg}, nil
}
//
// struct {
// uint8 message_type;
// opaque key_id<0..2^16-1>;
// opaque encrypted_message<1..2^16-1>;
// } ObliviousDoHMessage;
//
type ObliviousDNSMessage struct {
MessageType ObliviousMessageType
KeyID []byte
EncryptedMessage []byte
}
func (m ObliviousDNSMessage) Type() ObliviousMessageType {
return m.MessageType
}
func CreateObliviousDNSMessage(messageType ObliviousMessageType, keyID []byte, encryptedMessage []byte) *ObliviousDNSMessage {
return &ObliviousDNSMessage{
MessageType: messageType,
KeyID: keyID,
EncryptedMessage: encryptedMessage,
}
}
func (m ObliviousDNSMessage) Marshal() []byte {
encodedKey := encodeLengthPrefixedSlice(m.KeyID)
encodedMessage := encodeLengthPrefixedSlice(m.EncryptedMessage)
result := append([]byte{uint8(m.MessageType)}, encodedKey...)
result = append(result, encodedMessage...)
return result
}
func UnmarshalDNSMessage(data []byte) (ObliviousDNSMessage, error) {
if len(data) < 1 {
return ObliviousDNSMessage{}, fmt.Errorf("Invalid data length: %d", len(data))
}
messageType := data[0]
keyID, messageOffset, err := decodeLengthPrefixedSlice(data[1:])
if err != nil {
return ObliviousDNSMessage{}, err
}
encryptedMessage, _, err := decodeLengthPrefixedSlice(data[1+messageOffset:])
if err != nil {
return ObliviousDNSMessage{}, err
}
return ObliviousDNSMessage{
MessageType: ObliviousMessageType(messageType),
KeyID: keyID,
EncryptedMessage: encryptedMessage,
}, nil
}

564
vendor/github.com/cloudflare/odoh-go/odoh.go generated vendored Normal file
View File

@ -0,0 +1,564 @@
// The MIT License
//
// Copyright (c) 2019-2020, Cloudflare, Inc. and Apple, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package odoh
import (
"crypto/rand"
"crypto/subtle"
"encoding/binary"
"errors"
"fmt"
"github.com/cisco/go-hpke"
)
const (
ODOH_VERSION = uint16(0xff03)
ODOH_SECRET_LENGTH = 32
ODOH_PADDING_BYTE = uint8(0)
ODOH_LABEL_KEY_ID = "odoh key id"
ODOH_LABEL_KEY = "odoh key"
ODOH_LABEL_NONCE = "odoh nonce"
ODOH_LABEL_SECRET = "odoh secret"
ODOH_LABEL_QUERY = "odoh query"
ODOH_DEFAULT_KEMID hpke.KEMID = hpke.DHKEM_X25519
ODOH_DEFAULT_KDFID hpke.KDFID = hpke.KDF_HKDF_SHA256
ODOH_DEFAULT_AEADID hpke.AEADID = hpke.AEAD_AESGCM128
)
type ObliviousDoHConfigContents struct {
KemID hpke.KEMID
KdfID hpke.KDFID
AeadID hpke.AEADID
PublicKeyBytes []byte
}
func CreateObliviousDoHConfigContents(kemID hpke.KEMID, kdfID hpke.KDFID, aeadID hpke.AEADID, publicKeyBytes []byte) (ObliviousDoHConfigContents, error) {
suite, err := hpke.AssembleCipherSuite(kemID, kdfID, aeadID)
if err != nil {
return ObliviousDoHConfigContents{}, err
}
_, err = suite.KEM.Deserialize(publicKeyBytes)
if err != nil {
return ObliviousDoHConfigContents{}, err
}
return ObliviousDoHConfigContents{
KemID: kemID,
KdfID: kdfID,
AeadID: aeadID,
PublicKeyBytes: publicKeyBytes,
}, nil
}
func (k ObliviousDoHConfigContents) KeyID() []byte {
suite, err := hpke.AssembleCipherSuite(k.KemID, k.KdfID, k.AeadID)
if err != nil {
return nil
}
identifiers := make([]byte, 8)
binary.BigEndian.PutUint16(identifiers[0:], uint16(k.KemID))
binary.BigEndian.PutUint16(identifiers[2:], uint16(k.KdfID))
binary.BigEndian.PutUint16(identifiers[4:], uint16(k.AeadID))
binary.BigEndian.PutUint16(identifiers[6:], uint16(len(k.PublicKeyBytes)))
config := append(identifiers, k.PublicKeyBytes...)
prk := suite.KDF.Extract(nil, config)
identifier := suite.KDF.Expand(prk, []byte(ODOH_LABEL_KEY_ID), suite.KDF.OutputSize())
return identifier
}
func (k ObliviousDoHConfigContents) Marshal() []byte {
identifiers := make([]byte, 8)
binary.BigEndian.PutUint16(identifiers[0:], uint16(k.KemID))
binary.BigEndian.PutUint16(identifiers[2:], uint16(k.KdfID))
binary.BigEndian.PutUint16(identifiers[4:], uint16(k.AeadID))
binary.BigEndian.PutUint16(identifiers[6:], uint16(len(k.PublicKeyBytes)))
response := append(identifiers, k.PublicKeyBytes...)
return response
}
func UnmarshalObliviousDoHConfigContents(buffer []byte) (ObliviousDoHConfigContents, error) {
if len(buffer) < 8 {
return ObliviousDoHConfigContents{}, errors.New("Invalid serialized ObliviousDoHConfigContents")
}
kemId := binary.BigEndian.Uint16(buffer[0:])
kdfId := binary.BigEndian.Uint16(buffer[2:])
aeadId := binary.BigEndian.Uint16(buffer[4:])
publicKeyLength := binary.BigEndian.Uint16(buffer[6:])
if len(buffer[8:]) < int(publicKeyLength) {
return ObliviousDoHConfigContents{}, errors.New("Invalid serialized ObliviousDoHConfigContents")
}
publicKeyBytes := buffer[8 : 8+publicKeyLength]
var KemID hpke.KEMID
var KdfID hpke.KDFID
var AeadID hpke.AEADID
switch kemId {
case 0x0010:
KemID = hpke.DHKEM_P256
break
case 0x0012:
KemID = hpke.DHKEM_P521
break
case 0x0020:
KemID = hpke.DHKEM_X25519
break
case 0x0021:
KemID = hpke.DHKEM_X448
break
case 0xFFFE:
KemID = hpke.KEM_SIKE503
break
case 0xFFFF:
KemID = hpke.KEM_SIKE751
break
default:
return ObliviousDoHConfigContents{}, errors.New(fmt.Sprintf("Unsupported KEMID: %04x", kemId))
}
switch kdfId {
case 0x0001:
KdfID = hpke.KDF_HKDF_SHA256
break
case 0x0002:
KdfID = hpke.KDF_HKDF_SHA384
break
case 0x0003:
KdfID = hpke.KDF_HKDF_SHA512
break
default:
return ObliviousDoHConfigContents{}, errors.New(fmt.Sprintf("Unsupported KDFID: %04x", kdfId))
}
switch aeadId {
case 0x0001:
AeadID = hpke.AEAD_AESGCM128
break
case 0x0002:
AeadID = hpke.AEAD_AESGCM256
break
case 0x0003:
AeadID = hpke.AEAD_CHACHA20POLY1305
break
default:
return ObliviousDoHConfigContents{}, errors.New(fmt.Sprintf("Unsupported AEADID: %04x", aeadId))
}
suite, err := hpke.AssembleCipherSuite(KemID, KdfID, AeadID)
if err != nil {
return ObliviousDoHConfigContents{}, errors.New(fmt.Sprintf("Unsupported HPKE ciphersuite"))
}
_, err = suite.KEM.Deserialize(publicKeyBytes)
if err != nil {
return ObliviousDoHConfigContents{}, errors.New(fmt.Sprintf("Invalid HPKE public key bytes"))
}
return ObliviousDoHConfigContents{
KemID: KemID,
KdfID: KdfID,
AeadID: AeadID,
PublicKeyBytes: publicKeyBytes,
}, nil
}
func (k ObliviousDoHConfigContents) PublicKey() []byte {
return k.PublicKeyBytes
}
func (k ObliviousDoHConfigContents) CipherSuite() (hpke.CipherSuite, error) {
return hpke.AssembleCipherSuite(k.KemID, k.KdfID, k.AeadID)
}
type ObliviousDoHConfig struct {
Version uint16
Contents ObliviousDoHConfigContents
}
func CreateObliviousDoHConfig(contents ObliviousDoHConfigContents) ObliviousDoHConfig {
return ObliviousDoHConfig{
Version: ODOH_VERSION,
Contents: contents,
}
}
func (c ObliviousDoHConfig) Marshal() []byte {
marshalledConfig := c.Contents.Marshal()
buffer := make([]byte, 4)
binary.BigEndian.PutUint16(buffer[0:], uint16(c.Version))
binary.BigEndian.PutUint16(buffer[2:], uint16(len(marshalledConfig)))
configBytes := append(buffer, marshalledConfig...)
return configBytes
}
func parseConfigHeader(buffer []byte) (uint16, uint16, error) {
if len(buffer) < 4 {
return uint16(0), uint16(0), errors.New("Invalid ObliviousDoHConfig encoding")
}
version := binary.BigEndian.Uint16(buffer[0:])
length := binary.BigEndian.Uint16(buffer[2:])
return version, length, nil
}
func isSupportedConfigVersion(version uint16) bool {
return version == ODOH_VERSION
}
func UnmarshalObliviousDoHConfig(buffer []byte) (ObliviousDoHConfig, error) {
version, length, err := parseConfigHeader(buffer)
if err != nil {
return ObliviousDoHConfig{}, err
}
if !isSupportedConfigVersion(version) {
return ObliviousDoHConfig{}, errors.New(fmt.Sprintf("Unsupported version: %04x", version))
}
if len(buffer[4:]) < int(length) {
return ObliviousDoHConfig{}, errors.New(fmt.Sprintf("Invalid serialized ObliviousDoHConfig, expected %v bytes, got %v", length, len(buffer[4:])))
}
configContents, err := UnmarshalObliviousDoHConfigContents(buffer[4:])
if err != nil {
return ObliviousDoHConfig{}, err
}
return ObliviousDoHConfig{
Version: version,
Contents: configContents,
}, nil
}
type ObliviousDoHConfigs struct {
Configs []ObliviousDoHConfig
}
func CreateObliviousDoHConfigs(configs []ObliviousDoHConfig) ObliviousDoHConfigs {
return ObliviousDoHConfigs{
Configs: configs,
}
}
func (c ObliviousDoHConfigs) Marshal() []byte {
serializedConfigs := make([]byte, 0)
for _, config := range c.Configs {
serializedConfigs = append(serializedConfigs, config.Marshal()...)
}
buffer := make([]byte, 2)
binary.BigEndian.PutUint16(buffer[0:], uint16(len(serializedConfigs)))
result := append(buffer, serializedConfigs...)
return result
}
func UnmarshalObliviousDoHConfigs(buffer []byte) (ObliviousDoHConfigs, error) {
if len(buffer) < 2 {
return ObliviousDoHConfigs{}, errors.New("Invalid ObliviousDoHConfigs encoding")
}
configs := make([]ObliviousDoHConfig, 0)
length := binary.BigEndian.Uint16(buffer[0:])
offset := uint16(2)
for {
configVersion, configLength, err := parseConfigHeader(buffer[offset:])
if err != nil {
return ObliviousDoHConfigs{}, errors.New("Invalid ObliviousDoHConfigs encoding")
}
if uint16(len(buffer[offset:])) < configLength {
// The configs vector is encoded incorrectly, so discard the whole thing
return ObliviousDoHConfigs{}, errors.New(fmt.Sprintf("Invalid serialized ObliviousDoHConfig, expected %v bytes, got %v", length, len(buffer[offset:])))
}
if isSupportedConfigVersion(configVersion) {
config, err := UnmarshalObliviousDoHConfig(buffer[offset:])
if err == nil {
configs = append(configs, config)
}
} else {
// Skip over unsupported versions
}
offset += 4 + configLength
if offset >= 2+length {
// Stop reading
break
}
}
return CreateObliviousDoHConfigs(configs), nil
}
type ObliviousDoHKeyPair struct {
Config ObliviousDoHConfig
secretKey hpke.KEMPrivateKey
Seed []byte
}
func CreateKeyPairFromSeed(kemID hpke.KEMID, kdfID hpke.KDFID, aeadID hpke.AEADID, ikm []byte) (ObliviousDoHKeyPair, error) {
suite, err := hpke.AssembleCipherSuite(kemID, kdfID, aeadID)
if err != nil {
return ObliviousDoHKeyPair{}, err
}
sk, pk, err := suite.KEM.DeriveKeyPair(ikm)
if err != nil {
return ObliviousDoHKeyPair{}, err
}
configContents, err := CreateObliviousDoHConfigContents(kemID, kdfID, aeadID, suite.KEM.Serialize(pk))
if err != nil {
return ObliviousDoHKeyPair{}, err
}
config := CreateObliviousDoHConfig(configContents)
return ObliviousDoHKeyPair{
Config: config,
secretKey: sk,
Seed: ikm,
}, nil
}
func CreateDefaultKeyPairFromSeed(seed []byte) (ObliviousDoHKeyPair, error) {
return CreateKeyPairFromSeed(ODOH_DEFAULT_KEMID, ODOH_DEFAULT_KDFID, ODOH_DEFAULT_AEADID, seed)
}
func CreateKeyPair(kemID hpke.KEMID, kdfID hpke.KDFID, aeadID hpke.AEADID) (ObliviousDoHKeyPair, error) {
suite, err := hpke.AssembleCipherSuite(kemID, kdfID, aeadID)
if err != nil {
return ObliviousDoHKeyPair{}, err
}
ikm := make([]byte, suite.KEM.PrivateKeySize())
rand.Reader.Read(ikm)
sk, pk, err := suite.KEM.DeriveKeyPair(ikm)
if err != nil {
return ObliviousDoHKeyPair{}, err
}
configContents, err := CreateObliviousDoHConfigContents(kemID, kdfID, aeadID, suite.KEM.Serialize(pk))
if err != nil {
return ObliviousDoHKeyPair{}, err
}
config := CreateObliviousDoHConfig(configContents)
return ObliviousDoHKeyPair{
Config: config,
secretKey: sk,
Seed: ikm,
}, nil
}
func CreateDefaultKeyPair() (ObliviousDoHKeyPair, error) {
return CreateKeyPair(ODOH_DEFAULT_KEMID, ODOH_DEFAULT_KDFID, ODOH_DEFAULT_AEADID)
}
type QueryContext struct {
odohSecret []byte
suite hpke.CipherSuite
query []byte
publicKey ObliviousDoHConfigContents
}
func (c QueryContext) DecryptResponse(message ObliviousDNSMessage) ([]byte, error) {
aad := append([]byte{byte(ResponseType)}, []byte{0x00, 0x00}...) // 0-length encoded KeyID
odohPRK := c.suite.KDF.Extract(c.query, c.odohSecret)
key := c.suite.KDF.Expand(odohPRK, []byte(ODOH_LABEL_KEY), c.suite.AEAD.KeySize())
nonce := c.suite.KDF.Expand(odohPRK, []byte(ODOH_LABEL_NONCE), c.suite.AEAD.NonceSize())
aead, err := c.suite.AEAD.New(key)
if err != nil {
return nil, err
}
return aead.Open(nil, nonce, message.EncryptedMessage, aad)
}
type ResponseContext struct {
query []byte
suite hpke.CipherSuite
odohSecret []byte
}
func (c ResponseContext) EncryptResponse(response *ObliviousDNSResponse) (ObliviousDNSMessage, error) {
aad := append([]byte{byte(ResponseType)}, []byte{0x00, 0x00}...) // 0-length encoded KeyID
odohPRK := c.suite.KDF.Extract(c.query, c.odohSecret)
key := c.suite.KDF.Expand(odohPRK, []byte(ODOH_LABEL_KEY), c.suite.AEAD.KeySize())
nonce := c.suite.KDF.Expand(odohPRK, []byte(ODOH_LABEL_NONCE), c.suite.AEAD.NonceSize())
aead, err := c.suite.AEAD.New(key)
if err != nil {
return ObliviousDNSMessage{}, err
}
ciphertext := aead.Seal(nil, nonce, response.Marshal(), aad)
odohMessage := ObliviousDNSMessage{
KeyID: nil,
MessageType: ResponseType,
EncryptedMessage: ciphertext,
}
return odohMessage, nil
}
func (targetKey ObliviousDoHConfigContents) EncryptQuery(query *ObliviousDNSQuery) (ObliviousDNSMessage, QueryContext, error) {
suite, err := hpke.AssembleCipherSuite(targetKey.KemID, targetKey.KdfID, targetKey.AeadID)
if err != nil {
return ObliviousDNSMessage{}, QueryContext{}, err
}
pkR, err := suite.KEM.Deserialize(targetKey.PublicKeyBytes)
if err != nil {
return ObliviousDNSMessage{}, QueryContext{}, err
}
enc, ctxI, err := hpke.SetupBaseS(suite, rand.Reader, pkR, []byte(ODOH_LABEL_QUERY))
if err != nil {
return ObliviousDNSMessage{}, QueryContext{}, err
}
keyID := targetKey.KeyID()
keyIDLength := make([]byte, 2)
binary.BigEndian.PutUint16(keyIDLength, uint16(len(keyID)))
aad := append([]byte{byte(QueryType)}, keyIDLength...)
aad = append(aad, keyID...)
encodedMessage := query.Marshal()
ct := ctxI.Seal(aad, encodedMessage)
odohSecret := ctxI.Export([]byte(ODOH_LABEL_SECRET), ODOH_SECRET_LENGTH)
return ObliviousDNSMessage{
KeyID: targetKey.KeyID(),
MessageType: QueryType,
EncryptedMessage: append(enc, ct...),
}, QueryContext{
odohSecret: odohSecret,
suite: suite,
query: query.Marshal(),
publicKey: targetKey,
}, nil
}
func validateMessagePadding(padding []byte) bool {
validPadding := 1
for _, v := range padding {
validPadding &= subtle.ConstantTimeByteEq(v, ODOH_PADDING_BYTE)
}
return validPadding == 1
}
func (privateKey ObliviousDoHKeyPair) DecryptQuery(message ObliviousDNSMessage) (*ObliviousDNSQuery, ResponseContext, error) {
if message.MessageType != QueryType {
return nil, ResponseContext{}, errors.New("message is not a query")
}
suite, err := hpke.AssembleCipherSuite(privateKey.Config.Contents.KemID, privateKey.Config.Contents.KdfID, privateKey.Config.Contents.AeadID)
if err != nil {
return nil, ResponseContext{}, err
}
keySize := suite.KEM.PublicKeySize()
enc := message.EncryptedMessage[0:keySize]
ct := message.EncryptedMessage[keySize:]
ctxR, err := hpke.SetupBaseR(suite, privateKey.secretKey, enc, []byte(ODOH_LABEL_QUERY))
if err != nil {
return nil, ResponseContext{}, err
}
odohSecret := ctxR.Export([]byte(ODOH_LABEL_SECRET), ODOH_SECRET_LENGTH)
keyID := privateKey.Config.Contents.KeyID()
keyIDLength := make([]byte, 2)
binary.BigEndian.PutUint16(keyIDLength, uint16(len(keyID)))
aad := append([]byte{byte(QueryType)}, keyIDLength...)
aad = append(aad, keyID...)
dnsMessage, err := ctxR.Open(aad, ct)
if err != nil {
return nil, ResponseContext{}, err
}
query, err := UnmarshalQueryBody(dnsMessage)
if err != nil {
return nil, ResponseContext{}, err
}
if !validateMessagePadding(query.Padding) {
return nil, ResponseContext{}, errors.New("invalid padding")
}
responseContext := ResponseContext{
odohSecret: odohSecret,
suite: suite,
query: query.Marshal(),
}
return query, responseContext, nil
}
func SealQuery(dnsQuery []byte, publicKey ObliviousDoHConfigContents) (ObliviousDNSMessage, QueryContext, error) {
odohQuery := CreateObliviousDNSQuery(dnsQuery, 0)
odohMessage, queryContext, err := publicKey.EncryptQuery(odohQuery)
if err != nil {
return ObliviousDNSMessage{}, QueryContext{}, err
}
return odohMessage, queryContext, nil
}
func (c QueryContext) OpenAnswer(message ObliviousDNSMessage) ([]byte, error) {
if message.MessageType != ResponseType {
return nil, errors.New("message is not a response")
}
decryptedResponseBytes, err := c.DecryptResponse(message)
if err != nil {
return nil, errors.New("unable to decrypt the obtained response using the symmetric key sent")
}
decryptedResponse, err := UnmarshalResponseBody(decryptedResponseBytes)
if err != nil {
return nil, err
}
return decryptedResponse.DnsMessage, nil
}

File diff suppressed because one or more lines are too long

View File

@ -26,7 +26,6 @@ avoiding breaking changes wherever reasonable. We support the last two versions
A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/coredns/coredns
* https://cloudflare.com
* https://github.com/abh/geodns
* https://github.com/baidu/bfe
* http://www.statdns.com/
@ -42,11 +41,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/StalkR/dns-reverse-proxy
* https://github.com/tianon/rawdns
* https://mesosphere.github.io/mesos-dns/
* https://pulse.turbobytes.com/
* https://github.com/fcambus/statzone
* https://github.com/benschw/dns-clb-go
* https://github.com/corny/dnscheck for <http://public-dns.info/>
* https://namesmith.io
* https://github.com/miekg/unbound
* https://github.com/miekg/exdns
* https://dnslookup.org
@ -55,24 +52,22 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/mehrdadrad/mylg
* https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns
* http://kelda.io
* https://github.com/ipdcode/hades <https://jd.com>
* https://github.com/StackExchange/dnscontrol/
* https://www.dnsperf.com/
* https://dnssectest.net/
* https://dns.apebits.com
* https://github.com/oif/apex
* https://github.com/jedisct1/dnscrypt-proxy
* https://github.com/jedisct1/rpdns
* https://github.com/xor-gate/sshfp
* https://github.com/rs/dnstrace
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
* https://github.com/semihalev/sdns
* https://render.com
* https://github.com/peterzen/goresolver
* https://github.com/folbricht/routedns
* https://domainr.com/
* https://zonedb.org/
* https://router7.org/
Send pull request if you want to be listed here.

View File

@ -34,7 +34,7 @@ type Client struct {
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext)
// Client.Dialer) or context.Context.Deadline (see ExchangeContext)
Timeout time.Duration
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
@ -106,7 +106,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
if err != nil {
return nil, err
}
conn.UDPSize = c.UDPSize
return conn, nil
}

View File

@ -6,6 +6,7 @@ import (
"encoding/binary"
"encoding/hex"
"net"
"sort"
"strings"
)
@ -612,6 +613,65 @@ func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
return off, nil
}
func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
var xs []SVCBKeyValue
var code uint16
var length uint16
var err error
for off < len(msg) {
code, off, err = unpackUint16(msg, off)
if err != nil {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
length, off, err = unpackUint16(msg, off)
if err != nil || off+int(length) > len(msg) {
return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
}
e := makeSVCBKeyValue(SVCBKey(code))
if e == nil {
return nil, len(msg), &Error{err: "bad SVCB key"}
}
if err := e.unpack(msg[off : off+int(length)]); err != nil {
return nil, len(msg), err
}
if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
}
xs = append(xs, e)
off += int(length)
}
return xs, off, nil
}
func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
pairs = append([]SVCBKeyValue(nil), pairs...)
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].Key() < pairs[j].Key()
})
prev := svcb_RESERVED
for _, el := range pairs {
if el.Key() == prev {
return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
}
prev = el.Key()
packed, err := el.pack()
if err != nil {
return len(msg), err
}
off, err = packUint16(uint16(el.Key()), msg, off)
if err != nil {
return len(msg), &Error{err: "overflow packing SVCB"}
}
off, err = packUint16(uint16(len(packed)), msg, off)
if err != nil || off+len(packed) > len(msg) {
return len(msg), &Error{err: "overflow packing SVCB"}
}
copy(msg[off:off+len(packed)], packed)
off += len(packed)
}
return off, nil
}
func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
var (
servers []string
@ -683,6 +743,13 @@ func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
if p.Negation {
n = 0x80
}
// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
i := len(addr) - 1
for ; i >= 0 && addr[i] == 0; i-- {
}
addr = addr[:i+1]
adflen := uint8(len(addr)) & 0x7f
off, err = packUint8(n|adflen, msg, off)
if err != nil {

29
vendor/github.com/miekg/dns/scan.go generated vendored
View File

@ -1210,11 +1210,29 @@ func stringToCm(token string) (e, m uint8, ok bool) {
if cmeters, err = strconv.Atoi(s[1]); err != nil {
return
}
// There's no point in having more than 2 digits in this part, and would rather make the implementation complicated ('123' should be treated as '12').
// So we simply reject it.
// We also make sure the first character is a digit to reject '+-' signs.
if len(s[1]) > 2 || s[1][0] < '0' || s[1][0] > '9' {
return
}
if len(s[1]) == 1 {
// 'nn.1' must be treated as 'nn-meters and 10cm, not 1cm.
cmeters *= 10
}
if len(s[0]) == 0 {
// This will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm).
break
}
fallthrough
case 1:
if meters, err = strconv.Atoi(s[0]); err != nil {
return
}
// RFC1876 states the max value is 90000000.00. The latter two conditions enforce it.
if s[0][0] < '0' || s[0][0] > '9' || meters > 90000000 || (meters == 90000000 && cmeters != 0) {
return
}
case 0:
// huh?
return 0, 0, false
@ -1227,13 +1245,10 @@ func stringToCm(token string) (e, m uint8, ok bool) {
e = 0
val = cmeters
}
for val > 10 {
for val >= 10 {
e++
val /= 10
}
if e > 9 {
ok = false
}
m = uint8(val)
return
}
@ -1275,6 +1290,9 @@ func appendOrigin(name, origin string) string {
// LOC record helper function
func locCheckNorth(token string, latitude uint32) (uint32, bool) {
if latitude > 90 * 1000 * 60 * 60 {
return latitude, false
}
switch token {
case "n", "N":
return LOC_EQUATOR + latitude, true
@ -1286,6 +1304,9 @@ func locCheckNorth(token string, latitude uint32) (uint32, bool) {
// LOC record helper function
func locCheckEast(token string, longitude uint32) (uint32, bool) {
if longitude > 180 * 1000 * 60 * 60 {
return longitude, false
}
switch token {
case "e", "E":
return LOC_EQUATOR + longitude, true

View File

@ -590,7 +590,7 @@ func (rr *LOC) parse(c *zlexer, o string) *ParseError {
// North
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
if e != nil || l.err || i > 90 {
return &ParseError{"", "bad LOC Latitude", l}
}
rr.Latitude = 1000 * 60 * 60 * uint32(i)
@ -601,7 +601,7 @@ func (rr *LOC) parse(c *zlexer, o string) *ParseError {
if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
goto East
}
if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err {
if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
return &ParseError{"", "bad LOC Latitude minutes", l}
} else {
rr.Latitude += 1000 * 60 * uint32(i)
@ -609,7 +609,7 @@ func (rr *LOC) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank
l, _ = c.Next()
if i, err := strconv.ParseFloat(l.token, 32); err != nil || l.err {
if i, err := strconv.ParseFloat(l.token, 32); err != nil || l.err || i < 0 || i >= 60 {
return &ParseError{"", "bad LOC Latitude seconds", l}
} else {
rr.Latitude += uint32(1000 * i)
@ -627,7 +627,7 @@ East:
// East
c.Next() // zBlank
l, _ = c.Next()
if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err {
if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 180 {
return &ParseError{"", "bad LOC Longitude", l}
} else {
rr.Longitude = 1000 * 60 * 60 * uint32(i)
@ -638,14 +638,14 @@ East:
if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
goto Altitude
}
if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err {
if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
return &ParseError{"", "bad LOC Longitude minutes", l}
} else {
rr.Longitude += 1000 * 60 * uint32(i)
}
c.Next() // zBlank
l, _ = c.Next()
if i, err := strconv.ParseFloat(l.token, 32); err != nil || l.err {
if i, err := strconv.ParseFloat(l.token, 32); err != nil || l.err || i < 0 || i >= 60 {
return &ParseError{"", "bad LOC Longitude seconds", l}
} else {
rr.Longitude += uint32(1000 * i)
@ -668,7 +668,7 @@ Altitude:
if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
l.token = l.token[0 : len(l.token)-1]
}
if i, err := strconv.ParseFloat(l.token, 32); err != nil {
if i, err := strconv.ParseFloat(l.token, 64); err != nil {
return &ParseError{"", "bad LOC Altitude", l}
} else {
rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
@ -893,8 +893,7 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
l, _ = c.Next()
if i, err := StringToTime(l.token); err != nil {
// Try to see if all numeric and use it as epoch
if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
// TODO(miek): error out on > MAX_UINT32, same below
if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
rr.Expiration = uint32(i)
} else {
return &ParseError{"", "bad RRSIG Expiration", l}
@ -906,7 +905,7 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank
l, _ = c.Next()
if i, err := StringToTime(l.token); err != nil {
if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
rr.Inception = uint32(i)
} else {
return &ParseError{"", "bad RRSIG Inception", l}

View File

@ -91,7 +91,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
// are redirected to the parent zone (if that is also registered),
// otherwise the child gets the query.
//
// If no handler is found, or there is no question, a standard SERVFAIL
// If no handler is found, or there is no question, a standard REFUSED
// message is returned
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
var h Handler
@ -102,7 +102,7 @@ func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
if h != nil {
h.ServeDNS(w, req)
} else {
HandleFailed(w, req)
handleRefused(w, req)
}
}

View File

@ -78,7 +78,15 @@ type response struct {
writer Writer // writer to output the raw DNS bits
}
// handleRefused returns a HandlerFunc that returns REFUSED for every request it gets.
func handleRefused(w ResponseWriter, r *Msg) {
m := new(Msg)
m.SetRcode(r, RcodeRefused)
w.WriteMsg(m)
}
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
// Deprecated: This function is going away.
func HandleFailed(w ResponseWriter, r *Msg) {
m := new(Msg)
m.SetRcode(r, RcodeServerFailure)

773
vendor/github.com/miekg/dns/svcb.go generated vendored Normal file
View File

@ -0,0 +1,773 @@
package dns
import (
"bytes"
"encoding/binary"
"errors"
"net"
"sort"
"strconv"
"strings"
)
type SVCBKey uint16
// Keys defined in draft-ietf-dnsop-svcb-https-02 Section 11.1.2
const (
SVCB_MANDATORY SVCBKey = 0
SVCB_ALPN SVCBKey = 1
SVCB_NO_DEFAULT_ALPN SVCBKey = 2
SVCB_PORT SVCBKey = 3
SVCB_IPV4HINT SVCBKey = 4
SVCB_ECHCONFIG SVCBKey = 5
SVCB_IPV6HINT SVCBKey = 6
svcb_RESERVED SVCBKey = 65535
)
var svcbKeyToStringMap = map[SVCBKey]string{
SVCB_MANDATORY: "mandatory",
SVCB_ALPN: "alpn",
SVCB_NO_DEFAULT_ALPN: "no-default-alpn",
SVCB_PORT: "port",
SVCB_IPV4HINT: "ipv4hint",
SVCB_ECHCONFIG: "echconfig",
SVCB_IPV6HINT: "ipv6hint",
}
var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap)
func reverseSVCBKeyMap(m map[SVCBKey]string) map[string]SVCBKey {
n := make(map[string]SVCBKey, len(m))
for u, s := range m {
n[s] = u
}
return n
}
// String takes the numerical code of an SVCB key and returns its name.
// Returns an empty string for reserved keys.
// Accepts unassigned keys as well as experimental/private keys.
func (key SVCBKey) String() string {
if x := svcbKeyToStringMap[key]; x != "" {
return x
}
if key == svcb_RESERVED {
return ""
}
return "key" + strconv.FormatUint(uint64(key), 10)
}
// svcbStringToKey returns the numerical code of an SVCB key.
// Returns svcb_RESERVED for reserved/invalid keys.
// Accepts unassigned keys as well as experimental/private keys.
func svcbStringToKey(s string) SVCBKey {
if strings.HasPrefix(s, "key") {
a, err := strconv.ParseUint(s[3:], 10, 16)
// no leading zeros
// key shouldn't be registered
if err != nil || a == 65535 || s[3] == '0' || svcbKeyToStringMap[SVCBKey(a)] != "" {
return svcb_RESERVED
}
return SVCBKey(a)
}
if key, ok := svcbStringToKeyMap[s]; ok {
return key
}
return svcb_RESERVED
}
func (rr *SVCB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{l.token, "bad SVCB priority", l}
}
rr.Priority = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Target = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{l.token, "bad SVCB Target", l}
}
rr.Target = name
// Values (if any)
l, _ = c.Next()
var xs []SVCBKeyValue
// Helps require whitespace between pairs.
// Prevents key1000="a"key1001=...
canHaveNextKey := true
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
if !canHaveNextKey {
// The key we can now read was probably meant to be
// a part of the last value.
return &ParseError{l.token, "bad SVCB value quotation", l}
}
// In key=value pairs, value does not have to be quoted unless value
// contains whitespace. And keys don't need to have values.
// Similarly, keys with an equality signs after them don't need values.
// l.token includes at least up to the first equality sign.
idx := strings.IndexByte(l.token, '=')
var key, value string
if idx < 0 {
// Key with no value and no equality sign
key = l.token
} else if idx == 0 {
return &ParseError{l.token, "bad SVCB key", l}
} else {
key, value = l.token[:idx], l.token[idx+1:]
if value == "" {
// We have a key and an equality sign. Maybe we have nothing
// after "=" or we have a double quote.
l, _ = c.Next()
if l.value == zQuote {
// Only needed when value ends with double quotes.
// Any value starting with zQuote ends with it.
canHaveNextKey = false
l, _ = c.Next()
switch l.value {
case zString:
// We have a value in double quotes.
value = l.token
l, _ = c.Next()
if l.value != zQuote {
return &ParseError{l.token, "SVCB unterminated value", l}
}
case zQuote:
// There's nothing in double quotes.
default:
return &ParseError{l.token, "bad SVCB value", l}
}
}
}
}
kv := makeSVCBKeyValue(svcbStringToKey(key))
if kv == nil {
return &ParseError{l.token, "bad SVCB key", l}
}
if err := kv.parse(value); err != nil {
return &ParseError{l.token, err.Error(), l}
}
xs = append(xs, kv)
case zQuote:
return &ParseError{l.token, "SVCB key can't contain double quotes", l}
case zBlank:
canHaveNextKey = true
default:
return &ParseError{l.token, "bad SVCB values", l}
}
l, _ = c.Next()
}
rr.Value = xs
if rr.Priority == 0 && len(xs) > 0 {
return &ParseError{l.token, "SVCB aliasform can't have values", l}
}
return nil
}
// makeSVCBKeyValue returns an SVCBKeyValue struct with the key
// or nil for reserved keys.
func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue {
switch key {
case SVCB_MANDATORY:
return new(SVCBMandatory)
case SVCB_ALPN:
return new(SVCBAlpn)
case SVCB_NO_DEFAULT_ALPN:
return new(SVCBNoDefaultAlpn)
case SVCB_PORT:
return new(SVCBPort)
case SVCB_IPV4HINT:
return new(SVCBIPv4Hint)
case SVCB_ECHCONFIG:
return new(SVCBECHConfig)
case SVCB_IPV6HINT:
return new(SVCBIPv6Hint)
case svcb_RESERVED:
return nil
default:
e := new(SVCBLocal)
e.KeyCode = key
return e
}
}
// SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-00)
// The one with the smallest priority should be given preference. Of those with
// equal priority, a random one should be preferred for load balancing.
type SVCB struct {
Hdr RR_Header
Priority uint16
Target string `dns:"domain-name"`
Value []SVCBKeyValue `dns:"pairs"` // This must be empty if Priority is non-zero
}
// HTTPS RR. Everything valid for SVCB applies to HTTPS as well
// except that the HTTPS record is intended for use with the HTTP and HTTPS protocols.
type HTTPS struct {
SVCB
}
func (rr *HTTPS) String() string {
return rr.SVCB.String()
}
func (rr *HTTPS) parse(c *zlexer, o string) *ParseError {
return rr.SVCB.parse(c, o)
}
// SVCBKeyValue defines a key=value pair for the SVCB RR type.
// An SVCB RR can have multiple SVCBKeyValues appended to it.
type SVCBKeyValue interface {
// Key returns the numerical key code.
Key() SVCBKey
// pack returns the encoded value.
pack() ([]byte, error)
// unpack sets the value.
unpack([]byte) error
// String returns the string representation of the value.
String() string
// parse sets the value to the given string representation of the value.
parse(string) error
// copy returns a deep-copy of the pair.
copy() SVCBKeyValue
// len returns the length of value in the wire format.
len() int
}
// SVCBMandatory pair adds to required keys that must be interpreted for the RR
// to be functional.
// Basic use pattern for creating a mandatory option:
//
// o := new(dns.SVCB)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.TypeSVCB
// e := new(dns.SVCBMandatory)
// e.Code = []uint16{65403}
// o.Value = append(o.Value, e)
// // Then add key-value pair for key65403
type SVCBMandatory struct {
Code []SVCBKey // Must not include mandatory
}
func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY }
func (s *SVCBMandatory) String() string {
str := make([]string, len(s.Code))
for i, e := range s.Code {
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBMandatory) pack() ([]byte, error) {
codes := append([]SVCBKey(nil), s.Code...)
sort.Slice(codes, func(i, j int) bool {
return codes[i] < codes[j]
})
b := make([]byte, 2*len(codes))
for i, e := range codes {
binary.BigEndian.PutUint16(b[2*i:], uint16(e))
}
return b, nil
}
func (s *SVCBMandatory) unpack(b []byte) error {
if len(b)%2 != 0 {
return errors.New("dns: svcbmandatory: value length is not a multiple of 2")
}
codes := make([]SVCBKey, 0, len(b)/2)
for i := 0; i < len(b); i += 2 {
// We assume strictly increasing order.
codes = append(codes, SVCBKey(binary.BigEndian.Uint16(b[i:])))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) parse(b string) error {
str := strings.Split(b, ",")
codes := make([]SVCBKey, 0, len(str))
for _, e := range str {
codes = append(codes, svcbStringToKey(e))
}
s.Code = codes
return nil
}
func (s *SVCBMandatory) len() int {
return 2 * len(s.Code)
}
func (s *SVCBMandatory) copy() SVCBKeyValue {
return &SVCBMandatory{
append([]SVCBKey(nil), s.Code...),
}
}
// SVCBAlpn pair is used to list supported connection protocols.
// Protocol ids can be found at:
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
// Basic use pattern for creating an alpn option:
//
// o := new(dns.HTTPS)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.TypeHTTPS
// e := new(dns.SVCBAlpn)
// e.Alpn = []string{"h2", "http/1.1"}
// o.Value = append(o.Value, e)
type SVCBAlpn struct {
Alpn []string
}
func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN }
func (s *SVCBAlpn) String() string { return strings.Join(s.Alpn, ",") }
// The spec requires the alpn keys including \ or , to be escaped.
// In practice, no standard key including those exists.
// Therefore those characters are not escaped.
func (s *SVCBAlpn) pack() ([]byte, error) {
// Liberally estimate the size of an alpn as 10 octets
b := make([]byte, 0, 10*len(s.Alpn))
for _, e := range s.Alpn {
if len(e) == 0 {
return nil, errors.New("dns: svcbalpn: empty alpn-id")
}
if len(e) > 255 {
return nil, errors.New("dns: svcbalpn: alpn-id too long")
}
b = append(b, byte(len(e)))
b = append(b, e...)
}
return b, nil
}
func (s *SVCBAlpn) unpack(b []byte) error {
// Estimate the size of the smallest alpn as 4 bytes
alpn := make([]string, 0, len(b)/4)
for i := 0; i < len(b); {
length := int(b[i])
i++
if i+length > len(b) {
return errors.New("dns: svcbalpn: alpn array overflowing")
}
alpn = append(alpn, string(b[i:i+length]))
i += length
}
s.Alpn = alpn
return nil
}
func (s *SVCBAlpn) parse(b string) error {
s.Alpn = strings.Split(b, ",")
return nil
}
func (s *SVCBAlpn) len() int {
var l int
for _, e := range s.Alpn {
l += 1 + len(e)
}
return l
}
func (s *SVCBAlpn) copy() SVCBKeyValue {
return &SVCBAlpn{
append([]string(nil), s.Alpn...),
}
}
// SVCBNoDefaultAlpn pair signifies no support for default connection protocols.
// Basic use pattern for creating a no-default-alpn option:
//
// o := new(dns.SVCB)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.SVCB
// e := new(dns.SVCBNoDefaultAlpn)
// o.Value = append(o.Value, e)
type SVCBNoDefaultAlpn struct {
// Empty
}
func (*SVCBNoDefaultAlpn) Key() SVCBKey { return SVCB_NO_DEFAULT_ALPN }
func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue { return &SVCBNoDefaultAlpn{} }
func (*SVCBNoDefaultAlpn) pack() ([]byte, error) { return []byte{}, nil }
func (*SVCBNoDefaultAlpn) String() string { return "" }
func (*SVCBNoDefaultAlpn) len() int { return 0 }
func (*SVCBNoDefaultAlpn) unpack(b []byte) error {
if len(b) != 0 {
return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
}
return nil
}
func (*SVCBNoDefaultAlpn) parse(b string) error {
if len(b) != 0 {
return errors.New("dns: svcbnodefaultalpn: no_default_alpn must have no value")
}
return nil
}
// SVCBPort pair defines the port for connection.
// Basic use pattern for creating a port option:
//
// o := new(dns.SVCB)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.SVCB
// e := new(dns.SVCBPort)
// e.Port = 80
// o.Value = append(o.Value, e)
type SVCBPort struct {
Port uint16
}
func (*SVCBPort) Key() SVCBKey { return SVCB_PORT }
func (*SVCBPort) len() int { return 2 }
func (s *SVCBPort) String() string { return strconv.FormatUint(uint64(s.Port), 10) }
func (s *SVCBPort) copy() SVCBKeyValue { return &SVCBPort{s.Port} }
func (s *SVCBPort) unpack(b []byte) error {
if len(b) != 2 {
return errors.New("dns: svcbport: port length is not exactly 2 octets")
}
s.Port = binary.BigEndian.Uint16(b)
return nil
}
func (s *SVCBPort) pack() ([]byte, error) {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, s.Port)
return b, nil
}
func (s *SVCBPort) parse(b string) error {
port, err := strconv.ParseUint(b, 10, 16)
if err != nil {
return errors.New("dns: svcbport: port out of range")
}
s.Port = uint16(port)
return nil
}
// SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the connection
// to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv4hint option:
//
// o := new(dns.HTTPS)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBIPv4Hint)
// e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()}
// // or
// e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()}
// o.Value = append(o.Value, e)
type SVCBIPv4Hint struct {
Hint []net.IP
}
func (*SVCBIPv4Hint) Key() SVCBKey { return SVCB_IPV4HINT }
func (s *SVCBIPv4Hint) len() int { return 4 * len(s.Hint) }
func (s *SVCBIPv4Hint) pack() ([]byte, error) {
b := make([]byte, 0, 4*len(s.Hint))
for _, e := range s.Hint {
x := e.To4()
if x == nil {
return nil, errors.New("dns: svcbipv4hint: expected ipv4, hint is ipv6")
}
b = append(b, x...)
}
return b, nil
}
func (s *SVCBIPv4Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%4 != 0 {
return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4")
}
x := make([]net.IP, 0, len(b)/4)
for i := 0; i < len(b); i += 4 {
x = append(x, net.IP(b[i:i+4]))
}
s.Hint = x
return nil
}
// String returns the string form of s, it returns "<nil>" if s is invalid.
func (s *SVCBIPv4Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
x := e.To4()
if x == nil {
return "<nil>"
}
str[i] = x.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv4Hint) parse(b string) error {
if strings.Contains(b, ":") {
return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e).To4()
if ip == nil {
return errors.New("dns: svcbipv4hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv4Hint) copy() SVCBKeyValue {
return &SVCBIPv4Hint{
append([]net.IP(nil), s.Hint...),
}
}
// SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx].
// Basic use pattern for creating an echconfig option:
//
// o := new(dns.HTTPS)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBECHConfig)
// e.ECH = "/wH...="
// o.Value = append(o.Value, e)
type SVCBECHConfig struct {
ECH []byte
}
func (*SVCBECHConfig) Key() SVCBKey { return SVCB_ECHCONFIG }
func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) }
func (s *SVCBECHConfig) len() int { return len(s.ECH) }
func (s *SVCBECHConfig) pack() ([]byte, error) {
return append([]byte(nil), s.ECH...), nil
}
func (s *SVCBECHConfig) copy() SVCBKeyValue {
return &SVCBECHConfig{
append([]byte(nil), s.ECH...),
}
}
func (s *SVCBECHConfig) unpack(b []byte) error {
s.ECH = append([]byte(nil), b...)
return nil
}
func (s *SVCBECHConfig) parse(b string) error {
x, err := fromBase64([]byte(b))
if err != nil {
return errors.New("dns: svcbechconfig: bad base64 echconfig")
}
s.ECH = x
return nil
}
// SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections
// if A and AAAA record responses for SVCB's Target domain haven't been received.
// In that case, optionally, A and AAAA requests can be made, after which the
// connection to the hinted IP address may be terminated and a new connection may be opened.
// Basic use pattern for creating an ipv6hint option:
//
// o := new(dns.HTTPS)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBIPv6Hint)
// e.Hint = []net.IP{net.ParseIP("2001:db8::1")}
// o.Value = append(o.Value, e)
type SVCBIPv6Hint struct {
Hint []net.IP
}
func (*SVCBIPv6Hint) Key() SVCBKey { return SVCB_IPV6HINT }
func (s *SVCBIPv6Hint) len() int { return 16 * len(s.Hint) }
func (s *SVCBIPv6Hint) pack() ([]byte, error) {
b := make([]byte, 0, 16*len(s.Hint))
for _, e := range s.Hint {
if len(e) != net.IPv6len || e.To4() != nil {
return nil, errors.New("dns: svcbipv6hint: expected ipv6, hint is ipv4")
}
b = append(b, e...)
}
return b, nil
}
func (s *SVCBIPv6Hint) unpack(b []byte) error {
if len(b) == 0 || len(b)%16 != 0 {
return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16")
}
x := make([]net.IP, 0, len(b)/16)
for i := 0; i < len(b); i += 16 {
ip := net.IP(b[i : i+16])
if ip.To4() != nil {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
x = append(x, ip)
}
s.Hint = x
return nil
}
// String returns the string form of s, it returns "<nil>" if s is invalid.
func (s *SVCBIPv6Hint) String() string {
str := make([]string, len(s.Hint))
for i, e := range s.Hint {
if x := e.To4(); x != nil {
return "<nil>"
}
str[i] = e.String()
}
return strings.Join(str, ",")
}
func (s *SVCBIPv6Hint) parse(b string) error {
if strings.Contains(b, ".") {
return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4")
}
str := strings.Split(b, ",")
dst := make([]net.IP, len(str))
for i, e := range str {
ip := net.ParseIP(e)
if ip == nil {
return errors.New("dns: svcbipv6hint: bad ip")
}
dst[i] = ip
}
s.Hint = dst
return nil
}
func (s *SVCBIPv6Hint) copy() SVCBKeyValue {
return &SVCBIPv6Hint{
append([]net.IP(nil), s.Hint...),
}
}
// SVCBLocal pair is intended for experimental/private use. The key is recommended
// to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER].
// Basic use pattern for creating a keyNNNNN option:
//
// o := new(dns.HTTPS)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.HTTPS
// e := new(dns.SVCBLocal)
// e.KeyCode = 65400
// e.Data = []byte("abc")
// o.Value = append(o.Value, e)
type SVCBLocal struct {
KeyCode SVCBKey // Never 65535 or any assigned keys
Data []byte // All byte sequences are allowed
}
func (s *SVCBLocal) Key() SVCBKey { return s.KeyCode }
func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil }
func (s *SVCBLocal) len() int { return len(s.Data) }
func (s *SVCBLocal) unpack(b []byte) error {
s.Data = append([]byte(nil), b...)
return nil
}
func (s *SVCBLocal) String() string {
var str strings.Builder
str.Grow(4 * len(s.Data))
for _, e := range s.Data {
if ' ' <= e && e <= '~' {
switch e {
case '"', ';', ' ', '\\':
str.WriteByte('\\')
str.WriteByte(e)
default:
str.WriteByte(e)
}
} else {
str.WriteString(escapeByte(e))
}
}
return str.String()
}
func (s *SVCBLocal) parse(b string) error {
data := make([]byte, 0, len(b))
for i := 0; i < len(b); {
if b[i] != '\\' {
data = append(data, b[i])
i++
continue
}
if i+1 == len(b) {
return errors.New("dns: svcblocal: svcb private/experimental key escape unterminated")
}
if isDigit(b[i+1]) {
if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) {
a, err := strconv.ParseUint(b[i+1:i+4], 10, 8)
if err == nil {
i += 4
data = append(data, byte(a))
continue
}
}
return errors.New("dns: svcblocal: svcb private/experimental key bad escaped octet")
} else {
data = append(data, b[i+1])
i += 2
}
}
s.Data = data
return nil
}
func (s *SVCBLocal) copy() SVCBKeyValue {
return &SVCBLocal{s.KeyCode,
append([]byte(nil), s.Data...),
}
}
func (rr *SVCB) String() string {
s := rr.Hdr.String() +
strconv.Itoa(int(rr.Priority)) + " " +
sprintName(rr.Target)
for _, e := range rr.Value {
s += " " + e.Key().String() + "=\"" + e.String() + "\""
}
return s
}
// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their
// copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function.
func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
a = append([]SVCBKeyValue(nil), a...)
b = append([]SVCBKeyValue(nil), b...)
sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() })
sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() })
for i, e := range a {
if e.Key() != b[i].Key() {
return false
}
b1, err1 := e.pack()
b2, err2 := b[i].pack()
if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) {
return false
}
}
return true
}

View File

@ -81,6 +81,8 @@ const (
TypeCDNSKEY uint16 = 60
TypeOPENPGPKEY uint16 = 61
TypeCSYNC uint16 = 62
TypeSVCB uint16 = 64
TypeHTTPS uint16 = 65
TypeSPF uint16 = 99
TypeUINFO uint16 = 100
TypeUID uint16 = 101

View File

@ -3,7 +3,7 @@ package dns
import "fmt"
// Version is current version of this library.
var Version = v{1, 1, 31}
var Version = v{1, 1, 32}
// v holds the version of this library.
type v struct {

View File

@ -402,6 +402,27 @@ func (r1 *HIP) isDuplicate(_r2 RR) bool {
return true
}
func (r1 *HTTPS) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*HTTPS)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *KEY) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*KEY)
if !ok {
@ -1076,6 +1097,27 @@ func (r1 *SSHFP) isDuplicate(_r2 RR) bool {
return true
}
func (r1 *SVCB) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*SVCB)
if !ok {
return false
}
_ = r2
if r1.Priority != r2.Priority {
return false
}
if !isDuplicateName(r1.Target, r2.Target) {
return false
}
if len(r1.Value) != len(r2.Value) {
return false
}
if !areSVCBPairArraysEqual(r1.Value, r2.Value) {
return false
}
return true
}
func (r1 *TA) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*TA)
if !ok {

82
vendor/github.com/miekg/dns/zmsg.go generated vendored
View File

@ -316,6 +316,22 @@ func (rr *HIP) pack(msg []byte, off int, compression compressionMap, compress bo
return off, nil
}
func (rr *HTTPS) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Flags, msg, off)
if err != nil {
@ -906,6 +922,22 @@ func (rr *SSHFP) pack(msg []byte, off int, compression compressionMap, compress
return off, nil
}
func (rr *SVCB) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.Priority, msg, off)
if err != nil {
return off, err
}
off, err = packDomainName(rr.Target, msg, off, compression, false)
if err != nil {
return off, err
}
off, err = packDataSVCB(rr.Value, msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
off, err = packUint16(rr.KeyTag, msg, off)
if err != nil {
@ -1559,6 +1591,31 @@ func (rr *HIP) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil
}
func (rr *HTTPS) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *KEY) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
@ -2461,6 +2518,31 @@ func (rr *SSHFP) unpack(msg []byte, off int) (off1 int, err error) {
return off, nil
}
func (rr *SVCB) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart
rr.Priority, off, err = unpackUint16(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Target, off, err = UnpackDomainName(msg, off)
if err != nil {
return off, err
}
if off == len(msg) {
return off, nil
}
rr.Value, off, err = unpackDataSVCB(msg, off)
if err != nil {
return off, err
}
return off, nil
}
func (rr *TA) unpack(msg []byte, off int) (off1 int, err error) {
rdStart := off
_ = rdStart

View File

@ -33,6 +33,7 @@ var TypeToRR = map[uint16]func() RR{
TypeGPOS: func() RR { return new(GPOS) },
TypeHINFO: func() RR { return new(HINFO) },
TypeHIP: func() RR { return new(HIP) },
TypeHTTPS: func() RR { return new(HTTPS) },
TypeKEY: func() RR { return new(KEY) },
TypeKX: func() RR { return new(KX) },
TypeL32: func() RR { return new(L32) },
@ -70,6 +71,7 @@ var TypeToRR = map[uint16]func() RR{
TypeSPF: func() RR { return new(SPF) },
TypeSRV: func() RR { return new(SRV) },
TypeSSHFP: func() RR { return new(SSHFP) },
TypeSVCB: func() RR { return new(SVCB) },
TypeTA: func() RR { return new(TA) },
TypeTALINK: func() RR { return new(TALINK) },
TypeTKEY: func() RR { return new(TKEY) },
@ -110,6 +112,7 @@ var TypeToString = map[uint16]string{
TypeGPOS: "GPOS",
TypeHINFO: "HINFO",
TypeHIP: "HIP",
TypeHTTPS: "HTTPS",
TypeISDN: "ISDN",
TypeIXFR: "IXFR",
TypeKEY: "KEY",
@ -153,6 +156,7 @@ var TypeToString = map[uint16]string{
TypeSPF: "SPF",
TypeSRV: "SRV",
TypeSSHFP: "SSHFP",
TypeSVCB: "SVCB",
TypeTA: "TA",
TypeTALINK: "TALINK",
TypeTKEY: "TKEY",
@ -191,6 +195,7 @@ func (rr *GID) Header() *RR_Header { return &rr.Hdr }
func (rr *GPOS) Header() *RR_Header { return &rr.Hdr }
func (rr *HINFO) Header() *RR_Header { return &rr.Hdr }
func (rr *HIP) Header() *RR_Header { return &rr.Hdr }
func (rr *HTTPS) Header() *RR_Header { return &rr.Hdr }
func (rr *KEY) Header() *RR_Header { return &rr.Hdr }
func (rr *KX) Header() *RR_Header { return &rr.Hdr }
func (rr *L32) Header() *RR_Header { return &rr.Hdr }
@ -229,6 +234,7 @@ func (rr *SOA) Header() *RR_Header { return &rr.Hdr }
func (rr *SPF) Header() *RR_Header { return &rr.Hdr }
func (rr *SRV) Header() *RR_Header { return &rr.Hdr }
func (rr *SSHFP) Header() *RR_Header { return &rr.Hdr }
func (rr *SVCB) Header() *RR_Header { return &rr.Hdr }
func (rr *TA) Header() *RR_Header { return &rr.Hdr }
func (rr *TALINK) Header() *RR_Header { return &rr.Hdr }
func (rr *TKEY) Header() *RR_Header { return &rr.Hdr }
@ -592,6 +598,15 @@ func (rr *SSHFP) len(off int, compression map[string]struct{}) int {
l += len(rr.FingerPrint) / 2
return l
}
func (rr *SVCB) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // Priority
l += domainNameLen(rr.Target, off+l, compression, false)
for _, x := range rr.Value {
l += 4 + int(x.len())
}
return l
}
func (rr *TA) len(off int, compression map[string]struct{}) int {
l := rr.Hdr.len(off, compression)
l += 2 // KeyTag
@ -753,6 +768,9 @@ func (rr *HIP) copy() RR {
copy(RendezvousServers, rr.RendezvousServers)
return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers}
}
func (rr *HTTPS) copy() RR {
return &HTTPS{*rr.SVCB.copy().(*SVCB)}
}
func (rr *KEY) copy() RR {
return &KEY{*rr.DNSKEY.copy().(*DNSKEY)}
}
@ -879,6 +897,13 @@ func (rr *SRV) copy() RR {
func (rr *SSHFP) copy() RR {
return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint}
}
func (rr *SVCB) copy() RR {
Value := make([]SVCBKeyValue, len(rr.Value))
for i, e := range rr.Value {
Value[i] = e.copy()
}
return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value}
}
func (rr *TA) copy() RR {
return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest}
}

View File

@ -6,7 +6,6 @@
package assert
import (
io "io"
http "net/http"
url "net/url"
time "time"
@ -202,11 +201,11 @@ func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, arg
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) bool {
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return HTTPBodyContains(t, handler, method, url, values, body, str, append([]interface{}{msg}, args...)...)
return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
}
// HTTPBodyNotContainsf asserts that a specified handler returns a
@ -215,11 +214,11 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) bool {
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return HTTPBodyNotContains(t, handler, method, url, values, body, str, append([]interface{}{msg}, args...)...)
return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
}
// HTTPErrorf asserts that a specified handler returns an error status code.

View File

@ -6,7 +6,6 @@
package assert
import (
io "io"
http "net/http"
url "net/url"
time "time"
@ -386,11 +385,11 @@ func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args .
// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) bool {
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return HTTPBodyContains(a.t, handler, method, url, values, body, str, msgAndArgs...)
return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
}
// HTTPBodyContainsf asserts that a specified handler returns a
@ -399,11 +398,11 @@ func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, u
// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) bool {
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return HTTPBodyContainsf(a.t, handler, method, url, values, body, str, msg, args...)
return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
}
// HTTPBodyNotContains asserts that a specified handler returns a
@ -412,11 +411,11 @@ func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string,
// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) bool {
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return HTTPBodyNotContains(a.t, handler, method, url, values, body, str, msgAndArgs...)
return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
}
// HTTPBodyNotContainsf asserts that a specified handler returns a
@ -425,11 +424,11 @@ func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string
// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) bool {
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return HTTPBodyNotContainsf(a.t, handler, method, url, values, body, str, msg, args...)
return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
}
// HTTPError asserts that a specified handler returns an error status code.

View File

@ -2,7 +2,6 @@ package assert
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
@ -112,13 +111,9 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
// HTTPBody is a helper that returns HTTP body of the response. It returns
// empty string if building a new request fails.
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values, body io.Reader) string {
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
w := httptest.NewRecorder()
if values != nil {
url = url + "?" + values.Encode()
}
req, err := http.NewRequest(method, url, body)
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
if err != nil {
return ""
}
@ -132,13 +127,13 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values, b
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) bool {
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
httpBody := HTTPBody(handler, method, url, values, body)
body := HTTPBody(handler, method, url, values)
contains := strings.Contains(httpBody, fmt.Sprint(str))
contains := strings.Contains(body, fmt.Sprint(str))
if !contains {
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
}
@ -152,13 +147,13 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) bool {
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
httpBody := HTTPBody(handler, method, url, values, body)
body := HTTPBody(handler, method, url, values)
contains := strings.Contains(httpBody, fmt.Sprint(str))
contains := strings.Contains(body, fmt.Sprint(str))
if contains {
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
}

View File

@ -7,7 +7,6 @@ package require
import (
assert "github.com/stretchr/testify/assert"
io "io"
http "net/http"
url "net/url"
time "time"
@ -489,11 +488,11 @@ func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...in
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) {
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.HTTPBodyContains(t, handler, method, url, values, body, str, msgAndArgs...) {
if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) {
return
}
t.FailNow()
@ -505,11 +504,11 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url s
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) {
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.HTTPBodyContainsf(t, handler, method, url, values, body, str, msg, args...) {
if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) {
return
}
t.FailNow()
@ -521,11 +520,11 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) {
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.HTTPBodyNotContains(t, handler, method, url, values, body, str, msgAndArgs...) {
if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) {
return
}
t.FailNow()
@ -537,11 +536,11 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, ur
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) {
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.HTTPBodyNotContainsf(t, handler, method, url, values, body, str, msg, args...) {
if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) {
return
}
t.FailNow()

View File

@ -7,7 +7,6 @@ package require
import (
assert "github.com/stretchr/testify/assert"
io "io"
http "net/http"
url "net/url"
time "time"
@ -387,11 +386,11 @@ func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args .
// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) {
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
HTTPBodyContains(a.t, handler, method, url, values, body, str, msgAndArgs...)
HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
}
// HTTPBodyContainsf asserts that a specified handler returns a
@ -400,11 +399,11 @@ func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, u
// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) {
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
HTTPBodyContainsf(a.t, handler, method, url, values, body, str, msg, args...)
HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
}
// HTTPBodyNotContains asserts that a specified handler returns a
@ -413,11 +412,11 @@ func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string,
// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msgAndArgs ...interface{}) {
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
HTTPBodyNotContains(a.t, handler, method, url, values, body, str, msgAndArgs...)
HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
}
// HTTPBodyNotContainsf asserts that a specified handler returns a
@ -426,11 +425,11 @@ func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string
// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, body io.Reader, str interface{}, msg string, args ...interface{}) {
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
HTTPBodyNotContainsf(a.t, handler, method, url, values, body, str, msg, args...)
HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
}
// HTTPError asserts that a specified handler returns an error status code.

View 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
}

View File

@ -0,0 +1,86 @@
// 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.
// +build !gccgo,!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
}

File diff suppressed because it is too large Load Diff

View 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
}

View File

@ -0,0 +1,15 @@
// 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.
// +build !amd64 gccgo 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)
}

View 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)
}

98
vendor/modules.txt vendored
View File

@ -1,19 +1,16 @@
# git.schwanenlied.me/yawning/x448.git v0.0.0-20170617130356-01b048fb03d6
git.schwanenlied.me/yawning/x448.git
# github.com/BurntSushi/toml v0.3.1
github.com/BurntSushi/toml
# github.com/DATA-DOG/go-sqlmock v1.3.3
## explicit
github.com/DATA-DOG/go-sqlmock
# github.com/acmacalister/skittles v0.0.0-20160609003031-7423546701e1
## explicit
github.com/acmacalister/skittles
# github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d
## explicit
github.com/alecthomas/units
# github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239
## explicit
github.com/anmitsu/go-shlex
# github.com/aws/aws-sdk-go v1.34.19
## explicit
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/arn
github.com/aws/aws-sdk-go/aws/awserr
@ -64,24 +61,32 @@ github.com/caddyserver/caddy
github.com/caddyserver/caddy/caddyfile
github.com/caddyserver/caddy/telemetry
# github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894
## explicit
github.com/certifi/gocertifi
# github.com/cespare/xxhash/v2 v2.1.1
github.com/cespare/xxhash/v2
# github.com/cisco/go-hpke v0.0.0-20201023221920-2866d2aa0603
github.com/cisco/go-hpke
# github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b
github.com/cisco/go-tls-syntax
# github.com/cloudflare/brotli-go v0.0.0-20191101163834-d34379f7ff93
## explicit
github.com/cloudflare/brotli-go
github.com/cloudflare/brotli-go/brotli
github.com/cloudflare/brotli-go/common
github.com/cloudflare/brotli-go/dec
github.com/cloudflare/brotli-go/enc
# github.com/cloudflare/circl v1.0.0
github.com/cloudflare/circl/dh/sidh
github.com/cloudflare/circl/dh/sidh/internal/common
github.com/cloudflare/circl/dh/sidh/internal/p503
github.com/cloudflare/circl/dh/sidh/internal/p751
github.com/cloudflare/circl/dh/sidh/internal/shake
# github.com/cloudflare/golibs v0.0.0-20170913112048-333127dbecfc
## explicit
github.com/cloudflare/golibs/lrucache
# github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58
github.com/cloudflare/golz4
# github.com/cloudflare/odoh-go v0.1.3
github.com/cloudflare/odoh-go
# github.com/coredns/coredns v1.7.0
## explicit
github.com/coredns/coredns/core/dnsserver
github.com/coredns/coredns/coremain
github.com/coredns/coredns/pb
@ -109,45 +114,27 @@ github.com/coredns/coredns/plugin/pkg/uniq
github.com/coredns/coredns/plugin/test
github.com/coredns/coredns/request
# github.com/coreos/go-oidc v0.0.0-20171002155002-a93f71fdfe73
## explicit
github.com/coreos/go-oidc/jose
# github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
## explicit
github.com/coreos/go-systemd/daemon
# github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d
github.com/cpuguy83/go-md2man/v2/md2man
# github.com/davecgh/go-spew v1.1.1
github.com/davecgh/go-spew/spew
# github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0
## explicit
github.com/denisenkom/go-mssqldb
github.com/denisenkom/go-mssqldb/internal/cp
github.com/denisenkom/go-mssqldb/internal/decimal
github.com/denisenkom/go-mssqldb/internal/querytext
# github.com/equinox-io/equinox v1.2.0
## explicit
# github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51
## explicit
# github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9
## explicit
# github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434
## explicit
github.com/facebookgo/grace/gracenet
# github.com/facebookgo/stack v0.0.0-20160209184415-751773369052
## explicit
# github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870
## explicit
# github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568
github.com/flynn/go-shlex
# github.com/frankban/quicktest v1.10.0
## explicit
# github.com/fsnotify/fsnotify v1.4.9
## explicit
github.com/fsnotify/fsnotify
# github.com/gdamore/encoding v1.0.0
github.com/gdamore/encoding
# github.com/gdamore/tcell v1.3.0
## explicit
github.com/gdamore/tcell
github.com/gdamore/tcell/terminfo
github.com/gdamore/tcell/terminfo/a/adm3a
@ -199,29 +186,22 @@ github.com/gdamore/tcell/terminfo/x/xnuppc
github.com/gdamore/tcell/terminfo/x/xterm
github.com/gdamore/tcell/terminfo/x/xterm_kitty
# github.com/getsentry/raven-go v0.0.0-20180517221441-ed7bcb39ff10
## explicit
github.com/getsentry/raven-go
# github.com/gliderlabs/ssh v0.0.0-20191009160644-63518b5243e0
## explicit
github.com/gliderlabs/ssh
# github.com/go-sql-driver/mysql v1.5.0
## explicit
github.com/go-sql-driver/mysql
# github.com/gobwas/httphead v0.0.0-20200921212729-da3d93bc3c58
## explicit
github.com/gobwas/httphead
# github.com/gobwas/pool v0.2.1
## explicit
github.com/gobwas/pool
github.com/gobwas/pool/internal/pmath
github.com/gobwas/pool/pbufio
github.com/gobwas/pool/pbytes
# github.com/gobwas/ws v1.0.4
## explicit
github.com/gobwas/ws
github.com/gobwas/ws/wsutil
# github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
## explicit
github.com/golang-collections/collections/queue
# github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
github.com/golang-sql/civil
@ -231,32 +211,22 @@ github.com/golang/protobuf/ptypes
github.com/golang/protobuf/ptypes/any
github.com/golang/protobuf/ptypes/duration
github.com/golang/protobuf/ptypes/timestamp
# github.com/google/go-cmp v0.5.2
## explicit
# github.com/google/uuid v1.1.2
## explicit
github.com/google/uuid
# github.com/gorilla/mux v1.7.3
## explicit
github.com/gorilla/mux
# github.com/gorilla/websocket v1.4.2
## explicit
github.com/gorilla/websocket
# github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc
# github.com/jmespath/go-jmespath v0.3.0
github.com/jmespath/go-jmespath
# github.com/jmoiron/sqlx v1.2.0
## explicit
github.com/jmoiron/sqlx
github.com/jmoiron/sqlx/reflectx
# github.com/json-iterator/go v1.1.10
## explicit
github.com/json-iterator/go
# github.com/kr/text v0.2.0
## explicit
# github.com/kshvakov/clickhouse v1.3.11
## explicit
github.com/kshvakov/clickhouse
github.com/kshvakov/clickhouse/lib/binary
github.com/kshvakov/clickhouse/lib/cityhash102
@ -267,10 +237,7 @@ github.com/kshvakov/clickhouse/lib/lz4
github.com/kshvakov/clickhouse/lib/protocol
github.com/kshvakov/clickhouse/lib/types
github.com/kshvakov/clickhouse/lib/writebuffer
# github.com/kylelemons/godebug v1.1.0
## explicit
# github.com/lib/pq v1.2.0
## explicit
github.com/lib/pq
github.com/lib/pq/oid
github.com/lib/pq/scram
@ -279,47 +246,35 @@ github.com/lucasb-eyer/go-colorful
# github.com/mattn/go-runewidth v0.0.8
github.com/mattn/go-runewidth
# github.com/mattn/go-sqlite3 v1.11.0
## explicit
github.com/mattn/go-sqlite3
# github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/miekg/dns v1.1.31
## explicit
# github.com/miekg/dns v1.1.32
github.com/miekg/dns
# github.com/mitchellh/go-homedir v1.1.0
## explicit
github.com/mitchellh/go-homedir
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/modern-go/concurrent
# github.com/modern-go/reflect2 v1.0.1
github.com/modern-go/reflect2
# github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e
## explicit
# github.com/opentracing/opentracing-go v1.2.0
## explicit
github.com/opentracing/opentracing-go
github.com/opentracing/opentracing-go/ext
github.com/opentracing/opentracing-go/log
# github.com/pierrec/lz4 v2.5.2+incompatible
## explicit
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0
github.com/pmezard/go-difflib/difflib
# github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35
## explicit
github.com/pquerna/cachecontrol
github.com/pquerna/cachecontrol/cacheobject
# github.com/prometheus/client_golang v1.7.1
## explicit
github.com/prometheus/client_golang/prometheus
github.com/prometheus/client_golang/prometheus/internal
github.com/prometheus/client_golang/prometheus/promhttp
# github.com/prometheus/client_model v0.2.0
github.com/prometheus/client_model/go
# github.com/prometheus/common v0.13.0
## explicit
github.com/prometheus/common/expfmt
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
github.com/prometheus/common/model
@ -327,10 +282,7 @@ github.com/prometheus/common/model
github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs
github.com/prometheus/procfs/internal/util
# github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
## explicit
# github.com/rivo/tview v0.0.0-20200712113419-c65badfc3d92
## explicit
github.com/rivo/tview
# github.com/rivo/uniseg v0.1.0
github.com/rivo/uniseg
@ -338,22 +290,19 @@ github.com/rivo/uniseg
github.com/russross/blackfriday/v2
# github.com/shurcooL/sanitized_anchor_name v1.0.0
github.com/shurcooL/sanitized_anchor_name
# github.com/stretchr/testify v1.6.0
## explicit
# github.com/stretchr/testify v1.6.1
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
# github.com/urfave/cli/v2 v2.2.0
## explicit
github.com/urfave/cli/v2
github.com/urfave/cli/v2/altsrc
# github.com/xo/dburl v0.0.0-20191005012637-293c3298d6c0
## explicit
github.com/xo/dburl
# golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
## explicit
golang.org/x/crypto/blake2b
golang.org/x/crypto/blowfish
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
@ -368,7 +317,6 @@ golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/terminal
# golang.org/x/net v0.0.0-20200904194848-62affa334b73
## explicit
golang.org/x/net/bpf
golang.org/x/net/context
golang.org/x/net/context/ctxhttp
@ -386,14 +334,11 @@ golang.org/x/net/proxy
golang.org/x/net/trace
golang.org/x/net/websocket
# golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
## explicit
golang.org/x/oauth2
golang.org/x/oauth2/internal
# golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
## explicit
golang.org/x/sync/errgroup
# golang.org/x/sys v0.0.0-20200909081042-eff7692f9009
## explicit
golang.org/x/sys/cpu
golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix
@ -418,10 +363,8 @@ google.golang.org/appengine/internal/remote_api
google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/urlfetch
# google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d
## explicit
google.golang.org/genproto/googleapis/rpc/status
# google.golang.org/grpc v1.32.0
## explicit
google.golang.org/grpc
google.golang.org/grpc/attributes
google.golang.org/grpc/backoff
@ -492,24 +435,17 @@ google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/known/anypb
google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/timestamppb
# gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f
## explicit
# gopkg.in/coreos/go-oidc.v2 v2.1.0
## explicit
gopkg.in/coreos/go-oidc.v2
# gopkg.in/square/go-jose.v2 v2.4.0
## explicit
gopkg.in/square/go-jose.v2
gopkg.in/square/go-jose.v2/cipher
gopkg.in/square/go-jose.v2/json
# gopkg.in/yaml.v2 v2.3.0
## explicit
gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
## explicit
gopkg.in/yaml.v3
# zombiezen.com/go/capnproto2 v2.18.0+incompatible
## explicit
zombiezen.com/go/capnproto2
zombiezen.com/go/capnproto2/encoding/text
zombiezen.com/go/capnproto2/internal/fulfiller