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

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

	if (!(context->flags & SSPI_GSS_C_CONF_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;

	if (fQOP)
		return SEC_E_QOP_NOT_SUPPORTED;

	flags |= context->acceptor ? FLAG_SENDER_IS_ACCEPTOR : 0;
	flags |= FLAG_WRAP_CONFIDENTIAL;
	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_SEAL : KG_USAGE_INITIATOR_SEAL;

	/* Set the lengths of the data (plaintext + header) */
	encrypt_iov[1].data.length = data_buffer->cbBuffer;
	encrypt_iov[2].data.length = 16;

	/* Get the lengths of the header, trailer, and padding and ensure sig_buffer is large enough */
	if (krb5_c_crypto_length_iov(context->ctx, krb5_k_key_enctype(context->ctx, key), encrypt_iov,
	                             ARRAYSIZE(encrypt_iov)))
		return SEC_E_INTERNAL_ERROR;
	if (sig_buffer->cbBuffer <
	    encrypt_iov[0].data.length + encrypt_iov[3].data.length + encrypt_iov[4].data.length + 32)
		return SEC_E_INSUFFICIENT_MEMORY;

	/* Set up the iov array in sig_buffer */
	header = sig_buffer->pvBuffer;
	encrypt_iov[2].data.data = header + 16;
	encrypt_iov[3].data.data = encrypt_iov[2].data.data + encrypt_iov[2].data.length;
	encrypt_iov[4].data.data = encrypt_iov[3].data.data + encrypt_iov[3].data.length;
	encrypt_iov[0].data.data = encrypt_iov[4].data.data + encrypt_iov[4].data.length;
	encrypt_iov[1].data.data = data_buffer->pvBuffer;

	/* Write the GSS header with 0 in RRC */
	Data_Write_UINT16_BE(header, TOK_ID_WRAP);
	header[2] = flags;
	header[3] = 0xFF;
	Data_Write_UINT32(header + 4, 0);
	Data_Write_UINT64_BE(header + 8, (context->local_seq + MessageSeqNo));

	/* Copy header to be encrypted */
	CopyMemory(encrypt_iov[2].data.data, header, 16);

	/* Set the correct RRC */
	Data_Write_UINT16_BE(header + 6, 16 + encrypt_iov[3].data.length + encrypt_iov[4].data.length);

	if (krb5_k_encrypt_iov(context->ctx, key, usage, NULL, encrypt_iov, ARRAYSIZE(encrypt_iov)))
		return SEC_E_INTERNAL_ERROR;

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

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

	if (!(context->flags & SSPI_GSS_C_CONF_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;

	if (fQOP)
		return SEC_E_QOP_NOT_SUPPORTED;

	flags |= context->acceptor ? FLAG_SENDER_IS_ACCEPTOR : 0;
	flags |= FLAG_WRAP_CONFIDENTIAL;
	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_SEAL : KG_USAGE_INITIATOR_SEAL;

	 
	encrypt_iov[1].data.length = data_buffer->cbBuffer;
	encrypt_iov[2].data.length = 16;

	 
	if (krb5_c_crypto_length_iov(context->ctx, krb5_k_key_enctype(context->ctx, key), encrypt_iov,
	                             ARRAYSIZE(encrypt_iov)))
		return SEC_E_INTERNAL_ERROR;
	if (sig_buffer->cbBuffer <
	    encrypt_iov[0].data.length + encrypt_iov[3].data.length + encrypt_iov[4].data.length + 32)
		return SEC_E_INSUFFICIENT_MEMORY;

	 
	header = sig_buffer->pvBuffer;
	encrypt_iov[2].data.data = header + 16;
	encrypt_iov[3].data.data = encrypt_iov[2].data.data + encrypt_iov[2].data.length;
	encrypt_iov[4].data.data = encrypt_iov[3].data.data + encrypt_iov[3].data.length;
	encrypt_iov[0].data.data = encrypt_iov[4].data.data + encrypt_iov[4].data.length;
	encrypt_iov[1].data.data = data_buffer->pvBuffer;

	 
	Data_Write_UINT16_BE(header, TOK_ID_WRAP);
	header[2] = flags;
	header[3] = 0xFF;
	Data_Write_UINT32(header + 4, 0);
	Data_Write_UINT64_BE(header + 8, (context->local_seq + MessageSeqNo));

	 
	CopyMemory(encrypt_iov[2].data.data, header, 16);

	 
	Data_Write_UINT16_BE(header + 6, 16 + encrypt_iov[3].data.length + encrypt_iov[4].data.length);

	if (krb5_k_encrypt_iov(context->ctx, key, usage, NULL, encrypt_iov, ARRAYSIZE(encrypt_iov)))
		return SEC_E_INTERNAL_ERROR;

	return SEC_E_OK;
#else
	return SEC_E_UNSUPPORTED_FUNCTION;
#endif
}