Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.8 KiB

  1. /*
  2. *************************************************************************
  3. * File: SECURITY.C
  4. *
  5. * Module: USBCCGP.SYS
  6. * USB Common Class Generic Parent driver.
  7. *
  8. * Copyright (c) 1998 Microsoft Corporation
  9. *
  10. *
  11. * Author: ervinp
  12. *
  13. *************************************************************************
  14. */
  15. #include <wdm.h>
  16. #include <usbdi.h>
  17. #include <usbdlib.h>
  18. #include <usbioctl.h>
  19. #include "usbccgp.h"
  20. #include "security.h"
  21. #include "debug.h"
  22. NTSTATUS GetUniqueIdFromCSInterface(PPARENT_FDO_EXT parentFdoExt, PMEDIA_SERIAL_NUMBER_DATA serialNumData, ULONG serialNumLen)
  23. {
  24. PUCHAR uniqueIdBuf;
  25. NTSTATUS status;
  26. ULONG bufLen = 0;
  27. // BUGBUG - check CSM#
  28. /*
  29. * Need to allocate a locked buffer for the call to USB.
  30. */
  31. uniqueIdBuf = ALLOCPOOL(NonPagedPool, CSM1_GET_UNIQUE_ID_LENGTH);
  32. if (uniqueIdBuf){
  33. URB urb = { 0 };
  34. urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  35. urb.UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
  36. urb.UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN;
  37. urb.UrbControlVendorClassRequest.TransferBufferLength = CSM1_GET_UNIQUE_ID_LENGTH;
  38. urb.UrbControlVendorClassRequest.TransferBuffer = uniqueIdBuf;
  39. urb.UrbControlVendorClassRequest.Request = CSM1_REQUEST_GET_UNIQUE_ID;
  40. urb.UrbControlVendorClassRequest.Value = 0;
  41. urb.UrbControlVendorClassRequest.Index = (USHORT)(parentFdoExt->CSInterfaceNumber | (parentFdoExt->CSChannelId << 8));
  42. status = SubmitUrb(parentFdoExt, &urb, TRUE, NULL, NULL);
  43. if (NT_SUCCESS(status)){
  44. bufLen = urb.UrbControlVendorClassRequest.TransferBufferLength;
  45. ASSERT(bufLen <= CSM1_GET_UNIQUE_ID_LENGTH);
  46. ASSERT(serialNumLen > 0);
  47. bufLen = MIN(bufLen, CSM1_GET_UNIQUE_ID_LENGTH);
  48. bufLen = MIN(bufLen, serialNumLen);
  49. RtlCopyMemory(serialNumData->SerialNumberData, uniqueIdBuf, bufLen);
  50. DBGDUMPBYTES("GetUniqueIdFromCSInterface - unique id:", serialNumData->SerialNumberData, bufLen);
  51. }
  52. else {
  53. DBGERR(("CSM1_REQUEST_GET_UNIQUE_ID failed with %xh.", status));
  54. }
  55. FREEPOOL(uniqueIdBuf);
  56. }
  57. else {
  58. DBGERR(("couldn't allocate unique id buf"));
  59. status = STATUS_INSUFFICIENT_RESOURCES;
  60. }
  61. serialNumData->SerialNumberLength = bufLen;
  62. serialNumData->Result = status;
  63. return status;
  64. }
  65. NTSTATUS GetMediaSerialNumber(PPARENT_FDO_EXT parentFdoExt, PIRP irp)
  66. {
  67. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
  68. PMEDIA_SERIAL_NUMBER_DATA serialNumData;
  69. NTSTATUS status;
  70. ULONG serialNumLen;
  71. DBGVERBOSE(("*** IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER ***"));
  72. /*
  73. * IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER is a METHOD_BUFFERED irp.
  74. * So the kernel allocated a systemBuffer for us IF the app passed
  75. * in a non-zero buffer size. So we don't need to probe the buffer
  76. * itself, but we do need to:
  77. * 1. verify that the buffer was indeed allocated
  78. * 2. that it is large enough
  79. *
  80. * The buffer is a var-size struct; be careful to not dereference any
  81. * field until it is verified that the struct is longer than the offset
  82. * of that field.
  83. * Note that serialNumData->SerialNumberLength is the alleged size
  84. * of the serialNumData->SerialNumberData array, not of the entire structure.
  85. */
  86. serialNumData = irp->AssociatedIrp.SystemBuffer;
  87. if (serialNumData &&
  88. (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(MEDIA_SERIAL_NUMBER_DATA))) {
  89. // Serial number buffer length is the size of the output buffer minus
  90. // the size of the MEDIA_SERIAL_NUMBER_DATA structure.
  91. serialNumLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength -
  92. sizeof(MEDIA_SERIAL_NUMBER_DATA);
  93. status = GetUniqueIdFromCSInterface(parentFdoExt, serialNumData, serialNumLen);
  94. irp->IoStatus.Information = FIELD_OFFSET(MEDIA_SERIAL_NUMBER_DATA, SerialNumberData) +
  95. serialNumData->SerialNumberLength;
  96. }
  97. else {
  98. DBGERR(("Bad buffer with IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, irp=%ph.", irp));
  99. status = STATUS_INVALID_BUFFER_SIZE;
  100. }
  101. return status;
  102. }
  103. /*
  104. * GetChannelDescForInterface
  105. *
  106. * BUGBUG - INCOMPLETE
  107. * We don't support multiple channel descriptors yet.
  108. * Eventually we'll need to return a channel id
  109. * for a particular protected interface/endpoint.
  110. */
  111. CS_CHANNEL_DESCRIPTOR *GetChannelDescForInterface(PPARENT_FDO_EXT parentFdoExt, ULONG interfaceNum)
  112. {
  113. PUSB_INTERFACE_DESCRIPTOR interfaceDesc;
  114. CS_CHANNEL_DESCRIPTOR *channelDesc = NULL;
  115. CS_METHOD_AND_VARIANT *methodAndVar;
  116. interfaceDesc = USBD_ParseConfigurationDescriptorEx(
  117. parentFdoExt->configDesc,
  118. parentFdoExt->configDesc,
  119. -1,
  120. 0, // BUGBUG - allow alternate CS interfaces ?
  121. USB_DEVICE_CLASS_CONTENT_SECURITY,
  122. -1,
  123. -1);
  124. if (interfaceDesc){
  125. PUSB_COMMON_DESCRIPTOR commonDesc = (PUSB_COMMON_DESCRIPTOR)interfaceDesc;
  126. while (POINTER_DISTANCE(commonDesc, parentFdoExt->configDesc) < parentFdoExt->configDesc->wTotalLength){
  127. if (commonDesc->bDescriptorType == CS_DESCRIPTOR_TYPE_CHANNEL){
  128. channelDesc = (CS_CHANNEL_DESCRIPTOR *)commonDesc;
  129. break;
  130. }
  131. (PUCHAR)commonDesc += commonDesc->bLength;
  132. }
  133. }
  134. if (channelDesc){
  135. /*
  136. * Make sure that this channel descriptor supports CSM1,
  137. * which is all we support right now.
  138. * BUGBUG
  139. */
  140. BOOLEAN foundSupportedCSM = FALSE;
  141. for (methodAndVar = channelDesc->methodAndVariant;
  142. POINTER_DISTANCE(methodAndVar, channelDesc) < channelDesc->bLength;
  143. methodAndVar++){
  144. if (methodAndVar->bMethod == CSM_BASIC){
  145. foundSupportedCSM = TRUE;
  146. break;
  147. }
  148. }
  149. if (!foundSupportedCSM){
  150. DBGERR(("Did not find supported CSM !"));
  151. channelDesc = NULL;
  152. }
  153. }
  154. ASSERT(channelDesc);
  155. return channelDesc;
  156. }
  157. VOID InitCSInfo(PPARENT_FDO_EXT parentFdoExt, ULONG CSIfaceNumber)
  158. {
  159. CS_CHANNEL_DESCRIPTOR *channelDesc;
  160. channelDesc = GetChannelDescForInterface(parentFdoExt, 0); // BUGBUG iface# not used because only support one channel desc
  161. if (channelDesc){
  162. parentFdoExt->CSChannelId = channelDesc->bChannelID;
  163. parentFdoExt->CSInterfaceNumber = CSIfaceNumber;
  164. parentFdoExt->haveCSInterface = TRUE;
  165. }
  166. else {
  167. ASSERT(channelDesc);
  168. }
  169. }