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  }