Securing the Message Exchange

After a security context is established, the application can use the SSPI message support functions to transmit signed messages. The process of signing a message ensures that the message cannot be tampered with.

If an application wants to generate signed messages, the client must set the ISC_REQ_REPLAY_DETECT or ISC_REQ_SEQUENCE_DETECT flag of the context attribute argument when first calling the InitializeSecurityContext function.

Signing messages requires that the client and the server service providers establish a common session key used to sign messages on the sender side of the communication and verify messages on the receiver side of the communication. Algorithms used in message signatures are known only to the security package.

After an authenticated connection has been established, the client or server can pass the security context and a message to the MakeSignature function to generate a secure signature. MakeSignature generates a checksum of the message and also provides sequencing data to prevent the message from being modified in transit. A checksum is a calculated value used to test data for the presence of errors that can occur when data is transmitted.

The following code example shows how to implement MakeSignature and how to append the signature to the message so that the receiver can extract it when the message is received.

SecBuffer OutSecBuffer[2];
SecBufferDesc OutBufferDesc;

// Set up the buffer descriptors.
OutBufferDesc.ulVersion = 0;
OutBufferDesc.cBuffers = 2;
OutBufferDesc.pBuffers = &OutSecBuffer[0];

OutSecBuffer[0].cbBuffer = MessageLen;
OutSecBuffer[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
OutSecBuffer[0].pvBuffer = pMessage;

OutSecBuffer[1].cbBuffer = SignatureLen;
OutSecBuffer[1].BufferType = SECBUFFER_EMPTY;
OutSecBuffer[1].pvBuffer = (pMessage + MessageLen); 

// Call MakeSignature to get it signed.
status = (*pSecurityInterface->MakeSignature) (&hContext,
                                               0,
                                               &BufferDesc,
                                               ulMessageSeqNum);

The sender then uses the buffer descriptor, including the signature, to construct a message to send to the receiver. The receiver takes the message and disassembles it to recreate the buffer descriptor. The receiver then calls the VerifySignature function to verify that the message received is correct according to the data in the signature.

The following code example shows how to implement VerifySignature.

SecBuffer InSecBuffer[2];
SecBufferDesc InBufferDesc;

// Set up the buffer descriptors.
InBufferDesc.ulVersion = 0;
InBufferDesc.cBuffers = 2;
InBufferDesc.pBuffers = &InSecBuffer[0];

InSecBuffer[0].cbBuffer = MessageLen;
InSecBuffer[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
InSecBuffer[0].pvBuffer = pMessage;

InSecBuffer[1].cbBuffer = SignatureLen;
InSecBuffer[1].BufferType = SECBUFFER_TOKEN;
InSecBuffer[1].pvBuffer = (pMessage + MessageLen); 

// Call VerifySignature to verify the message signature.
status = (*pSecurityInterface->VerifySignature) (&hContext,
                                                 &BufferDesc,
                                                 ulMessageSeqNum,
                                                 &ulQualityProtection);