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