freeotfecypherdriver.c
来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· C语言 代码 · 共 1,734 行 · 第 1/5 页
C
1,734 行
CypherDetails.BlockSize,
(DIOCBufferIn->DataLength * 8)));
status = STATUS_INVALID_PARAMETER;
return status;
}
// IV length must = the blocksize
if ((CypherDetails.BlockSize > 0) && (CypherDetails.BlockSize != DIOCBufferIn->IVLength))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("The cypher blocksize is greater than 0; the IV length MUST equal the cypher's blocksize (cypher blocksize: %d bits; supplied IV was: %d bits\n", CypherDetails.BlockSize, DIOCBufferIn->IVLength));
status = STATUS_INVALID_PARAMETER;
return status;
}
// KeyLength must = the keysize
if ((CypherDetails.KeySize >= 0) && (CypherDetails.KeySize != DIOCBufferIn->KeyLength))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Keylength must = the cypher's keysize (cypher keysize: %d bits; supplied keysize: %d bits\n", CypherDetails.KeySize, DIOCBufferIn->KeyLength));
status = STATUS_INVALID_PARAMETER;
return status;
}
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Sanity checks OK\n"));
// ASCII representation of "Key".
// Number of chars/nibbles
// +1 to include NULL terminator
// This is included as an optimisation for
// ciphers which use the NIST AES API
keyASCIIBufferLen = ((DIOCBufferIn->KeyLength / 4)+1);
keyASCII = ExAllocatePool(
NonPagedPool,
keyASCIIBufferLen
);
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("keyASCIIBufferLen = %d bytes\n", keyASCIIBufferLen));
// Convert the data passed in to it's ASCII representation
ConvertDataToASCIIRep(
DIOCBufferIn->KeyLength, // In bits
ptrInKey,
keyASCII
);
if (NT_SUCCESS(status))
{
// Create a tmp buffer; this is done so that we don't pass both
// the DIOC input and output buffers (the *same* buffer!) to the
// implementation function
// (Also backup dataLength for the same reason)
dataLength = DIOCBufferIn->DataLength;
tmpBuffer = ExAllocatePool(
NonPagedPool,
dataLength
);
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("About to decrypt...\n"));
status = ImpCypherDecryptData(
&DIOCBufferIn->CypherGUID,
DIOCBufferIn->KeyLength, // In bits
ptrInKey,
keyASCII,
DIOCBufferIn->IVLength, // In bits
ptrInIV,
DIOCBufferIn->DataLength, // In bytes
ptrInData,
tmpBuffer
);
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Done decryption: %d (want status: %d)\n", status, STATUS_SUCCESS));
RtlCopyMemory(&DIOCBufferOut->Data, tmpBuffer, dataLength);
SecZeroMemory(tmpBuffer, dataLength);
ExFreePool(tmpBuffer);
}
SecZeroMemory(keyASCII, keyASCIIBufferLen);
ExFreePool(keyASCII);
Irp->IoStatus.Information = sizeof(DIOC_CYPHER_DATA_OUT)+(dataLength * sizeof(DIOCBufferOut->Data))-sizeof(DIOCBufferOut->Data);
DEBUGOUTCYPHERDRV(DEBUGLEV_EXIT, ("IOCTL_FreeOTFECypherIOCTL_Decrypt\n"));
return status;
}
// =========================================================================
// Create the main device object; the one which user code will normally
// talk to when creating new devices, carrying out general driver
// queries, etc
// DeviceObject will be set to the newly created device object
NTSTATUS
CreateDevice (
IN PDRIVER_OBJECT DriverObject,
OUT PDEVICE_OBJECT *DeviceObject
)
{
NTSTATUS status;
UNICODE_STRING devName;
PDEVICE_EXTENSION devExtension;
HANDLE threadHandle;
PDEVICE_OBJECT devObj;
ANSI_STRING tmpANSIName;
GUID driverGUID;
CYPHER_DRIVER_INFO tmpDevExt;
DEBUGOUTCYPHERDRV(DEBUGLEV_ENTER, ("CreateDevice\n"));
ASSERT(DriverObject != NULL);
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Building device name...\n"));
// We subtrace a sizeof(WCHAR) to discount the #NULL - required
// since although the UNICODE_STRING string doesn't require it, swprintf
// adds one on anyway
// This is a bit of a hack to get the driver's GUID
ImpCypherDriverExtDetailsInit(&tmpDevExt);
driverGUID = tmpDevExt.DriverGUID;
ImpCypherDriverExtDetailsCleardown(&tmpDevExt);
devName.MaximumLength = sizeof(DEVICE_CYPHER_DIR_NAME)
// ^^ dir name
+ sizeof(WCHAR)
// ^^ slash
+ GUID_STRING_REP_UNICODE_BYTE_LENGTH
// ^^ GUID length
+ sizeof(WCHAR);
// ^^ terminating NULL
devName.Buffer = ExAllocatePool(
NonPagedPool,
devName.MaximumLength
);
RtlZeroMemory(devName.Buffer, devName.MaximumLength);
// Note the "/" in the format string
devName.Length = (USHORT)swprintf(devName.Buffer, L"%s\\", DEVICE_CYPHER_DIR_NAME);
// swprintf returns the number of WCHARs, not the length in bytes
devName.Length = devName.Length * sizeof(WCHAR);
status = AppendGUIDToUnicodeString(driverGUID, &devName);
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("AppendGUIDToUnicodeString NOT OK\n"));
return status;
}
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("xdevNameLength: %d\n",
devName.Length));
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("xdevNameMaximumLength: %d\n",
devName.MaximumLength));
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("About to create device: %ls\n", devName.Buffer));
// Hmmm... I'd prefer to use FILE_DEVICE_UNKNOWN, but since
// IOCTL control codes pass through the device type, and we just
// pass then through...
// (See other call to IoCreateDevice in this file for details why we don't
// use FILE_DEVICE_VIRTUAL_DISK)
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&devObj
);
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Status NOT OK\n"));
return status;
}
devExtension = (PDEVICE_EXTENSION)devObj->DeviceExtension;
devExtension->zzDeviceName = devName;
devExtension->ThreadObject = NULL;
devExtension->zzSymbolicLinkName.Buffer = NULL;
status = ImpCypherDriverExtDetailsInit(&(devExtension->DriverInfo));
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Failed to ImpCypherDriverExtDetailsInit.\n"));
DestroyDevice(devObj);
return status;
}
// Create symlink; his allows user applications to CreateFile with
// "SymbolicName"
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Building symlink name...\n"));
// We add on sizeof(WCHAR) to include the terminating #NULL - required
// since although the UNICODE_STRING string doesn't require it, swprintf
// adds one on anyway
devExtension->zzSymbolicLinkName.MaximumLength = sizeof(DEVICE_CYPHER_SYMLINK_PREFIX)
// ^^ dir name
+ sizeof(WCHAR)
// ^^ slash
+ GUID_STRING_REP_UNICODE_BYTE_LENGTH
// ^^ GUID length
+ sizeof(WCHAR);
// ^^ terminating NULL
devExtension->zzSymbolicLinkName.Buffer = ExAllocatePool(
NonPagedPool,
devExtension->zzSymbolicLinkName.MaximumLength
);
RtlZeroMemory(devExtension->zzSymbolicLinkName.Buffer, devExtension->zzSymbolicLinkName.MaximumLength);
devExtension->zzSymbolicLinkName.Length = (USHORT)swprintf(
devExtension->zzSymbolicLinkName.Buffer,
L"%s",
DEVICE_CYPHER_SYMLINK_PREFIX
);
// swprintf returns the number of WCHARs, not the length in bytes
devExtension->zzSymbolicLinkName.Length = devExtension->zzSymbolicLinkName.Length * sizeof(WCHAR);
status = AppendGUIDToUnicodeString(driverGUID, &devExtension->zzSymbolicLinkName);
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("AppendGUIDToUnicodeString NOT OK\n"));
DestroyDevice(devObj);
return status;
}
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Unicoded symlink name: %ls\n",
devExtension->zzSymbolicLinkName.Buffer));
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Length: %d\n",
devExtension->zzSymbolicLinkName.Length));
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("MaximumLength: %d\n",
devExtension->zzSymbolicLinkName.MaximumLength));
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("About to create dosdevice symlink: %ls -> %ls\n", devExtension->zzSymbolicLinkName.Buffer, devExtension->zzDeviceName.Buffer));
status = IoCreateSymbolicLink(&devExtension->zzSymbolicLinkName, &devExtension->zzDeviceName);
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Done, checking status...\n"));
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Status NOT OK\n"));
DestroyDevice(devObj);
return status;
}
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("OK\n"));
devObj->Flags |= DO_DIRECT_IO;
devObj->Characteristics |= FILE_READ_ONLY_DEVICE;
// (Some of the bits following are taken from the DDK src/general/cancel example)
// This is used to serailize access to the queue.
KeInitializeSpinLock(&devExtension->IRPQueueLock);
KeInitializeSemaphore(&devExtension->IRPQueueSemaphore, 0, MAXLONG );
// Initialize the pending Irp devicequeue
InitializeListHead(&devExtension->PendingIRPQueue);
// Initialize the cancel safe queue
IoCsqInitialize(&devExtension->CancelSafeQueue,
CSQInsertIrp,
CSQRemoveIrp,
CSQPeekNextIrp,
CSQAcquireLock,
CSQReleaseLock,
CSQCompleteCanceledIrp);
// Create a thread for the device object
devExtension->TerminateThread = FALSE;
status = PsCreateSystemThread(
&threadHandle,
(ACCESS_MASK)0,
NULL,
(HANDLE)0L, // )0L because it's a
// driver-created thread
NULL,
FreeOTFEThread,
devObj
);
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Create thread FAILED.\n"));
DestroyDevice(devObj);
return status;
}
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("OK\n"));
// Convert the Thread object handle into a pointer to the Thread object
// itself. Then close the handle.
status = ObReferenceObjectByHandle(
threadHandle,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&devExtension->ThreadObject,
NULL
);
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Done processing thread; checking status.\n"));
if (!NT_SUCCESS(status))
{
DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Status FAILED.\n"));
ZwClose(threadHandle);
DestroyDevice(devObj);
return status;
}
DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("OK\n"));
// Close the thread handle
ZwClose(threadHandle);
// This is an easy thing to overlook - we do *not* have to unset the
// device's DO_DEVICE_INITIALIZING "Flags" as this function is carried out
// undef DriverEntry, and not something like AddDevice
*DeviceObject = devObj;
DEBUGOUTCYPHERDRV(DEBUGLEV_EXIT, ("CreateDevice\n"));
return STATUS_SUCCESS;
}
// =========================================================================
// Cancel all IRPs currently on the queue
void
CancelAllQueuedIRPs(
IN PDEVICE_OBJECT DeviceObject
)
{
PIRP pendingIrp;
PDEVICE_EXTENSION devExt;
DEBUGOUTMAINDRV(DEBUGLEV_ENTER, ("CancelAllQueuedIRPs\n"));
devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
// We only check one member of the struct; this will tell us if the CancelSafeQueue has
// been initialised or not
if (devExt->CancelSafeQueue.CsqRemoveIrp != NULL)
{
DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Cancelling all queued IRPs.\n"));
while(pendingIrp = IoCsqRemoveNextIrp(&devExt->CancelSafeQueue, NULL))
{
// Cancel the IRP
DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Cancelling an IRP...\n"));
pendingIrp->IoStatus.Information = 0;
pendingIrp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?