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