From 8ac2846c8070e2cfbac41099e5742bbdea0cf552 Mon Sep 17 00:00:00 2001 From: Tom D <40675700+twitchy-jsonp@users.noreply.github.com> Date: Tue, 11 Jun 2019 10:52:49 -0700 Subject: [PATCH] Attempt fix for EKCert parsing errors when falling back to NVRAM (#38) * Fix parsing errors for EKCert when falling back to NVRAM --- attest/pcp_windows.go | 4 ++-- attest/tpm.go | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/attest/pcp_windows.go b/attest/pcp_windows.go index 73d3d93..a5b5fca 100644 --- a/attest/pcp_windows.go +++ b/attest/pcp_windows.go @@ -404,8 +404,8 @@ func (h *winPCP) EKCerts() ([]*x509.Certificate, error) { var out []*x509.Certificate for _, der := range c { - cert, err := x509.ParseCertificate(der) - if err != nil && x509.IsFatal(err) { + cert, err := parseCert(der) + if err != nil { return nil, err } out = append(out, cert) diff --git a/attest/tpm.go b/attest/tpm.go index f3dda26..5eedbbb 100644 --- a/attest/tpm.go +++ b/attest/tpm.go @@ -15,8 +15,10 @@ package attest import ( + "bytes" "crypto" "encoding/asn1" + "encoding/binary" "fmt" "io" "math/big" @@ -128,6 +130,17 @@ func readTPM2VendorAttributes(tpm io.ReadWriter) (TCGVendorID, string, error) { } func parseCert(ekCert []byte) (*x509.Certificate, error) { + // TCG PC Specific Implementation section 7.3.2 specifies + // a prefix when storing a certificate in NVRAM. We look + // for and unwrap the certificate if its present. + if len(ekCert) > 5 && bytes.Equal(ekCert[:3], []byte{0x10, 0x01, 0x00}) { + certLen := binary.BigEndian.Uint16(ekCert[3:5]) + if len(ekCert) < int(certLen+5) { + return nil, fmt.Errorf("parsing nvram header: ekCert size %d smaller than specified cert length %d", len(ekCert), certLen) + } + ekCert = ekCert[5 : 5+certLen] + } + // If the cert parses fine without any changes, we are G2G. if c, err := x509.ParseCertificate(ekCert); err == nil { return c, nil @@ -142,7 +155,11 @@ func parseCert(ekCert []byte) (*x509.Certificate, error) { if _, err := asn1.Unmarshal(ekCert, &cert); err != nil { return nil, err } - return x509.ParseCertificate(cert.Raw) + c, err := x509.ParseCertificate(cert.Raw) + if err != nil && x509.IsFatal(err) { + return nil, err + } + return c, nil } func readEKCertFromNVRAM20(tpm io.ReadWriter) (*x509.Certificate, error) {