Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions tools/show/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# `show` CLI tool

This binary is a CLI tool for parsing and displaying Intel TDX quotes.

The tool's input is a quote.

The tool's output is the quote in any specified format to either standard out
or directly to a file.

## Usage

```
./show [options...]
```

### `-in`

This flag provides the path to the quote to show. Stdin is "-".

### `-inform`

The format that input takes. One of

* `bin`: for a raw binary quote.
* `proto`: A binary serialized `tdx.QuoteV4` message.
* `textproto`: The `tdx.QuoteV4` message in textproto format.

Default value is `bin`.

### `-out`

Path to output file to write quote to.

Default is empty, interpreted as stdout.

### `-outform`

The format that output takes. Currently only `textproto` is supported.

Default value is `textproto`.

### `-verbosity`

Used to set the verbosity of logger, where higher number means more verbose output.

Default value is `0`.
162 changes: 162 additions & 0 deletions tools/show/show.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main implements a CLI tool for showing Intel TDX quotes.
package main

import (
"flag"
"fmt"
"io"
"os"

"github.com/google/go-tdx-guest/abi"
pb "github.com/google/go-tdx-guest/proto/tdx"
"github.com/google/logger"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
)

var (
infile = flag.String("in", "-", "Path to the TDX quote to show. Stdin is \"-\".")
inform = flag.String("inform", "bin", "The input format for the TDX quote. One of \"bin\", \"proto\", \"textproto\".")
out = flag.String("out", "", "Path to output file to write attestation report to. "+
"If unset, outputs to stdout.")
outform = flag.String("outform", "textproto", "The format of the output attestation report. Currently only \"textproto\" is supported.")
verbosity = flag.Int("verbosity", 0, "The output verbosity. Higher number means more verbose output.")
)

func parseQuoteBytes(b []byte) (any, error) {
quote, err := abi.QuoteToProto(b)
if err != nil {
return nil, fmt.Errorf("could not parse the TDX Quote from %q: %v", *infile, err)
}

return quote, nil
}

func parseQuote(b []byte) (any, error) {
switch *inform {
case "bin":
return parseQuoteBytes(b)
case "proto":
result := &pb.QuoteV4{}
if err := proto.Unmarshal(b, result); err != nil {
return nil, fmt.Errorf("could not parse %q as proto: %v", *infile, err)
}
return result, nil
case "textproto":
result := &pb.QuoteV4{}
if err := prototext.Unmarshal(b, result); err != nil {
return nil, fmt.Errorf("could not parse %q as textproto: %v", *infile, err)
}
return result, nil
default:
return nil, fmt.Errorf("unknown value -inform=%s", *inform)
}
}

func readQuote() (any, error) {
var in io.Reader
var f *os.File
if *infile == "-" {
in = os.Stdin
} else {
file, err := os.Open(*infile)
if err != nil {
return nil, fmt.Errorf("could not open %q: %v", *infile, err)
}
f = file
in = file
}
defer func() {
if f != nil {
f.Close()
}
}()

contents, err := io.ReadAll(in)
if err != nil {
return nil, fmt.Errorf("could not read %q: %v", *infile, err)
}
return parseQuote(contents)
}

func marshalAndWriteBytes(quote any, out io.Writer) error {
switch q := quote.(type) {
case *pb.QuoteV4:
mo := prototext.MarshalOptions{
Multiline: true,
Indent: " ",
EmitASCII: true,
}
bytes, err := mo.Marshal(q)
if err != nil {
return err
}
if _, err := out.Write(bytes); err != nil {
return err
}
return nil
default:
return fmt.Errorf("unsupported quote type: %T", quote)
}
}

func outWriter() (io.Writer, *os.File, error) {
if *out == "" {
return os.Stdout, nil, nil
}
file, err := os.Create(*out)
if err != nil {
return nil, nil, err
}
return file, file, nil
}

func writeQuote(quote any, out io.Writer) error {
switch *outform {
case "textproto":
return marshalAndWriteBytes(quote, out)
default:
return fmt.Errorf("unknown value -outform=%s", *outform)
}
}

func main() {
logger.Init("", false, false, os.Stdout)
flag.Parse()
logger.SetLevel(logger.Level(*verbosity))

quote, err := readQuote()
if err != nil {
logger.Fatal(err)
}
logger.V(1).Info("TDX Quote parsed successfully")

outwriter, filetoclose, err := outWriter()
if err != nil {
logger.Fatalf("failed to open output file: %v", err)
}
defer func() {
if filetoclose != nil {
filetoclose.Close()
}
}()

err2 := writeQuote(quote, outwriter)
if err2 != nil {
logger.Fatal(err2)
}
}