github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/securelaunch/measurement/cpuid.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 "log" 12 "strings" 13 14 "github.com/intel-go/cpuid" 15 slaunch "github.com/u-root/u-root/pkg/securelaunch" 16 "github.com/u-root/u-root/pkg/securelaunch/tpm" 17 ) 18 19 const ( 20 defaultCPUIDFile = "cpuid.txt" //only used if user doesn't provide any 21 ) 22 23 /* describes the "cpuid" portion of policy file */ 24 type CPUIDCollector struct { 25 Type string `json:"type"` 26 Location string `json:"location"` 27 } 28 29 /* 30 * NewCPUIDCollector extracts the "cpuid" portion from the policy file, 31 * initializes a new CPUIDCollector structure and returns error 32 * if unmarshalling of CPUIDCollector fails 33 */ 34 func NewCPUIDCollector(config []byte) (Collector, error) { 35 slaunch.Debug("New CPUID Collector initialized\n") 36 var fc = new(CPUIDCollector) 37 err := json.Unmarshal(config, &fc) 38 if err != nil { 39 return nil, err 40 } 41 return fc, nil 42 } 43 44 /* 45 * getCPUIDInfo used a string builder to store data obtained from intel-go/cpuid package. 46 * returns a byte slice of the string built via string builder. 47 */ 48 func getCPUIDInfo() []byte { 49 var w strings.Builder 50 fmt.Fprintf(&w, "VendorString: %s\n", cpuid.VendorIdentificatorString) 51 fmt.Fprintf(&w, "ProcessorBrandString: %s\n", cpuid.ProcessorBrandString) 52 fmt.Fprintf(&w, "SteppingId: %d\n", cpuid.SteppingId) 53 fmt.Fprintf(&w, "ProcessorType: %d\n", cpuid.ProcessorType) 54 fmt.Fprintf(&w, "DisplayFamily: %d\n", cpuid.DisplayFamily) 55 fmt.Fprintf(&w, "DisplayModel: %d\n", cpuid.DisplayModel) 56 fmt.Fprintf(&w, "CacheLineSize: %d\n", cpuid.CacheLineSize) 57 fmt.Fprintf(&w, "MaxLogocalCPUId:%d\n", cpuid.MaxLogocalCPUId) 58 fmt.Fprintf(&w, "InitialAPICId: %d\n", cpuid.InitialAPICId) 59 fmt.Fprintf(&w, "Smallest monitor-line size in bytes: %d\n", cpuid.MonLineSizeMin) 60 fmt.Fprintf(&w, "Largest monitor-line size in bytes: %d\n", cpuid.MonLineSizeMax) 61 fmt.Fprintf(&w, "Monitor Interrupt break-event is supported: %v\n", cpuid.MonitorIBE) 62 fmt.Fprintf(&w, "MONITOR/MWAIT extensions are supported: %v\n", cpuid.MonitorEMX) 63 fmt.Fprintf(&w, "AVX state: %v\n", cpuid.EnabledAVX) 64 fmt.Fprintf(&w, "AVX-512 state: %v\n", cpuid.EnabledAVX512) 65 fmt.Fprintf(&w, "Interrupt thresholds in digital thermal sensor: %v\n", cpuid.ThermalSensorInterruptThresholds) 66 67 fmt.Fprintf(&w, "Features: ") 68 for i := uint64(0); i < 64; i++ { 69 if cpuid.HasFeature(1 << i) { 70 fmt.Fprintf(&w, "%s ", cpuid.FeatureNames[1<<i]) 71 } 72 } 73 fmt.Fprintf(&w, "\n") 74 75 fmt.Fprintf(&w, "ExtendedFeatures: ") 76 for i := uint64(0); i < 64; i++ { 77 if cpuid.HasExtendedFeature(1 << i) { 78 fmt.Fprintf(&w, "%s ", cpuid.ExtendedFeatureNames[1<<i]) 79 } 80 } 81 fmt.Fprintf(&w, "\n") 82 83 fmt.Fprintf(&w, "ExtraFeatures: ") 84 for i := uint64(0); i < 64; i++ { 85 if cpuid.HasExtraFeature(1 << i) { 86 fmt.Fprintf(&w, "%s ", cpuid.ExtraFeatureNames[1<<i]) 87 } 88 } 89 fmt.Fprintf(&w, "\n") 90 91 fmt.Fprintf(&w, "ThermalAndPowerFeatures: ") 92 for i := uint32(0); i < 64; i++ { 93 if cpuid.HasThermalAndPowerFeature(1 << i) { 94 if name, found := cpuid.ThermalAndPowerFeatureNames[1<<i]; found { 95 fmt.Fprintf(&w, "%s ", name) 96 } 97 } 98 } 99 fmt.Fprintf(&w, "\n") 100 101 for _, cacheDescription := range cpuid.CacheDescriptors { 102 fmt.Fprintf(&w, "CacheDescriptor: %v\n", cacheDescription) 103 } 104 105 return []byte(w.String()) 106 } 107 108 /* 109 * measureCPUIDFile stores the CPUIDInfo obtained from cpuid package 110 * into the tpm device */ 111 func measureCPUIDFile() ([]byte, error) { 112 d := getCPUIDInfo() // return strings builder 113 eventDesc := "CPUID Collector: Measured CPUID Info" 114 if e := tpm.ExtendPCRDebug(pcr, bytes.NewReader(d), eventDesc); e != nil { 115 return nil, e 116 } 117 118 return d, nil 119 } 120 121 /* 122 * Collect satisfies collector interface. It calls various functions to 123 * 1. get the cpuid info from cpuid package 124 * 2. stores hash of the result in the tpm device. 125 * 3. also keeps a copy of the result on disk at location provided in policy file. 126 */ 127 func (s *CPUIDCollector) Collect() error { 128 129 d, err := measureCPUIDFile() 130 if err != nil { 131 log.Printf("CPUID Collector: err = %v", err) 132 return err 133 } 134 135 return slaunch.AddToPersistQueue("CPUID Collector", d, s.Location, defaultCPUIDFile) 136 }