File: pcrs.go

package info (click to toggle)
golang-github-google-go-tpm 0.9.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,932 kB
  • sloc: makefile: 13
file content (55 lines) | stat: -rw-r--r-- 2,001 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package tpm2

// pcrSelectionFormatter is a Platform TPM Profile-specific interface for
// formatting TPM PCR selections.
// This interface isn't (yet) part of the go-tpm public interface. After we
// add a second implementation, we should consider making it public.
type pcrSelectionFormatter interface {
	// PCRs returns the TPM PCR selection bitmask associated with the given PCR indices.
	PCRs(pcrs ...uint) []byte
}

// PCClientCompatible is a pcrSelectionFormatter that formats PCR selections
// suitable for use in PC Client PTP-compatible TPMs (the vast majority):
// https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
// PC Client mandates at least 24 PCRs but does not provide an upper limit.
var PCClientCompatible pcrSelectionFormatter = pcClient{}

type pcClient struct{}

// The TPM requires all PCR selections to be at least big enough to select all
// the PCRs in the minimum PCR allocation.
const pcClientMinimumPCRCount = 24

func (pcClient) PCRs(pcrs ...uint) []byte {
	// Find the biggest PCR we selected.
	maxPCR := uint(0)
	for _, pcr := range pcrs {
		if pcr > maxPCR {
			maxPCR = pcr
		}
	}
	selectionSize := maxPCR/8 + 1

	// Enforce the minimum PCR selection size.
	if selectionSize < (pcClientMinimumPCRCount / 8) {
		selectionSize = (pcClientMinimumPCRCount / 8)
	}

	// Allocate a byte array to store the bitfield, that has at least
	// enough bits to store our selections.
	selection := make([]byte, selectionSize)
	for _, pcr := range pcrs {
		// The PCR selection mask is byte-wise little-endian:
		//   select[0] contains bits representing the selection of PCRs 0 through 7
		//   select[1] contains PCRs 8 through 15, and so on.
		byteIdx := pcr / 8
		// Within the byte, the PCR selection is bit-wise big-endian:
		//   bit 0 of select[0] contains the selection of PCR 0
		//   bit 1 of select[0] contains the selection of PCR 1, and so on.
		bitIdx := pcr % 8

		selection[byteIdx] |= (1 << bitIdx)
	}
	return selection
}