ReactOS  0.4.15-dev-3745-g356babc
aacs.c
Go to the documentation of this file.
1 /*--
2 
3 Copyright (C) Microsoft Corporation. All rights reserved.
4 
5 Module Name:
6 
7  aacs.c
8 
9 Abstract:
10 
11  The CDROM class driver implementation of handling AACS IOCTLs.
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 
20 Revision History:
21 
22 --*/
23 
24 #include "stddef.h"
25 #include "string.h"
26 
27 #include "ntddk.h"
28 #include "ntddstor.h"
29 #include "cdrom.h"
30 #include "ioctl.h"
31 #include "scratch.h"
32 
33 #ifdef DEBUG_USE_WPP
34 #include "aacs.tmh"
35 #endif
36 
37 #ifdef ALLOC_PRAGMA
38 
39 #pragma alloc_text(PAGE, DeviceHandleAacsReadMediaKeyBlock)
40 #pragma alloc_text(PAGE, DeviceHandleAacsStartSession)
41 #pragma alloc_text(PAGE, DeviceHandleAacsEndSession)
42 #pragma alloc_text(PAGE, DeviceHandleAacsSendCertificate)
43 #pragma alloc_text(PAGE, DeviceHandleAacsGetCertificate)
44 #pragma alloc_text(PAGE, DeviceHandleAacsGetChallengeKey)
45 #pragma alloc_text(PAGE, DeviceHandleAacsReadSerialNumber)
46 #pragma alloc_text(PAGE, DeviceHandleAacsReadMediaId)
47 #pragma alloc_text(PAGE, DeviceHandleAacsReadBindingNonce)
48 #pragma alloc_text(PAGE, DeviceHandleAacsGenerateBindingNonce)
49 #pragma alloc_text(PAGE, DeviceHandleReadVolumeId)
50 #pragma alloc_text(PAGE, DeviceHandleSendChallengeKey)
51 
52 #endif
53 
56 DeviceHandleAacsReadMediaKeyBlock(
57  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
58  _In_ WDFREQUEST Request,
60  _Out_ size_t * DataLength
61  )
62 /*++
63 
64 Routine Description:
65  This routine is used to process IOCTLs:
66  IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
67  IOCTL_AACS_READ_MEDIA_KEY_BLOCK
68 Arguments:
69  DeviceExtension - device context
70 
71  Request - the request that will be formatted
72 
73  RequestParameters - request parameter structur
74 
75  DataLength - data transferred length
76 
77 Return Value:
78  NTSTATUS
79 
80  --*/
81 {
83  PAACS_LAYER_NUMBER layerNumber = NULL;
84  PVOID outputBuffer = NULL;
85  ULONG transferSize = sizeof(READ_DVD_STRUCTURES_HEADER);
86 
87  PAGED_CODE();
88 
89  *DataLength = 0;
90 
91  status = WdfRequestRetrieveInputBuffer(Request,
93  (PVOID*)&layerNumber,
94  NULL);
95 
96  if (NT_SUCCESS(status))
97  {
98  status = WdfRequestRetrieveOutputBuffer(Request,
99  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
100  (PVOID*)&outputBuffer,
101  NULL);
102  }
103 
104  if (NT_SUCCESS(status))
105  {
107  {
108  // maximum size for this transfer is one pack + header
109  transferSize += AACS_MKB_PACK_SIZE;
110  }
111 
112  if (transferSize > DeviceExtension->ScratchContext.ScratchBufferSize)
113  {
114  // rare case. normally the size of scratch buffer is 64k.
116  }
117  }
118 
119  if (NT_SUCCESS(status))
120  {
121  UCHAR rmdBlockNumber = 0;
122  BOOLEAN sendChangedCommand = TRUE;
123  BOOLEAN shouldRetry = TRUE;
124  CDB cdb;
125 
126  ScratchBuffer_BeginUse(DeviceExtension);
127 
128  RtlZeroMemory(&cdb, sizeof(CDB));
129  // Set up the CDB
130  cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE;
131  // cdb->AsByte[1] = 0x01; // AACS sub-command not required for this
132 
133  cdb.READ_DVD_STRUCTURE.LayerNumber = (UCHAR)(*layerNumber);
134  cdb.READ_DVD_STRUCTURE.Format = 0x83; // MKB
135  cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(transferSize >> (8*1));
136  cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(transferSize >> (8*0));
137 
138  while (sendChangedCommand)
139  {
140  // RMDBlockNumber is set to zero....
141  // RMDBlockNumber[3] maybe changed for other blocks.
142  cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3] = rmdBlockNumber;
143 
144  if (shouldRetry)
145  {
146  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, TRUE, &cdb, 12);
147  }
148 
149  #ifdef ENABLE_AACS_TESTING
151  {
152  static const UCHAR results[] = { 0x80, 0x02, 0x00, 0x02 };
153  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
155  }
157  {
158  static const UCHAR results[] = { 0x80, 0x02, 0x00, 0x02 };
159  static const UCHAR defaultFill = 0x30; // '0'
160  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x8004, defaultFill);
161  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
163  }
164  #endif //ENABLE_AACS_TESTING
165 
166  if (NT_SUCCESS(status))
167  {
168  // command succeeded, process data...
169  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
170  UCHAR thisPackNumber = cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3];
171  UCHAR otherPacks = header->Reserved[1];
172 
173  // validate and zero-base the otherPacks
174  if (otherPacks == 0)
175  {
176  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
177  "AACS: Device is reporting zero total packs (invalid)\n"));
178  *DataLength = 0;
180  }
181  else
182  {
183  otherPacks--;
184 
186  {
187  // if not already requested last pack, do so now
188  if (otherPacks != thisPackNumber)
189  {
190  // re-send the command for the other pack number.
191  // this is safe here because NT_SUCCESS() is TRUE,
192  // and all the rest of this routine does is SetHardError()
193  // and release of resources we're still about to use.
194 
195  // re-zero the output buffer
196  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchBuffer, sizeof(READ_DVD_STRUCTURES_HEADER));
197 
198  // modify the CDB to get the very last pack of the MKB
199  rmdBlockNumber = otherPacks;
200 
201  transferSize = sizeof(READ_DVD_STRUCTURES_HEADER);
202 
203  // keep items clean
204  ScratchBuffer_ResetItems(DeviceExtension, TRUE);
205 
206  // make sure the loop will be executed for modified command.
207  sendChangedCommand = TRUE;
208  shouldRetry = TRUE;
209  }
210  else
211  {
212  // this request already got the last pack
213  // so just interpret the data
214  REVERSE_SHORT(&header->Length);
216  {
217  *DataLength = 0;
219  }
220  else
221  {
222  ULONG totalSize = header->Length;
223  // subtract out any remaining bytes in the header
224  // to get the number of usable bytes in this pack
226  totalSize += otherPacks * AACS_MKB_PACK_SIZE;
227 
228  // save the result and complete the request
229  *((PULONG)outputBuffer) = totalSize;
230  *DataLength = sizeof(ULONG);
232  }
233  // This will exit the loop of sendChangedCommand
234  sendChangedCommand = FALSE;
235  shouldRetry = FALSE;
236  }
237  }
239  {
240  // make length field native byte ordering
241  REVERSE_SHORT(&header->Length);
242 
243  // exit if getting invalid data from the drive
245  {
246  *DataLength = 0;
248  }
249  else
250  {
251  // success, how many bytes to copy for this pack?
252  ULONG totalSize = header->Length;
253  size_t originalBufferSize;
254 
255  // subtract out any remaining bytes in the header
256  // to get the number of usable bytes in this pack
258 
259  // if not the final pack, this should be a full transfer per spec
260  NT_ASSERT( (totalSize == AACS_MKB_PACK_SIZE) || (thisPackNumber == otherPacks) );
261 
262  // validate the user's buffer is large enough to accept the full data
263  originalBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
264 
265  if (originalBufferSize < (totalSize + (AACS_MKB_PACK_SIZE*thisPackNumber)))
266  {
267  // just return a slightly bigger-than-normal size
268  *DataLength = (otherPacks + 1)*AACS_MKB_PACK_SIZE;
270  }
271  else
272  {
273  PUCHAR whereToCopy;
274  // determine where to copy to the user's memory
275  whereToCopy = outputBuffer;
276  whereToCopy += AACS_MKB_PACK_SIZE * thisPackNumber;
277 
278  RtlCopyMemory(whereToCopy, header->Data, totalSize);
279 
280  // update the Information field here because we already
281  // have calculated the size of the block
282  *DataLength = totalSize + (AACS_MKB_PACK_SIZE * thisPackNumber);
284 
285  // if there are more packs to get from the device, send it again....
286  if (thisPackNumber != otherPacks)
287  {
288  // re-send the command for the next pack number.
289  // this is safe here because NT_SUCCESS() is TRUE,
290  // and all the rest of this routine does is SetHardError()
291  // and release of resources we're still about to use.
292 
293  // re-zero the output buffer
294  RtlZeroMemory(DeviceExtension->ScratchContext.ScratchBuffer, sizeof(READ_DVD_STRUCTURES_HEADER));
295 
296  // modify the CDB to get the next pack of the MKB
297  rmdBlockNumber = cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3]++;
298 
299  // modify the SRB to be resent
300  //
301  transferSize = AACS_MKB_PACK_SIZE + sizeof(READ_DVD_STRUCTURES_HEADER);
302 
303  // keep items clean
304  ScratchBuffer_ResetItems(DeviceExtension, FALSE);
305 
306  // make sure the loop will be executed for modified command.
307  sendChangedCommand = TRUE;
308  shouldRetry = TRUE;
309  }
310  else
311  {
312  // else, that was the end of the transfer, so just complete the request
313  sendChangedCommand = FALSE;
314  }
315  }
316  }
317 
318  } // end of IOCTL_AACS_READ_MEDIA_KEY_BLOCK
319  }
320  } // end of NT_SUCCESS(status)
321 
322  if (!NT_SUCCESS(status))
323  {
324  // command failed.
325  sendChangedCommand = FALSE;
326  }
327  } //end of while (sendChangedCommand)
328 
329  ScratchBuffer_EndUse(DeviceExtension);
330  }
331 
332  return status;
333 }
334 
336 NTSTATUS
337 DeviceHandleAacsStartSession(
338  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
339  _In_ WDFREQUEST Request,
341  _Out_ size_t * DataLength
342  )
343 /*++
344 
345 Routine Description:
346  This routine is used to process IOCTL:
347  IOCTL_AACS_START_SESSION
348 Arguments:
349  DeviceExtension - device context
350 
351  Request - the request that will be formatted
352 
353  RequestParameters - request parameter structur
354 
355  DataLength - data transferred length
356 
357 Return Value:
358  NTSTATUS
359 
360  --*/
361 {
362  //AacsGetAgid
363 
365  PDVD_SESSION_ID sessionId = NULL;
366 
367  PAGED_CODE();
368 
369  *DataLength = 0;
370 
371  status = WdfRequestRetrieveOutputBuffer(Request,
372  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
373  (PVOID*)&sessionId,
374  NULL);
375 
376  if (NT_SUCCESS(status))
377  {
378  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(CDVD_REPORT_AGID_DATA);
379  CDB cdb;
380 
381  ScratchBuffer_BeginUse(DeviceExtension);
382 
383  RtlZeroMemory(&cdb, sizeof(CDB));
384  // Set up the CDB
385  cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY;
386  cdb.AsByte[7] = 0x02; // AACS key class
387  cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
388  cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
389  cdb.REPORT_KEY.KeyFormat = 0x00; // DVD_REPORT_AGID?
390 
391  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
392 
393 #ifdef ENABLE_AACS_TESTING
394  static const UCHAR results[] = { 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0 };
395  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
397 #endif
398  if (NT_SUCCESS(status))
399  {
400  PCDVD_KEY_HEADER keyHeader = DeviceExtension->ScratchContext.ScratchBuffer;
401  PCDVD_REPORT_AGID_DATA keyData = (PCDVD_REPORT_AGID_DATA)keyHeader->Data;
402 
403  *sessionId = (DVD_SESSION_ID)(keyData->AGID);
404  *DataLength = sizeof(DVD_SESSION_ID);
405  }
406 
407  ScratchBuffer_EndUse(DeviceExtension);
408  }
409 
410  return status;
411 }
412 
414 NTSTATUS
415 DeviceHandleAacsEndSession(
416  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
417  _In_ WDFREQUEST Request,
419  _Out_ size_t * DataLength
420  )
421 /*++
422 
423 Routine Description:
424  This routine is used to process IOCTL:
425  IOCTL_AACS_END_SESSION
426 Arguments:
427  DeviceExtension - device context
428 
429  Request - the request that will be formatted
430 
431  RequestParameters - request parameter structur
432 
433  DataLength - data transferred length
434 
435 Return Value:
436  NTSTATUS
437 
438  --*/
439 {
440  //AacsReleaseAgid
441 
443  PDVD_SESSION_ID sessionId = NULL;
444 
445  PAGED_CODE();
446 
447  *DataLength = 0;
448 
449  status = WdfRequestRetrieveInputBuffer(Request,
450  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
451  (PVOID*)&sessionId,
452  NULL);
453 
454  if (NT_SUCCESS(status))
455  {
456  ULONG transferSize = 0;
457  CDB cdb;
458  DVD_SESSION_ID currentSession = 0;
459  DVD_SESSION_ID limitSession = 0;
460 
461  if(*sessionId == DVD_END_ALL_SESSIONS)
462  {
463  currentSession = 0;
464  limitSession = MAX_COPY_PROTECT_AGID - 1;
465  }
466  else
467  {
468  currentSession = *sessionId;
469  limitSession = *sessionId;
470  }
471 
472  ScratchBuffer_BeginUse(DeviceExtension);
473 
474  do
475  {
476  RtlZeroMemory(&cdb, sizeof(CDB));
477  // Set up the CDB
478  cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY;
479  cdb.AsByte[7] = 0x02; // AACS key class
480  cdb.SEND_KEY.AGID = (UCHAR)(currentSession);
481  cdb.SEND_KEY.KeyFormat = DVD_INVALIDATE_AGID;
482 
483  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12);
484 
485  currentSession++;
486  } while ((currentSession <= limitSession) && NT_SUCCESS(status));
487 
488 #ifdef ENABLE_AACS_TESTING
490 #endif
491 
492  ScratchBuffer_EndUse(DeviceExtension);
493  }
494 
495  return status;
496 }
497 
499 NTSTATUS
500 DeviceHandleAacsSendCertificate(
501  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
502  _In_ WDFREQUEST Request,
504  _Out_ size_t * DataLength
505  )
506 /*++
507 
508 Routine Description:
509  This routine is used to process IOCTL:
510  IOCTL_AACS_SEND_CERTIFICATE
511 Arguments:
512  DeviceExtension - device context
513 
514  Request - the request that will be formatted
515 
516  RequestParameters - request parameter structur
517 
518  DataLength - data transferred length
519 
520 Return Value:
521  NTSTATUS
522 
523  --*/
524 {
525  //AacsSendHostCertificate
526 
529 
530  PAGED_CODE();
531 
532  *DataLength = 0;
533 
534  status = WdfRequestRetrieveInputBuffer(Request,
535  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
536  (PVOID*)&input,
537  NULL);
538 
539  if (NT_SUCCESS(status))
540  {
541  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CERTIFICATE);
542  CDB cdb;
543 
544  ScratchBuffer_BeginUse(DeviceExtension);
545 
546  // copy the input buffer to the data buffer for the transfer
547  {
548  PCDVD_KEY_HEADER header = (PCDVD_KEY_HEADER)DeviceExtension->ScratchContext.ScratchBuffer;
549  ULONG tmp = dataTransferLength;
550 
552 
553  header->DataLength[0] = (UCHAR)(tmp >> (8*1));
554  header->DataLength[1] = (UCHAR)(tmp >> (8*0));
555  RtlCopyMemory(header->Data, &(input->Certificate), sizeof(AACS_CERTIFICATE));
556  }
557 
558  RtlZeroMemory(&cdb, sizeof(CDB));
559  // Set up the CDB
560  cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY;
561  cdb.AsByte[7] = 0x02; // AACS key class
562  cdb.SEND_KEY.ParameterListLength[0] = (UCHAR)(dataTransferLength >> (8*1));
563  cdb.SEND_KEY.ParameterListLength[1] = (UCHAR)(dataTransferLength >> (8*0));
564  cdb.SEND_KEY.AGID = (UCHAR)( input->SessionId );
565  cdb.SEND_KEY.KeyFormat = 0x01; // Send Host Challenge Certificate
566 
567  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, FALSE, &cdb, 12);
568 
569 #ifdef ENABLE_AACS_TESTING
571 #endif
572  if (NT_SUCCESS(status))
573  {
574  *DataLength = 0;
575  }
576 
577  ScratchBuffer_EndUse(DeviceExtension);
578  }
579 
580  return status;
581 }
582 
584 NTSTATUS
585 DeviceHandleAacsGetCertificate(
586  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
587  _In_ WDFREQUEST Request,
589  _Out_ size_t * DataLength
590  )
591 /*++
592 
593 Routine Description:
594  This routine is used to process IOCTL:
595  IOCTL_AACS_GET_CERTIFICATE
596 Arguments:
597  DeviceExtension - device context
598 
599  Request - the request that will be formatted
600 
601  RequestParameters - request parameter structur
602 
603  DataLength - data transferred length
604 
605 Return Value:
606  NTSTATUS
607 
608  --*/
609 {
610  //AacsGetDriveCertificate
611 
614  PVOID outputBuffer = NULL;
615 
616  PAGED_CODE();
617 
618  *DataLength = 0;
619 
620  status = WdfRequestRetrieveInputBuffer(Request,
621  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
622  (PVOID*)&input,
623  NULL);
624 
625  if (NT_SUCCESS(status))
626  {
627  status = WdfRequestRetrieveOutputBuffer(Request,
628  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
629  (PVOID*)&outputBuffer,
630  NULL);
631  }
632 
633  if (NT_SUCCESS(status))
634  {
635  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CERTIFICATE);
636  CDB cdb;
637 
638  ScratchBuffer_BeginUse(DeviceExtension);
639 
640  RtlZeroMemory(&cdb, sizeof(CDB));
641  // Set up the CDB
642  cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY;
643  cdb.AsByte[7] = 0x02; // AACS key class
644  cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
645  cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
646  cdb.REPORT_KEY.AGID = (UCHAR)(*input);
647  cdb.REPORT_KEY.KeyFormat = 0x01; // Return a drive certificate challenge
648 
649  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
650 
651 #ifdef ENABLE_AACS_TESTING
652  static const UCHAR results[] = { 0x00, 0x72, 0x00, 0x00 };
653  static const UCHAR defaultFill = 0x31; // '1'
654  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0074, defaultFill);
655  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
657 #endif
658  if (NT_SUCCESS(status))
659  {
660  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
661  ULONG dataLengthToCopy = sizeof(AACS_CERTIFICATE);
662 
663  // make length field native byte ordering
664  REVERSE_SHORT(&header->Length);
665 
666  // exit if getting invalid data from the drive
668  {
669  *DataLength = 0;
671  }
672 
673  if (NT_SUCCESS(status))
674  {
675  // adjust data length to reflect only the addition data
677 
678  // exit if the drive is returning an unexpected data size
679  if (header->Length != dataLengthToCopy)
680  {
681  *DataLength = 0;
683  }
684  }
685 
686  if (NT_SUCCESS(status))
687  {
688  // else copy the data to the user's buffer
689  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
690  *DataLength = dataLengthToCopy;
691  }
692  }
693 
694  ScratchBuffer_EndUse(DeviceExtension);
695  }
696 
697  return status;
698 }
699 
701 NTSTATUS
702 DeviceHandleAacsGetChallengeKey(
703  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
704  _In_ WDFREQUEST Request,
706  _Out_ size_t * DataLength
707  )
708 /*++
709 
710 Routine Description:
711  This routine is used to process IOCTL:
712  IOCTL_AACS_GET_CHALLENGE_KEY
713 Arguments:
714  DeviceExtension - device context
715 
716  Request - the request that will be formatted
717 
718  RequestParameters - request parameter structur
719 
720  DataLength - data transferred length
721 
722 Return Value:
723  NTSTATUS
724 
725  --*/
726 {
727  //AacsGetChallengeKey
728 
731  PVOID outputBuffer = NULL;
732 
733  PAGED_CODE();
734 
735  *DataLength = 0;
736 
737  status = WdfRequestRetrieveInputBuffer(Request,
738  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
739  (PVOID*)&input,
740  NULL);
741 
742  if (NT_SUCCESS(status))
743  {
744  status = WdfRequestRetrieveOutputBuffer(Request,
745  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
746  (PVOID*)&outputBuffer,
747  NULL);
748  }
749 
750  if (NT_SUCCESS(status))
751  {
752  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CHALLENGE_KEY);
753  CDB cdb;
754 
755  ScratchBuffer_BeginUse(DeviceExtension);
756 
757  RtlZeroMemory(&cdb, sizeof(CDB));
758  // Set up the CDB
759  cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY;
760  cdb.AsByte[7] = 0x02; // AACS key class
761  cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
762  cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
763  cdb.REPORT_KEY.AGID = (UCHAR)(*input);
764  cdb.REPORT_KEY.KeyFormat = 0x02; // Return a drive certificate challenge
765 
766  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
767 
768 #ifdef ENABLE_AACS_TESTING
769  static const UCHAR results[] = { 0x00, 0x52, 0x00, 0x00 };
770  static const UCHAR defaultFill = 0x32; // '2'
771  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0054, defaultFill);
772  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
774 #endif
775  if (NT_SUCCESS(status))
776  {
777  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
778  ULONG dataLengthToCopy = sizeof(AACS_CHALLENGE_KEY);
779 
780  // make length field native byte ordering
781  REVERSE_SHORT(&header->Length);
782 
783  // exit if getting invalid data from the drive
785  {
786  *DataLength = 0;
788  }
789 
790  if (NT_SUCCESS(status))
791  {
792  // adjust data length to reflect only the addition data
794 
795  // exit if the drive is returning an unexpected data size
796  if (header->Length != dataLengthToCopy)
797  {
798  *DataLength = 0;
800  }
801  }
802 
803  if (NT_SUCCESS(status))
804  {
805  // else copy the data to the user's buffer
806  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
807  *DataLength = dataLengthToCopy;
808  }
809  }
810 
811  ScratchBuffer_EndUse(DeviceExtension);
812  }
813 
814  return status;
815 }
816 
818 NTSTATUS
819 DeviceHandleSendChallengeKey(
820  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
821  _In_ WDFREQUEST Request,
823  _Out_ size_t * DataLength
824  )
825 /*++
826 
827 Routine Description:
828  This routine is used to process IOCTL:
829  IOCTL_AACS_SEND_CHALLENGE_KEY
830 Arguments:
831  DeviceExtension - device context
832 
833  Request - the request that will be formatted
834 
835  RequestParameters - request parameter structur
836 
837  DataLength - data transferred length
838 
839 Return Value:
840  NTSTATUS
841 
842  --*/
843 {
844  //AacsSendChallengeKey
845 
848 
849  PAGED_CODE();
850 
851  *DataLength = 0;
852 
853  status = WdfRequestRetrieveInputBuffer(Request,
854  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
855  (PVOID*)&input,
856  NULL);
857 
858  if (NT_SUCCESS(status))
859  {
860  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CHALLENGE_KEY);
861  CDB cdb;
862 
863  ScratchBuffer_BeginUse(DeviceExtension);
864 
865  // copy the input buffer to the data buffer for the transfer
866  {
867  PCDVD_KEY_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
868  ULONG tmp = dataTransferLength;
870 
871  header->DataLength[0] = (UCHAR)(tmp >> (8*1));
872  header->DataLength[1] = (UCHAR)(tmp >> (8*0));
873  RtlCopyMemory(header->Data, &(input->ChallengeKey), sizeof(AACS_CHALLENGE_KEY));
874  }
875 
876  RtlZeroMemory(&cdb, sizeof(CDB));
877  // Set up the CDB
878  cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY;
879  cdb.AsByte[7] = 0x02; // AACS key class
880  cdb.SEND_KEY.ParameterListLength[0] = (UCHAR)(dataTransferLength >> (8*1));
881  cdb.SEND_KEY.ParameterListLength[1] = (UCHAR)(dataTransferLength >> (8*0));
882  cdb.SEND_KEY.AGID = (UCHAR)( input->SessionId );
883  cdb.SEND_KEY.KeyFormat = 0x02; // Send Host Challenge Certificate
884 
885  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, FALSE, &cdb, 12);
886 
887 #ifdef ENABLE_AACS_TESTING
889 #endif
890  if (NT_SUCCESS(status))
891  {
892  *DataLength = 0;
893  }
894 
895  ScratchBuffer_EndUse(DeviceExtension);
896  }
897 
898  return status;
899 }
900 
902 NTSTATUS
903 DeviceHandleReadVolumeId(
904  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
905  _In_ WDFREQUEST Request,
907  _Out_ size_t * DataLength
908  )
909 /*++
910 
911 Routine Description:
912  This routine is used to process IOCTL:
913  IOCTL_AACS_READ_VOLUME_ID
914 Arguments:
915  DeviceExtension - device context
916 
917  Request - the request that will be formatted
918 
919  RequestParameters - request parameter structur
920 
921  DataLength - data transferred length
922 
923 Return Value:
924  NTSTATUS
925 
926  --*/
927 {
928  //AacsReadVolumeID
929 
932  PVOID outputBuffer = NULL;
933 
934  PAGED_CODE();
935 
936  *DataLength = 0;
937 
938  status = WdfRequestRetrieveInputBuffer(Request,
939  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
940  (PVOID*)&input,
941  NULL);
942 
943  if (NT_SUCCESS(status))
944  {
945  status = WdfRequestRetrieveOutputBuffer(Request,
946  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
947  (PVOID*)&outputBuffer,
948  NULL);
949  }
950 
951  if (NT_SUCCESS(status))
952  {
953  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_VOLUME_ID);
954  CDB cdb;
955 
956  ScratchBuffer_BeginUse(DeviceExtension);
957 
958  RtlZeroMemory(&cdb, sizeof(CDB));
959  // Set up the CDB
960  cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE;
961  cdb.READ_DVD_STRUCTURE.Format = 0x80; // Return the AACS volumeID
962  cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
963  cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
964  cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)(*input);
965 
966  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
967 
968 #ifdef ENABLE_AACS_TESTING
969  static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 };
970  static const UCHAR defaultFill = 0x33; // '3'
971  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill);
972  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
974 #endif
975  if (NT_SUCCESS(status))
976  {
977  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
978  ULONG dataLengthToCopy = sizeof(AACS_VOLUME_ID);
979 
980  // make length field native byte ordering
981  REVERSE_SHORT(&header->Length);
982 
983  // exit if getting invalid data from the drive
985  {
986  *DataLength = 0;
988  }
989 
990  if (NT_SUCCESS(status))
991  {
992  // adjust data length to reflect only the addition data
994 
995  // exit if the drive is returning an unexpected data size
996  if (header->Length != dataLengthToCopy)
997  {
998  *DataLength = 0;
1000  }
1001  }
1002 
1003  if (NT_SUCCESS(status))
1004  {
1005  // else copy the data to the user's buffer
1006  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
1007  *DataLength = dataLengthToCopy;
1008  }
1009  }
1010 
1011  ScratchBuffer_EndUse(DeviceExtension);
1012  }
1013 
1014  return status;
1015 }
1016 
1018 NTSTATUS
1019 DeviceHandleAacsReadSerialNumber(
1020  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1021  _In_ WDFREQUEST Request,
1023  _Out_ size_t * DataLength
1024  )
1025 /*++
1026 
1027 Routine Description:
1028  This routine is used to process IOCTL:
1029  IOCTL_AACS_READ_SERIAL_NUMBER
1030 Arguments:
1031  DeviceExtension - device context
1032 
1033  Request - the request that will be formatted
1034 
1035  RequestParameters - request parameter structur
1036 
1037  DataLength - data transferred length
1038 
1039 Return Value:
1040  NTSTATUS
1041 
1042  --*/
1043 {
1044  //AacsReadSerialNumber
1045 
1048  PVOID outputBuffer = NULL;
1049 
1050  PAGED_CODE();
1051 
1052  *DataLength = 0;
1053 
1054  status = WdfRequestRetrieveInputBuffer(Request,
1055  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
1056  (PVOID*)&input,
1057  NULL);
1058 
1059  if (NT_SUCCESS(status))
1060  {
1061  status = WdfRequestRetrieveOutputBuffer(Request,
1062  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
1063  (PVOID*)&outputBuffer,
1064  NULL);
1065  }
1066 
1067  if (NT_SUCCESS(status))
1068  {
1069  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_SERIAL_NUMBER);
1070  CDB cdb;
1071 
1072  ScratchBuffer_BeginUse(DeviceExtension);
1073 
1074  RtlZeroMemory(&cdb, sizeof(CDB));
1075  // Set up the CDB
1076  cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE;
1077  cdb.READ_DVD_STRUCTURE.Format = 0x81; // Return the AACS volumeID
1078  cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
1079  cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
1080  cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)(*input);
1081 
1082  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
1083 
1084 #ifdef ENABLE_AACS_TESTING
1085  static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 };
1086  static const UCHAR defaultFill = 0x34; // '4'
1087  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill);
1088  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
1090 #endif
1091  if (NT_SUCCESS(status))
1092  {
1093  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
1094  ULONG dataLengthToCopy = sizeof(AACS_SERIAL_NUMBER);
1095 
1096  // make length field native byte ordering
1097  REVERSE_SHORT(&header->Length);
1098 
1099  // exit if getting invalid data from the drive
1101  {
1102  *DataLength = 0;
1104  }
1105 
1106  if (NT_SUCCESS(status))
1107  {
1108  // adjust data length to reflect only the addition data
1110 
1111  // exit if the drive is returning an unexpected data size
1112  if (header->Length != dataLengthToCopy)
1113  {
1114  *DataLength = 0;
1116  }
1117  }
1118 
1119  if (NT_SUCCESS(status))
1120  {
1121  // else copy the data to the user's buffer
1122  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
1123  *DataLength = dataLengthToCopy;
1124  }
1125  }
1126 
1127  ScratchBuffer_EndUse(DeviceExtension);
1128  }
1129 
1130  return status;
1131 }
1132 
1134 NTSTATUS
1135 DeviceHandleAacsReadMediaId(
1136  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1137  _In_ WDFREQUEST Request,
1139  _Out_ size_t * DataLength
1140  )
1141 /*++
1142 
1143 Routine Description:
1144  This routine is used to process IOCTL:
1145  IOCTL_AACS_READ_MEDIA_ID
1146 Arguments:
1147  DeviceExtension - device context
1148 
1149  Request - the request that will be formatted
1150 
1151  RequestParameters - request parameter structur
1152 
1153  DataLength - data transferred length
1154 
1155 Return Value:
1156  NTSTATUS
1157 
1158  --*/
1159 {
1160  //AacsReadMediaID
1161 
1164  PVOID outputBuffer = NULL;
1165 
1166  PAGED_CODE();
1167 
1168  *DataLength = 0;
1169 
1170  status = WdfRequestRetrieveInputBuffer(Request,
1171  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
1172  (PVOID*)&input,
1173  NULL);
1174 
1175  if (NT_SUCCESS(status))
1176  {
1177  status = WdfRequestRetrieveOutputBuffer(Request,
1178  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
1179  (PVOID*)&outputBuffer,
1180  NULL);
1181  }
1182 
1183  if (NT_SUCCESS(status))
1184  {
1185  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_MEDIA_ID);
1186  CDB cdb;
1187 
1188  ScratchBuffer_BeginUse(DeviceExtension);
1189 
1190  RtlZeroMemory(&cdb, sizeof(CDB));
1191  // Set up the CDB
1192  cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE;
1193  cdb.READ_DVD_STRUCTURE.Format = 0x82; // Return the AACS volumeID
1194  cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
1195  cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
1196  cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)(*input);
1197 
1198  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
1199 
1200 #ifdef ENABLE_AACS_TESTING
1201  static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 };
1202  static const UCHAR defaultFill = 0x35; // '5'
1203  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill);
1204  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
1206 #endif
1207  if (NT_SUCCESS(status))
1208  {
1209  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
1210  ULONG dataLengthToCopy = sizeof(AACS_MEDIA_ID);
1211 
1212  // make length field native byte ordering
1213  REVERSE_SHORT(&header->Length);
1214 
1215  // exit if getting invalid data from the drive
1217  {
1218  *DataLength = 0;
1220  }
1221 
1222  if (NT_SUCCESS(status))
1223  {
1224  // adjust data length to reflect only the addition data
1226 
1227  // exit if the drive is returning an unexpected data size
1228  if (header->Length != dataLengthToCopy)
1229  {
1230  *DataLength = 0;
1232  }
1233  }
1234 
1235  if (NT_SUCCESS(status))
1236  {
1237  // else copy the data to the user's buffer
1238  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
1239  *DataLength = dataLengthToCopy;
1240  }
1241  }
1242 
1243  ScratchBuffer_EndUse(DeviceExtension);
1244  }
1245 
1246  return status;
1247 }
1248 
1250 NTSTATUS
1251 DeviceHandleAacsReadBindingNonce(
1252  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1253  _In_ WDFREQUEST Request,
1255  _Out_ size_t * DataLength
1256  )
1257 /*++
1258 
1259 Routine Description:
1260  This routine is used to process IOCTL:
1261  IOCTL_AACS_READ_BINDING_NONCE
1262 Arguments:
1263  DeviceExtension - device context
1264 
1265  Request - the request that will be formatted
1266 
1267  RequestParameters - request parameter structur
1268 
1269  DataLength - data transferred length
1270 
1271 Return Value:
1272  NTSTATUS
1273 
1274  --*/
1275 {
1276  //AacsReadBindingNonce
1277 
1280  PVOID outputBuffer = NULL;
1281 
1282  PAGED_CODE();
1283 
1284  *DataLength = 0;
1285 
1286  status = WdfRequestRetrieveInputBuffer(Request,
1287  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
1288  (PVOID*)&input,
1289  NULL);
1290 
1291  if (NT_SUCCESS(status))
1292  {
1293  status = WdfRequestRetrieveOutputBuffer(Request,
1294  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
1295  (PVOID*)&outputBuffer,
1296  NULL);
1297  }
1298 
1299  if (NT_SUCCESS(status))
1300  {
1301  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_BINDING_NONCE);
1302  CDB cdb;
1303 
1304  ScratchBuffer_BeginUse(DeviceExtension);
1305 
1306  RtlZeroMemory(&cdb, sizeof(CDB));
1307  // Set up the CDB
1308  cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY;
1309  cdb.REPORT_KEY.LogicalBlockAddress[0] = (UCHAR)( input->StartLba >> (3*8) );
1310  cdb.REPORT_KEY.LogicalBlockAddress[1] = (UCHAR)( input->StartLba >> (2*8) );
1311  cdb.REPORT_KEY.LogicalBlockAddress[2] = (UCHAR)( input->StartLba >> (1*8) );
1312  cdb.REPORT_KEY.LogicalBlockAddress[3] = (UCHAR)( input->StartLba >> (0*8) );
1313  cdb.AsByte[6] = (UCHAR)( input->NumberOfSectors );
1314  cdb.AsByte[7] = 0x02; // AACS key class
1315  cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1));
1316  cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0));
1317  cdb.REPORT_KEY.AGID = (UCHAR)( input->SessionId );
1318  cdb.REPORT_KEY.KeyFormat = 0x21; // Return an existing binding nonce
1319 
1320  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
1321 
1322 #ifdef ENABLE_AACS_TESTING
1323  static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 };
1324  static const UCHAR defaultFill = 0x36; // '6'
1325  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill);
1326  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
1328 #endif
1329  if (NT_SUCCESS(status))
1330  {
1331  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
1332  ULONG dataLengthToCopy = sizeof(AACS_BINDING_NONCE);
1333 
1334  // make length field native byte ordering
1335  REVERSE_SHORT(&header->Length);
1336 
1337  // exit if getting invalid data from the drive
1339  {
1340  *DataLength = 0;
1342  }
1343 
1344  if (NT_SUCCESS(status))
1345  {
1346  // adjust data length to reflect only the addition data
1348 
1349  // exit if the drive is returning an unexpected data size
1350  if (header->Length != dataLengthToCopy)
1351  {
1352  *DataLength = 0;
1354  }
1355  }
1356 
1357  if (NT_SUCCESS(status))
1358  {
1359  // else copy the data to the user's buffer
1360  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
1361  *DataLength = dataLengthToCopy;
1362  }
1363  }
1364 
1365  ScratchBuffer_EndUse(DeviceExtension);
1366  }
1367 
1368  return status;
1369 }
1370 
1372 NTSTATUS
1373 DeviceHandleAacsGenerateBindingNonce(
1374  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1375  _In_ WDFREQUEST Request,
1377  _Out_ size_t * DataLength
1378  )
1379 /*++
1380 
1381 Routine Description:
1382  This routine is used to process IOCTL:
1383  IOCTL_AACS_GENERATE_BINDING_NONCE
1384 Arguments:
1385  DeviceExtension - device context
1386 
1387  Request - the request that will be formatted
1388 
1389  RequestParameters - request parameter structur
1390 
1391  DataLength - data transferred length
1392 
1393 Return Value:
1394  NTSTATUS
1395 
1396  --*/
1397 {
1398  //AacsGenerateBindingNonce
1399 
1402  PVOID outputBuffer = NULL;
1403 
1404  PAGED_CODE();
1405 
1406  *DataLength = 0;
1407 
1408  status = WdfRequestRetrieveInputBuffer(Request,
1409  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
1410  (PVOID*)&input,
1411  NULL);
1412 
1413  if (NT_SUCCESS(status))
1414  {
1415  status = WdfRequestRetrieveOutputBuffer(Request,
1416  RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
1417  (PVOID*)&outputBuffer,
1418  NULL);
1419  }
1420 
1421  if (NT_SUCCESS(status))
1422  {
1423  ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_BINDING_NONCE);
1424  CDB cdb;
1425 
1426  ScratchBuffer_BeginUse(DeviceExtension);
1427 
1428  RtlZeroMemory(&cdb, sizeof(CDB));
1429  // Set up the CDB
1430 
1431  status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12);
1432 
1433 #ifdef ENABLE_AACS_TESTING
1434  static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 };
1435  static const UCHAR defaultFill = 0x37; // '7'
1436  RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill);
1437  RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results));
1439 #endif
1440  if (NT_SUCCESS(status))
1441  {
1442  PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer;
1443  ULONG dataLengthToCopy = sizeof(AACS_BINDING_NONCE);
1444 
1445  // make length field native byte ordering
1446  REVERSE_SHORT(&header->Length);
1447 
1448  // exit if getting invalid data from the drive
1450  {
1451  *DataLength = 0;
1453  }
1454 
1455  if (NT_SUCCESS(status))
1456  {
1457  // adjust data length to reflect only the addition data
1459 
1460  // exit if the drive is returning an unexpected data size
1461  if (header->Length != dataLengthToCopy)
1462  {
1463  *DataLength = 0;
1465  }
1466  }
1467 
1468  if (NT_SUCCESS(status))
1469  {
1470  // else copy the data to the user's buffer
1471  RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy);
1472  *DataLength = dataLengthToCopy;
1473  }
1474  }
1475 
1476  ScratchBuffer_EndUse(DeviceExtension);
1477  }
1478 
1479  return status;
1480 }
1481 
* PAACS_LAYER_NUMBER
Definition: ntddcdvd.h:255
#define MAX_COPY_PROTECT_AGID
Definition: cdrom.h:712
ULONG * PDVD_SESSION_ID
Definition: cdrw_usr.h:1544
FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: scratch.h:104
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_IRQL_requires_max_(APC_LEVEL)
Definition: aacs.c:54
#define _Out_
Definition: ms_sal.h:345
#define TRUE
Definition: types.h:120
struct _CDB::_REPORT_KEY REPORT_KEY
unsigned char * PUCHAR
Definition: retypes.h:3
struct _AACS_CHALLENGE_KEY AACS_CHALLENGE_KEY
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define SCSIOP_SEND_KEY
Definition: cdrw_hw.h:951
#define SCSIOP_REPORT_KEY
Definition: cdrw_hw.h:952
UCHAR Data[0]
Definition: scsi.h:2066
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
VOID ScratchBuffer_ResetItems(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN ResetRequestHistory)
Definition: scratch.c:343
struct _AACS_CERTIFICATE AACS_CERTIFICATE
struct _DVD_DESCRIPTOR_HEADER DVD_DESCRIPTOR_HEADER
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
union _WDF_REQUEST_PARAMETERS::@3631 Parameters
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
struct _CDB::_SEND_KEY SEND_KEY
#define ScratchBuffer_BeginUse(context)
Definition: scratch.h:87
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
Definition: ntddcdvd.h:58
struct _AACS_VOLUME_ID AACS_VOLUME_ID
#define _In_
Definition: ms_sal.h:308
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
struct _READ_DVD_STRUCTURES_HEADER READ_DVD_STRUCTURES_HEADER
#define AACS_MKB_PACK_SIZE
Definition: cdrom.h:764
#define SIZEOF_ARRAY(ar)
Definition: cdrom.h:1482
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define DVD_INVALIDATE_AGID
Definition: scsi.h:135
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
struct _test_info results[8]
Definition: SetCursorPos.c:29
unsigned char UCHAR
Definition: xmlstorage.h:181
ULONG DVD_SESSION_ID
Definition: cdrw_usr.h:1544
struct _CDB::_READ_DVD_STRUCTURE READ_DVD_STRUCTURE
struct _CDVD_REPORT_AGID_DATA * PCDVD_REPORT_AGID_DATA
#define DVD_END_ALL_SESSIONS
Definition: ntddcdvd.h:195
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
struct _CDVD_KEY_HEADER CDVD_KEY_HEADER
#define REVERSE_SHORT(Short)
Definition: scsi.h:3481
GLenum GLenum GLenum input
Definition: glext.h:9031
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK
Definition: ntddcdvd.h:61
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define SCSIOP_READ_DVD_STRUCTURE
Definition: cdrw_hw.h:960
struct _CDVD_KEY_HEADER * PCDVD_KEY_HEADER
struct _AACS_MEDIA_ID AACS_MEDIA_ID
unsigned int ULONG
Definition: retypes.h:1
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:137
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
struct _AACS_BINDING_NONCE AACS_BINDING_NONCE
#define STATUS_SUCCESS
Definition: shellext.h:65
static SERVICE_STATUS status
Definition: service.c:31
#define APC_LEVEL
Definition: env_spec_w32.h:695
struct _WDF_REQUEST_PARAMETERS::@3631::@3635 DeviceIoControl
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _AACS_SERIAL_NUMBER AACS_SERIAL_NUMBER
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3310
Definition: ps.c:97