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 }