diff --git a/attest/tpm.go b/attest/tpm.go index d995d7ca..1f0539f3 100644 --- a/attest/tpm.go +++ b/attest/tpm.go @@ -39,10 +39,12 @@ const ( // Defined in "Registry of reserved TPM 2.0 handles and localities". nvramRSACertIndex = 0x1c00002 nvramRSAEkNonceIndex = 0x1c00003 + nvramECCCertIndex = 0x1c0000a // Defined in "Registry of reserved TPM 2.0 handles and localities", and checked on a glinux machine. commonSrkEquivalentHandle = 0x81000001 commonRSAEkEquivalentHandle = 0x81010001 + commonECCEkEquivalentHandle = 0x81010002 ) var ( @@ -297,6 +299,7 @@ type tpmBase interface { close() error tpmVersion() TPMVersion eks() ([]EK, error) + ekCertificates() ([]EK, error) info() (*TPMInfo, error) loadAK(opaqueBlob []byte) (*AK, error) @@ -324,6 +327,12 @@ func (t *TPM) EKs() ([]EK, error) { return t.tpm.eks() } +// EKCertificates returns the endorsement key certificates burned-in to the platform. +// It is guaranteed that each EK.Certificate field will be populated. +func (t *TPM) EKCertificates() ([]EK, error) { + return t.tpm.ekCertificates() +} + // Info returns information about the TPM. func (t *TPM) Info() (*TPMInfo, error) { return t.tpm.info() diff --git a/attest/tpm12_linux.go b/attest/tpm12_linux.go index a2eba7d2..50594967 100644 --- a/attest/tpm12_linux.go +++ b/attest/tpm12_linux.go @@ -94,7 +94,7 @@ func readEKCertFromNVRAM12(ctx *tspi.Context) (*x509.Certificate, error) { return ParseEKCertificate(ekCert) } -func (t *trousersTPM) eks() ([]EK, error) { +func (t *trousersTPM) ekCertificates() ([]EK, error) { cert, err := readEKCertFromNVRAM12(t.ctx) if err != nil { return nil, fmt.Errorf("readEKCertFromNVRAM failed: %v", err) @@ -104,6 +104,10 @@ func (t *trousersTPM) eks() ([]EK, error) { }, nil } +func (t *trousersTPM) eks() ([]EK, error) { + return t.ekCertificates() +} + func (t *trousersTPM) newKey(*AK, *KeyConfig) (*Key, error) { return nil, fmt.Errorf("not implemented") } diff --git a/attest/tpm_windows.go b/attest/tpm_windows.go index 0203c767..6bbdcf14 100644 --- a/attest/tpm_windows.go +++ b/attest/tpm_windows.go @@ -152,6 +152,18 @@ func (t *windowsTPM) info() (*TPMInfo, error) { return &tInfo, nil } +func (t *windowsTPM) ekCertificates() ([]EK, error) { + ekCerts, err := t.pcp.EKCerts() + if err != nil { + return nil, fmt.Errorf("could not read EKCerts: %v", err) + } + var eks []EK + for _, cert := range ekCerts { + eks = append(eks, EK{Certificate: cert, Public: cert.PublicKey}) + } + return eks, nil +} + func (t *windowsTPM) eks() ([]EK, error) { ekCerts, err := t.pcp.EKCerts() if err != nil { diff --git a/attest/wrapped_tpm20.go b/attest/wrapped_tpm20.go index d4efb97d..dd08dfe2 100644 --- a/attest/wrapped_tpm20.go +++ b/attest/wrapped_tpm20.go @@ -94,6 +94,10 @@ func (t *wrappedTPM20) getEndorsementKeyHandle(ek *EK) (tpmutil.Handle, bool, er ekTemplate = t.rsaEkTemplate() } else { ekHandle = ek.handle + if ekHandle == 0 { + // Assume RSA EK handle if it was not provided. + ekHandle = commonRSAEkEquivalentHandle + } switch pub := ek.Public.(type) { case *rsa.PublicKey: ekTemplate = t.rsaEkTemplate() @@ -148,6 +152,17 @@ func (t *wrappedTPM20) getStorageRootKeyHandle(pHnd tpmutil.Handle) (tpmutil.Han return pHnd, true, nil } +func (t *wrappedTPM20) ekCertificates() ([]EK, error) { + var res []EK + if rsaCert, err := readEKCertFromNVRAM20(t.rwc, nvramRSACertIndex); err == nil { + res = append(res, EK{Public: crypto.PublicKey(rsaCert.PublicKey), Certificate: rsaCert, handle: commonRSAEkEquivalentHandle}) + } + if eccCert, err := readEKCertFromNVRAM20(t.rwc, nvramECCCertIndex); err == nil { + res = append(res, EK{Public: crypto.PublicKey(eccCert.PublicKey), Certificate: eccCert, handle: commonECCEkEquivalentHandle}) + } + return res, nil +} + func (t *wrappedTPM20) eks() ([]EK, error) { if cert, err := readEKCertFromNVRAM20(t.rwc, nvramRSACertIndex); err == nil { return []EK{