func()

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
}