Skip to content

Commit

Permalink
Move crypto alg handles to Device object
Browse files Browse the repository at this point in the history
This is done in preparation for multí-peer support.

Fixes #55

Signed-off-by: Lev Stipakov <[email protected]>
Signed-off-by: Leon Dang <[email protected]>

Co-authored-by: Leon Dang <[email protected]>
  • Loading branch information
lstipakov and ldnetgate committed Nov 30, 2023
1 parent 1b8b417 commit c4b7b26
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 33 deletions.
6 changes: 6 additions & 0 deletions Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ VOID OvpnEvtDeviceCleanup(WDFOBJECT obj) {
device->Adapter = WDF_NO_HANDLE;
ExReleaseSpinLockExclusive(&device->SpinLock, irql);

// OvpnCryptoUninitAlgHandles called outside of lock because
// it requires PASSIVE_LEVEL.
OvpnCryptoUninitAlgHandles(device->AesAlgHandle, device->ChachaAlgHandle);

LOG_EXIT();
}

Expand Down Expand Up @@ -470,6 +474,8 @@ OvpnEvtDeviceAdd(WDFDRIVER wdfDriver, PWDFDEVICE_INIT deviceInit) {
GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnBufferQueueCreate(&device->ControlRxBufferQueue));
GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnBufferQueueCreate(&device->DataRxBufferQueue));

GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnCryptoInitAlgHandles(&device->AesAlgHandle, &device->ChachaAlgHandle));

LOG_IF_NOT_NT_SUCCESS(status = OvpnAdapterCreate(device));

done:
Expand Down
3 changes: 3 additions & 0 deletions Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ struct OVPN_DEVICE {
_Guarded_by_(SpinLock)
WDFTIMER KeepaliveRecvTimer;

BCRYPT_ALG_HANDLE AesAlgHandle;
BCRYPT_ALG_HANDLE ChachaAlgHandle;

// set from the userspace, defines TCP Maximum Segment Size
_Guarded_by_(SpinLock)
UINT16 MSS;
Expand Down
2 changes: 1 addition & 1 deletion PropertySheet.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<PropertyGroup Label="UserMacros">
<OVPN_DCO_VERSION_MAJOR>1</OVPN_DCO_VERSION_MAJOR>
<OVPN_DCO_VERSION_MINOR>0</OVPN_DCO_VERSION_MINOR>
<OVPN_DCO_VERSION_PATCH>0</OVPN_DCO_VERSION_PATCH>
<OVPN_DCO_VERSION_PATCH>1</OVPN_DCO_VERSION_PATCH>
</PropertyGroup>
<PropertyGroup />
<ItemDefinitionGroup>
Expand Down
15 changes: 1 addition & 14 deletions crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ OvpnCryptoEncryptAEAD(OvpnCryptoKeySlot* keySlot, UCHAR* buf, SIZE_T len)

_Use_decl_annotations_
NTSTATUS
OvpnCryptoNewKey(OvpnCryptoContext* cryptoContext, POVPN_CRYPTO_DATA cryptoData)
OvpnCryptoNewKey(OvpnCryptoContext* cryptoContext, POVPN_CRYPTO_DATA cryptoData, BCRYPT_ALG_HANDLE algHandle)
{
OvpnCryptoKeySlot* keySlot = NULL;
NTSTATUS status = STATUS_SUCCESS;
Expand Down Expand Up @@ -249,19 +249,6 @@ OvpnCryptoNewKey(OvpnCryptoContext* cryptoContext, POVPN_CRYPTO_DATA cryptoData)
keySlot->DecKey = NULL;
}

BCRYPT_ALG_HANDLE algHandle = NULL;
if (cryptoData->CipherAlg == OVPN_CIPHER_ALG_AES_GCM) {
algHandle = cryptoContext->AesAlgHandle;
}
else {
if (cryptoContext->ChachaAlgHandle == NULL) {
LOG_ERROR("CHACHA20-POLY1305 is not available");
status = STATUS_INVALID_DEVICE_REQUEST;
goto done;
}
algHandle = cryptoContext->ChachaAlgHandle;
}

// generate keys from key materials
GOTO_IF_NOT_NT_SUCCESS(done, status, BCryptGenerateSymmetricKey(algHandle, &keySlot->EncKey, NULL, 0, cryptoData->Encrypt.Key, cryptoData->Encrypt.KeyLen, 0));
GOTO_IF_NOT_NT_SUCCESS(done, status, BCryptGenerateSymmetricKey(algHandle, &keySlot->DecKey, NULL, 0, cryptoData->Decrypt.Key, cryptoData->Decrypt.KeyLen, 0));
Expand Down
5 changes: 1 addition & 4 deletions crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,6 @@ typedef OVPN_CRYPTO_DECRYPT* POVPN_CRYPTO_DECRYPT;

struct OvpnCryptoContext
{
BCRYPT_ALG_HANDLE AesAlgHandle;
BCRYPT_ALG_HANDLE ChachaAlgHandle;

OvpnCryptoKeySlot Primary;
OvpnCryptoKeySlot Secondary;

Expand All @@ -101,7 +98,7 @@ OvpnCryptoUninit(_In_ OvpnCryptoContext* cryptoContext);

_Must_inspect_result_
NTSTATUS
OvpnCryptoNewKey(_In_ OvpnCryptoContext* cryptoContext, _In_ POVPN_CRYPTO_DATA cryptoData);
OvpnCryptoNewKey(_In_ OvpnCryptoContext* cryptoContext, _In_ POVPN_CRYPTO_DATA cryptoData, _In_opt_ BCRYPT_ALG_HANDLE algHandle);

_Must_inspect_result_
OvpnCryptoKeySlot*
Expand Down
33 changes: 19 additions & 14 deletions peer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,8 @@ OvpnPeerNew(POVPN_DEVICE device, WDFREQUEST request)
GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnSocketInit(&driver->WskProviderNpi, &driver->WskRegistration, peer->Local.Addr4.sin_family, proto_tcp, (PSOCKADDR)&peer->Local,
(PSOCKADDR)&peer->Remote, remoteAddrSize, device, &socket));

BCRYPT_ALG_HANDLE aesAlgHandle = NULL, chachaAlgHandle = NULL;
GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnCryptoInitAlgHandles(&aesAlgHandle, &chachaAlgHandle));

KIRQL kirql = ExAcquireSpinLockExclusive(&device->SpinLock);
RtlZeroMemory(&device->CryptoContext, sizeof(OvpnCryptoContext));
device->CryptoContext.AesAlgHandle = aesAlgHandle;
device->CryptoContext.ChachaAlgHandle = chachaAlgHandle;
device->Socket.Socket = socket;
device->Socket.Tcp = proto_tcp;
RtlZeroMemory(&device->Socket.TcpState, sizeof(OvpnSocketTcpState));
Expand Down Expand Up @@ -112,16 +107,11 @@ OvpnPeerDel(POVPN_DEVICE device)
return STATUS_INVALID_DEVICE_REQUEST;
}

BCRYPT_ALG_HANDLE aesAlgHandle = NULL, chachaAlgHandle = NULL;

KIRQL kirql = ExAcquireSpinLockExclusive(&device->SpinLock);

OvpnTimerDestroy(&device->KeepaliveXmitTimer);
OvpnTimerDestroy(&device->KeepaliveRecvTimer);

aesAlgHandle = device->CryptoContext.AesAlgHandle;
chachaAlgHandle = device->CryptoContext.ChachaAlgHandle;

OvpnCryptoUninit(&device->CryptoContext);

InterlockedExchange(&device->UserspacePid, 0);
Expand All @@ -132,11 +122,9 @@ OvpnPeerDel(POVPN_DEVICE device)
RtlZeroMemory(&device->Socket.TcpState, sizeof(OvpnSocketTcpState));
RtlZeroMemory(&device->Socket.UdpState, sizeof(OvpnSocketUdpState));

// OvpnCryptoUninitAlgHandles and OvpnSocketClose require PASSIVE_LEVEL, so must release lock
// OvpnSocketClose requires PASSIVE_LEVEL, so must release lock
ExReleaseSpinLockExclusive(&device->SpinLock, kirql);

OvpnCryptoUninitAlgHandles(aesAlgHandle, chachaAlgHandle);

LOG_IF_NOT_NT_SUCCESS(OvpnSocketClose(socket));

// flush buffers in control queue so that client won't get control channel messages from previous session
Expand Down Expand Up @@ -278,7 +266,24 @@ OvpnPeerNewKey(POVPN_DEVICE device, WDFREQUEST request)
NTSTATUS status;

GOTO_IF_NOT_NT_SUCCESS(done, status, WdfRequestRetrieveInputBuffer(request, sizeof(OVPN_CRYPTO_DATA), (PVOID*)&cryptoData, nullptr));
GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnCryptoNewKey(&device->CryptoContext, cryptoData));

BCRYPT_ALG_HANDLE algHandle = NULL;
switch (cryptoData->CipherAlg) {
case OVPN_CIPHER_ALG_AES_GCM:
algHandle = device->AesAlgHandle;
break;

case OVPN_CIPHER_ALG_CHACHA20_POLY1305:
algHandle = device->ChachaAlgHandle;
if (algHandle == NULL) {
LOG_ERROR("CHACHA20-POLY1305 is not available");
status = STATUS_INVALID_DEVICE_REQUEST;
goto done;
}
break;
}

GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnCryptoNewKey(&device->CryptoContext, cryptoData, algHandle));

done:
LOG_EXIT();
Expand Down

0 comments on commit c4b7b26

Please sign in to comment.