gitee.com/mirrors_u-root/u-root@v7.0.0+incompatible/pkg/securelaunch/measurement/dmi.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  	"errors"
    11  	"fmt"
    12  	"log"
    13  	"strings"
    14  
    15  	slaunch "github.com/u-root/u-root/pkg/securelaunch"
    16  	"github.com/u-root/u-root/pkg/securelaunch/tpm"
    17  	"github.com/u-root/u-root/pkg/smbios"
    18  )
    19  
    20  type fieldCluster struct {
    21  	Label  string   `json:"label"`
    22  	Fields []string `json:"fields"`
    23  }
    24  
    25  /* describes the "dmi" portion of policy file */
    26  type DmiCollector struct {
    27  	Type     string         `json:"type"`
    28  	Clusters []fieldCluster `json:"events"`
    29  }
    30  
    31  /*
    32   * NewDmiCollector extracts the "dmi" portion from the policy file.
    33   * initializes a new DmiCollector structure.
    34   * returns error if unmarshalling of DmiCollector fails
    35   */
    36  func NewDmiCollector(config []byte) (Collector, error) {
    37  	slaunch.Debug("New DMI Collector initialized")
    38  	var dc = new(DmiCollector)
    39  	err := json.Unmarshal(config, &dc)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	return dc, nil
    44  }
    45  
    46  /*
    47   * below look up table is from man dmidecode.
    48   * used to lookup the dmi type parsed from policy file.
    49   * e.g if policy file contains BIOS, this table would return 0.
    50   */
    51  var typeTable = map[string]uint8{
    52  	"bios":                             0,
    53  	"system":                           1,
    54  	"base board":                       2,
    55  	"chassis":                          3,
    56  	"processor":                        4,
    57  	"memory controller":                5,
    58  	"memory module":                    6,
    59  	"cache":                            7,
    60  	"port connector":                   8,
    61  	"system slots":                     9,
    62  	"on board devices":                 10,
    63  	"oem strings":                      11,
    64  	"system configuration options":     12,
    65  	"bios language":                    13,
    66  	"group associations":               14,
    67  	"system event log":                 15,
    68  	"physical memory array":            16,
    69  	"memory device":                    17,
    70  	"32-bit memory error":              18,
    71  	"memory array mapped address":      19,
    72  	"memory device mapped address":     20,
    73  	"built-in pointing device":         21,
    74  	"portable battery":                 22,
    75  	"system reset":                     23,
    76  	"hardware security":                24,
    77  	"system power controls":            25,
    78  	"voltage probe":                    26,
    79  	"cooling device":                   27,
    80  	"temperature probe":                28,
    81  	"electrical current probe":         29,
    82  	"out-of-band remote access":        30,
    83  	"boot integrity services":          31,
    84  	"system boot":                      32,
    85  	"64-bit memory error":              33,
    86  	"management device":                34,
    87  	"management device component":      35,
    88  	"management device threshold data": 36,
    89  	"memory channel":                   37,
    90  	"ipmi device":                      38,
    91  	"power supply":                     39,
    92  	"additional information":           40,
    93  	"onboard device":                   41,
    94  }
    95  
    96  // parseTypeFilter looks up type in typeTable and sets the corresponding entry in map to true.
    97  func parseTypeFilter(typeStrings []string) (map[smbios.TableType]bool, error) {
    98  	types := map[smbios.TableType]bool{}
    99  	for _, ts := range typeStrings {
   100  		if tg, ok := typeTable[strings.ToLower(ts)]; ok {
   101  			types[smbios.TableType(tg)] = true
   102  		}
   103  	}
   104  	return types, nil
   105  }
   106  
   107  /*
   108   * Collect satisfies collector interface. It calls
   109   * 1. smbios package to get all smbios data,
   110   * 2. then, filters smbios data based on type provided in policy file, and
   111   * 3. the filtered data is then measured into the tpm device.
   112   */
   113  func (s *DmiCollector) Collect() error {
   114  	slaunch.Debug("DMI Collector: Entering ")
   115  	if s.Type != "dmi" {
   116  		return errors.New("invalid type passed to a DmiCollector method")
   117  	}
   118  
   119  	var labels []string // collect all types entered by user in one slice
   120  	for _, fieldCluster := range s.Clusters {
   121  		labels = append(labels, fieldCluster.Label)
   122  	}
   123  
   124  	slaunch.Debug("DMI Collector: len(labels)=%d", len(labels))
   125  
   126  	// lables would be []{BIOS, Chassis, Processor}
   127  	typeFilter, err := parseTypeFilter(labels)
   128  	if err != nil {
   129  		return fmt.Errorf("invalid --type: %v", err)
   130  	}
   131  
   132  	slaunch.Debug("DMI Collector: len(typeFilter)=%d", len(typeFilter))
   133  
   134  	si, err := smbios.FromSysfs()
   135  	if err != nil {
   136  		return fmt.Errorf("error parsing data: %v", err)
   137  	}
   138  
   139  	slaunch.Debug("DMI Collector: len(si.Tables)=%d", len(si.Tables))
   140  
   141  	for _, t := range si.Tables {
   142  		if len(typeFilter) != 0 && !typeFilter[t.Type] {
   143  			continue
   144  		}
   145  
   146  		pt, err := smbios.ParseTypedTable(t)
   147  		if err != nil {
   148  			log.Printf("DMI Collector: skipping type %s, err=%v", t.Type, err)
   149  			continue
   150  		}
   151  
   152  		slaunch.Debug(pt.String())
   153  		b := []byte(pt.String())
   154  		eventDesc := fmt.Sprintf("DMI Collector: Measured dmi label=[%v]", t.Type)
   155  		if e := tpm.ExtendPCRDebug(pcr, bytes.NewReader(b), eventDesc); e != nil {
   156  			log.Printf("DMI Collector: err =%v", e)
   157  			return e // return error if any single type fails ..
   158  		}
   159  	}
   160  
   161  	return nil
   162  }