xref: /reactos/drivers/crypto/ksecdd/dispatch.c (revision 1734f297)
1 /*
2  * PROJECT:         ReactOS Drivers
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PURPOSE:         Kernel Security Support Provider Interface Driver
5  *
6  * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "ksecdd.h"
12 #include <ksecioctl.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 
18 /* FUNCTIONS ******************************************************************/
19 
20 static
21 NTSTATUS
22 KsecQueryFileInformation(
23     PVOID InfoBuffer,
24     FILE_INFORMATION_CLASS FileInformationClass,
25     PSIZE_T BufferLength)
26 {
27     PFILE_STANDARD_INFORMATION StandardInformation;
28 
29     /* Only FileStandardInformation is supported */
30     if (FileInformationClass != FileStandardInformation)
31     {
32         return STATUS_INVALID_INFO_CLASS;
33     }
34 
35     /* Validate buffer size */
36     if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
37     {
38         *BufferLength = sizeof(FILE_STANDARD_INFORMATION);
39         return STATUS_INFO_LENGTH_MISMATCH;
40     }
41 
42     /* Fill the structure */
43     StandardInformation = (PFILE_STANDARD_INFORMATION)InfoBuffer;
44     StandardInformation->AllocationSize.QuadPart = 0;
45     StandardInformation->EndOfFile.QuadPart = 0;
46     StandardInformation->NumberOfLinks = 1;
47     StandardInformation->DeletePending = FALSE;
48     StandardInformation->Directory = FALSE;
49     *BufferLength = sizeof(FILE_STANDARD_INFORMATION);
50 
51     return STATUS_SUCCESS;
52 }
53 
54 static
55 NTSTATUS
56 KsecQueryVolumeInformation(
57     PVOID InfoBuffer,
58     FS_INFORMATION_CLASS FsInformationClass,
59     PSIZE_T BufferLength)
60 {
61     PFILE_FS_DEVICE_INFORMATION DeviceInformation;
62 
63     /* Only FileFsDeviceInformation is supported */
64     if (FsInformationClass != FileFsDeviceInformation)
65     {
66         return STATUS_INVALID_INFO_CLASS;
67     }
68 
69     /* Validate buffer size */
70     if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
71     {
72         *BufferLength = sizeof(FILE_FS_DEVICE_INFORMATION);
73         return STATUS_INFO_LENGTH_MISMATCH;
74     }
75 
76     /* Fill the structure */
77     DeviceInformation = (PFILE_FS_DEVICE_INFORMATION)InfoBuffer;
78     DeviceInformation->DeviceType = FILE_DEVICE_NULL;
79     DeviceInformation->Characteristics = 0;
80     *BufferLength = sizeof(FILE_FS_DEVICE_INFORMATION);
81 
82     return STATUS_SUCCESS;
83 }
84 
85 static
86 NTSTATUS
87 KsecDeviceControl(
88     ULONG IoControlCode,
89     PVOID Buffer,
90     SIZE_T InputLength,
91     PSIZE_T OutputLength)
92 {
93     NTSTATUS Status;
94 
95     if ((IoControlCode == IOCTL_KSEC_RANDOM_FILL_BUFFER) ||
96         (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_PROCESS) ||
97         (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_PROCESS) ||
98         (IoControlCode == IOCTL_KSEC_ENCRYPT_CROSS_PROCESS) ||
99         (IoControlCode == IOCTL_KSEC_DECRYPT_CROSS_PROCESS) ||
100         (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_LOGON) ||
101         (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_LOGON))
102     {
103         /* Make sure we have a valid output buffer */
104         if ((Buffer == NULL) || (OutputLength == NULL))
105         {
106             return STATUS_INVALID_PARAMETER;
107         }
108 
109         /* Check if the input is smaller than the output */
110         if (InputLength < *OutputLength)
111         {
112             /* We might have uninitialized memory, zero it out */
113             RtlSecureZeroMemory((PUCHAR)Buffer + InputLength,
114                                 *OutputLength - InputLength);
115         }
116     }
117 
118     /* Check ioctl code */
119     switch (IoControlCode)
120     {
121         case IOCTL_KSEC_REGISTER_LSA_PROCESS:
122 
123             Status = STATUS_SUCCESS;
124             break;
125 
126         case IOCTL_KSEC_RANDOM_FILL_BUFFER:
127 
128             Status = KsecGenRandom(Buffer, *OutputLength);
129             break;
130 
131         case IOCTL_KSEC_ENCRYPT_SAME_PROCESS:
132 
133             Status = KsecEncryptMemory(Buffer,
134                                        *OutputLength,
135                                        RTL_ENCRYPT_OPTION_SAME_PROCESS);
136             break;
137 
138         case IOCTL_KSEC_DECRYPT_SAME_PROCESS:
139 
140             Status = KsecDecryptMemory(Buffer,
141                                        *OutputLength,
142                                        RTL_ENCRYPT_OPTION_SAME_PROCESS);
143             break;
144 
145         case IOCTL_KSEC_ENCRYPT_CROSS_PROCESS:
146 
147             Status = KsecEncryptMemory(Buffer,
148                                        *OutputLength,
149                                        RTL_ENCRYPT_OPTION_CROSS_PROCESS);
150             break;
151 
152         case IOCTL_KSEC_DECRYPT_CROSS_PROCESS:
153 
154             Status = KsecDecryptMemory(Buffer,
155                                        *OutputLength,
156                                        RTL_ENCRYPT_OPTION_CROSS_PROCESS);
157             break;
158 
159         case IOCTL_KSEC_ENCRYPT_SAME_LOGON:
160 
161             Status = KsecEncryptMemory(Buffer,
162                                        *OutputLength,
163                                        RTL_ENCRYPT_OPTION_SAME_LOGON);
164             break;
165 
166         case IOCTL_KSEC_DECRYPT_SAME_LOGON:
167 
168             Status = KsecDecryptMemory(Buffer,
169                                        *OutputLength,
170                                        RTL_ENCRYPT_OPTION_SAME_LOGON);
171             break;
172 
173         default:
174             DPRINT1("Unhandled control code 0x%lx\n", IoControlCode);
175             __debugbreak();
176             return STATUS_INVALID_PARAMETER;
177     }
178 
179     return Status;
180 }
181 
182 NTSTATUS
183 NTAPI
184 KsecDdDispatch(
185     PDEVICE_OBJECT DeviceObject,
186     PIRP Irp)
187 {
188     PIO_STACK_LOCATION IoStackLocation;
189     ULONG_PTR Information;
190     NTSTATUS Status;
191     PVOID Buffer;
192     SIZE_T InputLength, OutputLength;
193     FILE_INFORMATION_CLASS FileInfoClass;
194     FS_INFORMATION_CLASS FsInfoClass;
195     ULONG IoControlCode;
196 
197     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
198 
199     switch (IoStackLocation->MajorFunction)
200     {
201         case IRP_MJ_CREATE:
202         case IRP_MJ_CLOSE:
203 
204             /* Just return success */
205             Status = STATUS_SUCCESS;
206             Information = 0;
207             break;
208 
209         case IRP_MJ_READ:
210 
211             /* There is nothing to read */
212             Status = STATUS_END_OF_FILE;
213             Information = 0;
214             break;
215 
216         case IRP_MJ_WRITE:
217 
218             /* Pretend to have written everything */
219             Status = STATUS_SUCCESS;
220             Information = IoStackLocation->Parameters.Write.Length;
221             break;
222 
223         case IRP_MJ_QUERY_INFORMATION:
224 
225             /* Extract the parameters */
226             Buffer = Irp->AssociatedIrp.SystemBuffer;
227             OutputLength = IoStackLocation->Parameters.QueryFile.Length;
228             FileInfoClass = IoStackLocation->Parameters.QueryFile.FileInformationClass;
229 
230             /* Call the internal function */
231             Status = KsecQueryFileInformation(Buffer,
232                                               FileInfoClass,
233                                               &OutputLength);
234             Information = OutputLength;
235             break;
236 
237         case IRP_MJ_QUERY_VOLUME_INFORMATION:
238 
239             /* Extract the parameters */
240             Buffer = Irp->AssociatedIrp.SystemBuffer;
241             OutputLength = IoStackLocation->Parameters.QueryVolume.Length;
242             FsInfoClass = IoStackLocation->Parameters.QueryVolume.FsInformationClass;
243 
244             /* Call the internal function */
245             Status = KsecQueryVolumeInformation(Buffer,
246                                                 FsInfoClass,
247                                                 &OutputLength);
248             Information = OutputLength;
249             break;
250 
251         case IRP_MJ_DEVICE_CONTROL:
252 
253             /* Extract the parameters */
254             InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
255             OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
256             IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
257 
258             /* Check for METHOD_OUT_DIRECT method */
259             if ((METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_OUT_DIRECT) &&
260                 (OutputLength != 0))
261             {
262                 /* Use the provided MDL */
263                 OutputLength = Irp->MdlAddress->ByteCount;
264                 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,
265                                                       NormalPagePriority);
266                 if (Buffer == NULL)
267                 {
268                     Status = STATUS_INSUFFICIENT_RESOURCES;
269                     Information = 0;
270                     break;
271                 }
272             }
273             else
274             {
275                 /* Otherwise this is METHOD_BUFFERED, use the SystemBuffer */
276                 Buffer = Irp->AssociatedIrp.SystemBuffer;
277             }
278 
279             /* Call the internal function */
280             Status = KsecDeviceControl(IoControlCode,
281                                        Buffer,
282                                        InputLength,
283                                        &OutputLength);
284             Information = OutputLength;
285             break;
286 
287         default:
288             DPRINT1("Unhandled major function %lu!\n",
289                     IoStackLocation->MajorFunction);
290             ASSERT(FALSE);
291             return STATUS_INVALID_DEVICE_REQUEST;
292     }
293 
294     /* Return the information */
295     Irp->IoStatus.Status = Status;
296     Irp->IoStatus.Information = Information;
297 
298     /* Complete the request */
299     IoCompleteRequest(Irp, IO_NO_INCREMENT);
300 
301     return Status;
302 }
303