github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/securelaunch/measurement/files.go (about)

     1  // Copyright 2019 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package measurement
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"fmt"
    11  	"log"
    12  	"os"
    13  
    14  	"github.com/mvdan/u-root-coreutils/pkg/mount"
    15  	slaunch "github.com/mvdan/u-root-coreutils/pkg/securelaunch"
    16  	"github.com/mvdan/u-root-coreutils/pkg/securelaunch/tpm"
    17  )
    18  
    19  // Describes the "files" portion of policy file.
    20  type FileCollector struct {
    21  	Type  string   `json:"type"`
    22  	Paths []string `json:"paths"`
    23  }
    24  
    25  // NewFileCollector extracts the "files" portion from the policy file and
    26  // initializes a new FileCollector structure.
    27  // It returns an error if unmarshalling of FileCollector fails.
    28  func NewFileCollector(config []byte) (Collector, error) {
    29  	slaunch.Debug("New Files Collector initialized\n")
    30  	fc := new(FileCollector)
    31  	err := json.Unmarshal(config, &fc)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	return fc, nil
    36  }
    37  
    38  // HashBytes extends PCR with a byte array and sends an event to sysfs.
    39  // the sent event is described via eventDesc.
    40  func HashBytes(b []byte, eventDesc string) error {
    41  	return tpm.ExtendPCRDebug(pcr, bytes.NewReader(b), eventDesc)
    42  }
    43  
    44  // HashFile opens and reads the given file and measures it into the TPM.
    45  //
    46  // inputVal is of format <block device identifier>:<path>
    47  // (e.g., `sda:/path/to/file` or `UUID:/path/to/file`).
    48  func HashFile(inputVal string) error {
    49  	// inputVal is of type sda:path
    50  	mntFilePath, e := slaunch.GetMountedFilePath(inputVal, mount.MS_RDONLY)
    51  	if e != nil {
    52  		log.Printf("HashFile: GetMountedFilePath err=%v", e)
    53  		return fmt.Errorf("failed to get mount path, err=%v", e)
    54  	}
    55  	slaunch.Debug("File Collector: Reading file=%s", mntFilePath)
    56  
    57  	slaunch.Debug("File Collector: fileP=%s\n", mntFilePath)
    58  	d, err := os.ReadFile(mntFilePath)
    59  	if err != nil {
    60  		return fmt.Errorf("failed to read target file: filePath=%s, inputVal=%s, err=%v",
    61  			mntFilePath, inputVal, err)
    62  	}
    63  
    64  	eventDesc := fmt.Sprintf("File Collector: measured %s", inputVal)
    65  	return tpm.ExtendPCRDebug(pcr, bytes.NewReader(d), eventDesc)
    66  }
    67  
    68  // Collect loops over the given file paths and for each file path calls
    69  // HashFile(), which measures a file into the TPM.
    70  //
    71  // It satisfies the Collector interface.
    72  func (s *FileCollector) Collect() error {
    73  	for _, inputVal := range s.Paths {
    74  		// inputVal is of type sda:/path/to/file
    75  		err := HashFile(inputVal)
    76  		if err != nil {
    77  			log.Printf("File Collector: input=%s, err = %v", inputVal, err)
    78  			return err
    79  		}
    80  	}
    81  
    82  	return nil
    83  }