diff --git a/attest/tpm.go b/attest/tpm.go index 5a251d8..b1a3625 100644 --- a/attest/tpm.go +++ b/attest/tpm.go @@ -40,6 +40,7 @@ const ( nvramRSACertIndex = 0x1c00002 nvramRSAEkNonceIndex = 0x1c00003 nvramECCCertIndex = 0x1c0000a + nvramECCEkNonceIndex = 0x1c0000b // Defined in "Registry of reserved TPM 2.0 handles and localities", and checked on a glinux machine. commonSrkEquivalentHandle = 0x81000001 @@ -74,7 +75,7 @@ var ( KeyBits: 2048, }, } - // Default RSA EK template defined in: + // Default RSA and ECC EK templates defined in: // https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf defaultRSAEKTemplate = tpm2.Public{ Type: tpm2.AlgRSA, @@ -99,6 +100,32 @@ var ( ModulusRaw: make([]byte, 256), }, } + defaultECCEKTemplate = tpm2.Public{ + Type: tpm2.AlgECC, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | + tpm2.FlagAdminWithPolicy | tpm2.FlagRestricted | tpm2.FlagDecrypt, + AuthPolicy: []byte{ + 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, + 0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D, + 0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52, + 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, + 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, + 0x69, 0xAA, + }, + ECCParameters: &tpm2.ECCParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + CurveID: tpm2.CurveNISTP256, + Point: tpm2.ECPoint{ + XRaw: make([]byte, 32), + YRaw: make([]byte, 32), + }, + }, + } // Basic template for an ECDSA key signing outside-TPM objects. Other // fields are populated depending on the key creation options. ecdsaKeyTemplate = tpm2.Public{ diff --git a/attest/wrapped_tpm20.go b/attest/wrapped_tpm20.go index 65a18e4..20166ca 100644 --- a/attest/wrapped_tpm20.go +++ b/attest/wrapped_tpm20.go @@ -35,6 +35,7 @@ type wrappedTPM20 struct { interf TPMInterface rwc CommandChannelTPM20 tpmRSAEkTemplate *tpm2.Public + tpmECCEkTemplate *tpm2.Public } func (t *wrappedTPM20) rsaEkTemplate() tpm2.Public { @@ -54,6 +55,23 @@ func (t *wrappedTPM20) rsaEkTemplate() tpm2.Public { return *t.tpmRSAEkTemplate } +func (t *wrappedTPM20) eccEkTemplate() tpm2.Public { + if t.tpmECCEkTemplate != nil { + return *t.tpmECCEkTemplate + } + + nonce, err := tpm2.NVReadEx(t.rwc, nvramECCEkNonceIndex, tpm2.HandleOwner, "", 0) + if err != nil { + t.tpmECCEkTemplate = &defaultECCEKTemplate // No nonce, use the default template + } else { + template := defaultECCEKTemplate + copy(template.ECCParameters.Point.XRaw, nonce) + t.tpmECCEkTemplate = &template + } + + return *t.tpmECCEkTemplate +} + func (t *wrappedTPM20) tpmVersion() TPMVersion { return TPMVersion20 } @@ -102,7 +120,7 @@ func (t *wrappedTPM20) getEndorsementKeyHandle(ek *EK) (tpmutil.Handle, bool, er case *rsa.PublicKey: ekTemplate = t.rsaEkTemplate() case *ecdsa.PublicKey: - return 0, false, errors.New("ECC EKs are not supported") + ekTemplate = t.eccEkTemplate() default: return 0, false, fmt.Errorf("unsupported public key type %T", pub) }