func()

in server/server.go [313:399]


func (s *SecureSessionService) NegotiateAttestation(ctx context.Context, req *sspb.NegotiateAttestationRequest) (*sspb.NegotiateAttestationResponse, error) {
	if err := s.verifyToken(ctx); err != nil {
		return nil, fmt.Errorf("failed to verify JWT: %w", err)
	}

	connID := base64.StdEncoding.EncodeToString(req.SessionContext)
	ch, found := s.channels[connID]

	if !found {
		return nil, fmt.Errorf("session with id: %v not found", connID)
	}

	if ch.state != ServerStateHandshakeCompleted {
		return nil, fmt.Errorf("session with id: %v in unexpected state: %d. Expecting: %d", connID, ch.state, ServerStateHandshakeCompleted)
	}

	if len(req.OfferedEvidenceTypesRecords) == 0 {
		return nil, fmt.Errorf("TLS records were empty")
	}

	ch.shim.QueueReceiveBuf(req.OfferedEvidenceTypesRecords)

	buf := make([]byte, len(req.OfferedEvidenceTypesRecords))
	bufLen, err := ch.conn.Read(buf)

	if err != nil {
		ch.state = ServerStateFailed
		return nil, fmt.Errorf("failed to read client's OfferedEvidenceTypeRecords message from tls connection : %v", err)
	}

	var clientAttList attpb.AttestationEvidenceTypeList

	err = proto.Unmarshal(buf[:bufLen], &clientAttList)
	if err != nil {
		ch.state = ServerStateFailed
		return nil, fmt.Errorf("failed to unmarshal AttestationEvidenceTypeList: %v", err)
	}

	serverSelection := attpb.AttestationEvidenceTypeList{}
	offeredMap := make(map[attpb.AttestationEvidenceType]bool)
	for _, tp := range clientAttList.Types {
		switch tp {
		case attpb.AttestationEvidenceType_NULL_ATTESTATION:
			offeredMap[attpb.AttestationEvidenceType_NULL_ATTESTATION] = true
		case attpb.AttestationEvidenceType_TPM2_QUOTE:
			offeredMap[attpb.AttestationEvidenceType_TPM2_QUOTE] = true
		case attpb.AttestationEvidenceType_TCG_EVENT_LOG:
			offeredMap[attpb.AttestationEvidenceType_TCG_EVENT_LOG] = true
		}
	}

	if offeredMap[attpb.AttestationEvidenceType_TCG_EVENT_LOG] != offeredMap[attpb.AttestationEvidenceType_TPM2_QUOTE] {
		return nil, errors.New("if offering either the TPM2 Quote or the TCG Event Log, must offer both")
	}

	if offeredMap[attpb.AttestationEvidenceType_TPM2_QUOTE] {
		serverSelection.Types = []attpb.AttestationEvidenceType{attpb.AttestationEvidenceType_TPM2_QUOTE, attpb.AttestationEvidenceType_TCG_EVENT_LOG}
	} else if offeredMap[attpb.AttestationEvidenceType_NULL_ATTESTATION] {
		serverSelection.Types = []attpb.AttestationEvidenceType{attpb.AttestationEvidenceType_NULL_ATTESTATION}
	}

	if len(serverSelection.Types) == 0 {
		return nil, fmt.Errorf("unable to negotiate any acceptable attestation evidence types")
	}

	ch.attestationEvidenceTypes = serverSelection.Types

	buf, err = proto.Marshal(&serverSelection)
	if err != nil {
		ch.state = ServerStateFailed
		return nil, fmt.Errorf("failed to marshal server's AttestationEvidenceTypeList: %v", err)
	}

	go func() {
		_, err := ch.conn.Write(buf)
		if err != nil {
			ch.state = ServerStateFailed
			glog.Warningf("server failed to send selected evidence via TLS connection: %v", err.Error())
		}
	}()

	rep := &sspb.NegotiateAttestationResponse{}
	rep.RequiredEvidenceTypesRecords = ch.shim.DrainSendBuf()

	ch.state = ServerStateAttestationNegotiated
	return rep, nil
}