diff --git a/osbase/tpm/tpm.go b/osbase/tpm/tpm.go
new file mode 100644
index 0000000..b77c36d
--- /dev/null
+++ b/osbase/tpm/tpm.go
@@ -0,0 +1,631 @@
+// Copyright 2020 The Monogon Project Authors.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tpm
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+
+	tpm2tools "github.com/google/go-tpm-tools/client"
+	"github.com/google/go-tpm/tpm2"
+	"github.com/google/go-tpm/tpmutil"
+	"golang.org/x/crypto/nacl/secretbox"
+	"golang.org/x/sys/unix"
+	"google.golang.org/protobuf/proto"
+
+	tpmpb "source.monogon.dev/osbase/tpm/proto"
+
+	"source.monogon.dev/osbase/logtree"
+	"source.monogon.dev/osbase/sysfs"
+)
+
+var (
+	// SecureBootPCRs are all PCRs that measure the current Secure Boot
+	// configuration.  This is what we want if we rely on secure boot to verify
+	// boot integrity. The firmware hashes the secure boot policy and custom
+	// keys into the PCR.
+	//
+	// This requires an extra step that provisions the custom keys.
+	//
+	// Some background: https://mjg59.dreamwidth.org/48897.html?thread=1847297
+	// (the initramfs issue mentioned in the article has been solved by
+	// integrating it into the kernel binary, and we don't have a shim
+	// bootloader)
+	//
+	// PCR7 alone is not sufficient - it needs to be combined with firmware
+	// measurements.
+	SecureBootPCRs = []int{7}
+
+	// FirmwarePCRs are alle PCRs that contain the firmware measurements. See:
+	//   https://trustedcomputinggroup.org/wp-content/uploads/TCG_EFI_Platform_1_22_Final_-v15.pdf
+	FirmwarePCRs = []int{
+		0, // platform firmware
+		2, // option ROM code
+		3, // option ROM configuration and data
+	}
+
+	// FullSystemPCRs are all PCRs that contain any measurements up to the
+	// currently running EFI payload.
+	FullSystemPCRs = []int{
+		0, // platform firmware
+		1, // host platform configuration
+		2, // option ROM code
+		3, // option ROM configuration and data
+		4, // EFI payload
+	}
+
+	// Using FullSystemPCRs is the most secure, but also the most brittle
+	// option since updating the EFI binary, updating the platform firmware,
+	// changing platform settings or updating the binary would invalidate the
+	// sealed data. It's annoying (but possible) to predict values for PCR4,
+	// and even more annoying for the firmware PCR (comparison to known values
+	// on similar hardware is the only thing that comes to mind).
+	//
+	// See also: https://github.com/mxre/sealkey (generates PCR4 from EFI
+	// image, BSD license)
+	//
+	// Using only SecureBootPCRs is the easiest and still reasonably secure, if
+	// we assume that the platform knows how to take care of itself (i.e. Intel
+	// Boot Guard), and that secure boot is implemented properly. It is,
+	// however, a much larger amount of code we need to trust.
+	//
+	// We do not care about PCR 5 (GPT partition table) since modifying it is
+	// harmless. All of the boot options and cmdline are hardcoded in the
+	// kernel image, and we use no bootloader, so there's no PCR for bootloader
+	// configuration or kernel cmdline.
+)
+
+var (
+	numSRTMPCRs = 16
+	srtmPCRs    = tpm2.PCRSelection{Hash: tpm2.AlgSHA256, PCRs: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}
+	// TCG Trusted Platform Module Library Level 00 Revision 0.99 Table 6
+	tpmGeneratedValue = uint32(0xff544347)
+)
+
+var (
+	// ErrNotExists is returned when no TPMs are available in the system
+	ErrNotExists = errors.New("no TPMs found")
+	// ErrNotInitialized is returned when this package was not initialized
+	// successfully
+	ErrNotInitialized = errors.New("no TPM was initialized")
+)
+
+// Singleton since the TPM is too
+var tpm *TPM
+
+// We're serializing all TPM operations since it has a limited number of
+// handles and recovering if it runs out is difficult to implement correctly.
+// Might also be marginally more secure.
+var lock sync.Mutex
+
+// TPM represents a high-level interface to a connected TPM 2.0
+type TPM struct {
+	logger logtree.LeveledLogger
+	device io.ReadWriteCloser
+
+	// We keep the AK loaded since it's used fairly often and deriving it is
+	// expensive
+	akHandleCache tpmutil.Handle
+	akPublicKey   crypto.PublicKey
+}
+
+// Initialize finds and opens the TPM (if any). If there is no TPM available it
+// returns ErrNotExists
+func Initialize(logger logtree.LeveledLogger) error {
+	lock.Lock()
+	defer lock.Unlock()
+	tpmDir, err := os.Open("/sys/class/tpm")
+	if err != nil {
+		return fmt.Errorf("failed to open sysfs TPM class: %w", err)
+	}
+	defer tpmDir.Close()
+
+	tpms, err := tpmDir.Readdirnames(2)
+	if err != nil {
+		return fmt.Errorf("failed to read TPM device class: %w", err)
+	}
+
+	if len(tpms) == 0 {
+		return ErrNotExists
+	}
+	if len(tpms) > 1 {
+		// If this is changed GetMeasurementLog() needs to be updated too
+		logger.Warningf("Found more than one TPM, using the first one")
+	}
+	tpmName := tpms[0]
+	ueventData, err := sysfs.ReadUevents(filepath.Join("/sys/class/tpm", tpmName, "uevent"))
+	if err != nil {
+		return fmt.Errorf("failed to read uevents: %w", err)
+	}
+	majorDev, err := strconv.Atoi(ueventData["MAJOR"])
+	if err != nil {
+		return fmt.Errorf("failed to convert uevent: %w", err)
+	}
+	minorDev, err := strconv.Atoi(ueventData["MINOR"])
+	if err != nil {
+		return fmt.Errorf("failed to convert uevent: %w", err)
+	}
+	if err := unix.Mknod("/dev/tpm", 0600|unix.S_IFCHR, int(unix.Mkdev(uint32(majorDev), uint32(minorDev)))); err != nil {
+		return fmt.Errorf("failed to create TPM device node: %w", err)
+	}
+	device, err := tpm2.OpenTPM("/dev/tpm")
+	if err != nil {
+		return fmt.Errorf("failed to open TPM: %w", err)
+	}
+	tpm = &TPM{
+		device: device,
+		logger: logger,
+	}
+	return nil
+}
+
+// IsInitialized returns true if Initialize was called an at least one
+// TPM 2.0 was found and initialized. Otherwise it returns false.
+func IsInitialized() bool {
+	lock.Lock()
+	defer lock.Unlock()
+	return tpm != nil
+}
+
+// GenerateSafeKey uses two sources of randomness (Kernel & TPM) to generate
+// the key
+func GenerateSafeKey(size uint16) ([]byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, ErrNotInitialized
+	}
+	encryptionKeyHost := make([]byte, size)
+	if _, err := io.ReadFull(rand.Reader, encryptionKeyHost); err != nil {
+		return nil, fmt.Errorf("failed to generate host portion of new key: %w", err)
+	}
+	var encryptionKeyTPM []byte
+	for i := 48; i > 0; i-- {
+		tpmKeyPart, err := tpm2.GetRandom(tpm.device, size-uint16(len(encryptionKeyTPM)))
+		if err != nil {
+			return nil, fmt.Errorf("failed to generate TPM portion of new key: %w", err)
+		}
+		encryptionKeyTPM = append(encryptionKeyTPM, tpmKeyPart...)
+		if len(encryptionKeyTPM) >= int(size) {
+			break
+		}
+	}
+
+	if len(encryptionKeyTPM) != int(size) {
+		return nil, fmt.Errorf("got incorrect amount of TPM randomess: %v, requested %v", len(encryptionKeyTPM), size)
+	}
+
+	encryptionKey := make([]byte, size)
+	for i := uint16(0); i < size; i++ {
+		encryptionKey[i] = encryptionKeyHost[i] ^ encryptionKeyTPM[i]
+	}
+	return encryptionKey, nil
+}
+
+// Seal seals sensitive data and only allows access if the current platform
+// configuration in matches the one the data was sealed on.
+func Seal(data []byte, pcrs []int) ([]byte, error) {
+	// Generate a key and use secretbox to encrypt and authenticate the actual
+	// payload as go-tpm2 uses a raw seal operation limiting payload size to
+	// 128 bytes which is insufficient.
+	boxKey, err := GenerateSafeKey(32)
+	if err != nil {
+		return nil, fmt.Errorf("failed to generate boxKey: %w", err)
+	}
+	lock.Lock()
+	defer lock.Unlock()
+	srk, err := tpm2tools.StorageRootKeyRSA(tpm.device)
+	if err != nil {
+		return nil, fmt.Errorf("failed to load TPM SRK: %w", err)
+	}
+	defer srk.Close()
+	var boxKeyArr [32]byte
+	copy(boxKeyArr[:], boxKey)
+	// Nonce is not used as we're generating a new boxKey for every operation,
+	// therefore we can just leave it all-zero.
+	var unusedNonce [24]byte
+	encryptedData := secretbox.Seal(nil, data, &unusedNonce, &boxKeyArr)
+	sealedKey, err := srk.Seal(boxKey, tpm2tools.SealOpts{Current: tpm2.PCRSelection{Hash: tpm2.AlgSHA256, PCRs: pcrs}})
+	if err != nil {
+		return nil, fmt.Errorf("failed to seal boxKey: %w", err)
+	}
+	sealedBytes := tpmpb.ExtendedSealedBytes{
+		SealedKey:        sealedKey,
+		EncryptedPayload: encryptedData,
+	}
+	rawSealedBytes, err := proto.Marshal(&sealedBytes)
+	if err != nil {
+		return nil, fmt.Errorf("failed to marshal sealed data: %w", err)
+	}
+	return rawSealedBytes, nil
+}
+
+// Unseal unseals sensitive data if the current platform configuration allows
+// and sealing constraints allow it.
+func Unseal(data []byte) ([]byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, ErrNotInitialized
+	}
+	srk, err := tpm2tools.StorageRootKeyRSA(tpm.device)
+	if err != nil {
+		return nil, fmt.Errorf("failed to load TPM SRK: %w", err)
+	}
+	defer srk.Close()
+
+	var sealedBytes tpmpb.ExtendedSealedBytes
+	if err := proto.Unmarshal(data, &sealedBytes); err != nil {
+		return nil, fmt.Errorf("failed to unmarshal sealed data: %w", err)
+	}
+	if sealedBytes.SealedKey == nil {
+		return nil, fmt.Errorf("sealed data structure is invalid: no sealed key")
+	}
+	// Logging this for auditing purposes
+	var pcrList []string
+	for _, pcr := range sealedBytes.SealedKey.Pcrs {
+		pcrList = append(pcrList, strconv.FormatUint(uint64(pcr), 10))
+	}
+	tpm.logger.Infof("Attempting to unseal key protected with PCRs %s", strings.Join(pcrList, ","))
+	unsealedKey, err := srk.Unseal(sealedBytes.SealedKey, tpm2tools.UnsealOpts{})
+	if err != nil {
+		return nil, fmt.Errorf("failed to unseal key: %w", err)
+	}
+	var key [32]byte
+	if len(unsealedKey) != len(key) {
+		return nil, fmt.Errorf("unsealed key has wrong length: expected %v bytes, got %v", len(key), len(unsealedKey))
+	}
+	copy(key[:], unsealedKey)
+	var unusedNonce [24]byte
+	payload, ok := secretbox.Open(nil, sealedBytes.EncryptedPayload, &unusedNonce, &key)
+	if !ok {
+		return nil, errors.New("payload box cannot be opened")
+	}
+	return payload, nil
+}
+
+// Standard AK template for RSA2048 non-duplicatable restricted signing for
+// attestation
+var akTemplate = tpm2.Public{
+	Type:       tpm2.AlgRSA,
+	NameAlg:    tpm2.AlgSHA256,
+	Attributes: tpm2.FlagSignerDefault,
+	RSAParameters: &tpm2.RSAParams{
+		Sign: &tpm2.SigScheme{
+			Alg:  tpm2.AlgRSASSA,
+			Hash: tpm2.AlgSHA256,
+		},
+		KeyBits: 2048,
+	},
+}
+
+func loadAK() error {
+	var err error
+	// Rationale: The AK is an EK-equivalent key and used only for attestation.
+	// Using a non-primary key here would require us to store the wrapped
+	// version somewhere, which is inconvenient.  This being a primary key in
+	// the Endorsement hierarchy means that it can always be recreated and can
+	// never be "destroyed". Under our security model this is of no concern
+	// since we identify a node by its IK (Identity Key) which we can destroy.
+	tpm.akHandleCache, tpm.akPublicKey, err = tpm2.CreatePrimary(tpm.device, tpm2.HandleEndorsement,
+		tpm2.PCRSelection{}, "", "", akTemplate)
+	return err
+}
+
+// Process documented in TCG EK Credential Profile 2.2.1
+func loadEK() (tpmutil.Handle, crypto.PublicKey, error) {
+	// The EK is a primary key which is supposed to be certified by the
+	// manufacturer of the TPM.  Its public attributes are standardized in TCG
+	// EK Credential Profile 2.0 Table 1. These need to match exactly or we
+	// aren't getting the key the manufacturere signed. tpm2tools contains such
+	// a template already, so we're using that instead of redoing it ourselves.
+	// This ignores the more complicated ways EKs can be specified, the
+	// additional stuff you can do is just absolutely crazy (see 2.2.1.2
+	// onward)
+	return tpm2.CreatePrimary(tpm.device, tpm2.HandleEndorsement,
+		tpm2.PCRSelection{}, "", "", tpm2tools.DefaultEKTemplateRSA())
+}
+
+// GetAKPublic gets the TPM2T_PUBLIC of the AK key
+func GetAKPublic() ([]byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, ErrNotInitialized
+	}
+	if tpm.akHandleCache == tpmutil.Handle(0) {
+		if err := loadAK(); err != nil {
+			return nil, fmt.Errorf("failed to load AK primary key: %w", err)
+		}
+	}
+	public, _, _, err := tpm2.ReadPublic(tpm.device, tpm.akHandleCache)
+	if err != nil {
+		return nil, err
+	}
+	return public.Encode()
+}
+
+// TCG TPM v2.0 Provisioning Guidance v1.0 7.8 Table 2 and TCG EK Credential
+// Profile v2.1 2.2.1.4 de-facto Standard for Windows These are both
+// non-normative and reference Windows 10 documentation that's no longer
+// available :( But in practice this is what people are using, so if it's
+// normative or not doesn't really matter
+const ekCertHandle = 0x01c00002
+
+// GetEKPublic gets the public key and (if available) Certificate of the EK
+func GetEKPublic() ([]byte, []byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, []byte{}, ErrNotInitialized
+	}
+	ekHandle, publicRaw, err := loadEK()
+	if err != nil {
+		return nil, []byte{}, fmt.Errorf("failed to load EK primary key: %w", err)
+	}
+	defer tpm2.FlushContext(tpm.device, ekHandle)
+	// Don't question the use of HandleOwner, that's the Standard™
+	ekCertRaw, err := tpm2.NVReadEx(tpm.device, ekCertHandle, tpm2.HandleOwner, "", 0)
+	if err != nil {
+		return nil, []byte{}, err
+	}
+
+	publicKey, err := x509.MarshalPKIXPublicKey(publicRaw)
+	if err != nil {
+		return nil, []byte{}, err
+	}
+
+	return publicKey, ekCertRaw, nil
+}
+
+// MakeAKChallenge generates a challenge for TPM residency and attributes of
+// the AK
+func MakeAKChallenge(ekPubKey, akPub []byte, nonce []byte) ([]byte, []byte, error) {
+	ekPubKeyData, err := x509.ParsePKIXPublicKey(ekPubKey)
+	if err != nil {
+		return nil, []byte{}, fmt.Errorf("failed to decode EK pubkey: %w", err)
+	}
+	akPubData, err := tpm2.DecodePublic(akPub)
+	if err != nil {
+		return nil, []byte{}, fmt.Errorf("failed to decode AK public part: %w", err)
+	}
+	// Make sure we're attesting the right attributes (in particular Restricted)
+	if !akPubData.MatchesTemplate(akTemplate) {
+		return nil, []byte{}, errors.New("the key being challenged is not a valid AK")
+	}
+	akName, err := akPubData.Name()
+	if err != nil {
+		return nil, []byte{}, fmt.Errorf("failed to derive AK name: %w", err)
+	}
+	return generateRSA(akName.Digest, ekPubKeyData.(*rsa.PublicKey), 16, nonce, rand.Reader)
+}
+
+// SolveAKChallenge solves a challenge for TPM residency of the AK
+func SolveAKChallenge(credBlob, secretChallenge []byte) ([]byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, ErrNotInitialized
+	}
+	if tpm.akHandleCache == tpmutil.Handle(0) {
+		if err := loadAK(); err != nil {
+			return nil, fmt.Errorf("failed to load AK primary key: %w", err)
+		}
+	}
+
+	ekHandle, _, err := loadEK()
+	if err != nil {
+		return nil, fmt.Errorf("failed to load EK: %w", err)
+	}
+	defer tpm2.FlushContext(tpm.device, ekHandle)
+
+	// This is necessary since the EK requires an endorsement handle policy in
+	// its session.  For us this is stupid because we keep all hierarchies open
+	// anyways since a) we cannot safely store secrets on the OS side
+	// pre-global unlock and b) it makes no sense in this security model since
+	// an uncompromised host OS will not let an untrusted entity attest as
+	// itself and a compromised OS can either not pass PCR policy checks or the
+	// game's already over (you successfully runtime-exploited a production
+	// Metropolis node).
+	endorsementSession, _, err := tpm2.StartAuthSession(
+		tpm.device,
+		tpm2.HandleNull,
+		tpm2.HandleNull,
+		make([]byte, 16),
+		nil,
+		tpm2.SessionPolicy,
+		tpm2.AlgNull,
+		tpm2.AlgSHA256)
+	if err != nil {
+		panic(err)
+	}
+	defer tpm2.FlushContext(tpm.device, endorsementSession)
+
+	_, _, err = tpm2.PolicySecret(tpm.device, tpm2.HandleEndorsement, tpm2.AuthCommand{Session: tpm2.HandlePasswordSession, Attributes: tpm2.AttrContinueSession}, endorsementSession, nil, nil, nil, 0)
+	if err != nil {
+		return nil, fmt.Errorf("failed to make a policy secret session: %w", err)
+	}
+
+	for {
+		solution, err := tpm2.ActivateCredentialUsingAuth(tpm.device, []tpm2.AuthCommand{
+			// Use standard no-password authenatication
+			{Session: tpm2.HandlePasswordSession, Attributes: tpm2.AttrContinueSession},
+			// Use a full policy session for the EK
+			{Session: endorsementSession, Attributes: tpm2.AttrContinueSession},
+		}, tpm.akHandleCache, ekHandle, credBlob, secretChallenge)
+		var warn tpm2.Warning
+		if errors.As(err, &warn) && warn.Code == tpm2.RCRetry {
+			time.Sleep(100 * time.Millisecond)
+			continue
+		}
+		return solution, err
+	}
+}
+
+// FlushTransientHandles flushes all sessions and non-persistent handles
+func FlushTransientHandles() error {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return ErrNotInitialized
+	}
+	flushHandleTypes := []tpm2.HandleType{tpm2.HandleTypeTransient, tpm2.HandleTypeLoadedSession, tpm2.HandleTypeSavedSession}
+	for _, handleType := range flushHandleTypes {
+		handles, err := tpm2tools.Handles(tpm.device, handleType)
+		if err != nil {
+			return err
+		}
+		for _, handle := range handles {
+			if err := tpm2.FlushContext(tpm.device, handle); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// AttestPlatform performs a PCR quote using the AK and returns the quote and
+// its signature
+func AttestPlatform(nonce []byte) ([]byte, []byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, []byte{}, ErrNotInitialized
+	}
+	if tpm.akHandleCache == tpmutil.Handle(0) {
+		if err := loadAK(); err != nil {
+			return nil, []byte{}, fmt.Errorf("failed to load AK primary key: %w", err)
+		}
+	}
+	// We only care about SHA256 since SHA1 is weak. This is supported on at
+	// least GCE and Intel / AMD fTPM, which is good enough for now. Alg is
+	// null because that would just hash the nonce, which is dumb.
+	quote, signature, err := tpm2.Quote(tpm.device, tpm.akHandleCache, "", "", nonce, srtmPCRs,
+		tpm2.AlgNull)
+	if err != nil {
+		return nil, []byte{}, fmt.Errorf("failed to quote PCRs: %w", err)
+	}
+	return quote, signature.RSA.Signature, err
+}
+
+// VerifyAttestPlatform verifies a given attestation. You can rely on all data
+// coming back as being from the TPM on which the AK is bound to.
+func VerifyAttestPlatform(nonce, akPub, quote, signature []byte) (*tpm2.AttestationData, error) {
+	hash := crypto.SHA256.New()
+	hash.Write(quote)
+
+	akPubData, err := tpm2.DecodePublic(akPub)
+	if err != nil {
+		return nil, fmt.Errorf("invalid AK: %w", err)
+	}
+	akPublicKey, err := akPubData.Key()
+	if err != nil {
+		return nil, fmt.Errorf("invalid AK: %w", err)
+	}
+	akRSAKey, ok := akPublicKey.(*rsa.PublicKey)
+	if !ok {
+		return nil, errors.New("invalid AK: invalid key type")
+	}
+
+	if err := rsa.VerifyPKCS1v15(akRSAKey, crypto.SHA256, hash.Sum(nil), signature); err != nil {
+		return nil, err
+	}
+
+	quoteData, err := tpm2.DecodeAttestationData(quote)
+	if err != nil {
+		return nil, err
+	}
+	// quoteData.Magic works together with the TPM's Restricted key attribute.
+	// If this attribute is set (which it needs to be for the AK to be
+	// considered valid) the TPM will not sign external data having this prefix
+	// with such a key. Only data that originates inside the TPM like quotes
+	// and key certifications can have this prefix and sill be signed by a
+	// restricted key. This check is thus vital, otherwise somebody can just
+	// feed the TPM an arbitrary attestation to sign with its AK and this
+	// function will happily accept the forged attestation.
+	if quoteData.Magic != tpmGeneratedValue {
+		return nil, errors.New("invalid TPM quote: data marker for internal data not set - forged attestation")
+	}
+	if quoteData.Type != tpm2.TagAttestQuote {
+		return nil, errors.New("invalid TPM qoute: not a TPM quote")
+	}
+	if !bytes.Equal(quoteData.ExtraData, nonce) {
+		return nil, errors.New("invalid TPM quote: wrong nonce")
+	}
+
+	return quoteData, nil
+}
+
+// GetPCRs returns all SRTM PCRs in-order
+func GetPCRs() ([][]byte, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	if tpm == nil {
+		return nil, ErrNotInitialized
+	}
+	pcrs := make([][]byte, numSRTMPCRs)
+
+	// The TPM can (and most do) return partial results. Let's just retry as
+	// many times as we have PCRs since each read should return at least one
+	// PCR.
+readLoop:
+	for i := 0; i < numSRTMPCRs; i++ {
+		sel := tpm2.PCRSelection{Hash: tpm2.AlgSHA256}
+		for pcrN := 0; pcrN < numSRTMPCRs; pcrN++ {
+			if len(pcrs[pcrN]) == 0 {
+				sel.PCRs = append(sel.PCRs, pcrN)
+			}
+		}
+
+		readPCRs, err := tpm2.ReadPCRs(tpm.device, sel)
+		if err != nil {
+			return nil, fmt.Errorf("failed to read PCRs: %w", err)
+		}
+
+		for pcrN, pcr := range readPCRs {
+			pcrs[pcrN] = pcr
+		}
+		for _, pcr := range pcrs {
+			// If at least one PCR is still not read, continue
+			if len(pcr) == 0 {
+				continue readLoop
+			}
+		}
+		break
+	}
+
+	return pcrs, nil
+}
+
+// GetMeasurementLog returns the binary log of all data hashed into PCRs. The
+// result can be parsed by eventlog.  As this library currently doesn't support
+// extending PCRs it just returns the log as supplied by the EFI interface.
+func GetMeasurementLog() ([]byte, error) {
+	return os.ReadFile("/sys/kernel/security/tpm0/binary_bios_measurements")
+}
