github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/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  	"io/ioutil"
    12  	"log"
    13  
    14  	"github.com/u-root/u-root/pkg/mount"
    15  	slaunch "github.com/u-root/u-root/pkg/securelaunch"
    16  	"github.com/u-root/u-root/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  /*
    26   * NewFileCollector extracts the "files" portion from the policy file.
    27   * initializes a new FileCollector structure.
    28   * returns error if unmarshalling of FileCollector fails
    29   */
    30  func NewFileCollector(config []byte) (Collector, error) {
    31  	slaunch.Debug("New Files Collector initialized\n")
    32  	var fc = new(FileCollector)
    33  	err := json.Unmarshal(config, &fc)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	return fc, nil
    38  }
    39  
    40  // HashBytes extends PCR with a byte array and sends an event to sysfs.
    41  // the sent event is described via eventDesc.
    42  func HashBytes(b []byte, eventDesc string) error {
    43  	return tpm.ExtendPCRDebug(pcr, bytes.NewReader(b), eventDesc)
    44  }
    45  
    46  /*
    47   * HashFile reads file input by user and calls TPM to measure it and store the hash.
    48   *
    49   * inputVal is of format <block device identifier>:<path>
    50   * E.g sda:/path/to/file _OR UUID:/path/to/file
    51   * Performs following actions
    52   * 1. mount device
    53   * 2. Read file on device into a byte slice.
    54   * 3. Unmount device
    55   * 4. Call tpm package which measures byte slice and stores it.
    56   */
    57  func HashFile(inputVal string) error {
    58  	// inputVal is of type sda:path
    59  	mntFilePath, e := slaunch.GetMountedFilePath(inputVal, mount.MS_RDONLY)
    60  	if e != nil {
    61  		log.Printf("HashFile: GetMountedFilePath err=%v", e)
    62  		return fmt.Errorf("failed to get mount path, err=%v", e)
    63  	}
    64  	slaunch.Debug("File Collector: Reading file=%s", mntFilePath)
    65  
    66  	slaunch.Debug("File Collector: fileP=%s\n", mntFilePath)
    67  	d, err := ioutil.ReadFile(mntFilePath)
    68  	if err != nil {
    69  		return fmt.Errorf("failed to read target file: filePath=%s, inputVal=%s, err=%v",
    70  			mntFilePath, inputVal, err)
    71  	}
    72  
    73  	eventDesc := fmt.Sprintf("File Collector: measured %s", inputVal)
    74  	return tpm.ExtendPCRDebug(pcr, bytes.NewReader(d), eventDesc)
    75  }
    76  
    77  /*
    78   * Collect satisfies Collector Interface. It loops over all file paths provided by user
    79   * and for each file path,  calls HashFile. HashFile measures each file on
    80   * that path and stores the result in TPM.
    81   */
    82  func (s *FileCollector) Collect() error {
    83  	for _, inputVal := range s.Paths {
    84  		// inputVal is of type sda:/path/to/file
    85  		err := HashFile(inputVal)
    86  		if err != nil {
    87  			log.Printf("File Collector: input=%s, err = %v", inputVal, err)
    88  			return err
    89  		}
    90  	}
    91  
    92  	return nil
    93  }