github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/binary_transparency/firmware/api/http.go (about)

     1  // Copyright 2020 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package api
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"strconv"
    21  	"strings"
    22  
    23  	"github.com/transparency-dev/formats/log"
    24  	"golang.org/x/mod/sumdb/note"
    25  )
    26  
    27  const (
    28  	// HTTPAddFirmware is the path of the URL to publish a firmware entry.
    29  	HTTPAddFirmware = "ft/v0/add-firmware"
    30  	// HTTPAddAnnotationMalware is the path of the URL to publish annotations about malware scans.
    31  	HTTPAddAnnotationMalware = "ft/v0/add-annotation-malware"
    32  	// HTTPGetConsistency is the path of the URL to get a consistency proof between log roots.
    33  	HTTPGetConsistency = "ft/v0/get-consistency"
    34  	// HTTPGetInclusion is the path of the URL to get inclusion proofs for entries in the log.
    35  	HTTPGetInclusion = "ft/v0/get-inclusion"
    36  	// HTTPGetManifestEntryAndProof is the path of the URL to get firmware manifest entries with inclusion proofs.
    37  	HTTPGetManifestEntryAndProof = "ft/v0/get-firmware-manifest-entry-and-proof"
    38  	// HTTPGetFirmwareImage is the path of the URL for getting firmware images from the CAS.
    39  	HTTPGetFirmwareImage = "ft/v0/get-firmware-image"
    40  	// HTTPGetRoot is the path of the URL to get a recent log root.
    41  	HTTPGetRoot = "ft/v0/get-root"
    42  
    43  	// FTLogOrigin is the identifier of the demo log.
    44  	// TODO(al): extract this so it's a config option on the log.
    45  	FTLogOrigin = "Firmware Transparency Log"
    46  )
    47  
    48  // LogCheckpoint commits to the state of the log.
    49  // The serialisation format of this checkpoint is compatible with the format
    50  // specified at github.com/google/trillian-examples/tree/master/formats/log
    51  type LogCheckpoint struct {
    52  	log.Checkpoint
    53  	// The number of nanoseconds since the Unix epoch.
    54  	TimestampNanos uint64
    55  
    56  	// If set, Envelope contains the envelope from which this Checkpoint was parsed.
    57  	Envelope []byte
    58  }
    59  
    60  // String returns a compact printable representation of a LogCheckpoint.
    61  func (l LogCheckpoint) String() string {
    62  	return fmt.Sprintf("{size %d @ %d root: 0x%x}", l.Size, l.TimestampNanos, l.Hash)
    63  }
    64  
    65  // Marshal serialises the checkpoint.
    66  func (l LogCheckpoint) Marshal() []byte {
    67  	b := bytes.Buffer{}
    68  	b.Write(l.Checkpoint.Marshal())
    69  	b.WriteString(fmt.Sprintf("%d\n", l.TimestampNanos))
    70  	return b.Bytes()
    71  }
    72  
    73  // ParseCheckpoint wraps `log.ParseCheckpoint` with the additional behaviour of
    74  // enforcing that a timestamp is included in the `otherdata`, and returning a
    75  // LogCheckpoint constructed from this data.
    76  func ParseCheckpoint(chkpt []byte, logVerifier note.Verifier, otherVerifiers ...note.Verifier) (*LogCheckpoint, error) {
    77  	cp, otherData, _, err := log.ParseCheckpoint(chkpt, FTLogOrigin, logVerifier, otherVerifiers...)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	const delim = "\n"
    82  	lines := strings.Split(strings.TrimRight(string(otherData), delim), delim)
    83  	if el := len(lines); el != 1 {
    84  		return nil, fmt.Errorf("expected 1 line of other data, got %d", el)
    85  	}
    86  	ts, err := strconv.ParseUint(lines[0], 10, 64)
    87  	if err != nil {
    88  		return nil, fmt.Errorf("failed to parse timestamp: %w", err)
    89  	}
    90  	return &LogCheckpoint{
    91  		Checkpoint:     *cp,
    92  		TimestampNanos: ts,
    93  		Envelope:       chkpt,
    94  	}, err
    95  }
    96  
    97  // GetConsistencyRequest is sent to ask for a proof that the tree at ToSize
    98  // is append-only from the tree at FromSize. The response is a ConsistencyProof.
    99  type GetConsistencyRequest struct {
   100  	From uint64
   101  	To   uint64
   102  }
   103  
   104  // ConsistencyProof contains the hashes to demonstrate the append-only evolution
   105  // of the log.
   106  type ConsistencyProof struct {
   107  	Proof [][]byte
   108  }
   109  
   110  // GetFirmwareManifestRequest is sent to ask for the value at the given LeafIndex,
   111  // with an inclusion proof to the root at the given TreeSize.
   112  type GetFirmwareManifestRequest struct {
   113  	Index    uint64
   114  	TreeSize uint64
   115  }
   116  
   117  // InclusionProof contains the value at the requested index and the proof to the
   118  // requested tree size.
   119  type InclusionProof struct {
   120  	Value     []byte
   121  	LeafIndex uint64
   122  	Proof     [][]byte
   123  }
   124  
   125  // String returns a compact printable representation of an InclusionProof.
   126  func (l InclusionProof) String() string {
   127  	return fmt.Sprintf("{index %d, value: 0x%x, proof: %x}", l.LeafIndex, l.Value, l.Proof)
   128  }