static SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
                                                        PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
#ifdef WITH_GSSAPI
	KRB_CONTEXT* context;
	PSecBuffer sig_buffer, data_buffer;
	krb5_key key;
	krb5_keyusage usage;
	char* header;
	BYTE flags = 0;
	krb5_crypto_iov iov[] = { { KRB5_CRYPTO_TYPE_DATA, { 0 } },
		                      { KRB5_CRYPTO_TYPE_DATA, { 0 } },
		                      { KRB5_CRYPTO_TYPE_CHECKSUM, { 0 } } };

	context = sspi_SecureHandleGetLowerPointer(phContext);
	if (!context)
		return SEC_E_INVALID_HANDLE;

	if (!(context->flags & SSPI_GSS_C_INTEG_FLAG))
		return SEC_E_UNSUPPORTED_FUNCTION;

	sig_buffer = sspi_FindSecBuffer(pMessage, SECBUFFER_TOKEN);
	data_buffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);

	if (!sig_buffer || !data_buffer)
		return SEC_E_INVALID_TOKEN;

	flags |= context->acceptor ? FLAG_SENDER_IS_ACCEPTOR : 0;
	flags |= context->acceptor_key ? FLAG_ACCEPTOR_SUBKEY : 0;

	key = context->acceptor_key    ? context->acceptor_key
	      : context->initiator_key ? context->initiator_key
	                               : context->session_key;
	if (!key)
		return SEC_E_INTERNAL_ERROR;
	usage = context->acceptor ? KG_USAGE_ACCEPTOR_SIGN : KG_USAGE_INITIATOR_SIGN;

	/* Fill in the lengths of the iov array */
	iov[0].data.length = data_buffer->cbBuffer;
	iov[1].data.length = 16;
	if (krb5_c_crypto_length_iov(context->ctx, krb5_k_key_enctype(context->ctx, key), iov,
	                             ARRAYSIZE(iov)))
		return SEC_E_INTERNAL_ERROR;

	/* Ensure the buffer is big enough */
	if (sig_buffer->cbBuffer < iov[2].data.length + 16)
		return SEC_E_INSUFFICIENT_MEMORY;

	/* Write the header */
	header = sig_buffer->pvBuffer;
	Data_Write_UINT16_BE(header, TOK_ID_MIC);
	header[2] = flags;
	memset(header + 3, 0xFF, 5);
	Data_Write_UINT64_BE(header + 8, (context->local_seq + MessageSeqNo));

	/* Set up the iov array */
	iov[0].data.data = data_buffer->pvBuffer;
	iov[1].data.data = header;
	iov[2].data.data = header + 16;

	if (krb5_k_make_checksum_iov(context->ctx, 0, key, usage, iov, ARRAYSIZE(iov)))
		return SEC_E_INTERNAL_ERROR;

	sig_buffer->cbBuffer = iov[2].data.length + 16;

	return SEC_E_OK;
#else
	return SEC_E_UNSUPPORTED_FUNCTION;
#endif
}
static SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
                                                        PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
#ifdef WITH_GSSAPI
	KRB_CONTEXT* context;
	PSecBuffer sig_buffer, data_buffer;
	krb5_key key;
	krb5_keyusage usage;
	char* header;
	BYTE flags = 0;
	krb5_crypto_iov iov[] = { { KRB5_CRYPTO_TYPE_DATA, { 0 } },
		                      { KRB5_CRYPTO_TYPE_DATA, { 0 } },
		                      { KRB5_CRYPTO_TYPE_CHECKSUM, { 0 } } };

	context = sspi_SecureHandleGetLowerPointer(phContext);
	if (!context)
		return SEC_E_INVALID_HANDLE;

	if (!(context->flags & SSPI_GSS_C_INTEG_FLAG))
		return SEC_E_UNSUPPORTED_FUNCTION;

	sig_buffer = sspi_FindSecBuffer(pMessage, SECBUFFER_TOKEN);
	data_buffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA);

	if (!sig_buffer || !data_buffer)
		return SEC_E_INVALID_TOKEN;

	flags |= context->acceptor ? FLAG_SENDER_IS_ACCEPTOR : 0;
	flags |= context->acceptor_key ? FLAG_ACCEPTOR_SUBKEY : 0;

	key = context->acceptor_key    ? context->acceptor_key
	      : context->initiator_key ? context->initiator_key
	                               : context->session_key;
	if (!key)
		return SEC_E_INTERNAL_ERROR;
	usage = context->acceptor ? KG_USAGE_ACCEPTOR_SIGN : KG_USAGE_INITIATOR_SIGN;

	 
	iov[0].data.length = data_buffer->cbBuffer;
	iov[1].data.length = 16;
	if (krb5_c_crypto_length_iov(context->ctx, krb5_k_key_enctype(context->ctx, key), iov,
	                             ARRAYSIZE(iov)))
		return SEC_E_INTERNAL_ERROR;

	 
	if (sig_buffer->cbBuffer < iov[2].data.length + 16)
		return SEC_E_INSUFFICIENT_MEMORY;

	 
	header = sig_buffer->pvBuffer;
	Data_Write_UINT16_BE(header, TOK_ID_MIC);
	header[2] = flags;
	memset(header + 3, 0xFF, 5);
	Data_Write_UINT64_BE(header + 8, (context->local_seq + MessageSeqNo));

	 
	iov[0].data.data = data_buffer->pvBuffer;
	iov[1].data.data = header;
	iov[2].data.data = header + 16;

	if (krb5_k_make_checksum_iov(context->ctx, 0, key, usage, iov, ARRAYSIZE(iov)))
		return SEC_E_INTERNAL_ERROR;

	sig_buffer->cbBuffer = iov[2].data.length + 16;

	return SEC_E_OK;
#else
	return SEC_E_UNSUPPORTED_FUNCTION;
#endif
}