3 Copyright (C) Microsoft Corporation. All rights reserved.
11 The CDROM class driver implementation of handling AACS IOCTLs.
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)
54 _IRQL_requires_max_(APC_LEVEL
)
56 DeviceHandleAacsReadMediaKeyBlock(
57 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
58 _In_ WDFREQUEST Request
,
59 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
60 _Out_
size_t * DataLength
65 This routine is used to process IOCTLs:
66 IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
67 IOCTL_AACS_READ_MEDIA_KEY_BLOCK
69 DeviceExtension - device context
71 Request - the request that will be formatted
73 RequestParameters - request parameter structur
75 DataLength - data transferred length
82 NTSTATUS status
= STATUS_SUCCESS
;
83 PAACS_LAYER_NUMBER layerNumber
= NULL
;
84 PVOID outputBuffer
= NULL
;
85 ULONG transferSize
= sizeof(READ_DVD_STRUCTURES_HEADER
);
91 status
= WdfRequestRetrieveInputBuffer(Request
,
92 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
96 if (NT_SUCCESS(status
))
98 status
= WdfRequestRetrieveOutputBuffer(Request
,
99 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
100 (PVOID
*)&outputBuffer
,
104 if (NT_SUCCESS(status
))
106 if (RequestParameters
.Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AACS_READ_MEDIA_KEY_BLOCK
)
108 // maximum size for this transfer is one pack + header
109 transferSize
+= AACS_MKB_PACK_SIZE
;
112 if (transferSize
> DeviceExtension
->ScratchContext
.ScratchBufferSize
)
114 // rare case. normally the size of scratch buffer is 64k.
115 status
= STATUS_INTERNAL_ERROR
;
119 if (NT_SUCCESS(status
))
121 UCHAR rmdBlockNumber
= 0;
122 BOOLEAN sendChangedCommand
= TRUE
;
123 BOOLEAN shouldRetry
= TRUE
;
126 ScratchBuffer_BeginUse(DeviceExtension
);
128 RtlZeroMemory(&cdb
, sizeof(CDB
));
130 cdb
.READ_DVD_STRUCTURE
.OperationCode
= SCSIOP_READ_DVD_STRUCTURE
;
131 // cdb->AsByte[1] = 0x01; // AACS sub-command not required for this
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));
138 while (sendChangedCommand
)
140 // RMDBlockNumber is set to zero....
141 // RMDBlockNumber[3] maybe changed for other blocks.
142 cdb
.READ_DVD_STRUCTURE
.RMDBlockNumber
[3] = rmdBlockNumber
;
146 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, transferSize
, TRUE
, &cdb
, 12);
149 #ifdef ENABLE_AACS_TESTING
150 if (RequestParameters
.Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
)
152 static const UCHAR results
[] = { 0x80, 0x02, 0x00, 0x02 };
153 RtlCopyMemory(DeviceExtension
->ScratchContext
.ScratchBuffer
, results
, SIZEOF_ARRAY(results
));
154 status
= STATUS_SUCCESS
;
156 else if (RequestParameters
.Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AACS_READ_MEDIA_KEY_BLOCK
)
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
));
162 status
= STATUS_SUCCESS
;
164 #endif //ENABLE_AACS_TESTING
166 if (NT_SUCCESS(status
))
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];
173 // validate and zero-base the otherPacks
176 TracePrint((TRACE_LEVEL_WARNING
, TRACE_FLAG_INIT
,
177 "AACS: Device is reporting zero total packs (invalid)\n"));
179 status
= STATUS_IO_DEVICE_ERROR
;
185 if (RequestParameters
.Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
)
187 // if not already requested last pack, do so now
188 if (otherPacks
!= thisPackNumber
)
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.
195 // re-zero the output buffer
196 RtlZeroMemory(DeviceExtension
->ScratchContext
.ScratchBuffer
, sizeof(READ_DVD_STRUCTURES_HEADER
));
198 // modify the CDB to get the very last pack of the MKB
199 rmdBlockNumber
= otherPacks
;
201 transferSize
= sizeof(READ_DVD_STRUCTURES_HEADER
);
204 ScratchBuffer_ResetItems(DeviceExtension
, TRUE
);
206 // make sure the loop will be executed for modified command.
207 sendChangedCommand
= TRUE
;
212 // this request already got the last pack
213 // so just interpret the data
214 REVERSE_SHORT(&header
->Length
);
215 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
218 status
= STATUS_IO_DEVICE_ERROR
;
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
225 totalSize
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
226 totalSize
+= otherPacks
* AACS_MKB_PACK_SIZE
;
228 // save the result and complete the request
229 *((PULONG
)outputBuffer
) = totalSize
;
230 *DataLength
= sizeof(ULONG
);
231 status
= STATUS_SUCCESS
;
233 // This will exit the loop of sendChangedCommand
234 sendChangedCommand
= FALSE
;
238 else if (RequestParameters
.Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_AACS_READ_MEDIA_KEY_BLOCK
)
240 // make length field native byte ordering
241 REVERSE_SHORT(&header
->Length
);
243 // exit if getting invalid data from the drive
244 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
247 status
= STATUS_IO_DEVICE_ERROR
;
251 // success, how many bytes to copy for this pack?
252 ULONG totalSize
= header
->Length
;
253 size_t originalBufferSize
;
255 // subtract out any remaining bytes in the header
256 // to get the number of usable bytes in this pack
257 totalSize
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
259 // if not the final pack, this should be a full transfer per spec
260 NT_ASSERT( (totalSize
== AACS_MKB_PACK_SIZE
) || (thisPackNumber
== otherPacks
) );
262 // validate the user's buffer is large enough to accept the full data
263 originalBufferSize
= RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
;
265 if (originalBufferSize
< (totalSize
+ (AACS_MKB_PACK_SIZE
*thisPackNumber
)))
267 // just return a slightly bigger-than-normal size
268 *DataLength
= (otherPacks
+ 1)*AACS_MKB_PACK_SIZE
;
269 status
= STATUS_BUFFER_TOO_SMALL
;
274 // determine where to copy to the user's memory
275 whereToCopy
= outputBuffer
;
276 whereToCopy
+= AACS_MKB_PACK_SIZE
* thisPackNumber
;
278 RtlCopyMemory(whereToCopy
, header
->Data
, totalSize
);
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
);
283 status
= STATUS_SUCCESS
;
285 // if there are more packs to get from the device, send it again....
286 if (thisPackNumber
!= otherPacks
)
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.
293 // re-zero the output buffer
294 RtlZeroMemory(DeviceExtension
->ScratchContext
.ScratchBuffer
, sizeof(READ_DVD_STRUCTURES_HEADER
));
296 // modify the CDB to get the next pack of the MKB
297 rmdBlockNumber
= cdb
.READ_DVD_STRUCTURE
.RMDBlockNumber
[3]++;
299 // modify the SRB to be resent
301 transferSize
= AACS_MKB_PACK_SIZE
+ sizeof(READ_DVD_STRUCTURES_HEADER
);
304 ScratchBuffer_ResetItems(DeviceExtension
, FALSE
);
306 // make sure the loop will be executed for modified command.
307 sendChangedCommand
= TRUE
;
312 // else, that was the end of the transfer, so just complete the request
313 sendChangedCommand
= FALSE
;
318 } // end of IOCTL_AACS_READ_MEDIA_KEY_BLOCK
320 } // end of NT_SUCCESS(status)
322 if (!NT_SUCCESS(status
))
325 sendChangedCommand
= FALSE
;
327 } //end of while (sendChangedCommand)
329 ScratchBuffer_EndUse(DeviceExtension
);
335 _IRQL_requires_max_(APC_LEVEL
)
337 DeviceHandleAacsStartSession(
338 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
339 _In_ WDFREQUEST Request
,
340 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
341 _Out_
size_t * DataLength
346 This routine is used to process IOCTL:
347 IOCTL_AACS_START_SESSION
349 DeviceExtension - device context
351 Request - the request that will be formatted
353 RequestParameters - request parameter structur
355 DataLength - data transferred length
364 NTSTATUS status
= STATUS_SUCCESS
;
365 PDVD_SESSION_ID sessionId
= NULL
;
371 status
= WdfRequestRetrieveOutputBuffer(Request
,
372 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
376 if (NT_SUCCESS(status
))
378 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(CDVD_REPORT_AGID_DATA
);
381 ScratchBuffer_BeginUse(DeviceExtension
);
383 RtlZeroMemory(&cdb
, sizeof(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?
391 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
396 status
= STATUS_SUCCESS
;
398 if (NT_SUCCESS(status
))
400 PCDVD_KEY_HEADER keyHeader
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
401 PCDVD_REPORT_AGID_DATA keyData
= (PCDVD_REPORT_AGID_DATA
)keyHeader
->Data
;
403 *sessionId
= (DVD_SESSION_ID
)(keyData
->AGID
);
404 *DataLength
= sizeof(DVD_SESSION_ID
);
407 ScratchBuffer_EndUse(DeviceExtension
);
413 _IRQL_requires_max_(APC_LEVEL
)
415 DeviceHandleAacsEndSession(
416 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
417 _In_ WDFREQUEST Request
,
418 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
419 _Out_
size_t * DataLength
424 This routine is used to process IOCTL:
425 IOCTL_AACS_END_SESSION
427 DeviceExtension - device context
429 Request - the request that will be formatted
431 RequestParameters - request parameter structur
433 DataLength - data transferred length
442 NTSTATUS status
= STATUS_SUCCESS
;
443 PDVD_SESSION_ID sessionId
= NULL
;
449 status
= WdfRequestRetrieveInputBuffer(Request
,
450 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
454 if (NT_SUCCESS(status
))
456 ULONG transferSize
= 0;
458 DVD_SESSION_ID currentSession
= 0;
459 DVD_SESSION_ID limitSession
= 0;
461 if(*sessionId
== DVD_END_ALL_SESSIONS
)
464 limitSession
= MAX_COPY_PROTECT_AGID
- 1;
468 currentSession
= *sessionId
;
469 limitSession
= *sessionId
;
472 ScratchBuffer_BeginUse(DeviceExtension
);
476 RtlZeroMemory(&cdb
, sizeof(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
;
483 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, transferSize
, FALSE
, &cdb
, 12);
486 } while ((currentSession
<= limitSession
) && NT_SUCCESS(status
));
488 #ifdef ENABLE_AACS_TESTING
489 status
= STATUS_SUCCESS
;
492 ScratchBuffer_EndUse(DeviceExtension
);
498 _IRQL_requires_max_(APC_LEVEL
)
500 DeviceHandleAacsSendCertificate(
501 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
502 _In_ WDFREQUEST Request
,
503 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
504 _Out_
size_t * DataLength
509 This routine is used to process IOCTL:
510 IOCTL_AACS_SEND_CERTIFICATE
512 DeviceExtension - device context
514 Request - the request that will be formatted
516 RequestParameters - request parameter structur
518 DataLength - data transferred length
525 //AacsSendHostCertificate
527 NTSTATUS status
= STATUS_SUCCESS
;
528 PAACS_SEND_CERTIFICATE input
= NULL
;
534 status
= WdfRequestRetrieveInputBuffer(Request
,
535 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
539 if (NT_SUCCESS(status
))
541 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_CERTIFICATE
);
544 ScratchBuffer_BeginUse(DeviceExtension
);
546 // copy the input buffer to the data buffer for the transfer
548 PCDVD_KEY_HEADER header
= (PCDVD_KEY_HEADER
)DeviceExtension
->ScratchContext
.ScratchBuffer
;
549 ULONG tmp
= dataTransferLength
;
551 tmp
-= RTL_SIZEOF_THROUGH_FIELD(CDVD_KEY_HEADER
, DataLength
);
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
));
558 RtlZeroMemory(&cdb
, sizeof(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
567 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, FALSE
, &cdb
, 12);
569 #ifdef ENABLE_AACS_TESTING
570 status
= STATUS_SUCCESS
;
572 if (NT_SUCCESS(status
))
577 ScratchBuffer_EndUse(DeviceExtension
);
583 _IRQL_requires_max_(APC_LEVEL
)
585 DeviceHandleAacsGetCertificate(
586 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
587 _In_ WDFREQUEST Request
,
588 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
589 _Out_
size_t * DataLength
594 This routine is used to process IOCTL:
595 IOCTL_AACS_GET_CERTIFICATE
597 DeviceExtension - device context
599 Request - the request that will be formatted
601 RequestParameters - request parameter structur
603 DataLength - data transferred length
610 //AacsGetDriveCertificate
612 NTSTATUS status
= STATUS_SUCCESS
;
613 PDVD_SESSION_ID input
= NULL
;
614 PVOID outputBuffer
= NULL
;
620 status
= WdfRequestRetrieveInputBuffer(Request
,
621 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
625 if (NT_SUCCESS(status
))
627 status
= WdfRequestRetrieveOutputBuffer(Request
,
628 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
629 (PVOID
*)&outputBuffer
,
633 if (NT_SUCCESS(status
))
635 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_CERTIFICATE
);
638 ScratchBuffer_BeginUse(DeviceExtension
);
640 RtlZeroMemory(&cdb
, sizeof(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
649 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
656 status
= STATUS_SUCCESS
;
658 if (NT_SUCCESS(status
))
660 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
661 ULONG dataLengthToCopy
= sizeof(AACS_CERTIFICATE
);
663 // make length field native byte ordering
664 REVERSE_SHORT(&header
->Length
);
666 // exit if getting invalid data from the drive
667 if (header
->Length
< (sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
)))
670 status
= STATUS_IO_DEVICE_ERROR
;
673 if (NT_SUCCESS(status
))
675 // adjust data length to reflect only the addition data
676 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
678 // exit if the drive is returning an unexpected data size
679 if (header
->Length
!= dataLengthToCopy
)
682 status
= STATUS_IO_DEVICE_ERROR
;
686 if (NT_SUCCESS(status
))
688 // else copy the data to the user's buffer
689 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
690 *DataLength
= dataLengthToCopy
;
694 ScratchBuffer_EndUse(DeviceExtension
);
700 _IRQL_requires_max_(APC_LEVEL
)
702 DeviceHandleAacsGetChallengeKey(
703 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
704 _In_ WDFREQUEST Request
,
705 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
706 _Out_
size_t * DataLength
711 This routine is used to process IOCTL:
712 IOCTL_AACS_GET_CHALLENGE_KEY
714 DeviceExtension - device context
716 Request - the request that will be formatted
718 RequestParameters - request parameter structur
720 DataLength - data transferred length
727 //AacsGetChallengeKey
729 NTSTATUS status
= STATUS_SUCCESS
;
730 PDVD_SESSION_ID input
= NULL
;
731 PVOID outputBuffer
= NULL
;
737 status
= WdfRequestRetrieveInputBuffer(Request
,
738 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
742 if (NT_SUCCESS(status
))
744 status
= WdfRequestRetrieveOutputBuffer(Request
,
745 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
746 (PVOID
*)&outputBuffer
,
750 if (NT_SUCCESS(status
))
752 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_CHALLENGE_KEY
);
755 ScratchBuffer_BeginUse(DeviceExtension
);
757 RtlZeroMemory(&cdb
, sizeof(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
766 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
773 status
= STATUS_SUCCESS
;
775 if (NT_SUCCESS(status
))
777 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
778 ULONG dataLengthToCopy
= sizeof(AACS_CHALLENGE_KEY
);
780 // make length field native byte ordering
781 REVERSE_SHORT(&header
->Length
);
783 // exit if getting invalid data from the drive
784 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
787 status
= STATUS_IO_DEVICE_ERROR
;
790 if (NT_SUCCESS(status
))
792 // adjust data length to reflect only the addition data
793 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
795 // exit if the drive is returning an unexpected data size
796 if (header
->Length
!= dataLengthToCopy
)
799 status
= STATUS_IO_DEVICE_ERROR
;
803 if (NT_SUCCESS(status
))
805 // else copy the data to the user's buffer
806 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
807 *DataLength
= dataLengthToCopy
;
811 ScratchBuffer_EndUse(DeviceExtension
);
817 _IRQL_requires_max_(APC_LEVEL
)
819 DeviceHandleSendChallengeKey(
820 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
821 _In_ WDFREQUEST Request
,
822 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
823 _Out_
size_t * DataLength
828 This routine is used to process IOCTL:
829 IOCTL_AACS_SEND_CHALLENGE_KEY
831 DeviceExtension - device context
833 Request - the request that will be formatted
835 RequestParameters - request parameter structur
837 DataLength - data transferred length
844 //AacsSendChallengeKey
846 NTSTATUS status
= STATUS_SUCCESS
;
847 PAACS_SEND_CHALLENGE_KEY input
= NULL
;
853 status
= WdfRequestRetrieveInputBuffer(Request
,
854 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
858 if (NT_SUCCESS(status
))
860 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_CHALLENGE_KEY
);
863 ScratchBuffer_BeginUse(DeviceExtension
);
865 // copy the input buffer to the data buffer for the transfer
867 PCDVD_KEY_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
868 ULONG tmp
= dataTransferLength
;
869 tmp
-= RTL_SIZEOF_THROUGH_FIELD(CDVD_KEY_HEADER
, DataLength
);
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
));
876 RtlZeroMemory(&cdb
, sizeof(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
885 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, FALSE
, &cdb
, 12);
887 #ifdef ENABLE_AACS_TESTING
888 status
= STATUS_SUCCESS
;
890 if (NT_SUCCESS(status
))
895 ScratchBuffer_EndUse(DeviceExtension
);
901 _IRQL_requires_max_(APC_LEVEL
)
903 DeviceHandleReadVolumeId(
904 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
905 _In_ WDFREQUEST Request
,
906 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
907 _Out_
size_t * DataLength
912 This routine is used to process IOCTL:
913 IOCTL_AACS_READ_VOLUME_ID
915 DeviceExtension - device context
917 Request - the request that will be formatted
919 RequestParameters - request parameter structur
921 DataLength - data transferred length
930 NTSTATUS status
= STATUS_SUCCESS
;
931 PDVD_SESSION_ID input
= NULL
;
932 PVOID outputBuffer
= NULL
;
938 status
= WdfRequestRetrieveInputBuffer(Request
,
939 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
943 if (NT_SUCCESS(status
))
945 status
= WdfRequestRetrieveOutputBuffer(Request
,
946 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
947 (PVOID
*)&outputBuffer
,
951 if (NT_SUCCESS(status
))
953 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_VOLUME_ID
);
956 ScratchBuffer_BeginUse(DeviceExtension
);
958 RtlZeroMemory(&cdb
, sizeof(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
);
966 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
973 status
= STATUS_SUCCESS
;
975 if (NT_SUCCESS(status
))
977 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
978 ULONG dataLengthToCopy
= sizeof(AACS_VOLUME_ID
);
980 // make length field native byte ordering
981 REVERSE_SHORT(&header
->Length
);
983 // exit if getting invalid data from the drive
984 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
987 status
= STATUS_IO_DEVICE_ERROR
;
990 if (NT_SUCCESS(status
))
992 // adjust data length to reflect only the addition data
993 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
995 // exit if the drive is returning an unexpected data size
996 if (header
->Length
!= dataLengthToCopy
)
999 status
= STATUS_IO_DEVICE_ERROR
;
1003 if (NT_SUCCESS(status
))
1005 // else copy the data to the user's buffer
1006 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
1007 *DataLength
= dataLengthToCopy
;
1011 ScratchBuffer_EndUse(DeviceExtension
);
1017 _IRQL_requires_max_(APC_LEVEL
)
1019 DeviceHandleAacsReadSerialNumber(
1020 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
1021 _In_ WDFREQUEST Request
,
1022 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
1023 _Out_
size_t * DataLength
1027 Routine Description:
1028 This routine is used to process IOCTL:
1029 IOCTL_AACS_READ_SERIAL_NUMBER
1031 DeviceExtension - device context
1033 Request - the request that will be formatted
1035 RequestParameters - request parameter structur
1037 DataLength - data transferred length
1044 //AacsReadSerialNumber
1046 NTSTATUS status
= STATUS_SUCCESS
;
1047 PDVD_SESSION_ID input
= NULL
;
1048 PVOID outputBuffer
= NULL
;
1054 status
= WdfRequestRetrieveInputBuffer(Request
,
1055 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
1059 if (NT_SUCCESS(status
))
1061 status
= WdfRequestRetrieveOutputBuffer(Request
,
1062 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
1063 (PVOID
*)&outputBuffer
,
1067 if (NT_SUCCESS(status
))
1069 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_SERIAL_NUMBER
);
1072 ScratchBuffer_BeginUse(DeviceExtension
);
1074 RtlZeroMemory(&cdb
, sizeof(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
);
1082 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
1089 status
= STATUS_SUCCESS
;
1091 if (NT_SUCCESS(status
))
1093 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
1094 ULONG dataLengthToCopy
= sizeof(AACS_SERIAL_NUMBER
);
1096 // make length field native byte ordering
1097 REVERSE_SHORT(&header
->Length
);
1099 // exit if getting invalid data from the drive
1100 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
1103 status
= STATUS_IO_DEVICE_ERROR
;
1106 if (NT_SUCCESS(status
))
1108 // adjust data length to reflect only the addition data
1109 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
1111 // exit if the drive is returning an unexpected data size
1112 if (header
->Length
!= dataLengthToCopy
)
1115 status
= STATUS_IO_DEVICE_ERROR
;
1119 if (NT_SUCCESS(status
))
1121 // else copy the data to the user's buffer
1122 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
1123 *DataLength
= dataLengthToCopy
;
1127 ScratchBuffer_EndUse(DeviceExtension
);
1133 _IRQL_requires_max_(APC_LEVEL
)
1135 DeviceHandleAacsReadMediaId(
1136 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
1137 _In_ WDFREQUEST Request
,
1138 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
1139 _Out_
size_t * DataLength
1143 Routine Description:
1144 This routine is used to process IOCTL:
1145 IOCTL_AACS_READ_MEDIA_ID
1147 DeviceExtension - device context
1149 Request - the request that will be formatted
1151 RequestParameters - request parameter structur
1153 DataLength - data transferred length
1162 NTSTATUS status
= STATUS_SUCCESS
;
1163 PDVD_SESSION_ID input
= NULL
;
1164 PVOID outputBuffer
= NULL
;
1170 status
= WdfRequestRetrieveInputBuffer(Request
,
1171 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
1175 if (NT_SUCCESS(status
))
1177 status
= WdfRequestRetrieveOutputBuffer(Request
,
1178 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
1179 (PVOID
*)&outputBuffer
,
1183 if (NT_SUCCESS(status
))
1185 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_MEDIA_ID
);
1188 ScratchBuffer_BeginUse(DeviceExtension
);
1190 RtlZeroMemory(&cdb
, sizeof(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
);
1198 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
1205 status
= STATUS_SUCCESS
;
1207 if (NT_SUCCESS(status
))
1209 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
1210 ULONG dataLengthToCopy
= sizeof(AACS_MEDIA_ID
);
1212 // make length field native byte ordering
1213 REVERSE_SHORT(&header
->Length
);
1215 // exit if getting invalid data from the drive
1216 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
1219 status
= STATUS_IO_DEVICE_ERROR
;
1222 if (NT_SUCCESS(status
))
1224 // adjust data length to reflect only the addition data
1225 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
1227 // exit if the drive is returning an unexpected data size
1228 if (header
->Length
!= dataLengthToCopy
)
1231 status
= STATUS_IO_DEVICE_ERROR
;
1235 if (NT_SUCCESS(status
))
1237 // else copy the data to the user's buffer
1238 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
1239 *DataLength
= dataLengthToCopy
;
1243 ScratchBuffer_EndUse(DeviceExtension
);
1249 _IRQL_requires_max_(APC_LEVEL
)
1251 DeviceHandleAacsReadBindingNonce(
1252 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
1253 _In_ WDFREQUEST Request
,
1254 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
1255 _Out_
size_t * DataLength
1259 Routine Description:
1260 This routine is used to process IOCTL:
1261 IOCTL_AACS_READ_BINDING_NONCE
1263 DeviceExtension - device context
1265 Request - the request that will be formatted
1267 RequestParameters - request parameter structur
1269 DataLength - data transferred length
1276 //AacsReadBindingNonce
1278 NTSTATUS status
= STATUS_SUCCESS
;
1279 PAACS_READ_BINDING_NONCE input
= NULL
;
1280 PVOID outputBuffer
= NULL
;
1286 status
= WdfRequestRetrieveInputBuffer(Request
,
1287 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
1291 if (NT_SUCCESS(status
))
1293 status
= WdfRequestRetrieveOutputBuffer(Request
,
1294 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
1295 (PVOID
*)&outputBuffer
,
1299 if (NT_SUCCESS(status
))
1301 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_BINDING_NONCE
);
1304 ScratchBuffer_BeginUse(DeviceExtension
);
1306 RtlZeroMemory(&cdb
, sizeof(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
1320 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
1327 status
= STATUS_SUCCESS
;
1329 if (NT_SUCCESS(status
))
1331 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
1332 ULONG dataLengthToCopy
= sizeof(AACS_BINDING_NONCE
);
1334 // make length field native byte ordering
1335 REVERSE_SHORT(&header
->Length
);
1337 // exit if getting invalid data from the drive
1338 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
1341 status
= STATUS_IO_DEVICE_ERROR
;
1344 if (NT_SUCCESS(status
))
1346 // adjust data length to reflect only the addition data
1347 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
1349 // exit if the drive is returning an unexpected data size
1350 if (header
->Length
!= dataLengthToCopy
)
1353 status
= STATUS_IO_DEVICE_ERROR
;
1357 if (NT_SUCCESS(status
))
1359 // else copy the data to the user's buffer
1360 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
1361 *DataLength
= dataLengthToCopy
;
1365 ScratchBuffer_EndUse(DeviceExtension
);
1371 _IRQL_requires_max_(APC_LEVEL
)
1373 DeviceHandleAacsGenerateBindingNonce(
1374 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
,
1375 _In_ WDFREQUEST Request
,
1376 _In_ WDF_REQUEST_PARAMETERS RequestParameters
,
1377 _Out_
size_t * DataLength
1381 Routine Description:
1382 This routine is used to process IOCTL:
1383 IOCTL_AACS_GENERATE_BINDING_NONCE
1385 DeviceExtension - device context
1387 Request - the request that will be formatted
1389 RequestParameters - request parameter structur
1391 DataLength - data transferred length
1398 //AacsGenerateBindingNonce
1400 NTSTATUS status
= STATUS_SUCCESS
;
1401 PAACS_READ_BINDING_NONCE input
= NULL
;
1402 PVOID outputBuffer
= NULL
;
1408 status
= WdfRequestRetrieveInputBuffer(Request
,
1409 RequestParameters
.Parameters
.DeviceIoControl
.InputBufferLength
,
1413 if (NT_SUCCESS(status
))
1415 status
= WdfRequestRetrieveOutputBuffer(Request
,
1416 RequestParameters
.Parameters
.DeviceIoControl
.OutputBufferLength
,
1417 (PVOID
*)&outputBuffer
,
1421 if (NT_SUCCESS(status
))
1423 ULONG dataTransferLength
= sizeof(CDVD_KEY_HEADER
) + sizeof(AACS_BINDING_NONCE
);
1426 ScratchBuffer_BeginUse(DeviceExtension
);
1428 RtlZeroMemory(&cdb
, sizeof(CDB
));
1431 status
= ScratchBuffer_ExecuteCdb(DeviceExtension
, Request
, dataTransferLength
, TRUE
, &cdb
, 12);
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
));
1438 status
= STATUS_SUCCESS
;
1440 if (NT_SUCCESS(status
))
1442 PDVD_DESCRIPTOR_HEADER header
= DeviceExtension
->ScratchContext
.ScratchBuffer
;
1443 ULONG dataLengthToCopy
= sizeof(AACS_BINDING_NONCE
);
1445 // make length field native byte ordering
1446 REVERSE_SHORT(&header
->Length
);
1448 // exit if getting invalid data from the drive
1449 if (header
->Length
< sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
))
1452 status
= STATUS_IO_DEVICE_ERROR
;
1455 if (NT_SUCCESS(status
))
1457 // adjust data length to reflect only the addition data
1458 header
->Length
-= sizeof(DVD_DESCRIPTOR_HEADER
) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER
, Length
);
1460 // exit if the drive is returning an unexpected data size
1461 if (header
->Length
!= dataLengthToCopy
)
1464 status
= STATUS_IO_DEVICE_ERROR
;
1468 if (NT_SUCCESS(status
))
1470 // else copy the data to the user's buffer
1471 RtlCopyMemory(outputBuffer
, header
->Data
, dataLengthToCopy
);
1472 *DataLength
= dataLengthToCopy
;
1476 ScratchBuffer_EndUse(DeviceExtension
);