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  }