1*ee69ca78SMark Jansen /*
2*ee69ca78SMark Jansen * PROJECT: ReactOS certutil
3*ee69ca78SMark Jansen * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4*ee69ca78SMark Jansen * PURPOSE: CertUtil stub
5*ee69ca78SMark Jansen * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
6*ee69ca78SMark Jansen *
7*ee69ca78SMark Jansen * Note: Only -hashfile is implemented for now, the rest is not present!
8*ee69ca78SMark Jansen */
9*ee69ca78SMark Jansen
10*ee69ca78SMark Jansen #include "precomp.h"
11*ee69ca78SMark Jansen #include <wincrypt.h>
12*ee69ca78SMark Jansen #include <stdlib.h>
13*ee69ca78SMark Jansen
14*ee69ca78SMark Jansen
hash_file(LPCWSTR Filename)15*ee69ca78SMark Jansen static BOOL hash_file(LPCWSTR Filename)
16*ee69ca78SMark Jansen {
17*ee69ca78SMark Jansen HCRYPTPROV hProv;
18*ee69ca78SMark Jansen BOOL bSuccess = FALSE;
19*ee69ca78SMark Jansen
20*ee69ca78SMark Jansen HANDLE hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ, NULL,
21*ee69ca78SMark Jansen OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
22*ee69ca78SMark Jansen
23*ee69ca78SMark Jansen if (hFile == INVALID_HANDLE_VALUE)
24*ee69ca78SMark Jansen {
25*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: -hashfile command failed: %d\n", GetLastError());
26*ee69ca78SMark Jansen return bSuccess;
27*ee69ca78SMark Jansen }
28*ee69ca78SMark Jansen
29*ee69ca78SMark Jansen if (CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
30*ee69ca78SMark Jansen {
31*ee69ca78SMark Jansen HCRYPTHASH hHash;
32*ee69ca78SMark Jansen
33*ee69ca78SMark Jansen if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
34*ee69ca78SMark Jansen {
35*ee69ca78SMark Jansen BYTE Buffer[2048];
36*ee69ca78SMark Jansen DWORD cbRead;
37*ee69ca78SMark Jansen
38*ee69ca78SMark Jansen while ((bSuccess = ReadFile(hFile, Buffer, sizeof(Buffer), &cbRead, NULL)))
39*ee69ca78SMark Jansen {
40*ee69ca78SMark Jansen if (cbRead == 0)
41*ee69ca78SMark Jansen break;
42*ee69ca78SMark Jansen
43*ee69ca78SMark Jansen if (!CryptHashData(hHash, Buffer, cbRead, 0))
44*ee69ca78SMark Jansen {
45*ee69ca78SMark Jansen bSuccess = FALSE;
46*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: -hashfile command failed to hash: %d\n", GetLastError());
47*ee69ca78SMark Jansen break;
48*ee69ca78SMark Jansen }
49*ee69ca78SMark Jansen }
50*ee69ca78SMark Jansen
51*ee69ca78SMark Jansen if (bSuccess)
52*ee69ca78SMark Jansen {
53*ee69ca78SMark Jansen BYTE rgbHash[20];
54*ee69ca78SMark Jansen DWORD cbHash, n;
55*ee69ca78SMark Jansen
56*ee69ca78SMark Jansen if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
57*ee69ca78SMark Jansen {
58*ee69ca78SMark Jansen ConPrintf(StdOut, L"SHA1 hash of %s:\n", Filename);
59*ee69ca78SMark Jansen for (n = 0; n < cbHash; ++n)
60*ee69ca78SMark Jansen {
61*ee69ca78SMark Jansen ConPrintf(StdOut, L"%02x", rgbHash[n]);
62*ee69ca78SMark Jansen }
63*ee69ca78SMark Jansen ConPuts(StdOut, L"\n");
64*ee69ca78SMark Jansen }
65*ee69ca78SMark Jansen else
66*ee69ca78SMark Jansen {
67*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: -hashfile command failed to extract hash: %d\n", GetLastError());
68*ee69ca78SMark Jansen bSuccess = FALSE;
69*ee69ca78SMark Jansen }
70*ee69ca78SMark Jansen }
71*ee69ca78SMark Jansen
72*ee69ca78SMark Jansen CryptDestroyHash(hHash);
73*ee69ca78SMark Jansen }
74*ee69ca78SMark Jansen else
75*ee69ca78SMark Jansen {
76*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: -hashfile command no algorithm: %d\n", GetLastError());
77*ee69ca78SMark Jansen }
78*ee69ca78SMark Jansen
79*ee69ca78SMark Jansen CryptReleaseContext(hProv, 0);
80*ee69ca78SMark Jansen }
81*ee69ca78SMark Jansen else
82*ee69ca78SMark Jansen {
83*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: -hashfile command no context: %d\n", GetLastError());
84*ee69ca78SMark Jansen }
85*ee69ca78SMark Jansen
86*ee69ca78SMark Jansen CloseHandle(hFile);
87*ee69ca78SMark Jansen return bSuccess;
88*ee69ca78SMark Jansen }
89*ee69ca78SMark Jansen
90*ee69ca78SMark Jansen
print_usage()91*ee69ca78SMark Jansen static void print_usage()
92*ee69ca78SMark Jansen {
93*ee69ca78SMark Jansen ConPuts(StdOut, L"Verbs:\n");
94*ee69ca78SMark Jansen ConPuts(StdOut, L" -hashfile -- Display cryptographic hash over a file\n");
95*ee69ca78SMark Jansen ConPuts(StdOut, L"\n");
96*ee69ca78SMark Jansen ConPuts(StdOut, L"CertUtil -? -- Display a list of all verbs\n");
97*ee69ca78SMark Jansen ConPuts(StdOut, L"CertUtil -hashfile -? -- Display help text for the 'hashfile' verb\n");
98*ee69ca78SMark Jansen }
99*ee69ca78SMark Jansen
wmain(int argc,WCHAR * argv[])100*ee69ca78SMark Jansen int wmain(int argc, WCHAR *argv[])
101*ee69ca78SMark Jansen {
102*ee69ca78SMark Jansen int n;
103*ee69ca78SMark Jansen
104*ee69ca78SMark Jansen /* Initialize the Console Standard Streams */
105*ee69ca78SMark Jansen ConInitStdStreams();
106*ee69ca78SMark Jansen
107*ee69ca78SMark Jansen if (argc == 1) /* i.e. no commandline arguments given */
108*ee69ca78SMark Jansen {
109*ee69ca78SMark Jansen print_usage();
110*ee69ca78SMark Jansen return EXIT_SUCCESS;
111*ee69ca78SMark Jansen }
112*ee69ca78SMark Jansen
113*ee69ca78SMark Jansen for (n = 1; n < argc; ++n)
114*ee69ca78SMark Jansen {
115*ee69ca78SMark Jansen if (!_wcsicmp(argv[n], L"-?"))
116*ee69ca78SMark Jansen {
117*ee69ca78SMark Jansen print_usage();
118*ee69ca78SMark Jansen return EXIT_SUCCESS;
119*ee69ca78SMark Jansen }
120*ee69ca78SMark Jansen else if (!_wcsicmp(argv[n], L"-hashfile"))
121*ee69ca78SMark Jansen {
122*ee69ca78SMark Jansen if (argc == 3)
123*ee69ca78SMark Jansen {
124*ee69ca78SMark Jansen if (!_wcsicmp(argv[n+1], L"-?"))
125*ee69ca78SMark Jansen {
126*ee69ca78SMark Jansen print_usage();
127*ee69ca78SMark Jansen return EXIT_SUCCESS;
128*ee69ca78SMark Jansen }
129*ee69ca78SMark Jansen else
130*ee69ca78SMark Jansen {
131*ee69ca78SMark Jansen if (!hash_file(argv[n+1]))
132*ee69ca78SMark Jansen {
133*ee69ca78SMark Jansen /* hash_file prints the failure itself */
134*ee69ca78SMark Jansen return EXIT_FAILURE;
135*ee69ca78SMark Jansen }
136*ee69ca78SMark Jansen
137*ee69ca78SMark Jansen ConPuts(StdOut, L"CertUtil: -hashfile command completed successfully\n");
138*ee69ca78SMark Jansen return EXIT_SUCCESS;
139*ee69ca78SMark Jansen }
140*ee69ca78SMark Jansen }
141*ee69ca78SMark Jansen else
142*ee69ca78SMark Jansen {
143*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: -hashfile expected 1 argument, got %d\n", argc - 2);
144*ee69ca78SMark Jansen return EXIT_FAILURE;
145*ee69ca78SMark Jansen }
146*ee69ca78SMark Jansen }
147*ee69ca78SMark Jansen else
148*ee69ca78SMark Jansen {
149*ee69ca78SMark Jansen ConPrintf(StdOut, L"CertUtil: Unknown verb: %s\n", argv[n]);
150*ee69ca78SMark Jansen return EXIT_FAILURE;
151*ee69ca78SMark Jansen }
152*ee69ca78SMark Jansen }
153*ee69ca78SMark Jansen
154*ee69ca78SMark Jansen return EXIT_SUCCESS;
155*ee69ca78SMark Jansen }
156