freeotfecypherdriver.c

来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· C语言 代码 · 共 1,734 行 · 第 1/5 页

C
1,734
字号
              - sizeof(DIOCBufferIn->Data)
            ),
            irpSp->Parameters.DeviceIoControl.InputBufferLength
            ));
        status = STATUS_INVALID_BUFFER_SIZE;
        return status;            
        }
    // Actual check...
    if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
            (
             sizeof(DIOC_CYPHER_DATA_IN)
              - sizeof(DIOCBufferIn->Key)
              - sizeof(DIOCBufferIn->IV)
              - sizeof(DIOCBufferIn->Data)
              + (DIOCBufferIn->KeyLength / 8)  // Bits -> Bytes
              + (DIOCBufferIn->IVLength / 8)  // Bits -> Bytes
              + (DIOCBufferIn->DataLength)  // Already counted in bytes
             )
       )
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("inBuffer size wrong size (expect actual: %d; got: %d)\n",
            (
             sizeof(DIOC_CYPHER_DATA_IN)
              - sizeof(DIOCBufferIn->Key)
              - sizeof(DIOCBufferIn->IV)
              - sizeof(DIOCBufferIn->Data)
              + (DIOCBufferIn->KeyLength / 8)  // Bits -> Bytes
              + (DIOCBufferIn->IVLength / 8)  // Bits -> Bytes
              + (DIOCBufferIn->DataLength)  // Already counted in bytes
             ),
            irpSp->Parameters.DeviceIoControl.InputBufferLength
            ));
        status = STATUS_INVALID_BUFFER_SIZE;
        return status;            
        }


    // Check size of OUTPUT buffer
    // Actual check...
    // NOTE THAT THIS USES THE DataLength MEMBER OF THE INPUT BUFFER - THE
    // OUTPUT IS THE SAME SIZE AS THE INPUT
    if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(DIOC_CYPHER_DATA_OUT)+(DIOCBufferIn->DataLength * sizeof(DIOCBufferOut->Data))-sizeof(DIOCBufferOut->Data))
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("outBuffer size wrong size (expect: %d; got: %d)\n",
            sizeof(DIOC_CYPHER_DATA_OUT)+DIOCBufferIn->DataLength-sizeof(DIOCBufferOut->Data),
            irpSp->Parameters.DeviceIoControl.OutputBufferLength
            ));
        status = STATUS_INVALID_BUFFER_SIZE;
        return status;            
        }

    // Request valid, process...

    // Since the variable length members of the input buffer can't be accessed
    // directly (their locations vary, depending on the size of earlier members)
    // we calculate pointers so they can be accessed easily...
    ptrInKey  = (char*)&DIOCBufferIn->Key;
    ptrInIV   = ptrInKey + ((DIOCBufferIn->KeyLength / 8) * sizeof(DIOCBufferIn->Key));
    ptrInData = ptrInIV + ((DIOCBufferIn->IVLength / 8) * sizeof(DIOCBufferIn->IV));

    // NOTE: THIS IS ONLY DUMPED OUT IF DEBUG IS NOT ENABLED; ONLY ON
    //       DEBUG BUILDS.
    //       Normal release builds cause DEBUGOUTCYPHERDRV to be a NOP, so
    //       this debug code gets removed
    DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Key length: %d bits\n", DIOCBufferIn->KeyLength));
    for(i = 0; i < (DIOCBufferIn->KeyLength / 8); i++)
        { 
        DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Key [%.2d]: %.2x\n", i, ptrInKey[i]));
        }                                
    DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- IV length: %d bits\n", DIOCBufferIn->IVLength));
    for(i = 0; i < (DIOCBufferIn->IVLength / 8); i++)
        { 
        DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- IV [%.2d]: %.2x\n", i, ptrInIV[i]));
        }                                
    DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Data length: %d bytes\n", DIOCBufferIn->DataLength));
    for(i = 0; i < (DIOCBufferIn->DataLength / 8); i++)
        { 
        DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Data [%.2d]: %.2x\n", i, ptrInData[i]));
        // Only dump out the first 5 bytes...
        if (i >= 5) 
            {
            DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Data [..]: (Debug output truncated to only show first few bytes)\n"));
            break;        
            }
        }                                


    // Sanity checks on the request wrt the cypher

    DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("About to get cypher details...\n"));
    status = GetCypherDetails(
                              &(DIOCBufferIn->CypherGUID),
                              &CypherDetails
                             );
    if (!(NT_SUCCESS(status)))
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Unable to locate requested cypher in driver\n"));
        return status;            
        }
    DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Cypher details got OK.\n"));

    // Input/output buffer must be a multiple of the blocksize
    // Output buffer length not explicitly checked, as we already made sure
    // that it's big enough to store the input data
    // Note: Multiply DataLength by 8 to get bits
    if ((CypherDetails.BlockSize > 0) && (((DIOCBufferIn->DataLength * 8) % CypherDetails.BlockSize) != 0))
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Length of data IN must be a multiple of the blocksize (bs: %d bits; bufSize: %d bits\n",
                                        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 encrypt...\n"));
        status = ImpCypherEncryptData(
                                    &DIOCBufferIn->CypherGUID,
                                    DIOCBufferIn->KeyLength,  // In bits
                                    ptrInKey,
                                    keyASCII,
                                    DIOCBufferIn->IVLength,  // In bits
                                    ptrInIV,
                                    DIOCBufferIn->DataLength,  // In bytes
                                    ptrInData,
                                    tmpBuffer
                                    );    
        DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Done encryption: %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_Encrypt\n"));
    return status;
}


// =========================================================================
// 
NTSTATUS
IOCTL_FreeOTFECypherIOCTL_Decrypt(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
)
{
    NTSTATUS status;
    PIO_STACK_LOCATION irpSp;
    PDIOC_CYPHER_DATA_IN DIOCBufferIn;
    PDIOC_CYPHER_DATA_OUT DIOCBufferOut;
    CYPHER CypherDetails;
    char* keyASCII;
    int keyASCIIBufferLen;
    int dataLength;
    char* tmpBuffer;
    unsigned char* ptrInKey;   // Pointer to where the key starts in the input buffer
    unsigned char* ptrInIV;    // Pointer to where the IV starts in the input buffer
    unsigned char* ptrInData;  // Pointer to where the data starts in the input buffer
    int i;

    DEBUGOUTCYPHERDRV(DEBUGLEV_ENTER, ("IOCTL_FreeOTFECypherIOCTL_Decrypt\n"));

    irpSp = IoGetCurrentIrpStackLocation(Irp);

    DIOCBufferIn = (PDIOC_CYPHER_DATA_IN)Irp->AssociatedIrp.SystemBuffer;
    DIOCBufferOut = (PDIOC_CYPHER_DATA_OUT)Irp->AssociatedIrp.SystemBuffer;

    // Check size of INPUT buffer
    // Minimum check...
    // (Done first in order to ensure that we can later access DIOCBufferIn->Data
    // for actual check)
    if (
        irpSp->Parameters.DeviceIoControl.InputBufferLength <
            (
             sizeof(DIOC_CYPHER_DATA_IN)
             - sizeof(DIOCBufferIn->Key)
             - sizeof(DIOCBufferIn->IV)
             - sizeof(DIOCBufferIn->Data)
            )
       )
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("inBuffer size wrong size (expect min: %d; got: %d)\n",
            (
             sizeof(DIOC_CYPHER_DATA_IN)
             - sizeof(DIOCBufferIn->Key)
             - sizeof(DIOCBufferIn->IV)
             - sizeof(DIOCBufferIn->Data)
            ),
            irpSp->Parameters.DeviceIoControl.InputBufferLength
            ));
        status = STATUS_INVALID_BUFFER_SIZE;
        return status;            
        }
    // Actual check...
    if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
            (
             sizeof(DIOC_CYPHER_DATA_IN)
             - sizeof(DIOCBufferIn->Key)
             - sizeof(DIOCBufferIn->IV)
             - sizeof(DIOCBufferIn->Data)
             + ((DIOCBufferIn->KeyLength / 8) * sizeof(DIOCBufferIn->Key))
             + ((DIOCBufferIn->IVLength / 8) * sizeof(DIOCBufferIn->IV))
             + (DIOCBufferIn->DataLength * sizeof(DIOCBufferIn->Data))
             )
       )
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("inBuffer size wrong size (expect actual: %d; got: %d)\n",
            (
             sizeof(DIOC_CYPHER_DATA_IN)
             - sizeof(DIOCBufferIn->Key)
             - sizeof(DIOCBufferIn->IV)
             - sizeof(DIOCBufferIn->Data)
             + ((DIOCBufferIn->KeyLength / 8) * sizeof(DIOCBufferIn->Key))
             + ((DIOCBufferIn->IVLength / 8) * sizeof(DIOCBufferIn->IV))
             + (DIOCBufferIn->DataLength * sizeof(DIOCBufferIn->Data))
             ),
            irpSp->Parameters.DeviceIoControl.InputBufferLength
            ));
        status = STATUS_INVALID_BUFFER_SIZE;
        return status;            
        }


    // Check size of OUTPUT buffer
    // Actual check...
    // NOTE THAT THIS USES THE DataLength MEMBER OF THE INPUT BUFFER - THE
    // OUTPUT IS THE SAME SIZE AS THE INPUT
    if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(DIOC_CYPHER_DATA_OUT)+(DIOCBufferIn->DataLength * sizeof(DIOCBufferOut->Data))-sizeof(DIOCBufferOut->Data))
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("outBuffer size wrong size (expect: %d; got: %d)\n",
            sizeof(DIOC_CYPHER_DATA_OUT)+DIOCBufferIn->DataLength-sizeof(DIOCBufferOut->Data),
            irpSp->Parameters.DeviceIoControl.OutputBufferLength
            ));
        status = STATUS_INVALID_BUFFER_SIZE;
        return status;            
        }

    // Request valid, process...

    // Since the variable length members of the input buffer can't be accessed
    // directly (their locations vary, depending on the size of earlier members)
    // we calculate pointers so they can be accessed easily...
    ptrInKey  = (char*)&DIOCBufferIn->Key;
    ptrInIV   = ptrInKey + ((DIOCBufferIn->KeyLength / 8) * sizeof(DIOCBufferIn->Key));
    ptrInData = ptrInIV + ((DIOCBufferIn->IVLength / 8) * sizeof(DIOCBufferIn->IV));

    // NOTE: THIS IS ONLY DUMPED OUT IF DEBUG IS NOT ENABLED; ONLY ON
    //       DEBUG BUILDS.
    //       Normal release builds cause DEBUGOUTCYPHERDRV to be a NOP, so
    //       this debug code gets removed
    DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Key length: %d bits\n", DIOCBufferIn->KeyLength));
    for(i = 0; i < (DIOCBufferIn->KeyLength / 8); i++)
        { 
        DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Key [%.2d]: %.2x\n", i, ptrInKey[i]));
        }                                
    DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- IV length: %d bits\n", DIOCBufferIn->IVLength));
    for(i = 0; i < (DIOCBufferIn->IVLength / 8); i++)
        { 
        DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- IV [%.2d]: %.2x\n", i, ptrInIV[i]));
        }                                
    DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Data length: %d bytes\n", DIOCBufferIn->DataLength));
    for(i = 0; i < (DIOCBufferIn->DataLength / 8); i++)
        { 
        DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Data [%.2d]: %.2x\n", i, ptrInData[i]));
        // Only dump out the first 5 bytes...
        if (i >= 5) 
            {
            DEBUGOUTCYPHERDRV(DEBUGLEV_VERBOSE_INFO, ("----- Data [..]: (Debug output truncated to only show first few bytes)\n"));
            break;        
            }
        }                                


    // Sanity checks on the request wrt the cypher

    DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("About to get cypher details...\n"));
    status = GetCypherDetails(
                              &(DIOCBufferIn->CypherGUID),
                              &CypherDetails
                             );
    if (!(NT_SUCCESS(status)))
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Unable to locate requested cypher in driver\n"));
        return status;            
        }
    DEBUGOUTCYPHERDRV(DEBUGLEV_INFO, ("Cypher details got OK.\n"));

    // Input/output buffer must be a multiple of the blocksize
    // Output buffer length not explicitly checked, as we already made sure
    // that it's big enough to store the input data
    // Note: Multiply DataLength by 8 to get bits
    if ((CypherDetails.BlockSize > 0) && (((DIOCBufferIn->DataLength * 8) % CypherDetails.BlockSize) != 0))
        {
        DEBUGOUTCYPHERDRV(DEBUGLEV_ERROR, ("Length of data IN must be a multiple of the blocksize (bs: %d bits; bufSize: %d bits\n",

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?