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