|
|
/*
************************************************************************* * File: SECURITY.C * * Module: USBCCGP.SYS * USB Common Class Generic Parent driver. * * Copyright (c) 1998 Microsoft Corporation * * * Author: ervinp * ************************************************************************* */
#include <wdm.h>
#include <usbdi.h>
#include <usbdlib.h>
#include <usbioctl.h>
#include "usbccgp.h"
#include "security.h"
#include "debug.h"
NTSTATUS GetUniqueIdFromCSInterface(PPARENT_FDO_EXT parentFdoExt, PMEDIA_SERIAL_NUMBER_DATA serialNumData, ULONG serialNumLen) { PUCHAR uniqueIdBuf; NTSTATUS status; ULONG bufLen = 0;
// BUGBUG - check CSM#
/*
* Need to allocate a locked buffer for the call to USB. */ uniqueIdBuf = ALLOCPOOL(NonPagedPool, CSM1_GET_UNIQUE_ID_LENGTH); if (uniqueIdBuf){ URB urb = { 0 };
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); urb.UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE; urb.UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN; urb.UrbControlVendorClassRequest.TransferBufferLength = CSM1_GET_UNIQUE_ID_LENGTH; urb.UrbControlVendorClassRequest.TransferBuffer = uniqueIdBuf; urb.UrbControlVendorClassRequest.Request = CSM1_REQUEST_GET_UNIQUE_ID; urb.UrbControlVendorClassRequest.Value = 0; urb.UrbControlVendorClassRequest.Index = (USHORT)(parentFdoExt->CSInterfaceNumber | (parentFdoExt->CSChannelId << 8));
status = SubmitUrb(parentFdoExt, &urb, TRUE, NULL, NULL); if (NT_SUCCESS(status)){
bufLen = urb.UrbControlVendorClassRequest.TransferBufferLength; ASSERT(bufLen <= CSM1_GET_UNIQUE_ID_LENGTH); ASSERT(serialNumLen > 0); bufLen = MIN(bufLen, CSM1_GET_UNIQUE_ID_LENGTH); bufLen = MIN(bufLen, serialNumLen);
RtlCopyMemory(serialNumData->SerialNumberData, uniqueIdBuf, bufLen);
DBGDUMPBYTES("GetUniqueIdFromCSInterface - unique id:", serialNumData->SerialNumberData, bufLen); } else { DBGERR(("CSM1_REQUEST_GET_UNIQUE_ID failed with %xh.", status)); }
FREEPOOL(uniqueIdBuf); } else { DBGERR(("couldn't allocate unique id buf")); status = STATUS_INSUFFICIENT_RESOURCES; }
serialNumData->SerialNumberLength = bufLen; serialNumData->Result = status;
return status; }
NTSTATUS GetMediaSerialNumber(PPARENT_FDO_EXT parentFdoExt, PIRP irp) { PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp); PMEDIA_SERIAL_NUMBER_DATA serialNumData; NTSTATUS status; ULONG serialNumLen;
DBGVERBOSE(("*** IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER ***"));
/*
* IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER is a METHOD_BUFFERED irp. * So the kernel allocated a systemBuffer for us IF the app passed * in a non-zero buffer size. So we don't need to probe the buffer * itself, but we do need to: * 1. verify that the buffer was indeed allocated * 2. that it is large enough * * The buffer is a var-size struct; be careful to not dereference any * field until it is verified that the struct is longer than the offset * of that field. * Note that serialNumData->SerialNumberLength is the alleged size * of the serialNumData->SerialNumberData array, not of the entire structure. */ serialNumData = irp->AssociatedIrp.SystemBuffer; if (serialNumData && (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(MEDIA_SERIAL_NUMBER_DATA))) {
// Serial number buffer length is the size of the output buffer minus
// the size of the MEDIA_SERIAL_NUMBER_DATA structure.
serialNumLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength - sizeof(MEDIA_SERIAL_NUMBER_DATA);
status = GetUniqueIdFromCSInterface(parentFdoExt, serialNumData, serialNumLen); irp->IoStatus.Information = FIELD_OFFSET(MEDIA_SERIAL_NUMBER_DATA, SerialNumberData) + serialNumData->SerialNumberLength; } else { DBGERR(("Bad buffer with IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, irp=%ph.", irp)); status = STATUS_INVALID_BUFFER_SIZE; }
return status; }
/*
* GetChannelDescForInterface * * BUGBUG - INCOMPLETE * We don't support multiple channel descriptors yet. * Eventually we'll need to return a channel id * for a particular protected interface/endpoint. */ CS_CHANNEL_DESCRIPTOR *GetChannelDescForInterface(PPARENT_FDO_EXT parentFdoExt, ULONG interfaceNum) { PUSB_INTERFACE_DESCRIPTOR interfaceDesc; CS_CHANNEL_DESCRIPTOR *channelDesc = NULL; CS_METHOD_AND_VARIANT *methodAndVar;
interfaceDesc = USBD_ParseConfigurationDescriptorEx( parentFdoExt->configDesc, parentFdoExt->configDesc, -1, 0, // BUGBUG - allow alternate CS interfaces ?
USB_DEVICE_CLASS_CONTENT_SECURITY, -1, -1); if (interfaceDesc){ PUSB_COMMON_DESCRIPTOR commonDesc = (PUSB_COMMON_DESCRIPTOR)interfaceDesc;
while (POINTER_DISTANCE(commonDesc, parentFdoExt->configDesc) < parentFdoExt->configDesc->wTotalLength){ if (commonDesc->bDescriptorType == CS_DESCRIPTOR_TYPE_CHANNEL){ channelDesc = (CS_CHANNEL_DESCRIPTOR *)commonDesc; break; } (PUCHAR)commonDesc += commonDesc->bLength; } }
if (channelDesc){ /*
* Make sure that this channel descriptor supports CSM1, * which is all we support right now. * BUGBUG */ BOOLEAN foundSupportedCSM = FALSE;
for (methodAndVar = channelDesc->methodAndVariant; POINTER_DISTANCE(methodAndVar, channelDesc) < channelDesc->bLength; methodAndVar++){
if (methodAndVar->bMethod == CSM_BASIC){ foundSupportedCSM = TRUE; break; } }
if (!foundSupportedCSM){ DBGERR(("Did not find supported CSM !")); channelDesc = NULL; } }
ASSERT(channelDesc); return channelDesc; }
VOID InitCSInfo(PPARENT_FDO_EXT parentFdoExt, ULONG CSIfaceNumber) { CS_CHANNEL_DESCRIPTOR *channelDesc;
channelDesc = GetChannelDescForInterface(parentFdoExt, 0); // BUGBUG iface# not used because only support one channel desc
if (channelDesc){ parentFdoExt->CSChannelId = channelDesc->bChannelID; parentFdoExt->CSInterfaceNumber = CSIfaceNumber; parentFdoExt->haveCSInterface = TRUE; } else { ASSERT(channelDesc); }
}
|