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 + -
显示快捷键?