github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/pkg/securelaunch/eventlog/eventlog.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 eventlog parses kernel event logs and saves the parsed data on a file on disk.
     6  package eventlog
     7  
     8  import (
     9  	"fmt"
    10  	"log"
    11  	"strings"
    12  
    13  	"github.com/9elements/tpmtool/pkg/tpm"
    14  	"github.com/u-root/u-root/pkg/mount"
    15  	slaunch "github.com/u-root/u-root/pkg/securelaunch"
    16  )
    17  
    18  /* describes the "eventlog" section of policy file */
    19  type EventLog struct {
    20  	Type     string `json:"type"`
    21  	Location string `json:"location"`
    22  }
    23  
    24  const (
    25  	eventLogFile        = "/sys/kernel/security/slaunch/eventlog"
    26  	defaultEventLogFile = "eventlog.txt" //only used if user doesn't provide any
    27  )
    28  
    29  /*
    30   * parseEvtlog uses tpmtool package to parse the event logs generated by a
    31   * kernel with CONFIG_SECURE_LAUNCH enabled and returns the parsed data in a byte slice.
    32   *
    33   * these event logs are originally in binary format and need to be parsed into human readable
    34   * format. error is returned if parsing code fails in tpmtool.
    35   */
    36  func parseEvtLog(evtLogFile string) ([]byte, error) {
    37  
    38  	tpm.DefaultTCPABinaryLog = evtLogFile
    39  	firmware := tpm.Txt
    40  	TPMSpecVersion := tpm.TPM20
    41  	tcpaLog, err := tpm.ParseLog(firmware, TPMSpecVersion)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	var w strings.Builder
    47  	for _, pcr := range tcpaLog.PcrList {
    48  		fmt.Fprintf(&w, "%s\n", pcr)
    49  		fmt.Fprintf(&w, "\n")
    50  	}
    51  	return []byte(w.String()), nil
    52  }
    53  
    54  /*
    55   * Persist uses tpmtool to parse event logs generated by the kernel into
    56   * human readable format, mounts the target disk and store the result in the file on
    57   * target disk.
    58   *
    59   * The location of the file on disk is specified in policy file by Location tag.
    60   * returns
    61   * - error if mounting the disk fails __OR_ writing to location on disk fails.
    62   */
    63  func (e *EventLog) Persist() error {
    64  
    65  	if e.Type != "file" {
    66  		return fmt.Errorf("unsupported eventlog type exiting")
    67  	}
    68  
    69  	slaunch.Debug("Identified EventLog Type = file")
    70  
    71  	// e.Location is of the form sda:path/to/file.txt
    72  	eventlogPath := e.Location
    73  	if eventlogPath == "" {
    74  		return fmt.Errorf("empty eventlog path provided exiting")
    75  	}
    76  
    77  	filePath, mountPath, r := slaunch.GetMountedFilePath(eventlogPath, 0) // 0 is flag value for rw mount option
    78  	if r != nil {
    79  		return fmt.Errorf("failed to mount target disk for target=%s, err=%v", eventlogPath, r)
    80  	}
    81  
    82  	dst := filePath // /tmp/boot-733276578/evtlog
    83  
    84  	// parse eventlog
    85  	data, err := parseEvtLog(eventLogFile)
    86  	if err != nil {
    87  		log.Printf("tpmtool could NOT parse Eventlogfile=%s, err=%s", eventLogFile, err)
    88  		if ret := mount.Unmount(mountPath, true, false); ret != nil {
    89  			log.Printf("Unmount failed. PANIC")
    90  			panic(ret)
    91  		}
    92  		return fmt.Errorf("parseEvtLog err=%v", err)
    93  	}
    94  
    95  	// write parsed data onto disk
    96  	target, err := slaunch.WriteToFile(data, dst, defaultEventLogFile)
    97  	if ret := mount.Unmount(mountPath, true, false); ret != nil {
    98  		log.Printf("Unmount failed. PANIC")
    99  		panic(ret)
   100  	}
   101  
   102  	if err != nil {
   103  		log.Printf("EventLog: Write err=%v, dst=%s, exiting", err, dst)
   104  		return fmt.Errorf("failed to write parsed eventLog to disk, err=%v, dst=%s, exiting", err, dst)
   105  	}
   106  
   107  	slaunch.Debug("EventLog: success, data written to %s", target)
   108  	return nil
   109  }