Skip to content

Commit

Permalink
Add nice tui, upload command and more insight
Browse files Browse the repository at this point in the history
Signed-off-by: Philipp Deppenwiese <[email protected]>
  • Loading branch information
zaolin committed Mar 8, 2023
1 parent fbea523 commit bc70273
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 55 deletions.
71 changes: 42 additions & 29 deletions cmd/tpm-vuln-checker/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ package main

import (
"fmt"
"io"
"net/url"

"github.com/fatih/color"
"github.com/immune-gmbh/tpm-vuln-checker/pkg/cloud"
"github.com/immune-gmbh/tpm-vuln-checker/pkg/cve"
"github.com/immune-gmbh/tpm-vuln-checker/pkg/tss"
"github.com/manifoldco/promptui"
)

const (
swtpmURL = "tcp://127.0.0.1:2321"
var (
NonVulnerableStyle = color.New(color.FgGreen, color.BgBlack, color.Bold).SprintFunc()
VulnerableStyle = color.New(color.FgRed, color.BgBlack, color.Bold).SprintFunc()
)

type context struct {
Expand All @@ -34,6 +36,7 @@ type versionCmd struct {
}

type checkCmd struct {
NonInteractive bool `flag optional name:"batch" help:"Always uploads anonymized data without asking"`
}

func (v *versionCmd) Run(ctx *context) error {
Expand All @@ -42,44 +45,54 @@ func (v *versionCmd) Run(ctx *context) error {
}

func (v *checkCmd) Run(ctx *context) error {
var err error
var rwc io.ReadWriteCloser
if ctx.Emulator {
var url *url.URL
url, err = url.Parse(swtpmURL)
if err != nil {
return err
}
rwc, err = tss.OpenNetTPM(url)
if err != nil {
return err
}
} else {
rwc, err = tss.OpenTPM()
if err != nil {
return err
}
socket, err := tss.NewTPM(ctx.Emulator)
if err != nil {
return err
}
defer socket.Close()
if !tss.IsTPM2(socket) {
return fmt.Errorf("no TPM 2.0 found")
}
defer rwc.Close()
found, err := cve.Detect(rwc)
tpmInfo, err := tss.ReadTPM2VendorAttributes(socket)
if err != nil {
return err
}
tpmInfo, err := tss.ReadTPM2VendorAttributes(rwc)
fmt.Printf("TPM Manufacturer: \t%s\nTPM Spec Revision: \t%s\nTPM Family: \t\t%s\nTPM Firmware: \t\t0x%s,0x%s\n",
tpmInfo.Manufacturer.String(), tpmInfo.SpecRevision.String(), tpmInfo.Family.String(),
tpmInfo.FWVersion1.String(), tpmInfo.FWVersion2.String())
vulnerable, cveData, err := cve.Detect(socket)
if err != nil {
return err
}
fmt.Printf("%s\n%s\n%s\n", tpmInfo.Manufacturer.String(), tpmInfo.SpecRevision, tpmInfo.Family)
if found {
fmt.Println("found")
if vulnerable {
fmt.Printf("CVE 2023-1017-1018: \t%s", VulnerableStyle("Vulnerable"))
} else {
fmt.Printf("CVE 2023-1017-1018: \t%s", NonVulnerableStyle("Not Vulnerable"))
}
fmt.Println()
if v.NonInteractive {
if err := cloud.UploadAnonData(tpmInfo, cveData, vulnerable); err != nil {
return err
}
} else {
fmt.Println("Not found")
prompt := promptui.Prompt{
Label: "Do you want to upload this data anonymized for analysis and tpm firmware update support",
IsConfirm: true,
}
fmt.Println()
_, err := prompt.Run()
if err != nil {
return nil
}
if err := cloud.UploadAnonData(tpmInfo, cveData, vulnerable); err != nil {
return err
}
}
return nil
}

var cli struct {
Emulator bool `help:"Enable emulator mode."`
Version versionCmd `cmd help:"Prints the version of the program"`
Check checkCmd `short:"c" cmd help:"Check TPM for CVE2023-1017-1018"`
Check checkCmd `short:"c" cmd help:"Check TPM for CVE 2023-1017-1018"`
}
2 changes: 2 additions & 0 deletions cmd/tpm-vuln-checker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,7 @@ func main() {
Summary: true,
}))
err := ctx.Run(&context{Emulator: cli.Emulator})
fmt.Println()
fmt.Println()
ctx.FatalIfErrorf(err)
}
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ go 1.20

require (
github.com/alecthomas/kong v0.7.1
github.com/fatih/color v1.14.1
github.com/google/go-tpm v0.3.3
github.com/manifoldco/promptui v0.9.0
)

require golang.org/x/sys v0.3.0 // indirect
require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
)

require (
github.com/google/uuid v1.3.0
golang.org/x/sys v0.3.0 // indirect
)
19 changes: 19 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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=
Expand All @@ -26,6 +32,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
Expand Down Expand Up @@ -58,6 +66,8 @@ github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo=
github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4=
github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0=
github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4=
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/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
Expand All @@ -75,6 +85,13 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
Expand Down Expand Up @@ -142,9 +159,11 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
59 changes: 59 additions & 0 deletions pkg/cloud/cloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cloud

import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"

"github.com/google/uuid"
"github.com/immune-gmbh/tpm-vuln-checker/pkg/cve"
"github.com/immune-gmbh/tpm-vuln-checker/pkg/tss"
)

const (
uploadURL = "https://upload.vuln.immune.gmbh"
)

type AnonInfo struct {
Info *tss.TPM20Info `json:"info"`
Vulnerable bool `json:"vulnerable"`
Raw *cve.CVEData `json:"cvedata"`
}

func UploadAnonData(info *tss.TPM20Info, raw *cve.CVEData, vuln bool) error {
if info == nil {
return fmt.Errorf("tpm info is nil")
}
var payload AnonInfo
payload.Info = info
payload.Vulnerable = vuln
payload.Raw = raw
data, err := json.Marshal(payload)
if err != nil {
return err
}
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
id := uuid.New().String()
part, _ := writer.CreateFormFile("file", id+".json")
io.Copy(part, bytes.NewReader(data))
writer.Close()
request, err := http.NewRequest("POST", uploadURL, body)
if err != nil {
return err
}
request.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound {
return fmt.Errorf("http status code %d, body: %v", response.StatusCode, response.Body)
}
return nil
}
40 changes: 23 additions & 17 deletions pkg/cve/cve.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,29 @@ import (
"github.com/immune-gmbh/tpm-vuln-checker/pkg/tss"
)

type CVEData struct {
RawString string
Err tpm2.ParameterError
}

func hex2int(hexStr string) uint64 {
cleaned := strings.Replace(hexStr, "0x", "", -1)
result, _ := strconv.ParseUint(cleaned, 16, 64)
return uint64(result)
}

func parserParameterError(err error) (*tpm2.ParameterError, error) {
var paramErr tpm2.ParameterError
func parserParameterError(err error) (*CVEData, error) {
var cveData CVEData
strErr := err.Error()
if err == nil {
return nil, fmt.Errorf("error is nil")
}
cveData.RawString = strErr
f := func(c rune) bool {
return c == ',' || c == ':' || c == ' '
}
info := strings.FieldsFunc(strErr, f)
if info[0] == "parameter" || info[0] == "session" {
if info[0] == "parameter" || info[0] == "session" || info[0] == "handle" {
param, err := strconv.Atoi(info[1])
if err != nil {
return nil, fmt.Errorf("couldn't parse parameter error parameter")
Expand All @@ -49,14 +55,14 @@ func parserParameterError(err error) (*tpm2.ParameterError, error) {
return nil, fmt.Errorf("couldn't parse parameter error code")
}
code := hex2int(info[4])
paramErr.Parameter = tpm2.RCIndex(param)
paramErr.Code = tpm2.RCFmt1(code)
return &paramErr, nil
cveData.Err.Parameter = tpm2.RCIndex(param)
cveData.Err.Code = tpm2.RCFmt1(code)
return &cveData, nil
}
return nil, fmt.Errorf("couldn't parse error strings: %s", strErr)
}

func Detect(rwc io.ReadWriteCloser) (bool, error) {
func Detect(rwc io.ReadWriteCloser) (bool, *CVEData, error) {
_ = tpm2.Startup(rwc, tpm2.StartupClear)
session, _, err := tss.StartAuthSession(
rwc,
Expand All @@ -68,33 +74,33 @@ func Detect(rwc io.ReadWriteCloser) (bool, error) {
tpm2.AlgXOR,
tpm2.AlgSHA256)
if err != nil {
return false, err
return false, nil, err
}
defer tpm2.FlushContext(rwc, session)

hnd, _, err := tpm2.CreatePrimary(rwc, tpm2.HandleEndorsement, tpm2.PCRSelection{}, "", "", tss.ECCPublicKey)
if err != nil {
return false, err
return false, nil, err
}
defer tpm2.FlushContext(rwc, hnd)
// We don't test oobwrite because it's dangerous
err = oobRead(rwc, tpm2.HandleEndorsement, session, nil)
if err == nil {
return false, fmt.Errorf("no tpm error returned")
return false, nil, fmt.Errorf("no tpm error returned")
}
paramErr, err := parserParameterError(err)
cveData, err := parserParameterError(err)
if err != nil {
return false, fmt.Errorf("couldn't parse parameter error %v", err)
return false, nil, fmt.Errorf("couldn't parse parameter error %v", err)
}
if paramErr != nil && paramErr.Parameter == 1 {
switch paramErr.Code {
if cveData != nil && cveData.Err.Parameter == 1 {
switch cveData.Err.Code {
case 0x1a:
return false, nil
return false, cveData, nil
case 0x15:
return true, nil
return true, cveData, nil
}
}
return false, fmt.Errorf("unknown TPM session error")
return false, cveData, nil
}

func oobRead(rwc io.ReadWriteCloser, owner, sess tpmutil.Handle, payload []byte) error {
Expand Down
Loading

0 comments on commit bc70273

Please sign in to comment.