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