AcquireCredentialsHandleW fails in kernelmode with error RPC_NT_CALL_FAILED

I’m trying to implement secure sockets in my kernel mode application. For this, I want to use Schannel provided by the Windows OS (KSecDD).

For some odd reason, my call to AcquireCredentialsHandleW fails with NT error RPC_NT_CALL_FAILED. All parameters passed to the function are allocated in usermode memory using ZwAllocateVirtualMemory.

My current code looks like this:

	NTSTATUS retVal;
	SECURITY_STATUS secStatus, initStatus;
	PSCHANNEL_CRED creds;
	SECURE_SOCKET_CONNECTION *con = NULL;
	PSECURITY_STRING packageName = NULL;

	creds = AllocUserMemory(sizeof(SCHANNEL_CRED));

	creds->dwVersion = SCHANNEL_CRED_VERSION;
	creds->grbitEnabledProtocols = SP_PROT_TLS1_2;
	creds->dwFlags = SCH_USE_STRONG_CRYPTO |
		SCH_CRED_AUTO_CRED_VALIDATION |
		SCH_CRED_NO_DEFAULT_CREDS;
	
	/*
	con = ExAllocatePool2(
		POOL_FLAG_NON_PAGED,
		sizeof(SECURE_SOCKET_CONNECTION),
		'noc'
	);
	*/

	con = AllocUserMemory(sizeof(SECURE_SOCKET_CONNECTION));

	if (!con)
	{
		retVal = STATUS_NO_MEMORY;
		goto Done;
	}

	packageName = AllocUnicodeStringUserMem(
		L"Microsoft Unified Security Protocol Provider"
	);

	if (!packageName)
	{
		retVal = STATUS_NO_MEMORY;
		goto Done;
	}

	con->SecureFuncs = InitSecurityInterfaceW();

	if (!con->SecureFuncs)
	{
		retVal = STATUS_UNSATISFIED_DEPENDENCIES;
		goto Done;
	}

	secStatus = con->SecureFuncs->AcquireCredentialsHandleW(
		NULL,
		packageName,
		SECPKG_CRED_OUTBOUND,
		NULL,
		creds,
		NULL,
		NULL,
		&con->CredHandle,
		NULL
	);

	DbgPrintEx(0, 0, "Str %wZ\n", packageName);
	DbgPrintEx(0, 0, "SecStatus %x\n", secStatus); //Error 0xC002001B

...

On top of that I have another question:
MSDN states that you have to call ApplyControlToken to shutdown a schannel connection. However, according to the documentation, this function is not available in kernelmode (although KSecDD.sys does export it). What am I supposed to do in this case? Is this an error with the documentation?

when you say secure sockets, I assume you mean one of the TLS protocols that have superseded SSL. Authentication is only one small part of an implementation like that, but I further assume that you want to implement windows integrated authentication via the SSPI API. This is not a trivial project, and it is unclear what you will gain by implementing your own. This is all well documented standard technology

as you your actual problem, APIs like AcquireCredentialHandle can often fail while a debugger is attached because the debugger prevents other activity in the system and causes timeouts. If that’s not your issue, then you need to tell us more about your setup

@MBond2 said:
when you say secure sockets, I assume you mean one of the TLS protocols that have superseded SSL. Authentication is only one small part of an implementation like that, but I further assume that you want to implement windows integrated authentication via the SSPI API. This is not a trivial project, and it is unclear what you will gain by implementing your own. This is all well documented standard technology

as you your actual problem, APIs like AcquireCredentialHandle can often fail while a debugger is attached because the debugger prevents other activity in the system and causes timeouts. If that’s not your issue, then you need to tell us more about your setup

Yes, I mean enabling secure communication using TLS. As a student I think that this is an interesting project to study both kernel mode programming and networking.

I have solved the issue by allocating the parameters for AcquireCredentialsHandleW on the stack instead of the virtual user memory. One thing I don’t understand is why the documentation states that a kernel mode caller MUST allocate the buffers in user memory and not in the pool. What’s the reason for this? And why is it ok to allocate them on the stack?

The correct use of these APIs is a subject too large for a forum post. And the TLS protocol is much larger again. So good luck with your studies

As to your specific question, look at what your AllocUserMemory function does. Probably it allocates memory in a context that cannot be used. Then think about what this API must do and how that could be accomplished. what parts of the OS must be involved and what requirements do they have in terms of paging and memory accessibility