in client/securesession/securesession.go [402:500]
func (c *SecureSessionClient) addTpmEvidence(evidence *aepb.AttestationEvidence) (ret error) {
// Attempt to re-escalate execution privileges.
if err := tryReescalatePrivileges(); err != nil {
return fmt.Errorf("failed to re-escalate to root privileges to generate attestation: %w", err)
}
defer func() {
// If failed to deescalate and there are no other errors, override the return.
if err := tryDeescalatePrivileges(); err != nil && ret == nil {
ret = fmt.Errorf("failed to de-escalate to user privileges: %v", err)
}
}()
rwc, err := tpm2.OpenTPM("/dev/tpmrm0")
if err != nil {
glog.Errorf("Error opening TPM device: %v", err)
glog.Infof("Skipping attestation generation")
return nil
}
ek, err := tpmclient.GceAttestationKeyRSA(rwc)
if err != nil {
glog.Errorf("Error generating and loading the GCE RSA AK: %v", err)
glog.Infof("Skipping attestation generation")
return nil
}
defer ek.Close()
// Resolve the most recent supported nonce type from the server's response.
preferredNonceTypes := []aepb.NonceType{
aepb.NonceType_NONCE_EKM32,
}
// Fallback to NONCE_EKM32 if the server responds with a 0-length list of
// nonce types (this implies server has not implemented negotiation).
negotiatedNonceType := aepb.NonceType_NONCE_EKM32
nonceLoop:
for _, nonceType := range preferredNonceTypes {
for _, serverNonceType := range c.attestationTypes.GetNonceTypes() {
if nonceType == serverNonceType {
negotiatedNonceType = nonceType
break nonceLoop
}
}
}
var nonce []byte
switch negotiatedNonceType {
case aepb.NonceType_NONCE_EKM32:
// Generate exported keying material and attestation.
tlsState := c.tls.ConnectionState()
material, err := tlsState.ExportKeyingMaterial(constants.ExportLabel, nil, 32)
if err != nil {
return fmt.Errorf("error exporting key material: %v", err)
}
nonce = append(nonce, []byte(constants.AttestationPrefix)...)
nonce = append(nonce, material...)
default:
return fmt.Errorf("negotiated unknown nonce type: %v", negotiatedNonceType)
}
att, err := ek.Attest(tpmclient.AttestOpts{Nonce: nonce})
if err != nil {
return fmt.Errorf("error generating attestation: %v", err)
}
glog.Infof("Obtained attestation from the vTPM")
// Add GCE instance info to the attestation proto.
projectID, err := metadata.ProjectID()
// If unable to retrieve the Project ID, set to empty string.
if err != nil {
projectID = ""
}
zone, err := metadata.Zone()
// If unable to retrieve the Zone, set to empty string.
if err != nil {
zone = ""
}
instanceName, err := metadata.InstanceName()
// If unable to retrieve the Instance Name, set to empty string.
if err != nil {
instanceName = ""
}
att.InstanceInfo = &atpb.GCEInstanceInfo{
Zone: zone,
ProjectId: projectID,
InstanceName: instanceName,
}
evidence.Attestation = att
return nil
}