[pcr0tool] Add a comparator with TPM EventLog

Added flag "-compare-with-eventlog" to verb "sum" of pcr0tool. The
option allows to compare the expected measurements with actual
measurements from TPM EventLog and print all the found mismatches.

Also the comparator tries to restore the original value of PCR0_DATA
through bruteforcing.

Signed-off-by: Dmitrii Okunev <xaionaro@fb.com>
This commit is contained in:
Dmitrii Okunev 2022-04-13 16:55:46 +01:00 committed by Christopher Meis
parent 9c65fff579
commit ec7b2c5e5d
14 changed files with 2258 additions and 18 deletions

View File

@ -14,7 +14,10 @@ import (
"github.com/9elements/converged-security-suite/v2/cmd/pcr0tool/commands"
"github.com/9elements/converged-security-suite/v2/cmd/pcr0tool/commands/dumpregisters/helpers"
"github.com/9elements/converged-security-suite/v2/pkg/pcr"
"github.com/9elements/converged-security-suite/v2/pkg/pcrbruteforcer"
"github.com/9elements/converged-security-suite/v2/pkg/registers"
"github.com/9elements/converged-security-suite/v2/pkg/tpmdetection"
"github.com/9elements/converged-security-suite/v2/pkg/tpmeventlog"
"github.com/9elements/converged-security-suite/v2/pkg/uefi"
"github.com/google/go-tpm/tpm2"
)
@ -32,13 +35,17 @@ func assertNoError(err error) {
// Command is the implementation of `commands.Command`.
type Command struct {
isQuiet *bool
flow *string
hashFunc *string
registers helpers.FlagRegisters
tpmDevice *string
isQuiet *bool
flow *string
hashFunc *string
registers helpers.FlagRegisters
tpmDevice *string
compareWithEventLog *string
printMeasurementLengthLimit *uint
// Intel-specific advanced options
decrementACMPolicyStatus *uint
}
// Usage prints the syntax of arguments for this command
@ -59,7 +66,9 @@ func (cmd *Command) SetupFlagSet(flag *flag.FlagSet) {
cmd.hashFunc = flag.String("hash-func", "sha1", `which hash function use to hash measurements and to extend the PCR0; values: "sha1", "sha256"`)
flag.Var(&cmd.registers, "registers", "[optional] file that contains registers as a json array (use value '/dev' to use registers of the local machine)")
cmd.tpmDevice = flag.String("tpm-device", "", "[optional] tpm device used for measurements, values: "+commands.TPMTypeCommandLineValues())
cmd.compareWithEventLog = flag.String("compare-with-eventlog", "", "[optional] compare expected measurements with a TPM EventLog")
cmd.printMeasurementLengthLimit = flag.Uint("print-measurement-length-limit", 20, "length limit of measured data to be printed")
cmd.decrementACMPolicyStatus = flag.Uint("decrement-acm-policy-status", 0, "[advanced] decrement Intel ACM Policy Status value")
}
// Execute is the main function here. It is responsible to
@ -83,6 +92,21 @@ func (cmd Command) Execute(args []string) {
usageAndExit()
}
if *cmd.decrementACMPolicyStatus != 0 {
found := false
for idx, reg := range cmd.registers {
switch reg := reg.(type) {
case registers.ACMPolicyStatus:
cmd.registers[idx] = reg - registers.ACMPolicyStatus(*cmd.decrementACMPolicyStatus)
found = true
}
}
if !found {
_, _ = fmt.Fprintf(flag.CommandLine.Output(), "cannot decrement ACM Policy Status, because the register wasn't found\n")
usageAndExit()
}
}
var measureOpts []pcr.MeasureOption
measureOpts = append(measureOpts, pcr.SetFlow(flow))
measureOpts = append(measureOpts, pcr.SetRegisters(cmd.registers))
@ -137,4 +161,19 @@ func (cmd Command) Execute(args []string) {
fmt.Printf("Resulting PCR0: ")
}
fmt.Printf("%X\n", result)
if *cmd.compareWithEventLog != "" {
fmt.Println()
if *cmd.hashFunc != "sha1" {
panic("comparing with TPM EventLog is currently supported only for SHA1 digests")
}
f, err := os.Open(*cmd.compareWithEventLog)
assertNoError(err)
tpmEventLog, err := tpmeventlog.Parse(f)
assertNoError(err)
match, updatedACMPolicyStatus, err := pcrbruteforcer.ReproduceEventLog(tpmEventLog, measurements, firmware.Buf())
fmt.Printf("comparing with TPM EventLog result:\n\tmatch: %v\n\tupdated ACM Policy Status: %v\n\terr: %v\n",
match, updatedACMPolicyStatus, err)
}
}

8
go.mod
View File

@ -14,14 +14,15 @@ require (
github.com/golang-collections/go-datastructures v0.0.0-20150211160725-59788d5eb259
github.com/google/go-attestation v0.4.0
github.com/google/go-tpm v0.3.3-0.20210120190357-1ff48daca32f
github.com/google/uuid v1.2.0
github.com/google/uuid v1.3.0
github.com/klauspost/cpuid/v2 v2.0.9
github.com/kr/pretty v0.2.1 // indirect
github.com/linuxboot/fiano v1.0.6-0.20220208095308-e3fa29a6b2aa
github.com/linuxboot/contest v0.0.0-20220404120719-d952dfa563c4
github.com/linuxboot/fiano v1.1.1-0.20220414102525-737513644344
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/marcoguerri/go-tpm-tcti v0.0.0-20210425104733-8e8c8fe68e60
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.7.1
github.com/tidwall/pretty v1.0.2
github.com/tjfoc/gmsm v1.4.1
github.com/ulikunitz/xz v0.5.10
@ -29,7 +30,6 @@ require (
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9
github.com/xaionaro-go/unsafetools v0.0.0-20210722164218-75ba48cf7b3c
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
replace github.com/9elements/converged-security-suite/v2/testdata/firmware => ./testdata/firmware

251
go.sum
View File

@ -13,6 +13,8 @@ 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.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
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=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -32,49 +34,76 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/9elements/go-linux-lowlevel-hw v0.0.0-20211215141225-8375dd201aae h1:BsoCEtuZy+s7LuCNcY4iuGI8WaCyF4sCa116q3E/otM=
github.com/9elements/go-linux-lowlevel-hw v0.0.0-20211215141225-8375dd201aae/go.mod h1:NRv+EGNg4+XO4g9W9BzC/ckMg/5zgLNkRd/Hh09Nxr4=
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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.7/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/kong v0.2.11 h1:RKeJXXWfg9N47RYfMm0+igkxBCTF4bzbneAxaqid0c4=
github.com/alecthomas/kong v0.2.11/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.41.14/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
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/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chappjc/logrus-prefix v0.0.0-20180227015900-3a1d64819adb/go.mod h1:xzXc1S/L+64uglB3pw54o8kqyM6KFYpTeC9Q6+qZIu8=
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/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/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=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@ -86,6 +115,7 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cornelk/hashmap v1.0.1/go.mod h1:8wbysTUDnwJGrPZ1Iwsou3m+An6sldFrJItjRhfegCw=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -97,6 +127,7 @@ github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/siphash v1.1.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
@ -104,8 +135,12 @@ github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:Y
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
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=
@ -117,23 +152,34 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/fearful-symmetry/gomsr v0.0.1 h1:m208RzdTApWVbv8a9kf78rdPLQe+BY9AxRb/nSbHxSA=
github.com/fearful-symmetry/gomsr v0.0.1/go.mod h1:Qb/0Y7zwobP7v8Sji+M5mlL4N7Voyz5WaKXXRFPnLio=
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.2-0.20181113160402-cbabf5414432/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/gliderlabs/ssh v0.3.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
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.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
@ -168,7 +214,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
@ -181,11 +231,14 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-safeweb v0.0.0-20211026121254-697f59a9d57f/go.mod h1:Y/uYEmZs5exq8iiX9djfwjg1IkSo4183aw7DTSkb6KU=
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
github.com/google/go-tpm v0.2.1-0.20200615092505-5d8a91de9ae3/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
@ -200,9 +253,11 @@ github.com/google/go-tpm-tools v0.3.1/go.mod h1:PSg+r5hSZI5tP3X7LBQx2sW1VSZUqZHB
github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad h1:LnpS22S8V1HqbxjveESGAazHhi6BX9SwI2Rij7qZcXQ=
github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI=
github.com/google/goexpect v0.0.0-20191001010744-5b6988669ffa/go.mod h1:qtE5aAEkt0vOSA84DBh8aJsz6riL8ONfqfULY7lBjqc=
github.com/google/goexpect v0.0.0-20200703111054-623d5ca06f56/go.mod h1:qtE5aAEkt0vOSA84DBh8aJsz6riL8ONfqfULY7lBjqc=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
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=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -210,17 +265,22 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw=
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/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/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -233,7 +293,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@ -247,6 +309,7 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
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=
@ -260,31 +323,44 @@ github.com/hexdigest/gowrap v1.1.8/go.mod h1:H/JiFmQMp//tedlV8qt2xBdGzmne6bpbaSu
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/hugelgupf/p9 v0.1.0/go.mod h1:1rAW9NtDC5qvKmViRdQlPcDNtLcpo+yzOmQZqfVlS+U=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/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/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
github.com/insomniacslk/termhook v0.0.0-20210329134026-a267c978e590/go.mod h1:8eGC3NZFqSFxpbWduqdoolXfuhN3K8KH9wMmldc3sYs=
github.com/insomniacslk/xjson v0.0.0-20210106140854-1589ccfd1a1a/go.mod h1:G8c61yEjNgzQNF0lOvul8ls5IHE/MxbGx7M98ADBVEA=
github.com/intel-go/cpuid v0.0.0-20200819041909-2aa72927c3e2 h1:h+RKaNPjka7LRJGoeub/IQBdXSoEaJjfADkBq02hvjw=
github.com/intel-go/cpuid v0.0.0-20200819041909-2aa72927c3e2/go.mod h1:RmeVYf9XrPRbRc3XIx0gLYA8qOFvNoPOfaEZduRlEp4=
github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kaey/framebuffer v0.0.0-20140402104929-7b385489a1ff/go.mod h1:tS4qtlcKqtt3tCIHUflVSqeP3CLH5Qtv2szX9X2SyhU=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@ -294,6 +370,8 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
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.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
@ -305,24 +383,32 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/linuxboot/fiano v1.0.6-0.20220208095308-e3fa29a6b2aa h1:EdI6AWh797oO1RTEngQegbeIThWRddsGKN75TfKWC7U=
github.com/linuxboot/fiano v1.0.6-0.20220208095308-e3fa29a6b2aa/go.mod h1:lsLW5PqsAN0OvdhI6SBszDwTF16ab8wfVPpewsQBOu8=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/linuxboot/contest v0.0.0-20220404120719-d952dfa563c4 h1:yQv0m9WuXf5qm8cwtvmfv81VKp0BkNAt2jM9Fvgn2HY=
github.com/linuxboot/contest v0.0.0-20220404120719-d952dfa563c4/go.mod h1:u9tuZGucKhcl8HxTfBOZikI1k0/A/gk3JFrwQcTA7nA=
github.com/linuxboot/fiano v1.1.1-0.20220414102525-737513644344 h1:7KFaAKQB0rTCIPUlgdYr5gN4E96x63BX0XZTeBKbtnE=
github.com/linuxboot/fiano v1.1.1-0.20220414102525-737513644344/go.mod h1:lsLW5PqsAN0OvdhI6SBszDwTF16ab8wfVPpewsQBOu8=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/marcoguerri/go-tpm-tcti v0.0.0-20210425104733-8e8c8fe68e60 h1:6ZzceIckZYWVOe7mshJNP0VbCHovX6KUuARRLqjeM0Q=
github.com/marcoguerri/go-tpm-tcti v0.0.0-20210425104733-8e8c8fe68e60/go.mod h1:wD5IzQ+Bhi6Nj20Vb3TFPvJKTZbGo/hu1Yhr44rUcx4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
@ -331,6 +417,7 @@ github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcK
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
@ -351,49 +438,98 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo=
github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
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/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
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/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=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
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/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/orangecms/go-framebuffer v0.0.0-20200613202404-a0700d90c330/go.mod h1:3Myb/UszJY32F2G7yGkUtcW/ejHpjlGfYLim7cv2uKA=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
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/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.13.4/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pressly/goose v2.7.0+incompatible/go.mod h1:m+QHWCqxR3k8D9l7qfzuC/djtlfzxr34mozWDYEu1z8=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA=
github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q=
github.com/rck/unit v0.0.3/go.mod h1:jTOnzP4s1OjIP1vdxb4n76b23QPKS4EurYg7sYMr2DM=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rekby/gpt v0.0.0-20200219180433-a930afbc6edc/go.mod h1:scrOqOnnHVKCHENvFw8k9ajCb88uqLQDA4BvuJNJ2ew=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@ -403,14 +539,19 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
@ -422,11 +563,15 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
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=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@ -434,8 +579,9 @@ 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
@ -445,9 +591,13 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
github.com/trafficstars/metrics v0.0.0-20200814135838-ec71779fd01d/go.mod h1:HHFbOLT4Kf5raCtxlL8s5cDvsJC9knlxD1EL2B8pjGw=
github.com/twitchtv/twirp v5.8.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
github.com/u-root/cpu v0.0.0-20210922222005-0a371c3a086d/go.mod h1:1JzU+/YbK0tQ7WbufDMLA0iVbpIQNywhiCX/paytE4k=
github.com/u-root/iscsinl v0.1.1-0.20210528121423-84c32645822a/go.mod h1:RWIgJWqm9/0gjBZ0Hl8iR6MVGzZ+yAda2uqqLmetE2I=
github.com/u-root/u-root v0.0.0-20210724144310-637617c480d4/go.mod h1:IsKJYip9I42iZzwDxdcuaRl0f02HEJLVH4pQqcWJMoo=
github.com/u-root/u-root v6.0.1-0.20200118052101-6bcd1cda5996+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@ -459,13 +609,20 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066/go.mod h1:FSQhuTO7eHT34mPzX+B04SUAjiqLxtXs1et0S6l9k4k=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810/go.mod h1:dF0BBJ2YrV1+2eAIyEI+KeSidgA6HqoIP1u5XTlMq/o=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xaionaro-facebook/go-dmidecode v0.0.0-20220413144237-c42d5bef2498 h1:DungyLUCAeepf9LlCgBufekeSdeonRFkiMxzNIz2ZzM=
github.com/xaionaro-facebook/go-dmidecode v0.0.0-20220413144237-c42d5bef2498/go.mod h1:II0+Quqf1lG4nq4udbG0Jn3uvbUlrCL4iccqrN5XRjY=
github.com/xaionaro-go/atomicmap v0.0.0-20200307233044-c040bc137895/go.mod h1:WgfDl7x9++CVnKSu63ThFhBF3nvgj60Ft1nCgrOSgWM=
github.com/xaionaro-go/atomicmap v0.0.0-20210620215405-96a7f1f95a70/go.mod h1:WgfDl7x9++CVnKSu63ThFhBF3nvgj60Ft1nCgrOSgWM=
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9 h1:LZsotURuIwV1yjhoaTpbdZHf0/7QtWtvXH8VZ4zs/ug=
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9/go.mod h1:op5hoGu7YbHB+PlxrR0jAhl5OaCpYCEqtdCfusfZCYk=
github.com/xaionaro-go/gosrc v0.0.0-20201124181305-3fdf8476a735/go.mod h1:KWPOUqeg7VZ8gE4MQJJmG+YgmNf2yAkBiDI++R48tFg=
github.com/xaionaro-go/metrics v0.0.0-20210425194006-68050b337673/go.mod h1:mg+WWOABLgtBKT9UFqWxP+p+4C5Nj9ho1GicoVrhWsc=
github.com/xaionaro-go/spinlock v0.0.0-20190309154744-55278e21e817/go.mod h1:Nb/15eS0BMty6TMuWgRQM8WCDIUlyPZagcpchHT6c9Y=
github.com/xaionaro-go/spinlock v0.0.0-20200518175509-30e6d1ce68a1/go.mod h1:UwmTXX+EpoEYHuy0rSys1Rp5PW+eVTgZSjgMVLJENKg=
github.com/xaionaro-go/unsafetools v0.0.0-20210722164218-75ba48cf7b3c h1:WeiZrQbFImtlpYCHdxWpjm033Zm0n1ihx3bD/9b6rYI=
github.com/xaionaro-go/unsafetools v0.0.0-20210722164218-75ba48cf7b3c/go.mod h1:fnHPnf0CsRZNVxlSs0ZdUiYW49mLF5QFycfmoT+LuO4=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
@ -473,11 +630,15 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
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=
@ -486,12 +647,22 @@ 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.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
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.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
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.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -499,10 +670,14 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -527,6 +702,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -536,6 +712,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -545,6 +722,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -555,6 +733,7 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -574,15 +753,21 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -592,6 +777,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -600,6 +786,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -616,9 +803,14 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190903213830-1f305c863dab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -638,20 +830,33 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895 h1:iaNpwpnrgL5jzWS0vCNnfa8HqzxveCFpFx3uC/X4Tps=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0W+hLtAhkV1tPsXhutqs=
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -665,6 +870,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/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=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -694,7 +900,9 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200119215504-eb0d8dd85bcc/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@ -709,15 +917,23 @@ golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200915201639-f4cefd1cb5ba/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
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=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@ -734,7 +950,9 @@ google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
google.golang.org/api v0.24.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/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=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
@ -748,6 +966,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
@ -770,13 +989,20 @@ google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
@ -787,6 +1013,7 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -799,6 +1026,7 @@ 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/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@ -810,9 +1038,11 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
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/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -820,10 +1050,14 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@ -836,3 +1070,4 @@ 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/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

103
pkg/bruteforcer/README.md Normal file
View File

@ -0,0 +1,103 @@
```
goos: linux
goarch: amd64
pkg: privatecore/firmware/analyzer/pkg/bruteforcer
BenchmarkBruteForce/noop/distance_1/dataSize_1-8 111994 1034 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_2-8 90879 1277 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_3-8 78481 1559 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_4-8 71247 1691 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_5-8 66680 1880 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_6-8 60540 2244 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_7-8 43143 3073 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_1/dataSize_8-8 39789 2960 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_1-8 40298 3075 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_2-8 18277 7604 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_3-8 10000 12326 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_4-8 6253 18504 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_5-8 4112 28074 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_6-8 2814 37999 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_7-8 2494 48112 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_2/dataSize_8-8 2058 62783 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_1-8 17174 6390 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_2-8 4104 30334 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_3-8 1576 87300 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_4-8 606 202431 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_5-8 322 343400 ns/op 736 B/op 41 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_6-8 210 585882 ns/op 736 B/op 41 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_7-8 234 589251 ns/op 810 B/op 43 allocs/op
BenchmarkBruteForce/noop/distance_3/dataSize_8-8 193 557486 ns/op 926 B/op 47 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_1-8 9180 12062 ns/op 1183 B/op 62 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_2-8 1088 107128 ns/op 1184 B/op 62 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_3-8 237 492388 ns/op 1184 B/op 62 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_4-8 157 744349 ns/op 1256 B/op 66 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_5-8 79 1298786 ns/op 1860 B/op 76 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_6-8 45 2578822 ns/op 1482 B/op 76 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_7-8 32 4157079 ns/op 1524 B/op 78 allocs/op
BenchmarkBruteForce/noop/distance_4/dataSize_8-8 16 7103824 ns/op 1608 B/op 82 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_1-8 5882 19378 ns/op 1552 B/op 79 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_2-8 332 310768 ns/op 1776 B/op 87 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_3-8 90 1189687 ns/op 1995 B/op 93 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_4-8 51 3094867 ns/op 2210 B/op 105 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_5-8 13 8687901 ns/op 2432 B/op 115 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_6-8 5 21545071 ns/op 2467 B/op 115 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_7-8 3 46809559 ns/op 2544 B/op 117 allocs/op
BenchmarkBruteForce/noop/distance_5/dataSize_8-8 2 115921358 ns/op 2592 B/op 121 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_1-8 5816 22624 ns/op 1807 B/op 92 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_2-8 158 704658 ns/op 2480 B/op 116 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_3-8 39 2783654 ns/op 2994 B/op 136 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_4-8 7 14666064 ns/op 3282 B/op 148 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_5-8 2 55091357 ns/op 4336 B/op 160 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_6-8 1 160281045 ns/op 4368 B/op 160 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_7-8 1 401626326 ns/op 4128 B/op 162 allocs/op
BenchmarkBruteForce/noop/distance_6/dataSize_8-8 1 904420581 ns/op 3808 B/op 165 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_1-8 32188 3923 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_2-8 19854 5640 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_3-8 16796 7739 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_4-8 12583 9998 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_5-8 10000 10798 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_6-8 10018 12972 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_7-8 7606 14019 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_1/dataSize_8-8 6602 15338 ns/op 160 B/op 11 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_1-8 9416 12885 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_2-8 3691 33207 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_3-8 1880 68526 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_4-8 1135 115761 ns/op 368 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_5-8 734 190271 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_6-8 508 238664 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_7-8 368 361552 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_2/dataSize_8-8 316 413167 ns/op 384 B/op 24 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_1-8 4441 26912 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_2-8 739 148580 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_3-8 241 523242 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_4-8 90 1206058 ns/op 720 B/op 41 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_5-8 49 2096985 ns/op 736 B/op 41 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_6-8 28 3707970 ns/op 736 B/op 41 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_7-8 34 3323183 ns/op 776 B/op 43 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_3/dataSize_8-8 31 4505925 ns/op 856 B/op 47 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_1-8 2502 45961 ns/op 1184 B/op 62 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_2-8 214 541400 ns/op 1184 B/op 62 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_3-8 45 2749192 ns/op 1184 B/op 62 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_4-8 20 5497688 ns/op 1256 B/op 66 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_5-8 16 8363935 ns/op 1465 B/op 76 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_6-8 7 16828364 ns/op 1483 B/op 76 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_7-8 4 28859744 ns/op 1528 B/op 78 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_4/dataSize_8-8 3 46719665 ns/op 1605 B/op 82 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_1-8 1929 63682 ns/op 1552 B/op 79 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_2-8 73 1588963 ns/op 1776 B/op 87 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_3-8 16 7386752 ns/op 1931 B/op 93 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_4-8 6 18911062 ns/op 2216 B/op 105 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_5-8 2 52249364 ns/op 2504 B/op 115 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_6-8 1 138952445 ns/op 2480 B/op 115 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_7-8 1 281757950 ns/op 2608 B/op 118 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_5/dataSize_8-8 1 550915210 ns/op 2608 B/op 121 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_1-8 1660 79541 ns/op 1808 B/op 92 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_2-8 31 3773336 ns/op 2483 B/op 116 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_3-8 8 15691267 ns/op 3000 B/op 136 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_4-8 2 84575901 ns/op 3344 B/op 148 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_5-8 1 328253033 ns/op 3632 B/op 159 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_6-8 1 1024661015 ns/op 3600 B/op 158 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_7-8 1 2463266087 ns/op 3648 B/op 160 allocs/op
BenchmarkBruteForce/sha1.Sum/distance_6/dataSize_8-8 1 6358236131 ns/op 3808 B/op 165 allocs/op
PASS
ok privatecore/firmware/analyzer/pkg/bruteforcer 26.227s
```

View File

@ -0,0 +1,187 @@
package bruteforcer
import (
"fmt"
"math"
"math/big"
"runtime"
"sync"
"github.com/9elements/converged-security-suite/v2/pkg/errors"
)
const (
minIterationsPerCPU = 10000
)
// CheckFunc is the function used if the sought value is found. Return true
// if data is the sought value, and return false if it is not.
type CheckFunc func(ctx interface{}, data []byte) bool
// InitFunc is the function executed for each goroutine before brute-forcing.
// It returns a data, which will be passed as argument `ctx` to CheckFunc.
type InitFunc func() (interface{}, error)
type bruteForcer struct {
initialData []byte
initFunc InitFunc
checkFunc CheckFunc
}
// BruteForceBytes brute forces a value until checkFunc will return true or
// combinations will be out. It starts with value initialData and then
// tries combination with the hamming distance (relatively to initialDate) not
// greater than maxDistance.
//
// On success it returns the combination of bits which combination are required
// to be changed. To apply these changes use method ApplyBitFlips.
func BruteForceBytes(initialData []byte, maxDistance uint64, initFunc InitFunc, checkFunc CheckFunc, maxConcurrency uint) (UniqueUnorderedCombination, error) {
return newBruteForcer(initialData, initFunc, checkFunc).run(maxDistance, maxConcurrency)
}
func newBruteForcer(initialData []byte, initFunc InitFunc, checkFunc CheckFunc) *bruteForcer {
if initFunc == nil {
initFunc = func() (interface{}, error) { return nil, nil }
}
return &bruteForcer{
initialData: initialData,
initFunc: initFunc,
checkFunc: checkFunc,
}
}
func (b *bruteForcer) run(maxDistance uint64, maxConcurrency uint) (UniqueUnorderedCombination, error) {
ctx, err := b.initFunc()
if err != nil {
return nil, err
}
if b.checkFunc(ctx, b.initialData) {
return NewUniqueUnorderedCombination(0), nil
}
totalBitLength := uint64(len(b.initialData)) * 8
if maxDistance > totalBitLength {
maxDistance = totalBitLength
}
for distance := uint64(1); distance <= maxDistance; distance++ {
if totalBitLength < distance {
// no combinations possible
break
}
amountOfCombinationsBigInt := big.NewInt(1).Binomial(int64(totalBitLength), int64(distance))
// Current algorithm uses an uint64 as an iterator through combinations,
// thus we do not support more than math.MaxInt64 combinations.
//
// And amount of
//
// ">=" instead of ">" just for defense.
if amountOfCombinationsBigInt.Cmp(big.NewInt(math.MaxInt64)) >= 0 {
return nil, fmt.Errorf("distance is too high (amount of combinations causes uint64 overflow)")
}
amountOfCombinations := amountOfCombinationsBigInt.Uint64()
// Calculating:
// * concurrencyFactor -- how many concurrent goroutines are permitted.
// * and combinationsPiece -- how many combinations should one goroutine handle.
concurrencyFactor := runtime.GOMAXPROCS(0)
if uint64(concurrencyFactor) > amountOfCombinations/minIterationsPerCPU {
concurrencyFactor = int(amountOfCombinations / minIterationsPerCPU)
if concurrencyFactor < 1 {
concurrencyFactor = 1
}
}
if maxConcurrency > 0 && uint(concurrencyFactor) > maxConcurrency {
concurrencyFactor = int(maxConcurrency)
}
combinationsPiece := amountOfCombinations / uint64(concurrencyFactor)
// Brute force!
var locker sync.Mutex
var resultData UniqueUnorderedCombination
var wg sync.WaitGroup
errChan := make(chan error, concurrencyFactor)
for i := 0; i < concurrencyFactor; i++ {
combinationIDStart := uint64(i) * combinationsPiece
combinationIDEnd := uint64(i+1) * combinationsPiece
if i == concurrencyFactor-1 {
combinationIDEnd = amountOfCombinations
}
wg.Add(1)
go func(combinationIDStart, combinationIDEnd uint64, errChan chan<- error) {
defer wg.Done()
dataCopy := make([]byte, len(b.initialData))
copy(dataCopy, b.initialData)
iterator := NewUniqueUnorderedCombinationIterator(distance, int64(totalBitLength)-1)
iterator.SetCombinationID(combinationIDStart)
bfctx, err := b.initFunc()
if err != nil {
errChan <- fmt.Errorf("brute forcer initFunc error for range (%v, %v): %v", combinationIDStart, combinationIDEnd, err)
return
}
combinations := combinationIDEnd - combinationIDStart
for i := uint64(0); ; {
if resultData != nil {
// we do not need atomic in the condition above, because
// few false negatives will not affect anything much.
return
}
if b.try(bfctx, dataCopy, iterator) {
locker.Lock()
resultData = iterator.GetCombination()
locker.Unlock()
return
}
i++
if i >= combinations {
break
}
iterator.Next()
}
}(combinationIDStart, combinationIDEnd, errChan)
}
// wait for all workers and gather errors
wg.Wait()
close(errChan)
var errors errors.MultiError
for err := range errChan {
_ = errors.Add(err)
}
if len(errors) > 0 {
return nil, fmt.Errorf("workers had errors: %v", errors)
}
if resultData != nil {
return resultData, nil
}
}
return nil, nil
}
func (b *bruteForcer) try(ctx interface{}, data []byte, iterator *UniqueUnorderedCombinationIterator) bool {
// flipping the bits
iterator.ApplyBitFlips(data)
// try
if b.checkFunc(ctx, data) {
return true
}
// wrong, flipping back the bits
iterator.ApplyBitFlips(data)
return false
}

View File

@ -0,0 +1,70 @@
package bruteforcer
import (
"crypto/sha1"
"encoding/binary"
"fmt"
"sync"
"testing"
"github.com/stretchr/testify/require"
)
func TestBruteForce(t *testing.T) {
l := sync.Mutex{}
m := map[uint64]struct{}{}
maxDistance := 4
b := make([]byte, 4)
result, err := BruteForceBytes(b, uint64(maxDistance), nil, func(_ interface{}, data []byte) bool {
l.Lock()
defer l.Unlock()
buf := make([]byte, 8)
copy(buf, data)
key := binary.LittleEndian.Uint64(buf)
if _, ok := m[key]; ok {
t.Fail()
}
m[key] = struct{}{}
return false
}, 0)
require.Nil(t, result)
require.Nil(t, err)
amountOfCombinations := calcAmountOfCombinations(len(b)*8, maxDistance)
require.Len(t, m, int(amountOfCombinations), fmt.Sprintf("%d != %d", len(m), amountOfCombinations))
}
func BenchmarkBruteForce(b *testing.B) {
for _, checkFuncName := range []string{"noop", "sha1.Sum"} {
var checkFunc CheckFunc
switch checkFuncName {
case "noop":
checkFunc = func(_ interface{}, data []byte) bool {
return false
}
case "sha1.Sum":
checkFunc = func(_ interface{}, data []byte) bool {
sha1.Sum(data)
return false
}
default:
panic(checkFuncName)
}
b.Run(checkFuncName, func(b *testing.B) {
for distance := 1; distance <= 6; distance++ {
b.Run(fmt.Sprintf("distance_%d", distance), func(b *testing.B) {
for dataSize := 1; dataSize <= 8; dataSize++ {
b.Run(fmt.Sprintf("dataSize_%d", dataSize), func(b *testing.B) {
data := make([]byte, dataSize)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = BruteForceBytes(data, uint64(distance), nil, checkFunc, 0)
}
})
}
})
}
})
}
}

333
pkg/bruteforcer/indexes.go Normal file
View File

@ -0,0 +1,333 @@
package bruteforcer
import (
"fmt"
"math"
"math/big"
)
const (
// We expect the bitsize of a bruteforced value be lower than 1000
binomialCoefficientCacheMaxN = 1000
// We expect distance be lower than 10
binomialCoefficientCacheMaxK = 10
)
// Value is just an abstract index.
type Value int64
// UniqueUnorderedCombination is a combination of non-repeating
// unordered Value-s. To avoid combination duplication it is enforced
// that each next index should be greater than a previous one.
//
// See also: https://en.wikipedia.org/wiki/File:Combinations_without_repetition;_5_choose_3.svg
type UniqueUnorderedCombination []Value
// UniqueUnorderedCombinationIterator is a wrapper around
// UniqueUnorderedCombination which is able to set a next combination.
type UniqueUnorderedCombinationIterator struct {
combination UniqueUnorderedCombination
maxValue Value
}
// NewUniqueUnorderedCombination returns a UniqueUnorderedCombination with combination
// pre-defined to [0, 1, 2, ...] -- the very first combination of unique
// (non-repeating) combination.
func NewUniqueUnorderedCombination(amountOfIndexes uint64) UniqueUnorderedCombination {
s := make(UniqueUnorderedCombination, amountOfIndexes)
for idx := range s {
s[idx] = Value(idx)
}
return s
}
// ApplyBitFlips changes bit combination located in combination UniqueUnorderedCombination
// of a []byte.
func (s UniqueUnorderedCombination) ApplyBitFlips(b []byte) {
for _, idx := range s {
// major bits of "idx" are responsible for item index inside `b`
byteIdx := idx >> 3 // idx / 8
// minor bits of "idx" are responsible for bit-index inside `b[byteIndex]`
bitIdx := idx & 0x7 // idx mod 8
b[byteIdx] ^= 1 << bitIdx
}
}
// next sets the next combination.
func (s UniqueUnorderedCombination) next(maxIndexValue Value) bool {
if len(s) == 0 {
return false
}
lastIdx := Value(len(s) - 1)
idxIdx := lastIdx
for ; idxIdx >= 0; idxIdx-- {
s[idxIdx]++
if s[idxIdx] <= maxIndexValue-(lastIdx-idxIdx) {
break
}
}
idxIdx++
for ; idxIdx <= lastIdx; idxIdx++ {
if idxIdx == 0 {
return false
}
s[idxIdx] = s[idxIdx-1] + 1
}
return true
}
// AmountOfCombinations returns amount of possible combinations.
func (s UniqueUnorderedCombination) AmountOfCombinations(maxValue Value) uint64 {
return binomialCoefficientFast(uint64(maxValue+1), uint64(len(s)))
}
func (s UniqueUnorderedCombination) setCombinationID(maxValue Value, combinationID uint64) {
// To find the combination, first we try to iterate through the values
// of the major index. Then we try to iterate through the values of the
// next index. And so on until all indexes has correct values.
//
// Additional comment:
//
// We want to avoid stupid iterating through all combinations from
// the beginning until required combinationID is reached. Therefore
// we apply another algorithm. Relatively to axis of combinationID,
// it is basically an N-section (like bisection, but not specifically "bi-")
// search algorithm with unequal sections (if amount of indexes if at
// least 2, then sum of all next sections is less or equals to than
// the current section). Thus if amount of indexes is at least 2, then in
// any case it gives O(ln(n)):
// * If it is deep in left, then we will always increase depth, which
// gives O(ln(all_possible_combinations_amount))
// * If it is deep in right, then we switch to next sections, which
// gives O(ln(all_possible_combinations_amount)), since every next
// section is at least twice smaller than the previous one.
//
// To understand more on how it works: read the big comment inside
// function getCombinationID, first.
setSeries := func(idx int, newValue Value) {
l := len(s)
for i := idx; i < l; i, newValue = i+1, newValue+1 {
s[i] = newValue
}
if s[l-1] > maxValue {
panic(fmt.Sprintf("internal error: should never happen: value %d is greater than maxValue %d", s[l-1], maxValue))
}
}
// TODO: check maxValue and combinationID sanity.
setSeries(0, 0)
iteratorValueIndex := 0
for {
curID := s.getCombinationID(maxValue)
if curID == combinationID {
// Reached the required state.
return
}
if curID > combinationID {
// jumped over the required state, need to return and go deeper.
setSeries(iteratorValueIndex, s[iteratorValueIndex]-1)
iteratorValueIndex++
continue
}
setSeries(iteratorValueIndex, s[iteratorValueIndex]+1)
}
}
func (s UniqueUnorderedCombination) getCombinationID(maxValue Value) uint64 {
// Let's imagine we have amountOfIndexes == 3, maxValue == 4, it gives us
// these combinations:
// 0 1 2
// 0 1 3
// 0 1 4
// 0 2 3
// 0 2 4
// 0 3 4
// 1 2 3
// 1 2 4
// 1 3 4
// 2 3 4
//
// Here we have few combinations which has quite obvious IDs:
// 0 1 2 -- has ID == 0
// 1 2 3 -- has ID == C(5, 3) - C(4, 3)
// 2 3 4 -- has ID == C(5, 3) - 1
//
// Where C(n, k) -- is a binomial coefficient.
// For example let's explain why combination [1, 2, 3] has
// ID == C(5, 3) - C(4, 3):
// As an auxiliary step let's calculate these two values:
// * The total amount of combinations is C(5, 3).
// * The amount of combinations where the first value is
// greater or equals to "1" -- is C(4, 3), because it has 3 indexes
// and 4 possible values of an index.
// Now since the ">=1"-valued combinations are in the tail, we can just
// subtract C(4, 3) from C(5, 3) and receive the ID of the combination of
// the very first combination with the first index equals to "1".
//
// In total specifically in this combinations-set we can say that combination
// {x, x+1, x+2} has ID == C(5, 3) - C(5-x, 3)
//
//
// Let's assume a generic rule:
//
// For amountOfIndexes = A, maxValue = M, a combination
// x x+1 x+2 ... x+A-1 -- has ID = C(M+1, A) - C(M+1-x, A)
//
// And one may try to prove this method through mathematical induction or
// through unit-tests (see brute_force_test.go)
//
// The problem is kind of solved. But span C(M, A) - C(M-1, A) is too
// large (it is more than a half of all combinations) therefore we need
// to split it as well.
//
// So let's take a look at cases of amountOfIndexes == 3, maxValue == 4
// where index[0] == 0 and will try to construct a more
// detailed formula for "ID":
// 0 1 2
// 0 1 3
// 0 1 4
// 0 2 3
// 0 2 4
// 0 3 4
//
// One might see it is an equivalent of amountOfIndexes == 2, maxValue == 3:
// 0 1
// 0 2
// 0 3
// 1 2
// 1 3
// 2 3
// (just values are shifted by "-1" and the first index is removed)
//
// And we already know how to look for ID in here:
// subID = C(3+1 - m, 2)
//
// Thus if amountOfIndexes = A, maxValue = M then combination:
// n m m+1 m+2 ...
// will have ID = ( C(M+1, A) - C(M+1-n, A) ) + ( C(M+1-n-1, A-1) - C(M+1-n-1-m, A-1) )
//
// Let's construct a generic function (which again could be proved either
// through mathematical induction or through unit-tests):
//
// value_-1 = -1
// ID_i = C(M+1 - value_(i-1) - 1, A-i) - C(M+1 - value_i, A-i)
// ID = sum(i=0; i<A; i++) (ID_i)
//
// See unit-test: TestGetCombinationID
var id uint64
prevValue := uint64(math.MaxUint64) // effectively "-1"
a := uint64(len(s))
m := uint64(maxValue)
for i := uint64(0); i < a; i++ {
value := uint64(s[i])
subID := binomialCoefficientFast(m+1-prevValue-1, a-i) - binomialCoefficientFast(m+1-value, a-i)
id += subID
prevValue = value
}
return id
}
var binomialCoefficientsLookupTable = [binomialCoefficientCacheMaxN + 1][binomialCoefficientCacheMaxK + 1]uint64{}
func binomialCoefficientFast(n, k uint64) uint64 {
if n <= binomialCoefficientCacheMaxN && k <= binomialCoefficientCacheMaxK {
return binomialCoefficientsLookupTable[n][k]
}
// TODO: implement a faster algorithm for this case:
return big.NewInt(1).Binomial(int64(n), int64(k)).Uint64()
}
func initBinomialCoefficientsLookupTable() {
for n := 0; n <= binomialCoefficientCacheMaxN; n++ {
binomialCoefficientsLookupTable[n][0] = 1
}
for k := 1; k <= binomialCoefficientCacheMaxK; k++ {
binomialCoefficientsLookupTable[0][k] = 0
}
for n := 1; n <= binomialCoefficientCacheMaxN; n++ {
for k := 1; k <= binomialCoefficientCacheMaxK; k++ {
// Pascal's rule:
binomialCoefficientsLookupTable[n][k] = binomialCoefficientsLookupTable[n-1][k-1] + binomialCoefficientsLookupTable[n-1][k]
}
}
// Is the code is unclear, then feel free to just google/duckduckgo:
// "binomial coefficients dynamic programming".
}
func init() {
initBinomialCoefficientsLookupTable()
}
func (s UniqueUnorderedCombination) Copy() UniqueUnorderedCombination {
r := make(UniqueUnorderedCombination, len(s))
copy(r, s)
return r
}
// NewUniqueUnorderedCombinationIterator returns a new instance
// of UniqueUnorderedCombinationIterator.
func NewUniqueUnorderedCombinationIterator(amountOfValues uint64, maxValue int64) *UniqueUnorderedCombinationIterator {
return &UniqueUnorderedCombinationIterator{
combination: NewUniqueUnorderedCombination(amountOfValues),
maxValue: Value(maxValue),
}
}
// Next sets the combination to the next combination.
func (iter *UniqueUnorderedCombinationIterator) Next() bool {
return iter.combination.next(iter.maxValue)
}
// GetCombinationID returns current combination ID [0...amount_of_combinations)
func (iter *UniqueUnorderedCombinationIterator) GetCombinationID() uint64 {
return iter.combination.getCombinationID(iter.maxValue)
}
// AmountOfCombinations returns amount of possible combinations.
func (iter *UniqueUnorderedCombinationIterator) AmountOfCombinations() uint64 {
return iter.combination.AmountOfCombinations(iter.maxValue)
}
// SetCombinationID sets combination ID.
//
// The value should be within range [0...amount_of_combinations). Otherwise
// may hang or panic.
func (iter *UniqueUnorderedCombinationIterator) SetCombinationID(combinationID uint64) {
iter.combination.setCombinationID(iter.maxValue, combinationID)
}
// GetCombination is a safe getter of the current combination.
//
// It performs a copy and therefore slow.
func (iter *UniqueUnorderedCombinationIterator) GetCombination() UniqueUnorderedCombination {
// Go does not support read-only variables, therefore we copy:
return iter.combination.Copy()
}
// GetCombinationUnsafe is an unsafe (but fast) getter of the current combination.
func (iter *UniqueUnorderedCombinationIterator) GetCombinationUnsafe() UniqueUnorderedCombination {
return iter.combination
}
// ApplyBitFlips flips bits of `b`, indexes of which are defined by current combination.
func (iter *UniqueUnorderedCombinationIterator) ApplyBitFlips(b []byte) {
iter.combination.ApplyBitFlips(b)
}
// Copy returns a deep copy of the iterator.
func (iter UniqueUnorderedCombinationIterator) Copy() *UniqueUnorderedCombinationIterator {
iter.combination = iter.combination.Copy()
return &iter
}

View File

@ -0,0 +1,96 @@
package bruteforcer
import (
"fmt"
"math"
"math/big"
"math/rand"
"testing"
"github.com/stretchr/testify/require"
)
func TestGetCombinationID(t *testing.T) {
iter := NewUniqueUnorderedCombinationIterator(3, 70)
amountOfCombinations := uint64(binomialCoefficient(70, 3))
for combinationID := uint64(0); combinationID < amountOfCombinations; combinationID++ {
require.Equal(t, combinationID, iter.GetCombinationID())
iter.Next()
}
}
func TestSetGetCombinationID(t *testing.T) {
rand.Seed(0)
iter := NewUniqueUnorderedCombinationIterator(10, 70)
amountOfCombinations := uint64(binomialCoefficient(70, 10))
for i := 0; i < 100; i++ {
combinationID := rand.Uint64() % amountOfCombinations
iter.SetCombinationID(combinationID)
require.Equal(t, combinationID, iter.GetCombinationID())
iter.Next()
}
}
func TestAmountOfCombinations(t *testing.T) {
iter := NewUniqueUnorderedCombinationIterator(10, 70)
require.Equal(t, uint64(binomialCoefficient(71, 10)), iter.AmountOfCombinations())
}
func calcAmountOfCombinations(valueLimit, maxDistance int) int64 {
totalExpectedSize := int64(0)
for distance := 0; distance <= maxDistance; distance++ {
// See https://en.wikipedia.org/wiki/Combination#Number_of_k-combinations
expectedSize := binomialCoefficient(valueLimit, distance)
totalExpectedSize += expectedSize
}
return totalExpectedSize
}
func binomialCoefficient(n, k int) int64 {
v := big.NewInt(1).Binomial(int64(n), int64(k))
if v.Cmp(big.NewInt(math.MaxInt64)) > 0 {
panic("overflow")
}
return v.Int64()
}
func BenchmarkInitBinomialCoefficientsLookupTable(b *testing.B) {
for i := 0; i < b.N; i++ {
initBinomialCoefficientsLookupTable()
}
}
func BenchmarkGetCombinationID(b *testing.B) {
for n := uint64(0); n < 70; n++ {
for k := uint64(0); k <= n; k++ {
b.Run(fmt.Sprintf("n:%d_k:%d", n, k), func(b *testing.B) {
c := NewUniqueUnorderedCombination(k)
maxValue := Value(n - 1)
for i := 0; i < b.N; i++ {
c.getCombinationID(maxValue)
}
})
}
}
}
func BenchmarkSetCombinationID(b *testing.B) {
for n := uint64(0); n < 70; n++ {
for k := uint64(0); k <= n; k++ {
b.Run(fmt.Sprintf("n:%d_k:%d", n, k), func(b *testing.B) {
c := NewUniqueUnorderedCombination(k)
maxValue := Value(n - 1)
amountOfCombinations := uint64(binomialCoefficient(int(n), int(k)))
combinationID := amountOfCombinations / 3
b.Run("smart", func(b *testing.B) {
for i := 0; i < b.N; i++ {
c.setCombinationID(maxValue, 1)
c.setCombinationID(maxValue, combinationID)
}
})
})
}
}
}

View File

@ -0,0 +1,24 @@
package pcrbruteforcer
import (
"sync"
)
type registerHashCache struct {
m sync.Map
}
func newRegisterHashCache() *registerHashCache {
return &registerHashCache{}
}
func (c *registerHashCache) Get(reg uint64) (hash []byte) {
if hashI, ok := c.m.Load(reg); ok {
return hashI.([]byte)
}
return nil
}
func (c *registerHashCache) Set(reg uint64, hash []byte) {
c.m.Store(reg, hash)
}

View File

@ -0,0 +1,195 @@
package pcrbruteforcer
import (
"bytes"
"crypto/sha1"
"encoding/binary"
"fmt"
"hash"
"github.com/9elements/converged-security-suite/v2/pkg/bruteforcer"
multierror "github.com/9elements/converged-security-suite/v2/pkg/errors"
"github.com/9elements/converged-security-suite/v2/pkg/pcr"
"github.com/9elements/converged-security-suite/v2/pkg/registers"
"github.com/9elements/converged-security-suite/v2/pkg/tpmeventlog"
)
// ReproduceEventLog verifies measurements through TPM EventLog. If successful,
// the first returned variable is true; in any case all problems
// are reported through `error`; and if ACM_POLICY_STATUS should be amended,
// then the updated value is returned as the second variable.
//
// Current algorithm already supports disabling measurements, may be in future
// we will return the rest amended measurements as well.
//
// Currently we focus only on SHA1 measurements to simplify the code.
func ReproduceEventLog(
eventLog *tpmeventlog.TPMEventLog,
measurementsSHA1 pcr.Measurements,
imageBytes []byte,
) (bool, *registers.ACMPolicyStatus, error) {
if eventLog == nil {
return false, nil, fmt.Errorf("TPM EventLog is not provided")
}
events, err := eventLog.FilterEvents(0, tpmeventlog.TPMAlgorithmSHA1)
if err != nil {
return false, nil, fmt.Errorf("unable to filter events: %w", err)
}
mErr := &multierror.MultiError{}
var filteredMeasurements pcr.Measurements
for _, m := range measurementsSHA1 {
if m.IsFake() && m.ID != pcr.MeasurementIDInit {
continue
}
if len(m.EventLogEventTypes()) == 0 {
_ = mErr.Add(fmt.Errorf("the flow requires a measurement, which is not expected to be logged into EventLog"))
continue
}
filteredMeasurements = append(filteredMeasurements, m)
}
var updatedACMPolicyStatusValue *registers.ACMPolicyStatus
evIdx, mIdx := 0, 0
result := true
for evIdx < len(events) && mIdx < len(filteredMeasurements) {
m := filteredMeasurements[mIdx]
mIdx++
ev := eventLog.Events[evIdx]
matched := false
for _, eventType := range m.EventLogEventTypes() {
if *eventType == ev.Type {
matched = true
}
}
if !matched {
_ = mErr.Add(fmt.Errorf("missing measurement '%s' in EventLog (expected event types %v, but received %d on evIdx==%d)", m.ID, m.EventLogEventTypes(), ev.Type, evIdx))
// We assume it happened because some measurements are missing
// in the eventlog, therefore we skip the measurements hoping
// that next measurement match with the EventLog entry.
continue
}
evIdx++
if m.ID == pcr.MeasurementIDInit {
// Nothing to compare
continue
}
mHash := sha1.Sum(m.CompileMeasurableData(imageBytes))
if bytes.Equal(mHash[:], ev.Digest.Digest) {
// It matched, everything is OK, let's check next pair.
continue
}
// It haven't matched, something is wrong...
//
// Let's try to remediate if we have an idea how to do that, or
// just acknowledge a problem if we cannot remediate it.
switch {
case m.ID == pcr.MeasurementIDPCR0DATA:
// If this is the PCR0_DATA measurement then it could be just
// a corrupted ACM_POLICY_STATUS register value, let's try
// to restore it.
correctedACMPolicyStatus, err := bruteForceACMPolicyStatus(*m, imageBytes, ev.Digest.Digest)
if err != nil {
_ = mErr.Add(fmt.Errorf("PCR0_DATA measurement does not match the digest reported in EventLog and unable to brute force a possible bitflip: %X != %X", mHash[:], ev.Digest.Digest))
result = false
continue
}
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], uint64(correctedACMPolicyStatus))
_ = mErr.Add(fmt.Errorf("changed ACM_POLICY_STATUS from %X to %X", m.Data[0].ForceData, buf))
updatedACMPolicyStatusValue = &correctedACMPolicyStatus
default:
// I do not know how to remediate this problem.
_ = mErr.Add(fmt.Errorf("measurement '%s' does not match the digest reported in EventLog: %X != %X", m.ID, mHash[:], ev.Digest.Digest))
result = false
}
}
if evIdx == 0 {
// no-one EventLog entry matched, it could not be considered as "remediated"/"fixed".
result = false
}
for ; mIdx < len(filteredMeasurements); mIdx++ {
m := filteredMeasurements[mIdx]
_ = mErr.Add(fmt.Errorf("missing measurement '%s' in EventLog", m.ID))
}
for ; evIdx < len(events); evIdx++ {
ev := events[evIdx]
_ = mErr.Add(fmt.Errorf("extra EventLog entry: evIdx == %d: type == %v", evIdx, ev.Type))
}
return result, updatedACMPolicyStatusValue, mErr.ReturnValue()
}
type bruteForceACMPolicyStatusEventContext struct {
Hasher hash.Hash
Buf []byte
}
func bruteForceACMPolicyStatus(m pcr.Measurement, imageBytes []byte, expectedPCR0DATASHA1Digest []byte) (registers.ACMPolicyStatus, error) {
if len(m.Data) == 0 {
return 0, fmt.Errorf("no data in the measurement")
}
if m.ID != pcr.MeasurementIDPCR0DATA {
return 0, fmt.Errorf("PCR0_DATA excepted, but received %s", m.ID)
}
if len(m.Data) == 0 || m.Data[0].ID != pcr.DataChunkIDACMPolicyStatus {
return 0, fmt.Errorf("excepted the first data chunk of PCR0_DATA be the ACM_POLICY_STATUS register")
}
m = *m.Copy()
acmPolicyStatus := m.Data[0].ForceData
if len(acmPolicyStatus) != 8 {
return 0, fmt.Errorf("ACM POLICY STATUS register is expected to be 64bits, but it is %dbits", len(acmPolicyStatus)*8)
}
pcr0Data := m.CompileMeasurableData(imageBytes)
// maxDistance is the maximal hamming distance to brute force to, it is
// picked to 6, because it is maximal value for a reasonable brute-force
// time (about 1 second).
//
// For benchmark details see also README.md of package `bruteforcer`.
maxDistance := 6
newContextFunc := func() (interface{}, error) {
buf := make([]byte, len(pcr0Data))
copy(buf, pcr0Data)
return &bruteForceACMPolicyStatusEventContext{
Hasher: sha1.New(),
Buf: buf,
}, nil
}
verifyACMPolicyStatusFunc := func(_ctx interface{}, acmPolicyStatus []byte) bool {
ctx := _ctx.(*bruteForceACMPolicyStatusEventContext)
pcr0Data := ctx.Buf
hasher := ctx.Hasher
// overwriting the beginning of pcr0Data with new value of acmPolicyStatus.
copy(pcr0Data, acmPolicyStatus)
hasher.Write(pcr0Data)
hashValue := hasher.Sum(nil)
hasher.Reset()
return bytes.Equal(hashValue, expectedPCR0DATASHA1Digest)
}
combination, err := bruteforcer.BruteForceBytes(acmPolicyStatus, uint64(maxDistance), newContextFunc, verifyACMPolicyStatusFunc, 0)
if combination == nil {
return 0, fmt.Errorf("unable to brute force: %w", err)
}
combination.ApplyBitFlips(acmPolicyStatus)
return registers.ParseACMPolicyStatusRegister(binary.LittleEndian.Uint64(acmPolicyStatus)), nil
}

View File

@ -0,0 +1,91 @@
package pcrbruteforcer
import (
"encoding/hex"
"fmt"
"testing"
"github.com/9elements/converged-security-suite/v2/pkg/pcr"
"github.com/9elements/converged-security-suite/v2/pkg/registers"
"github.com/9elements/converged-security-suite/v2/pkg/tpmeventlog"
"github.com/9elements/converged-security-suite/v2/pkg/uefi"
"github.com/9elements/converged-security-suite/v2/testdata/firmware"
"github.com/google/go-tpm/tpm2"
"github.com/stretchr/testify/require"
)
func unhex(fataler fataler, h string) []byte {
b, err := hex.DecodeString(h)
if err != nil {
fataler.Fatal(err)
}
return b
}
func TestReproduceEventLog(t *testing.T) {
firmwareImage := firmware.FakeIntelFirmware
firmware, err := uefi.ParseUEFIFirmwareBytes(firmwareImage)
require.NoError(t, err)
measureOptions := []pcr.MeasureOption{
pcr.SetFlow(pcr.FlowIntelCBnT0T),
pcr.SetIBBHashDigest(tpm2.AlgSHA1),
pcr.SetRegisters(registers.Registers{
registers.ParseACMPolicyStatusRegister(0x0000000200108682),
}),
}
measurements, _, debugInfo, err := pcr.GetMeasurements(firmware, 0, measureOptions...)
require.NoError(t, err, fmt.Sprintf("debugInfo: '%v'", debugInfo))
eventLog := &tpmeventlog.TPMEventLog{
Events: []*tpmeventlog.Event{
{
PCRIndex: 0,
Type: tpmeventlog.EV_NO_ACTION,
Data: []byte("StartupLocality\000\003"),
Digest: &tpmeventlog.Digest{
HashAlgo: 4,
Digest: unhex(t, "0000000000000000000000000000000000000000"),
},
},
{
PCRIndex: 0,
Type: tpmeventlog.EV_S_CRTM_CONTENTS,
Digest: &tpmeventlog.Digest{
HashAlgo: 4,
Digest: unhex(t, "527C9A38B2F45FBF89C382547E0A0812722A47D3"),
},
},
{
PCRIndex: 0,
Type: tpmeventlog.EV_S_CRTM_VERSION,
Digest: &tpmeventlog.Digest{
HashAlgo: 4,
Digest: unhex(t, "C14F556E35C9BB45F189B03F383A6A3E31256681"),
},
},
{
PCRIndex: 0,
Type: tpmeventlog.EV_POST_CODE,
Digest: &tpmeventlog.Digest{
HashAlgo: 4,
Digest: unhex(t, "4C9836F73CC42ADBECE7D565B783E618B4A75C22"),
},
},
{
PCRIndex: 0,
Type: tpmeventlog.EV_SEPARATOR,
Digest: &tpmeventlog.Digest{
HashAlgo: 4,
Digest: unhex(t, "9069CA78E7450A285173431B3E52C5C25299E473"),
},
},
},
}
succeeded, acmPolicyStatus, _ := ReproduceEventLog(eventLog, measurements, firmwareImage)
require.True(t, succeeded)
require.NotNil(t, acmPolicyStatus)
require.Equal(t, uint64(0x0000000200108681), acmPolicyStatus.Raw())
}

View File

@ -0,0 +1,705 @@
package pcrbruteforcer
import (
"bytes"
"context"
"crypto/sha1"
"crypto/sha256"
"encoding/binary"
"fmt"
"hash"
"runtime"
"sync"
"sync/atomic"
"time"
"github.com/9elements/converged-security-suite/v2/pkg/bruteforcer"
"github.com/9elements/converged-security-suite/v2/pkg/errors"
"github.com/9elements/converged-security-suite/v2/pkg/pcr"
"github.com/9elements/converged-security-suite/v2/pkg/registers"
"github.com/linuxboot/contest/pkg/xcontext"
)
const (
// the limit for the linear bruteforcer
maxACMPolicyLinearDistance = 128
// the limit for the combinatorial bruteforcer (expensive)
maxACMPolicyCombinatorialDistance = 2
// defines minimal "disabled measurements" combinations handled by one goroutine
minCombinationsPerRoutine = 1
// enableCombinatorialStrategy enables a strategy to brute-force ACM Policy
// Status register by finding a combination of bits to flip. This was the
// initial approach before the nature of the corruptions was investaged,
// and it became clear that a more effective strategy is just linear
// decrement.
enableCombinatorialStrategy = false
)
// ReproduceExpectedPCR0 brute-forces measurements to achieve the expected PCR0
// SHA1 or SHA256 value.
//
// If succeeded to reproduce, then `isSuccess` is true.
//
// The updated ACM_POLICY_STATUS value is returned as `updatedACMPolicyStatus`.
//
// All the problems are returned through `returnErr`.
//
// Current algorithm already supports disabling measurements, may be in future
// we will return the rest amended measurements as well.
func ReproduceExpectedPCR0(
ctx xcontext.Context,
expectedPCR0 []byte,
flow pcr.Flow,
measurements pcr.Measurements,
imageBytes []byte,
) (isSuccess bool, locality uint8, updatedACMPolicyStatus *registers.ACMPolicyStatus, returnErr error) {
var realMeasurements pcr.Measurements
for _, ms := range measurements {
if ms.IsFake() {
continue
}
realMeasurements = append(realMeasurements, ms)
}
handler, err := newReproduceExpectedPCR0Handler(
expectedPCR0,
flow,
realMeasurements,
imageBytes,
)
if err != nil {
return false, 0, nil, fmt.Errorf("unable to initialize a handler: %w", err)
}
return handler.Execute(ctx)
}
type reproduceExpectedPCR0Handler struct {
expectedPCR0 []byte
flow pcr.Flow
precalculatedMeasurements []*pcr.CachedMeasurement
imageBytes []byte
hashFuncFactory func() hash.Hash
}
func newReproduceExpectedPCR0Handler(
expectedPCR0 []byte,
flow pcr.Flow,
measurements pcr.Measurements,
imageBytes []byte,
) (*reproduceExpectedPCR0Handler, error) {
var hashFuncFactory func() hash.Hash
switch len(expectedPCR0) {
case sha1.Size:
hashFuncFactory = sha1.New
case sha256.Size:
hashFuncFactory = sha256.New
default:
return nil, fmt.Errorf("invalid len for expectedPCR0: %d", len(expectedPCR0))
}
precalculatedMeasurements, err := cacheMeasurements(measurements, imageBytes, hashFuncFactory)
if err != nil {
return nil, fmt.Errorf("invalid measurements: %w", err)
}
return &reproduceExpectedPCR0Handler{
expectedPCR0: expectedPCR0,
flow: flow,
precalculatedMeasurements: precalculatedMeasurements,
imageBytes: imageBytes,
hashFuncFactory: hashFuncFactory,
}, nil
}
func (h *reproduceExpectedPCR0Handler) Execute(
_ctx context.Context,
) (
isSuccess bool,
locality uint8,
updatedACMPolicyStatus *registers.ACMPolicyStatus,
returnErr error,
) {
ctx, ok := _ctx.(xcontext.Context)
if !ok {
ctx = xcontext.Extend(_ctx)
}
// To speedup brute-force process we try the expected locality first,
// and only after that we try second expected locality.
defer ctx.Tracer().StartSpan("reproduceExpectedPCR0Handler").Finish()
// The expected locality.
isSuccess, locality, updatedACMPolicyStatus, returnErr = h.execute(ctx, []uint8{h.flow.TPMLocality()})
if isSuccess {
return
}
// The second expected locality (flipping 0 and 3).
var restLocalities []uint8
switch h.flow.TPMLocality() {
case 0:
restLocalities = []uint8{3}
case 3:
restLocalities = []uint8{0}
default:
// The expected locality is neither 0 nor 3? We are not aware of
// such cases. Let's try all other localities then :)
for tryLocality := uint8(0); tryLocality < 4; tryLocality++ {
if tryLocality == h.flow.TPMLocality() {
continue
}
restLocalities = append(restLocalities, tryLocality)
}
}
return h.execute(ctx, restLocalities)
}
func (h *reproduceExpectedPCR0Handler) execute(
ctx xcontext.Context,
localities []uint8,
) (
isSuccess bool,
locality uint8,
updatedACMPolicyStatus *registers.ACMPolicyStatus,
returnErr error,
) {
ctx, cancelFunc := xcontext.WithCancel(ctx)
returnErr = fmt.Errorf("unable to reproduce the expected PCR0 value")
var returnCount uint64
var wg sync.WaitGroup
defer wg.Wait()
for _, tryLocality := range localities {
wg.Add(1)
go func(tryLocality uint8) {
defer wg.Done()
ctx.Logger().Debugf("reproduce pcr0 starting bruteforce... (locality: %v)", tryLocality)
startTime := time.Now()
foundAnswer, v, err := h.newJob(tryLocality).Execute(ctx)
elapsed := time.Since(startTime)
if !foundAnswer && err == nil {
ctx.Logger().Debugf("reproduce pcr0 did not find an answer (locality: %v, elapsed: %v)", tryLocality, elapsed)
return
}
ctx.Logger().Debugf("reproduce pcr0 got an answer (locality: %v, elapsed: %v)", tryLocality, elapsed)
if c := atomic.AddUint64(&returnCount, 1); c != 1 {
ctx.Logger().Errorf("received a final answer with different localities")
return
}
ctx.Logger().Debugf("received an answer (locality:%d, expectedLocality:%d): %v %v", tryLocality, h.flow.TPMLocality(), foundAnswer, err)
cancelFunc()
if foundAnswer && tryLocality != h.flow.TPMLocality() {
// Append current errors (even if there are none) with an additional one:
err = (&errors.MultiError{}).Add(
err,
fmt.Errorf("locality mismatch, expected:%d, reproduced:%d", h.flow.TPMLocality(), tryLocality),
).ReturnValue()
}
isSuccess = true
locality = tryLocality
updatedACMPolicyStatus = v
returnErr = err
}(tryLocality)
}
return
}
func (h *reproduceExpectedPCR0Handler) newJob(
locality uint8,
) *reproduceExpectedPCR0Job {
return &reproduceExpectedPCR0Job{
imageBytes: h.imageBytes,
measurements: h.precalculatedMeasurements,
hashFuncFactory: h.hashFuncFactory,
expectedPCR0: h.expectedPCR0,
locality: locality,
registerHashCache: newRegisterHashCache(),
}
}
type reproduceExpectedPCR0Job struct {
// immutable fields:
imageBytes []byte
measurements []*pcr.CachedMeasurement
hashFuncFactory func() hash.Hash
expectedPCR0 []byte
locality uint8
registerHashCache *registerHashCache
}
func (j *reproduceExpectedPCR0Job) Execute(
ctx xcontext.Context,
) (isSuccess bool, actualACMPolicyStatus *registers.ACMPolicyStatus, retErr error) {
var mErr errors.MultiError
defer func() {
retErr = mErr.ReturnValue()
}()
concurrencyFactor := runtime.GOMAXPROCS(0)
ctx, cancelFn := xcontext.WithCancel(ctx)
for disabledMeasurements := 0; disabledMeasurements < len(j.measurements); disabledMeasurements++ {
disabledMeasurementsIterator := bruteforcer.NewUniqueUnorderedCombinationIterator(uint64(disabledMeasurements), int64(len(j.measurements)))
maxCombinationID := disabledMeasurementsIterator.AmountOfCombinations() - 1
combinationsPerRoutine := (maxCombinationID + 1) / uint64(concurrencyFactor)
if combinationsPerRoutine < minCombinationsPerRoutine {
combinationsPerRoutine = minCombinationsPerRoutine
}
type iterationResult struct {
isSuccess bool
actualACMPolicyStatus *registers.ACMPolicyStatus
err error
}
resultCh := make(chan iterationResult, concurrencyFactor+1)
var wg sync.WaitGroup
for startCombinationID := uint64(0); startCombinationID <= maxCombinationID; startCombinationID += combinationsPerRoutine {
wg.Add(1)
go func(disabledMeasurementsIterator *bruteforcer.UniqueUnorderedCombinationIterator, startCombinationID uint64) {
defer wg.Done()
endCombinationID := startCombinationID + combinationsPerRoutine
if endCombinationID > maxCombinationID {
endCombinationID = maxCombinationID + 1
}
if startCombinationID != 0 {
disabledMeasurementsIterator.SetCombinationID(startCombinationID)
}
for combinationID := startCombinationID; combinationID < endCombinationID; combinationID++ {
if ctx.IsSignaledWith() {
return
}
_isSuccess, _actualACMPolicyStatus, _err := j.tryDisabledMeasurementsCombination(ctx, disabledMeasurementsIterator.GetCombinationUnsafe(), j.hashFuncFactory)
if _isSuccess || _err != nil {
resultCh <- iterationResult{
isSuccess: _isSuccess,
actualACMPolicyStatus: _actualACMPolicyStatus,
err: _err,
}
cancelFn()
return
}
if !disabledMeasurementsIterator.Next() {
break
}
}
}(disabledMeasurementsIterator.Copy(), startCombinationID)
}
wg.Wait()
close(resultCh)
for result := range resultCh {
if result.isSuccess && !isSuccess {
isSuccess = true
actualACMPolicyStatus = result.actualACMPolicyStatus
}
if result.err != nil {
_ = mErr.Add(result.err)
}
}
if isSuccess || mErr.Count() != 0 {
return
}
}
return
}
func (j *reproduceExpectedPCR0Job) tryDisabledMeasurementsCombination(
ctx xcontext.Context,
disabledMeasurementsCombination bruteforcer.UniqueUnorderedCombination,
hashFuncFactory func() hash.Hash,
) (bool, *registers.ACMPolicyStatus, error) {
var enabledMeasurements []*pcr.CachedMeasurement
for idx, m := range j.measurements {
isDisabled := false
// TODO: refactor this O(N^2); generate the picked measurements from the get go
for _, disableIdx := range disabledMeasurementsCombination {
if idx == int(disableIdx) {
isDisabled = true
break
}
}
if isDisabled {
continue
}
enabledMeasurements = append(enabledMeasurements, m)
}
isSuccess, actualACMPolicyStatus, err := j.measurementsVerify(j.expectedPCR0, enabledMeasurements, hashFuncFactory)
if !isSuccess {
return false, nil, err
}
mErr := (&errors.MultiError{}).Add(err)
for _, disabledMeasurementIdx := range disabledMeasurementsCombination {
var m pcr.MeasureEvent
for idx := range j.measurements {
if int(disabledMeasurementIdx) == idx {
m = j.measurements[idx]
break
}
}
if m == nil {
ctx.Errorf("unable to find a measurement with index: %d", disabledMeasurementIdx)
continue
}
_ = mErr.Add(fmt.Errorf("measurement '%s' was disabled to reproduce the hash", m.GetID()))
}
return true, actualACMPolicyStatus, mErr.ReturnValue()
}
func (j *reproduceExpectedPCR0Job) measurementsVerify(
expectedHashValue []byte,
enabledMeasurements []*pcr.CachedMeasurement,
hasherFactory func() hash.Hash,
) (bool, *registers.ACMPolicyStatus, error) {
switch {
case len(enabledMeasurements) > 0 && enabledMeasurements[0].ID == pcr.MeasurementIDPCR0DATA:
isSuccess, actualACMPolicyStatus, err := j.measurementsVerifyWithBruteForceACMPolicyStatus(expectedHashValue, enabledMeasurements, hasherFactory)
if isSuccess || err != nil {
return isSuccess, actualACMPolicyStatus, err
}
default:
// just check that the measurements lead to the expected pcr0 value
ms := make([]pcr.MeasureEvent, 0, len(enabledMeasurements))
for _, m := range enabledMeasurements {
ms = append(ms, m)
}
pcr0HashValue, err := pcr.CalculatePCR(j.imageBytes, j.locality, ms, hasherFactory(), nil)
if err != nil {
return false, nil, fmt.Errorf("unable to calculate PCR0 value: %w", err)
}
if bytes.Equal(pcr0HashValue, expectedHashValue) {
return true, nil, nil
}
}
return false, nil, nil
}
func (j *reproduceExpectedPCR0Job) measurementsVerifyWithBruteForceACMPolicyStatus(
expectedHashValue []byte,
enabledMeasurements []*pcr.CachedMeasurement,
hasherFactory func() hash.Hash,
) (bool, *registers.ACMPolicyStatus, error) {
if len(enabledMeasurements) < 1 {
return false, nil, fmt.Errorf("empty measurements slice, cannot compute PCR0")
}
if enabledMeasurements[0].ID != pcr.MeasurementIDPCR0DATA {
return false, nil, fmt.Errorf("first measurement is not the ACM policy status register")
}
acmPolicyStatus := enabledMeasurements[0].Data[0].ForceData
if len(acmPolicyStatus) != 8 {
return false, nil, fmt.Errorf("ACM POLICY STATUS register is expected to be 64bits, but it is %d bits", len(acmPolicyStatus)*8)
}
// try these in series because each completely fills the cpu
strategies := []bruteForceStrategy{
newLinearSearch(maxACMPolicyLinearDistance, j.imageBytes, expectedHashValue, hasherFactory, j.registerHashCache),
}
if enableCombinatorialStrategy {
strategies = append(strategies, newCombinatorialSearch(maxACMPolicyCombinatorialDistance, j.imageBytes, expectedHashValue, hasherFactory, j.registerHashCache))
}
for _, s := range strategies {
reg, issue, err := s.Process(j.locality, enabledMeasurements)
if err != nil {
// TODO: this needs to get fixed; treating program errors and algo outcome issues the same way
return false, nil, err
}
if reg != nil {
return true, reg, issue
}
}
return false, nil, nil
}
//-----------------------------------------------------------------------------
// ACM bruteforcing strategies
//-----------------------------------------------------------------------------
type hashFactory func() hash.Hash
type issue error
type bruteForceStrategy interface {
Process(locality uint8, ms []*pcr.CachedMeasurement) (*registers.ACMPolicyStatus, issue, error)
}
func cacheMeasurements(ms pcr.Measurements, image []byte, hashFactory hashFactory) ([]*pcr.CachedMeasurement, error) {
msCached := make([]*pcr.CachedMeasurement, 0, len(ms))
for i := 0; i < len(ms); i++ {
cached, err := ms[i].Cache(image, hashFactory())
if err != nil {
return nil, err
}
msCached = append(msCached, cached)
}
return msCached, nil
}
type linearSearch struct {
limit int
image []byte
expected []byte
hashFactory hashFactory
registerHashCache *registerHashCache
}
func newLinearSearch(limit int, image []byte, expected []byte, hashFactory hashFactory, registerHashCache *registerHashCache) *linearSearch {
return &linearSearch{limit, image, expected, hashFactory, registerHashCache}
}
func (ls *linearSearch) Process(locality uint8, ms []*pcr.CachedMeasurement) (*registers.ACMPolicyStatus, issue, error) {
type bruteForceContext struct {
Hash hash.Hash
MeasureEvents []pcr.MeasureEvent
Buffer []byte
}
init := func() (*bruteForceContext, error) {
fastMS := prepareFastMeasurements(ms, ls.image, ls.registerHashCache)
return &bruteForceContext{
Hash: ls.hashFactory(),
MeasureEvents: fastMS,
Buffer: fastMS[0].(*pcr0DataFastMeasurement).Data[:len(ms[0].Data[0].ForceData)],
}, nil
}
check := func(ctx *bruteForceContext) (bool, error) {
// check if this series of measurements lead to the expected pcr0
pcr0HashValue, err := pcr.CalculatePCR(
ls.image, locality, ctx.MeasureEvents,
ctx.Hash, nil,
)
if err != nil {
return false, err
}
return bytes.Equal(pcr0HashValue, ls.expected), nil
}
start := ms[0].Data[0].ForceData
concurrencyFactor := runtime.GOMAXPROCS(0)
blockSize := ls.limit / concurrencyFactor
if blockSize < 1 {
blockSize = 1
}
var wg sync.WaitGroup
resultChan := make(chan []byte)
errChan := make(chan error)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for i := 0; i < concurrencyFactor; i++ {
blockStart := i * blockSize
blockEnd := (i + 1) * blockSize
if i == concurrencyFactor-1 {
blockEnd = ls.limit
}
wg.Add(1)
go func(blockStart, blockEnd int, resultChan chan<- []byte, errChan chan<- error) {
defer wg.Done()
sctx, err := init()
if err != nil {
select {
case errChan <- err:
case <-ctx.Done():
}
return
}
blockValue := binary.LittleEndian.Uint64(start) - uint64(blockStart)
for bi := blockStart; bi < blockEnd; bi++ {
select {
case <-ctx.Done():
return
default:
}
// will possibly underflow, but that's ok
binary.LittleEndian.PutUint64(sctx.Buffer, blockValue)
blockValue--
ok, err := check(sctx)
if err != nil {
select {
case errChan <- err:
case <-ctx.Done():
}
return
}
if ok {
select {
case resultChan <- sctx.Buffer:
case <-ctx.Done():
}
return
}
}
}(blockStart, blockEnd, resultChan, errChan)
}
// cancel if there are no answers
go func() {
wg.Wait()
cancel()
}()
select {
case <-ctx.Done():
// no answers and no errors, wg was just done
return nil, nil, nil
case err := <-errChan:
return nil, nil, err
case result := <-resultChan:
var issue issue
if !bytes.Equal(start, result) {
issue = fmt.Errorf("changed ACM_POLICY_STATUS from %X to %X", start, result)
}
correctACMReg := registers.ParseACMPolicyStatusRegister(binary.LittleEndian.Uint64(result))
return &correctACMReg, issue, nil
}
}
type combinatorialSearch struct {
limit int
image []byte
expected []byte
hashFactory hashFactory
registerHashCache *registerHashCache
}
func newCombinatorialSearch(limit int, image []byte, expected []byte, hashFactory hashFactory, registerHashCache *registerHashCache) *combinatorialSearch {
return &combinatorialSearch{limit, image, expected, hashFactory, registerHashCache}
}
type pcr0DataFastMeasurement struct {
Data []byte
RegisterHashCache *registerHashCache
}
var _ pcr.MeasureEvent = &pcr0DataFastMeasurement{}
func (*pcr0DataFastMeasurement) GetID() pcr.MeasurementID {
return pcr.MeasurementIDPCR0DATA
}
func (m *pcr0DataFastMeasurement) CompileMeasurableData(image []byte) []byte {
return m.Data
}
func (m *pcr0DataFastMeasurement) Calculate(image []byte, hashFunc hash.Hash) ([]byte, error) {
reg := binary.LittleEndian.Uint64(m.Data)
cachedHash := m.RegisterHashCache.Get(reg)
if cachedHash != nil {
return cachedHash, nil
}
_, err := hashFunc.Write(m.Data)
if err != nil {
return nil, err
}
defer hashFunc.Reset()
hashValue := hashFunc.Sum(nil)
m.RegisterHashCache.Set(reg, hashValue)
return hashValue, nil
}
func newPCR0DataFastMeasurement(origMeasurement *pcr.CachedMeasurement, image []byte, cache *registerHashCache) *pcr0DataFastMeasurement {
data := origMeasurement.CompileMeasurableData(image)
b := make([]byte, len(data))
copy(b, data)
return &pcr0DataFastMeasurement{
Data: b,
RegisterHashCache: cache,
}
}
func prepareFastMeasurements(ms []*pcr.CachedMeasurement, image []byte, cache *registerHashCache) []pcr.MeasureEvent {
copyMS := make([]pcr.MeasureEvent, len(ms))
for idx, m := range ms {
if m.ID == pcr.MeasurementIDPCR0DATA {
copyMS[idx] = newPCR0DataFastMeasurement(m, image, cache)
} else {
copyMS[idx] = m
}
}
return copyMS
}
func (cs *combinatorialSearch) Process(locality uint8, ms []*pcr.CachedMeasurement) (*registers.ACMPolicyStatus, issue, error) {
type bruteForceContext struct {
Hash hash.Hash
MeasureEvents []pcr.MeasureEvent
}
initFunc := func() (interface{}, error) {
return &bruteForceContext{
Hash: cs.hashFactory(),
MeasureEvents: prepareFastMeasurements(ms, cs.image, cs.registerHashCache),
}, nil
}
verifyFunc := func(_ctx interface{}, data []byte) bool {
ctx := _ctx.(*bruteForceContext)
copy(ctx.MeasureEvents[0].(*pcr0DataFastMeasurement).Data, data)
// check if this series of measurements lead to the expected pcr0
pcr0HashValue, err := pcr.CalculatePCR(
cs.image, locality, ctx.MeasureEvents,
ctx.Hash, nil,
)
if err != nil {
// TODO: should prob return the error here instead of eating it
return false
}
return bytes.Equal(pcr0HashValue, cs.expected)
}
start := ms[0].Data[0].ForceData
combination, err := bruteforcer.BruteForceBytes(start, uint64(cs.limit), initFunc, verifyFunc, 0)
if combination == nil || err != nil {
return nil, nil, err
}
ACMRegValue := make([]byte, len(start))
copy(ACMRegValue, start)
var issue error
if len(combination) != 0 {
combination.ApplyBitFlips(ACMRegValue)
issue = fmt.Errorf("changed ACM_POLICY_STATUS from %X to %X", start, ACMRegValue)
}
correctACMReg := registers.ParseACMPolicyStatusRegister(binary.LittleEndian.Uint64(ACMRegValue))
return &correctACMReg, issue, nil
}

View File

@ -0,0 +1,162 @@
package pcrbruteforcer
import (
"bytes"
"fmt"
"testing"
"github.com/9elements/converged-security-suite/v2/pkg/pcr"
"github.com/9elements/converged-security-suite/v2/pkg/registers"
"github.com/9elements/converged-security-suite/v2/pkg/uefi"
"github.com/9elements/converged-security-suite/v2/testdata/firmware"
"github.com/linuxboot/contest/pkg/xcontext/bundles/logrusctx"
"github.com/linuxboot/contest/pkg/xcontext/logger"
"github.com/google/go-tpm/tpm2"
"github.com/linuxboot/contest/pkg/xcontext"
"github.com/stretchr/testify/require"
)
type fataler interface {
Fatal(args ...interface{})
}
func getFirmware(fataler fataler) *uefi.UEFI {
firmwareImage := firmware.FakeIntelFirmware
firmware, err := uefi.ParseUEFIFirmwareBytes(firmwareImage)
if err != nil {
fataler.Fatal(err)
}
return firmware
}
func TestReproduceExpectedPCR0(t *testing.T) {
firmware := getFirmware(t)
const correctACMRegValue = 0x0000000200108681
pcr0Correct := unhex(t, "F4D6D480F066F64A78598D82D1DEC77BBD53DEC1")
// Take PCR0 with partially enabled measurements, only:
// * PCR0_DATA
// * DXE
// Thus without:
// * PCD Firmware Vendor Version
// * Separator
pcr0Incomplete := unhex(t, "4CB03F39E94B0AB4AD99F9A54E3FD0DEFB0BB2D4")
pcr0Invalid := unhex(t, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
testACM := func(t *testing.T, pcr0 []byte, acmReg uint64) {
measureOptions := []pcr.MeasureOption{
pcr.SetFlow(pcr.FlowIntelCBnT0T),
pcr.SetIBBHashDigest(tpm2.AlgSHA1),
pcr.SetRegisters(registers.Registers{
registers.ParseACMPolicyStatusRegister(acmReg),
}),
}
measurements, _, debugInfo, err := pcr.GetMeasurements(firmware, 0, measureOptions...)
require.NoError(t, err, fmt.Sprintf("debugInfo: '%v'", debugInfo))
succeeded, _, acmPolicyStatus, err := ReproduceExpectedPCR0(
logrusctx.NewContext(logger.LevelDebug),
pcr0,
pcr.FlowIntelCBnT0T,
measurements,
firmware.Buf(),
)
if bytes.Equal(pcr0, pcr0Invalid) {
require.False(t, succeeded)
require.Nil(t, acmPolicyStatus)
} else {
require.True(t, succeeded, "%v\n%v\n%v", err, measurements, debugInfo)
require.Equal(t, uint64(correctACMRegValue), acmPolicyStatus.Raw())
}
}
t.Run("test_uncorrupted", func(t *testing.T) { testACM(t, pcr0Correct, correctACMRegValue) })
t.Run("test_corrupted_linear", func(t *testing.T) { testACM(t, pcr0Correct, correctACMRegValue+0x1c) })
if enableCombinatorialStrategy {
t.Run("test_corrupted_combinatorial", func(t *testing.T) { testACM(t, pcr0Correct, correctACMRegValue^0x10000000) })
}
t.Run("test_incompletePCR0_corruptedACM", func(t *testing.T) { testACM(t, pcr0Incomplete, correctACMRegValue+1) })
t.Run("test_invalid_PCR0", func(t *testing.T) { testACM(t, pcr0Invalid, correctACMRegValue) })
}
func BenchmarkReproduceExpectedPCR0(b *testing.B) {
firmware := getFirmware(b)
const correctACMRegValue = 0x0000000200108681
ctx := xcontext.Background()
pcr0Correct := unhex(b, "F4D6D480F066F64A78598D82D1DEC77BBD53DEC1")
pcr0Incomplete := unhex(b, "4CB03F39E94B0AB4AD99F9A54E3FD0DEFB0BB2D4")
pcr0Invalid := unhex(b, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
var acmCorruptions []uint64
if enableCombinatorialStrategy {
acmCorruptions = append(acmCorruptions, []uint64{0x100000000, 0x100100000}...)
}
acmCorruptions = append(acmCorruptions, []uint64{0x1c, 0}...)
for _, acmCorruption := range acmCorruptions {
b.Run(fmt.Sprintf("acmCorruption_%X", acmCorruption), func(b *testing.B) {
measureOptions := []pcr.MeasureOption{
pcr.SetFlow(pcr.FlowIntelCBnT0T),
pcr.SetIBBHashDigest(tpm2.AlgSHA1),
pcr.SetRegisters(registers.Registers{
registers.ParseACMPolicyStatusRegister(correctACMRegValue + acmCorruption),
}),
}
measurements, _, _, err := pcr.GetMeasurements(firmware, 0, measureOptions...)
if err != nil {
b.Fatal(err)
}
b.Run("correctPCR0", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, _, _ = ReproduceExpectedPCR0(
ctx,
pcr0Correct,
pcr.FlowIntelCBnT0T,
measurements,
firmware.Buf(),
)
}
})
b.Run("incompletePCR0", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, _, _ = ReproduceExpectedPCR0(
ctx,
pcr0Incomplete,
pcr.FlowIntelCBnT0T,
measurements,
firmware.Buf(),
)
}
})
b.Run("invalidPCR0", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, _, _ = ReproduceExpectedPCR0(
ctx,
pcr0Invalid,
pcr.FlowIntelCBnT0T,
measurements,
firmware.Buf(),
)
}
})
})
}
}

View File

@ -7,7 +7,7 @@ type EventType uint32
// The list of available EventLog entry types.
const (
EV_PqREBOOT_CERT = EventType(0x00000000)
EV_PREBOOT_CERT = EventType(0x00000000)
EV_POST_CODE = EventType(0x00000001)
EV_UNUSED = EventType(0x00000002)
EV_NO_ACTION = EventType(0x00000003)