in server/server.go [256:311]
func (s *SecureSessionService) Handshake(ctx context.Context, req *sspb.HandshakeRequest) (*sspb.HandshakeResponse, 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 != ServerStateInitiated {
return nil, fmt.Errorf("session with id: %v in unexpected state: %d. Expecting: %d", connID, ch.state, ServerStateInitiated)
}
if len(req.TlsRecords) == 0 {
return nil, fmt.Errorf("TLS records were empty")
}
ch.shim.QueueReceiveBuf(req.TlsRecords)
// With the "Client Hello" and "Server Hello" records having already been
// exchanged as part of the BeginSession request, the records exchanged
// during this part of the handshake are "Client Change Cipher Spec" and
// "Client Handshake Finished", both of which are sent simultaneously here.
//
// However, there is a divergence between the behaviour of TLS 1.2 and 1.3+
// at this point: while in 1.2, the server must then respond with its
// "Server Change Cipher Spec" and "Server Handshake Finished" records
// before the client starts sending application data, in 1.3, the client
// sends its application data directly following its "Client Handshake
// Finished" (that is, there is no waiting on a "Server Handshake Finished"
// from the server).
//
// Because of this, under TLS 1.2, the underlying TLS implementation has
// records to drain here and send as part of the handshake response, whereas
// with TLS 1.3, there are no bytes, and attempting a read from the TLS
// implementation would result in 0 bytes. Therefore, we simply return an
// empty byte slice as the records in the response.
var records []byte
if ch.conn.ConnectionState().Version == tls.VersionTLS12 {
records = ch.shim.DrainSendBuf()
}
rep := &sspb.HandshakeResponse{
TlsRecords: records,
}
// Update state if TLS indicates handshake is complete, otherwise
// we expect to perform another Handshake call from the client.
if ch.conn.ConnectionState().HandshakeComplete {
ch.state = ServerStateHandshakeCompleted
}
return rep, nil
}