├── README.md ├── build.sh ├── steam-trace.sh ├── steam.sh ├── wine-2.0-rc1 └── dlls │ └── bcrypt │ ├── bcrypt.spec │ └── bcrypt_main.c └── winecfg.sh /README.md: -------------------------------------------------------------------------------- 1 | # wine20-bcrypt-doom 2 | ## Patched WINE bCrypt dll to run DOOM (2016) 3 | 4 | ### Wine-Staging realeased it's own implementation: 5 | ### https://github.com/wine-compholio/wine-staging/tree/master/patches/bcrypt-Improvements 6 | ### Consider using it instead of this workaround. 7 | 8 | 9 | 10 | ### This repo reimplements bCrypt using libgcrypt: 11 | ### https://github.com/isage/wine-doom 12 | 13 | 14 | irc: freenode.net #doom-wine 15 | 16 | ### Vulkan support note 17 | if you have vulkan available in your drivers, you can try it, but you will have to build wine-staging from 18 | https://github.com/wine-compholio/wine-patched 19 | instead of wine-2.0-rc1. 20 | 21 | and don't forget to copy `wine-2.0-rc1/include/bcrypt.h` to `wine-patched/include/` 22 | 23 | ### Current progress: 24 | 25 | Everything works now with current wine-staging implementation of bCrypt and fixes of winhttp. 26 | No need to use this workaround. 27 | 28 | ### If you have any build errors - check the build dependencies. 29 | on ubuntu libgnutls28-dev is required: https://github.com/thevoidnn/wine20-bcrypt-doom/issues/2 30 | 31 | ### How to build 32 | 33 | First, create a directory, where you will build wine: 34 | ``` 35 | $ mkdir ~/wine20 36 | $ cd ~/wine20 37 | ``` 38 | 39 | If you're on Arch Linux, you can run 40 | ``` 41 | $ yaourt -S wine-git 42 | ``` 43 | just to install all the build dependecies (but don't actually compile it or install this package!) 44 | ( you can see the dep list here https://aur.archlinux.org/packages/wine-git ) 45 | 46 | Then you have to get wine-2.0-rc1 sources from winehq ( https://www.winehq.org/news/2016120901 ) 47 | ``` 48 | $ wget https://dl.winehq.org/wine/source/2.0/wine-2.0-rc1.tar.bz2 49 | ``` 50 | 51 | Then you need to extract wine sources 52 | ``` 53 | $ tar xf wine-2.0-rc1.tar.bz2 54 | ``` 55 | 56 | Get my patch 57 | ``` 58 | $ git clone https://github.com/thevoidnn/wine20-bcrypt-doom.git 59 | ``` 60 | 61 | Apply my patch 62 | ``` 63 | $ cp -r wine20-bcrypt-doom/* . 64 | ``` 65 | 66 | Then you have to build it... 67 | 68 | If you're on Arch Linux - you can just run 69 | ``` 70 | $ ./build.sh 71 | ``` 72 | 73 | (But it's always a good idea to read it first) 74 | 75 | Now grab some tea/coffee and just wait till the building is done. 76 | 77 | 78 | I've also provided few ssh scripts to run steam and winecfg, 79 | but you have to edit them first, because they have wine prefix path 80 | which you probably don't have in your system. 81 | 82 | To install Steam in your new wineprefix, you have to run 83 | 84 | $ WINEPREFIX="/path/to/your/new/wineprefix" ./wine-2.0-rc1-64-build/wine ~/Downloads/SteamSetup.exe 85 | 86 | Don't forget to put the same wineprefix path in this scripts: 87 | 88 | $ $EDITOR ./winecfg.sh 89 | $ $EDITOR ./steam.sh 90 | $ $EDITOR ./steam-trace.sh 91 | 92 | If you want the game to start in a window you can use `+set r_fullscreen 0` 93 | 94 | Right click on DOOM in steam library -> Properties -> Set Launch Options: 95 | 96 | +set r_fullscreen 0 97 | 98 | 99 | http://steamcommunity.com/app/379720/discussions/0/152391995402132325/ 100 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | NCPU=`cat /proc/cpuinfo |grep vendor_id |wc -l` 2 | let NCPU=$NCPU+2 3 | echo "Will build with 'make -j$NCPU' ... please edit this script if incorrect." 4 | 5 | pkgname=wine-2.0-rc1 6 | 7 | srcdir=`pwd` 8 | 9 | function configure64 { 10 | ../$pkgname/configure \ 11 | --prefix=/usr \ 12 | --libdir=/usr/lib \ 13 | --with-x \ 14 | --with-xattr \ 15 | --with-gstreamer \ 16 | --disable-tests \ 17 | --enable-win64 18 | 19 | } 20 | 21 | _wine32opts=( 22 | --libdir=/usr/lib32 23 | --with-wine64="$srcdir/$pkgname-64-build" 24 | ) 25 | 26 | function configure32 { 27 | ../$pkgname/configure \ 28 | --prefix=/usr \ 29 | --with-x \ 30 | --with-xattr \ 31 | --with-gstreamer \ 32 | --disable-tests \ 33 | "${_wine32opts[@]}" 34 | 35 | } 36 | 37 | mkdir -p "$srcdir/$pkgname-32-build" 38 | mkdir -p "$srcdir/$pkgname-64-build" 39 | 40 | # Build x64 41 | 42 | echo "Building Wine-64..." 43 | cd "$srcdir/$pkgname-64-build" 44 | 45 | configure64 46 | make -j$NCPU 47 | #make 48 | 49 | # Build x32 50 | 51 | export PKG_CONFIG_PATH="/usr/lib32/pkgconfig" 52 | 53 | echo "Building Wine-32..." 54 | cd "$srcdir/$pkgname-32-build" 55 | 56 | configure32 57 | make -j$NCPU 58 | #make 59 | -------------------------------------------------------------------------------- /steam-trace.sh: -------------------------------------------------------------------------------- 1 | cd wine-2.0-rc1-64-build 2 | 3 | WINEPREFIX="/games/wine/steam/wineprefix" WINEDEBUG="-all,+winhttp" ./wine "C:\\\\Steam\\\\Steam.exe" "-no-cef-sandbox" 4 | -------------------------------------------------------------------------------- /steam.sh: -------------------------------------------------------------------------------- 1 | cd wine-2.0-rc1-64-build 2 | 3 | WINEPREFIX="/games/wine/steam/wineprefix" ./wine "C:\\\\Steam\\\\Steam.exe" "-no-cef-sandbox" 4 | -------------------------------------------------------------------------------- /wine-2.0-rc1/dlls/bcrypt/bcrypt.spec: -------------------------------------------------------------------------------- 1 | @ stub BCryptAddContextFunction 2 | @ stub BCryptAddContextFunctionProvider 3 | @ stdcall BCryptCloseAlgorithmProvider(ptr long) 4 | @ stub BCryptConfigureContext 5 | @ stub BCryptConfigureContextFunction 6 | @ stub BCryptCreateContext 7 | @ stdcall BCryptCreateHash(ptr ptr ptr long ptr long long) 8 | @ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long) 9 | @ stub BCryptDeleteContext 10 | @ stub BCryptDeriveKey 11 | @ stdcall BCryptDestroyHash(ptr) 12 | @ stdcall BCryptDestroyKey(ptr) 13 | @ stub BCryptDestroySecret 14 | @ stdcall BCryptDuplicateHash(ptr ptr ptr long long) 15 | @ stub BCryptDuplicateKey 16 | @ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) 17 | @ stdcall BCryptEnumAlgorithms(long ptr ptr long) 18 | @ stub BCryptEnumContextFunctionProviders 19 | @ stub BCryptEnumContextFunctions 20 | @ stub BCryptEnumContexts 21 | @ stub BCryptEnumProviders 22 | @ stub BCryptEnumRegisteredProviders 23 | @ stub BCryptExportKey 24 | @ stub BCryptFinalizeKeyPair 25 | @ stdcall BCryptFinishHash(ptr ptr long long) 26 | @ stub BCryptFreeBuffer 27 | @ stdcall BCryptGenRandom(ptr ptr long long) 28 | @ stub BCryptGenerateKeyPair 29 | @ stdcall BCryptGenerateSymmetricKey(ptr ptr ptr long ptr long long) 30 | @ stdcall BCryptGetFipsAlgorithmMode(ptr) 31 | @ stdcall BCryptGetProperty(ptr wstr ptr long ptr long) 32 | @ stdcall BCryptHash(ptr ptr long ptr long ptr long) 33 | @ stdcall BCryptHashData(ptr ptr long long) 34 | @ stub BCryptImportKey 35 | @ stub BCryptImportKeyPair 36 | @ stdcall BCryptOpenAlgorithmProvider(ptr wstr wstr long) 37 | @ stub BCryptQueryContextConfiguration 38 | @ stub BCryptQueryContextFunctionConfiguration 39 | @ stub BCryptQueryContextFunctionProperty 40 | @ stub BCryptQueryProviderRegistration 41 | @ stub BCryptRegisterConfigChangeNotify 42 | @ stub BCryptRegisterProvider 43 | @ stub BCryptRemoveContextFunction 44 | @ stub BCryptRemoveContextFunctionProvider 45 | @ stub BCryptResolveProviders 46 | @ stub BCryptSecretAgreement 47 | @ stub BCryptSetAuditingInterface 48 | @ stub BCryptSetContextFunctionProperty 49 | @ stub BCryptSetProperty 50 | @ stub BCryptSignHash 51 | @ stub BCryptUnregisterConfigChangeNotify 52 | @ stub BCryptUnregisterProvider 53 | @ stub BCryptVerifySignature 54 | @ stub GetAsymmetricEncryptionInterface 55 | @ stub GetCipherInterface 56 | @ stub GetHashInterface 57 | @ stub GetRngInterface 58 | @ stub GetSecretAgreementInterface 59 | @ stub GetSignatureInterface 60 | -------------------------------------------------------------------------------- /wine-2.0-rc1/dlls/bcrypt/bcrypt_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Henri Verbeet for CodeWeavers 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 | * 18 | */ 19 | 20 | #include "config.h" 21 | #include "wine/port.h" 22 | 23 | #include 24 | #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H 25 | #include 26 | #include 27 | #elif defined(SONAME_LIBGNUTLS) 28 | #include 29 | #include 30 | #endif 31 | 32 | #include "ntstatus.h" 33 | #define WIN32_NO_STATUS 34 | #include "windef.h" 35 | #include "winbase.h" 36 | #include "ntsecapi.h" 37 | #include "bcrypt.h" 38 | 39 | #include "wine/debug.h" 40 | #include "wine/library.h" 41 | #include "wine/unicode.h" 42 | 43 | WINE_DEFAULT_DEBUG_CHANNEL(bcrypt); 44 | 45 | static HINSTANCE instance; 46 | 47 | #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) 48 | WINE_DECLARE_DEBUG_CHANNEL(winediag); 49 | 50 | #define MAX_DUPLICATES 1024 51 | 52 | static void *libgnutls_handle; 53 | #define MAKE_FUNCPTR(f) static typeof(f) * p##f 54 | MAKE_FUNCPTR(gnutls_global_deinit); 55 | MAKE_FUNCPTR(gnutls_global_init); 56 | MAKE_FUNCPTR(gnutls_global_set_log_function); 57 | MAKE_FUNCPTR(gnutls_global_set_log_level); 58 | MAKE_FUNCPTR(gnutls_hash); 59 | MAKE_FUNCPTR(gnutls_hash_deinit); 60 | MAKE_FUNCPTR(gnutls_hash_init); 61 | MAKE_FUNCPTR(gnutls_hmac); 62 | MAKE_FUNCPTR(gnutls_hmac_deinit); 63 | MAKE_FUNCPTR(gnutls_hmac_init); 64 | // DOOM FUNCTIONS START 65 | MAKE_FUNCPTR(gnutls_cipher_deinit); 66 | MAKE_FUNCPTR(gnutls_cipher_init); 67 | MAKE_FUNCPTR(gnutls_cipher_encrypt2); 68 | MAKE_FUNCPTR(gnutls_cipher_decrypt2); 69 | MAKE_FUNCPTR(gnutls_cipher_set_iv); 70 | // DOOM FUNCTIONS END 71 | MAKE_FUNCPTR(gnutls_perror); 72 | #undef MAKE_FUNCPTR 73 | 74 | static void gnutls_log( int level, const char *msg ) 75 | { 76 | TRACE( "<%d> %s", level, msg ); 77 | } 78 | 79 | static BOOL gnutls_initialize(void) 80 | { 81 | int ret; 82 | 83 | if (!(libgnutls_handle = wine_dlopen( SONAME_LIBGNUTLS, RTLD_NOW, NULL, 0 ))) 84 | { 85 | ERR_(winediag)( "failed to load libgnutls, no support for crypto hashes\n" ); 86 | return FALSE; 87 | } 88 | 89 | #define LOAD_FUNCPTR(f) \ 90 | if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \ 91 | { \ 92 | ERR( "failed to load %s\n", #f ); \ 93 | goto fail; \ 94 | } 95 | 96 | LOAD_FUNCPTR(gnutls_global_deinit) 97 | LOAD_FUNCPTR(gnutls_global_init) 98 | LOAD_FUNCPTR(gnutls_global_set_log_function) 99 | LOAD_FUNCPTR(gnutls_global_set_log_level) 100 | LOAD_FUNCPTR(gnutls_hash); 101 | LOAD_FUNCPTR(gnutls_hash_deinit); 102 | LOAD_FUNCPTR(gnutls_hash_init); 103 | LOAD_FUNCPTR(gnutls_hmac); 104 | LOAD_FUNCPTR(gnutls_hmac_deinit); 105 | LOAD_FUNCPTR(gnutls_hmac_init); 106 | // DOOM FUNCTIONS START 107 | LOAD_FUNCPTR(gnutls_cipher_deinit); 108 | LOAD_FUNCPTR(gnutls_cipher_init); 109 | LOAD_FUNCPTR(gnutls_cipher_encrypt2); 110 | LOAD_FUNCPTR(gnutls_cipher_decrypt2); 111 | LOAD_FUNCPTR(gnutls_cipher_set_iv); 112 | // DOOM FUNCTIONS END 113 | LOAD_FUNCPTR(gnutls_perror) 114 | #undef LOAD_FUNCPTR 115 | 116 | if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS) 117 | { 118 | pgnutls_perror( ret ); 119 | goto fail; 120 | } 121 | 122 | if (TRACE_ON( bcrypt )) 123 | { 124 | pgnutls_global_set_log_level( 4 ); 125 | pgnutls_global_set_log_function( gnutls_log ); 126 | } 127 | 128 | return TRUE; 129 | 130 | fail: 131 | wine_dlclose( libgnutls_handle, NULL, 0 ); 132 | libgnutls_handle = NULL; 133 | return FALSE; 134 | } 135 | 136 | static void gnutls_uninitialize(void) 137 | { 138 | pgnutls_global_deinit(); 139 | wine_dlclose( libgnutls_handle, NULL, 0 ); 140 | libgnutls_handle = NULL; 141 | } 142 | #endif /* HAVE_GNUTLS_HASH && !HAVE_COMMONCRYPTO_COMMONDIGEST_H */ 143 | 144 | NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount, 145 | BCRYPT_ALGORITHM_IDENTIFIER **ppAlgList, ULONG dwFlags) 146 | { 147 | FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations, pAlgCount, ppAlgList, dwFlags); 148 | 149 | *ppAlgList=NULL; 150 | *pAlgCount=0; 151 | 152 | return STATUS_NOT_IMPLEMENTED; 153 | } 154 | 155 | #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0') 156 | #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H') 157 | #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0') 158 | 159 | struct object 160 | { 161 | ULONG magic; 162 | }; 163 | 164 | enum alg_id 165 | { 166 | ALG_ID_MD5, 167 | ALG_ID_RNG, 168 | ALG_ID_SHA1, 169 | ALG_ID_SHA256, 170 | ALG_ID_SHA384, 171 | ALG_ID_SHA512, 172 | 173 | ALG_ID_AES 174 | }; 175 | 176 | static const struct { 177 | ULONG hash_length; 178 | const WCHAR *alg_name; 179 | } alg_props[] = { 180 | /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM }, 181 | /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM }, 182 | /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM }, 183 | /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM }, 184 | /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM }, 185 | /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM } 186 | }; 187 | 188 | struct algorithm 189 | { 190 | struct object hdr; 191 | enum alg_id id; 192 | BOOL hmac; 193 | }; 194 | 195 | NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags) 196 | { 197 | const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG; 198 | struct algorithm *algorithm = handle; 199 | 200 | TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags); 201 | 202 | if (!algorithm) 203 | { 204 | /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG 205 | * is set. In this case the preferred system RNG is used. 206 | */ 207 | if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)) 208 | return STATUS_INVALID_HANDLE; 209 | } 210 | else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG) 211 | return STATUS_INVALID_HANDLE; 212 | 213 | if (!buffer) 214 | return STATUS_INVALID_PARAMETER; 215 | 216 | if (flags & ~supported_flags) 217 | FIXME("unsupported flags %08x\n", flags & ~supported_flags); 218 | 219 | if (algorithm) 220 | FIXME("ignoring selected algorithm\n"); 221 | 222 | /* When zero bytes are requested the function returns success too. */ 223 | if (!count) 224 | return STATUS_SUCCESS; 225 | 226 | if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)) 227 | { 228 | if (RtlGenRandom(buffer, count)) 229 | return STATUS_SUCCESS; 230 | } 231 | 232 | FIXME("called with unsupported parameters, returning error\n"); 233 | return STATUS_NOT_IMPLEMENTED; 234 | } 235 | 236 | NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags ) 237 | { 238 | struct algorithm *alg; 239 | enum alg_id alg_id; 240 | 241 | const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG; 242 | 243 | TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags ); 244 | 245 | if (!handle || !id) return STATUS_INVALID_PARAMETER; 246 | if (flags & ~supported_flags) 247 | { 248 | FIXME( "unsupported flags %08x\n", flags & ~supported_flags); 249 | return STATUS_NOT_IMPLEMENTED; 250 | } 251 | 252 | if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1; 253 | else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5; 254 | else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG; 255 | else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256; 256 | else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384; 257 | else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512; 258 | else if (!strcmpW( id, BCRYPT_AES_ALGORITHM )) alg_id = ALG_ID_AES; 259 | else 260 | { 261 | FIXME( "algorithm %s not supported\n", debugstr_w(id) ); 262 | return STATUS_NOT_IMPLEMENTED; 263 | } 264 | if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER )) 265 | { 266 | FIXME( "implementation %s not supported\n", debugstr_w(implementation) ); 267 | return STATUS_NOT_IMPLEMENTED; 268 | } 269 | 270 | if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY; 271 | alg->hdr.magic = MAGIC_ALG; 272 | alg->id = alg_id; 273 | alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG; 274 | 275 | *handle = alg; 276 | return STATUS_SUCCESS; 277 | } 278 | 279 | NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags ) 280 | { 281 | struct algorithm *alg = handle; 282 | 283 | TRACE( "%p, %08x\n", handle, flags ); 284 | 285 | if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; 286 | HeapFree( GetProcessHeap(), 0, alg ); 287 | return STATUS_SUCCESS; 288 | } 289 | 290 | NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled) 291 | { 292 | FIXME("%p - semi-stub\n", enabled); 293 | 294 | if (!enabled) 295 | return STATUS_INVALID_PARAMETER; 296 | 297 | *enabled = FALSE; 298 | return STATUS_SUCCESS; 299 | } 300 | 301 | #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H 302 | struct hash 303 | { 304 | struct object hdr; 305 | enum alg_id alg_id; 306 | BOOL hmac; 307 | union 308 | { 309 | CC_MD5_CTX md5_ctx; 310 | CC_SHA1_CTX sha1_ctx; 311 | CC_SHA256_CTX sha256_ctx; 312 | CC_SHA512_CTX sha512_ctx; 313 | CCHmacContext hmac_ctx; 314 | } u; 315 | }; 316 | 317 | static NTSTATUS hash_init( struct hash *hash ) 318 | { 319 | switch (hash->alg_id) 320 | { 321 | case ALG_ID_MD5: 322 | CC_MD5_Init( &hash->u.md5_ctx ); 323 | break; 324 | 325 | case ALG_ID_SHA1: 326 | CC_SHA1_Init( &hash->u.sha1_ctx ); 327 | break; 328 | 329 | case ALG_ID_SHA256: 330 | CC_SHA256_Init( &hash->u.sha256_ctx ); 331 | break; 332 | 333 | case ALG_ID_SHA384: 334 | CC_SHA384_Init( &hash->u.sha512_ctx ); 335 | break; 336 | 337 | case ALG_ID_SHA512: 338 | CC_SHA512_Init( &hash->u.sha512_ctx ); 339 | break; 340 | 341 | default: 342 | ERR( "unhandled id %u\n", hash->alg_id ); 343 | return STATUS_NOT_IMPLEMENTED; 344 | } 345 | return STATUS_SUCCESS; 346 | } 347 | 348 | static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) 349 | { 350 | CCHmacAlgorithm cc_algorithm; 351 | switch (hash->alg_id) 352 | { 353 | case ALG_ID_MD5: 354 | cc_algorithm = kCCHmacAlgMD5; 355 | break; 356 | 357 | case ALG_ID_SHA1: 358 | cc_algorithm = kCCHmacAlgSHA1; 359 | break; 360 | 361 | case ALG_ID_SHA256: 362 | cc_algorithm = kCCHmacAlgSHA256; 363 | break; 364 | 365 | case ALG_ID_SHA384: 366 | cc_algorithm = kCCHmacAlgSHA384; 367 | break; 368 | 369 | case ALG_ID_SHA512: 370 | cc_algorithm = kCCHmacAlgSHA512; 371 | break; 372 | 373 | default: 374 | ERR( "unhandled id %u\n", hash->alg_id ); 375 | return STATUS_NOT_IMPLEMENTED; 376 | } 377 | 378 | CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size ); 379 | return STATUS_SUCCESS; 380 | } 381 | 382 | 383 | static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) 384 | { 385 | switch (hash->alg_id) 386 | { 387 | case ALG_ID_MD5: 388 | CC_MD5_Update( &hash->u.md5_ctx, input, size ); 389 | break; 390 | 391 | case ALG_ID_SHA1: 392 | CC_SHA1_Update( &hash->u.sha1_ctx, input, size ); 393 | break; 394 | 395 | case ALG_ID_SHA256: 396 | CC_SHA256_Update( &hash->u.sha256_ctx, input, size ); 397 | break; 398 | 399 | case ALG_ID_SHA384: 400 | CC_SHA384_Update( &hash->u.sha512_ctx, input, size ); 401 | break; 402 | 403 | case ALG_ID_SHA512: 404 | CC_SHA512_Update( &hash->u.sha512_ctx, input, size ); 405 | break; 406 | 407 | default: 408 | ERR( "unhandled id %u\n", hash->alg_id ); 409 | return STATUS_NOT_IMPLEMENTED; 410 | } 411 | return STATUS_SUCCESS; 412 | } 413 | 414 | static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) 415 | { 416 | CCHmacUpdate( &hash->u.hmac_ctx, input, size ); 417 | return STATUS_SUCCESS; 418 | } 419 | 420 | static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) 421 | { 422 | switch (hash->alg_id) 423 | { 424 | case ALG_ID_MD5: 425 | CC_MD5_Final( output, &hash->u.md5_ctx ); 426 | break; 427 | 428 | case ALG_ID_SHA1: 429 | CC_SHA1_Final( output, &hash->u.sha1_ctx ); 430 | break; 431 | 432 | case ALG_ID_SHA256: 433 | CC_SHA256_Final( output, &hash->u.sha256_ctx ); 434 | break; 435 | 436 | case ALG_ID_SHA384: 437 | CC_SHA384_Final( output, &hash->u.sha512_ctx ); 438 | break; 439 | 440 | case ALG_ID_SHA512: 441 | CC_SHA512_Final( output, &hash->u.sha512_ctx ); 442 | break; 443 | 444 | default: 445 | ERR( "unhandled id %u\n", hash->alg_id ); 446 | break; 447 | } 448 | return STATUS_SUCCESS; 449 | } 450 | 451 | static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) 452 | { 453 | CCHmacFinal( &hash->u.hmac_ctx, output ); 454 | 455 | return STATUS_SUCCESS; 456 | } 457 | #elif defined(HAVE_GNUTLS_HASH) 458 | 459 | struct hash 460 | { 461 | struct object hdr; 462 | enum alg_id alg_id; 463 | BOOL hmac; 464 | 465 | struct hash *duplicate; 466 | 467 | union 468 | { 469 | gnutls_hash_hd_t hash_handle; 470 | gnutls_hmac_hd_t hmac_handle; 471 | } u; 472 | }; 473 | 474 | struct key 475 | { 476 | struct object hdr; 477 | enum alg_id alg_id; 478 | 479 | gnutls_datum_t key_storage; 480 | gnutls_cipher_hd_t cypher_handle; 481 | }; 482 | 483 | static NTSTATUS hash_init( struct hash *hash ) 484 | { 485 | gnutls_digest_algorithm_t alg; 486 | 487 | if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; 488 | 489 | switch (hash->alg_id) 490 | { 491 | case ALG_ID_MD5: 492 | alg = GNUTLS_DIG_MD5; 493 | break; 494 | case ALG_ID_SHA1: 495 | alg = GNUTLS_DIG_SHA1; 496 | break; 497 | 498 | case ALG_ID_SHA256: 499 | alg = GNUTLS_DIG_SHA256; 500 | break; 501 | 502 | case ALG_ID_SHA384: 503 | alg = GNUTLS_DIG_SHA384; 504 | break; 505 | 506 | case ALG_ID_SHA512: 507 | alg = GNUTLS_DIG_SHA512; 508 | break; 509 | 510 | default: 511 | ERR( "unhandled id %u\n", hash->alg_id ); 512 | return STATUS_NOT_IMPLEMENTED; 513 | } 514 | 515 | if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR; 516 | return STATUS_SUCCESS; 517 | } 518 | 519 | static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) 520 | { 521 | gnutls_mac_algorithm_t alg; 522 | 523 | if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; 524 | 525 | switch (hash->alg_id) 526 | { 527 | case ALG_ID_MD5: 528 | alg = GNUTLS_MAC_MD5; 529 | break; 530 | case ALG_ID_SHA1: 531 | alg = GNUTLS_MAC_SHA1; 532 | break; 533 | 534 | case ALG_ID_SHA256: 535 | alg = GNUTLS_MAC_SHA256; 536 | break; 537 | 538 | case ALG_ID_SHA384: 539 | alg = GNUTLS_MAC_SHA384; 540 | break; 541 | 542 | case ALG_ID_SHA512: 543 | alg = GNUTLS_MAC_SHA512; 544 | break; 545 | 546 | default: 547 | ERR( "unhandled id %u\n", hash->alg_id ); 548 | return STATUS_NOT_IMPLEMENTED; 549 | } 550 | 551 | if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR; 552 | return STATUS_SUCCESS; 553 | } 554 | 555 | static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) 556 | { 557 | if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR; 558 | return STATUS_SUCCESS; 559 | } 560 | 561 | static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) 562 | { 563 | if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR; 564 | return STATUS_SUCCESS; 565 | } 566 | 567 | static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) 568 | { 569 | pgnutls_hash_deinit( hash->u.hash_handle, output ); 570 | return STATUS_SUCCESS; 571 | } 572 | 573 | static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) 574 | { 575 | pgnutls_hmac_deinit( hash->u.hmac_handle, output ); 576 | return STATUS_SUCCESS; 577 | } 578 | 579 | // DOOM FUNCTIONS START 580 | 581 | static NTSTATUS hashmac_destroy_single( struct hash *hashmac ) 582 | { 583 | // TRACE( "%p\n", hashmac ); 584 | 585 | if (!hashmac) { 586 | // TRACE( "HANDLE IS NULL\n" ); 587 | return STATUS_SUCCESS; 588 | } 589 | 590 | HeapFree( GetProcessHeap(), 0, hashmac ); 591 | 592 | // TRACE( "hash destroy OK\n" ); 593 | return STATUS_SUCCESS; 594 | } 595 | 596 | static NTSTATUS hashmac_finish_single( struct hash *hashmac, UCHAR *output, ULONG size ) 597 | { 598 | // TRACE( "%p\n", hashmac ); 599 | 600 | if (!hashmac) { 601 | // TRACE( "HANDLE IS NULL\n" ); 602 | return STATUS_SUCCESS; 603 | } 604 | 605 | if (hashmac->hmac) 606 | { 607 | // TRACE( "Hash is HMAC\n" ); 608 | hmac_finish(hashmac, output, size); 609 | } 610 | else 611 | { 612 | // TRACE( "Hash is NOT HMAC\n" ); 613 | hash_finish(hashmac, output, size); 614 | } 615 | 616 | // TRACE( "hash finish OK\n" ); 617 | return STATUS_SUCCESS; 618 | } 619 | 620 | static NTSTATUS hashmac_update_single( struct hash *hashmac, UCHAR *input, ULONG size ) 621 | { 622 | // TRACE( "%p\n", hashmac); 623 | 624 | if (!hashmac) { 625 | // TRACE( "HANDLE IS NULL\n" ); 626 | return STATUS_SUCCESS; 627 | } 628 | 629 | if (hashmac->hmac) 630 | { 631 | // TRACE( "Hash is HMAC\n" ); 632 | return hmac_update(hashmac, input, size); 633 | } 634 | else 635 | { 636 | // TRACE( "Hash is NOT HMAC\n" ); 637 | return hash_update(hashmac, input, size); 638 | } 639 | } 640 | 641 | static NTSTATUS hashmac_init_single( struct hash **p_hashmac, struct algorithm *alg, UCHAR *secret, ULONG secret_size ) 642 | { 643 | struct hash *hashmac; 644 | NTSTATUS status; 645 | 646 | // TRACE( "%p\n", p_hashmac ); 647 | 648 | hashmac = HeapAlloc( GetProcessHeap(), 0, sizeof(*hashmac) ); 649 | if (!hashmac) { 650 | return STATUS_NO_MEMORY; 651 | } 652 | 653 | hashmac->duplicate = NULL; 654 | 655 | hashmac->hdr.magic = MAGIC_HASH; 656 | hashmac->alg_id = alg->id; 657 | hashmac->hmac = alg->hmac; 658 | 659 | if (hashmac->hmac) 660 | { 661 | // TRACE( "Hash is HMAC\n" ); 662 | status = hmac_init( hashmac, secret, secret_size ); 663 | } 664 | else 665 | { 666 | // TRACE( "Hash is NOT HMAC\n" ); 667 | status = hash_init( hashmac ); 668 | } 669 | 670 | if (status != STATUS_SUCCESS) 671 | { 672 | // TRACE( "hash init ERR\n" ); 673 | HeapFree( GetProcessHeap(), 0, hashmac ); 674 | return status; 675 | } 676 | 677 | *p_hashmac = hashmac; 678 | // TRACE( "hash init OK\n" ); 679 | return STATUS_SUCCESS; 680 | } 681 | 682 | static NTSTATUS hashmac_destroy_duplicated( struct hash *root ) 683 | { 684 | struct hash *child; 685 | 686 | // TRACE( "%p\n", root ); 687 | 688 | while (root) { 689 | child = root->duplicate; 690 | 691 | hashmac_destroy_single(root); 692 | 693 | root = child; 694 | } 695 | 696 | // TRACE( "hashes destroy OK\n" ); 697 | return STATUS_SUCCESS; 698 | } 699 | 700 | static NTSTATUS hashmac_finish_duplicated( struct hash *root, UCHAR *output, ULONG size ) 701 | { 702 | struct hash *child; 703 | BOOL done = FALSE; 704 | 705 | // TRACE( "%p\n", root ); 706 | 707 | while (root) { 708 | child = root->duplicate; 709 | 710 | if (done) { 711 | hashmac_finish_single(root, NULL, 0); 712 | } else { 713 | hashmac_finish_single(root, output, size); 714 | done = TRUE; 715 | } 716 | 717 | root = child; 718 | } 719 | 720 | // TRACE( "hashes finish OK\n" ); 721 | return STATUS_SUCCESS; 722 | } 723 | 724 | static NTSTATUS hashmac_update_duplicated( struct hash *root, UCHAR *input, ULONG size ) 725 | { 726 | struct hash *child; 727 | NTSTATUS status; 728 | 729 | // TRACE( "%p\n", root ); 730 | 731 | while (root) { 732 | child = root->duplicate; 733 | 734 | status = hashmac_update_single(root, input, size); 735 | 736 | if (status != STATUS_SUCCESS) { 737 | ERR( "hashes update ERR\n" ); 738 | // clean tree leftovers 739 | // hashmac_finish_duplicated(root->duplicate, NULL, 0); 740 | // hashmac_destroy_duplicated(root->duplicate); 741 | return status; 742 | } 743 | 744 | root = child; 745 | } 746 | 747 | // TRACE( "hashes update OK\n" ); 748 | return STATUS_SUCCESS; 749 | } 750 | 751 | static NTSTATUS hashmac_init_duplicated( struct hash **p_hashmac, struct algorithm *alg, UCHAR *secret, ULONG secret_size ) 752 | { 753 | struct hash *root; 754 | struct hash *hash; 755 | NTSTATUS status; 756 | int i; 757 | 758 | status = hashmac_init_single(&root, alg, secret, secret_size); 759 | if (status != STATUS_SUCCESS) { 760 | ERR( "hashes init ERR: unabled to create ROOT\n" ); 761 | return status; 762 | } 763 | 764 | hash = root; 765 | 766 | for (i = 0; i < MAX_DUPLICATES; i++) { 767 | 768 | status = hashmac_init_single(&hash->duplicate, alg, secret, secret_size); 769 | 770 | if (status != STATUS_SUCCESS) { 771 | ERR( "hashes init ERR: unable to create TREE\n" ); 772 | hashmac_finish_duplicated(root, NULL, 0); 773 | hashmac_destroy_duplicated(root); 774 | 775 | return status; 776 | } 777 | 778 | hash = hash->duplicate; 779 | } 780 | 781 | *p_hashmac = root; 782 | 783 | // TRACE( "hashes init OK\n" ); 784 | return STATUS_SUCCESS; 785 | } 786 | 787 | static NTSTATUS hashmac_get_last_duplicate( struct hash *root, struct hash **duplicate_out ) 788 | { 789 | struct hash **phash; 790 | ULONG count = 0; 791 | 792 | if (!root) { 793 | return STATUS_INVALID_HANDLE; 794 | } 795 | 796 | if (!root->duplicate) { 797 | ERR( "cannot create duplicate: no duplicates left for hash\n" ); 798 | return STATUS_NO_MEMORY; 799 | } 800 | 801 | phash = &root; 802 | 803 | while ((*phash)->duplicate && (*phash)->duplicate->duplicate) { 804 | phash = &(*phash)->duplicate; 805 | count++; 806 | } 807 | 808 | *duplicate_out = (*phash)->duplicate; 809 | (*phash)->duplicate = NULL; 810 | 811 | FIXME( "duplicates left for hash %p: %u\n", root, count ); 812 | 813 | return STATUS_SUCCESS; 814 | } 815 | 816 | static NTSTATUS key_init( struct key *key, UCHAR *secret, ULONG size ) 817 | { 818 | gnutls_cipher_algorithm_t alg; 819 | 820 | if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; 821 | 822 | switch (key->alg_id) 823 | { 824 | case ALG_ID_AES: 825 | switch (size) 826 | { 827 | case 128 / 8: 828 | FIXME( "128 bit key provided\n" ); 829 | alg = GNUTLS_CIPHER_AES_128_CBC; 830 | break; 831 | case 192 / 8: 832 | FIXME( "192 bit key provided\n" ); 833 | alg = GNUTLS_CIPHER_AES_192_CBC; 834 | break; 835 | case 256 / 8: 836 | FIXME( "256 bit key provided\n" ); 837 | alg = GNUTLS_CIPHER_AES_256_CBC; 838 | break; 839 | default: 840 | ERR( "unhandled key size %u\n", size ); 841 | return STATUS_NOT_IMPLEMENTED; 842 | } 843 | 844 | break; 845 | 846 | default: 847 | ERR( "unhandled id %u\n", key->alg_id ); 848 | return STATUS_NOT_IMPLEMENTED; 849 | } 850 | 851 | key->key_storage.data = secret; 852 | key->key_storage.size = size; 853 | 854 | // if (pgnutls_cipher_init( &key->cypher_handle, alg, &key->key_storage, NULL)) return STATUS_INTERNAL_ERROR; 855 | if (pgnutls_cipher_init( &key->cypher_handle, alg, &key->key_storage, NULL)) { 856 | ERR("gnutls failed to init cipher"); 857 | return STATUS_INTERNAL_ERROR; 858 | } 859 | return STATUS_SUCCESS; 860 | } 861 | 862 | static NTSTATUS key_finish( struct key *key ) 863 | { 864 | pgnutls_cipher_deinit ( key->cypher_handle ); 865 | return STATUS_SUCCESS; 866 | } 867 | 868 | static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_size, UCHAR *iv, ULONG iv_size, UCHAR *output, ULONG output_size ) 869 | { 870 | if (iv) { 871 | pgnutls_cipher_set_iv(key->cypher_handle, iv, iv_size); 872 | } 873 | 874 | if (pgnutls_cipher_encrypt2(key->cypher_handle, input, input_size, output, output_size)) return STATUS_INTERNAL_ERROR; 875 | return STATUS_SUCCESS; 876 | } 877 | 878 | static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_size, UCHAR *iv, ULONG iv_size, UCHAR *output, ULONG output_size ) 879 | { 880 | if (iv) { 881 | pgnutls_cipher_set_iv(key->cypher_handle, iv, iv_size); 882 | } 883 | 884 | if (pgnutls_cipher_decrypt2(key->cypher_handle, input, input_size, output, output_size)) return STATUS_INTERNAL_ERROR; 885 | return STATUS_SUCCESS; 886 | } 887 | 888 | // DOOM FUNCTIONS END 889 | 890 | #else 891 | struct hash 892 | { 893 | struct object hdr; 894 | BOOL hmac; 895 | enum alg_id alg_id; 896 | }; 897 | 898 | static NTSTATUS hash_init( struct hash *hash ) 899 | { 900 | ERR( "support for hashes not available at build time\n" ); 901 | return STATUS_NOT_IMPLEMENTED; 902 | } 903 | 904 | static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) 905 | { 906 | ERR( "support for hashes not available at build time\n" ); 907 | return STATUS_NOT_IMPLEMENTED; 908 | } 909 | 910 | static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) 911 | { 912 | ERR( "support for hashes not available at build time\n" ); 913 | return STATUS_NOT_IMPLEMENTED; 914 | } 915 | 916 | static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) 917 | { 918 | ERR( "support for hashes not available at build time\n" ); 919 | return STATUS_NOT_IMPLEMENTED; 920 | } 921 | 922 | static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) 923 | { 924 | ERR( "support for hashes not available at build time\n" ); 925 | return STATUS_NOT_IMPLEMENTED; 926 | } 927 | 928 | static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) 929 | { 930 | ERR( "support for hashes not available at build time\n" ); 931 | return STATUS_NOT_IMPLEMENTED; 932 | } 933 | #endif 934 | 935 | #define OBJECT_LENGTH_MD5 274 936 | #define OBJECT_LENGTH_SHA1 278 937 | #define OBJECT_LENGTH_SHA256 286 938 | #define OBJECT_LENGTH_SHA384 382 939 | #define OBJECT_LENGTH_SHA512 382 940 | 941 | // windows object length is 622, but we're doing memory management inside the lib 942 | // so we can provide 4 byte size here so DOOM will consume less memory 943 | #define OBJECT_LENGTH_AES 4 944 | 945 | // 128 bit key size default 946 | #define BLOCK_LENGTH_AES 16 947 | 948 | static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) 949 | { 950 | if (!strcmpW( prop, BCRYPT_HASH_LENGTH )) 951 | { 952 | *ret_size = sizeof(ULONG); 953 | if (size < sizeof(ULONG)) 954 | return STATUS_BUFFER_TOO_SMALL; 955 | if(buf) 956 | *(ULONG*)buf = alg_props[id].hash_length; 957 | return STATUS_SUCCESS; 958 | } 959 | 960 | if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME )) 961 | { 962 | *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR); 963 | if (size < *ret_size) 964 | return STATUS_BUFFER_TOO_SMALL; 965 | if(buf) 966 | memcpy(buf, alg_props[id].alg_name, *ret_size); 967 | return STATUS_SUCCESS; 968 | } 969 | 970 | return STATUS_NOT_IMPLEMENTED; 971 | } 972 | 973 | static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) 974 | { 975 | NTSTATUS status; 976 | ULONG value; 977 | 978 | status = generic_alg_property( id, prop, buf, size, ret_size ); 979 | if (status != STATUS_NOT_IMPLEMENTED) 980 | return status; 981 | 982 | switch (id) 983 | { 984 | case ALG_ID_MD5: 985 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 986 | { 987 | value = OBJECT_LENGTH_MD5; 988 | break; 989 | } 990 | FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) ); 991 | return STATUS_NOT_IMPLEMENTED; 992 | 993 | case ALG_ID_RNG: 994 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED; 995 | FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) ); 996 | return STATUS_NOT_IMPLEMENTED; 997 | 998 | case ALG_ID_SHA1: 999 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 1000 | { 1001 | value = OBJECT_LENGTH_SHA1; 1002 | break; 1003 | } 1004 | FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) ); 1005 | return STATUS_NOT_IMPLEMENTED; 1006 | 1007 | case ALG_ID_SHA256: 1008 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 1009 | { 1010 | value = OBJECT_LENGTH_SHA256; 1011 | break; 1012 | } 1013 | FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) ); 1014 | return STATUS_NOT_IMPLEMENTED; 1015 | 1016 | case ALG_ID_SHA384: 1017 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 1018 | { 1019 | value = OBJECT_LENGTH_SHA384; 1020 | break; 1021 | } 1022 | FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) ); 1023 | return STATUS_NOT_IMPLEMENTED; 1024 | 1025 | case ALG_ID_SHA512: 1026 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 1027 | { 1028 | value = OBJECT_LENGTH_SHA512; 1029 | break; 1030 | } 1031 | FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) ); 1032 | return STATUS_NOT_IMPLEMENTED; 1033 | 1034 | case ALG_ID_AES: 1035 | if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH )) 1036 | { 1037 | value = BLOCK_LENGTH_AES; 1038 | break; 1039 | } 1040 | if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 1041 | { 1042 | value = OBJECT_LENGTH_AES; 1043 | break; 1044 | } 1045 | FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); 1046 | return STATUS_NOT_IMPLEMENTED; 1047 | 1048 | default: 1049 | FIXME( "unsupported algorithm %u\n", id ); 1050 | return STATUS_NOT_IMPLEMENTED; 1051 | } 1052 | 1053 | if (size < sizeof(ULONG)) 1054 | { 1055 | *ret_size = sizeof(ULONG); 1056 | return STATUS_BUFFER_TOO_SMALL; 1057 | } 1058 | if (buf) *(ULONG *)buf = value; 1059 | *ret_size = sizeof(ULONG); 1060 | 1061 | return STATUS_SUCCESS; 1062 | } 1063 | 1064 | static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) 1065 | { 1066 | NTSTATUS status; 1067 | 1068 | status = generic_alg_property( id, prop, buf, size, ret_size ); 1069 | if (status == STATUS_NOT_IMPLEMENTED) 1070 | FIXME( "unsupported property %s\n", debugstr_w(prop) ); 1071 | return status; 1072 | } 1073 | 1074 | NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags ) 1075 | { 1076 | struct object *object = handle; 1077 | 1078 | TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags ); 1079 | 1080 | if (!object) return STATUS_INVALID_HANDLE; 1081 | if (!prop || !res) return STATUS_INVALID_PARAMETER; 1082 | 1083 | switch (object->magic) 1084 | { 1085 | case MAGIC_ALG: 1086 | { 1087 | const struct algorithm *alg = (const struct algorithm *)object; 1088 | return get_alg_property( alg->id, prop, buffer, count, res ); 1089 | } 1090 | case MAGIC_HASH: 1091 | { 1092 | const struct hash *hash = (const struct hash *)object; 1093 | return get_hash_property( hash->alg_id, prop, buffer, count, res ); 1094 | } 1095 | default: 1096 | WARN( "unknown magic %08x\n", object->magic ); 1097 | return STATUS_INVALID_HANDLE; 1098 | } 1099 | } 1100 | 1101 | static NTSTATUS Impl_BCryptCreateHash(BOOL with_duplicates, BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, 1102 | UCHAR *secret, ULONG secret_size, ULONG flags ) 1103 | { 1104 | struct algorithm *alg = algorithm; 1105 | struct hash *hash; 1106 | NTSTATUS status; 1107 | 1108 | TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen, 1109 | secret, secret_size, flags ); 1110 | if (flags) 1111 | { 1112 | FIXME( "unimplemented flags %08x\n", flags ); 1113 | return STATUS_NOT_IMPLEMENTED; 1114 | } 1115 | 1116 | if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; 1117 | if (object) FIXME( "ignoring object buffer\n" ); 1118 | 1119 | if (with_duplicates) { 1120 | status = hashmac_init_duplicated(&hash, alg, secret, secret_size); 1121 | } else { 1122 | status = hashmac_init_single(&hash, alg, secret, secret_size); 1123 | } 1124 | 1125 | if (status != STATUS_SUCCESS) { 1126 | return status; 1127 | } 1128 | 1129 | *handle = hash; 1130 | 1131 | TRACE( "hash create OK: %p\n", hash); 1132 | return STATUS_SUCCESS; 1133 | } 1134 | 1135 | NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, 1136 | UCHAR *secret, ULONG secret_size, ULONG flags ) 1137 | { 1138 | // Create duplicates by default 1139 | BOOL with_duplicates = TRUE; 1140 | return Impl_BCryptCreateHash( with_duplicates, algorithm, handle, object, objectlen, secret, secret_size, flags ); 1141 | } 1142 | 1143 | NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle ) 1144 | { 1145 | struct hash *hash = handle; 1146 | 1147 | TRACE( "%p\n", handle ); 1148 | 1149 | if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1150 | 1151 | // hashmac_destroy_single(hash); 1152 | hashmac_destroy_duplicated(hash); 1153 | 1154 | // TRACE( "hash destroy OK\n" ); 1155 | return STATUS_SUCCESS; 1156 | } 1157 | 1158 | NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *hash_handle_out, UCHAR *object, ULONG object_size, ULONG flags) 1159 | { 1160 | struct hash *hash = handle; 1161 | struct hash *duplicate; 1162 | NTSTATUS status; 1163 | 1164 | TRACE( "%p %p %p %u %08x\n", 1165 | handle, 1166 | hash_handle_out, 1167 | object, 1168 | object_size, 1169 | flags 1170 | ); 1171 | 1172 | if (flags) { 1173 | FIXME( "unimplemented flags %08x\n", flags ); 1174 | } 1175 | 1176 | if (object) FIXME( "ignoring object buffer\n" ); 1177 | 1178 | if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1179 | 1180 | status = hashmac_get_last_duplicate(hash, &duplicate); 1181 | 1182 | if (status != STATUS_SUCCESS) { 1183 | return status; 1184 | } 1185 | 1186 | *hash_handle_out = duplicate; 1187 | 1188 | // TRACE( "hash duplicate OK\n" ); 1189 | return STATUS_SUCCESS; 1190 | } 1191 | 1192 | NTSTATUS WINAPI BCryptGenerateSymmetricKey(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *key_handle_out, UCHAR *key_object, ULONG key_object_size, UCHAR *secret, ULONG secret_size, ULONG flags) 1193 | { 1194 | struct key *key; 1195 | struct algorithm *alg = algorithm; 1196 | NTSTATUS status; 1197 | 1198 | TRACE("%p %p %p %u %p %u %08x\n", 1199 | algorithm, 1200 | key_handle_out, 1201 | key_object, 1202 | key_object_size, 1203 | secret, 1204 | secret_size, 1205 | flags 1206 | ); 1207 | 1208 | if (key_object) FIXME( "ignoring object buffer\n" ); 1209 | 1210 | // if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; 1211 | if (!alg || alg->hdr.magic != MAGIC_ALG) { 1212 | FIXME("invalid alg handle"); 1213 | return STATUS_INVALID_HANDLE; 1214 | } 1215 | 1216 | if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) return STATUS_NO_MEMORY; 1217 | 1218 | key->hdr.magic = MAGIC_KEY; 1219 | key->alg_id = alg->id; 1220 | 1221 | status = key_init(key, secret, secret_size); 1222 | 1223 | if (status != STATUS_SUCCESS) { 1224 | ERR("key initiazation failed"); 1225 | HeapFree( GetProcessHeap(), 0, key ); 1226 | return status; 1227 | } 1228 | 1229 | *key_handle_out = key; 1230 | return STATUS_SUCCESS; 1231 | } 1232 | 1233 | NTSTATUS WINAPI BCryptDestroyKey(BCRYPT_KEY_HANDLE handle) 1234 | { 1235 | struct key *key = handle; 1236 | 1237 | TRACE( "%p\n", handle ); 1238 | 1239 | // if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; 1240 | if (!key || key->hdr.magic != MAGIC_KEY) { 1241 | ERR("invalid key handle"); 1242 | return STATUS_INVALID_HANDLE; 1243 | } 1244 | 1245 | key_finish(key); 1246 | 1247 | HeapFree( GetProcessHeap(), 0, key ); 1248 | return STATUS_SUCCESS; 1249 | } 1250 | 1251 | NTSTATUS WINAPI BCryptEncrypt(BCRYPT_KEY_HANDLE handle, UCHAR *pbInput, ULONG cbInput, void *pPaddingInfo, UCHAR *pbIV, ULONG cbIV, UCHAR *pbOutput, ULONG cbOutput, ULONG *pcbResult, ULONG flags) 1252 | { 1253 | struct key *key = handle; 1254 | 1255 | TRACE( "%p %p %u %p %p %u %p %u %p %08x\n", 1256 | handle, 1257 | pbInput, 1258 | cbInput, 1259 | pPaddingInfo, 1260 | pbIV, 1261 | cbIV, 1262 | pbOutput, 1263 | cbOutput, 1264 | pcbResult, 1265 | flags 1266 | ); 1267 | 1268 | // if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; 1269 | if (!key || key->hdr.magic != MAGIC_KEY) { 1270 | ERR("invalid key handle"); 1271 | return STATUS_INVALID_HANDLE; 1272 | } 1273 | 1274 | *pcbResult = cbOutput; 1275 | 1276 | return key_encrypt(key, pbInput, cbInput, pbIV, cbIV, pbOutput, cbOutput ); 1277 | } 1278 | 1279 | NTSTATUS WINAPI BCryptDecrypt(BCRYPT_KEY_HANDLE handle, UCHAR *pbInput, ULONG cbInput, void *pPaddingInfo, UCHAR *pbIV, ULONG cbIV, UCHAR *pbOutput, ULONG cbOutput, ULONG *pcbResult, ULONG flags) 1280 | { 1281 | struct key *key = handle; 1282 | 1283 | TRACE( "%p %p %u %p %p %u %p %u %p %08x\n", 1284 | handle, 1285 | pbInput, 1286 | cbInput, 1287 | pPaddingInfo, 1288 | pbIV, 1289 | cbIV, 1290 | pbOutput, 1291 | cbOutput, 1292 | pcbResult, 1293 | flags 1294 | ); 1295 | 1296 | // if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; 1297 | if (!key || key->hdr.magic != MAGIC_KEY) { 1298 | ERR("invalid key handle"); 1299 | return STATUS_INVALID_HANDLE; 1300 | } 1301 | 1302 | *pcbResult = cbOutput; 1303 | 1304 | return key_decrypt(key, pbInput, cbInput, pbIV, cbIV, pbOutput, cbOutput ); 1305 | } 1306 | 1307 | NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags ) 1308 | { 1309 | struct hash *hash = handle; 1310 | 1311 | TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags ); 1312 | 1313 | if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1314 | if (!input) return STATUS_SUCCESS; 1315 | 1316 | // return hashmac_update_single(hash, input, size); 1317 | return hashmac_update_duplicated(hash, input, size); 1318 | } 1319 | 1320 | NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags ) 1321 | { 1322 | struct hash *hash = handle; 1323 | 1324 | TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags ); 1325 | 1326 | if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1327 | if (!output) return STATUS_INVALID_PARAMETER; 1328 | 1329 | // return hashmac_finish_single(hash, output, size); 1330 | return hashmac_finish_duplicated(hash, output, size); 1331 | } 1332 | 1333 | NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen, 1334 | UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen ) 1335 | { 1336 | NTSTATUS status; 1337 | BCRYPT_HASH_HANDLE handle; 1338 | 1339 | // Single run, duplicates are useless in this case 1340 | BOOL with_duplicates = FALSE; 1341 | 1342 | TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen, 1343 | input, inputlen, output, outputlen ); 1344 | 1345 | status = Impl_BCryptCreateHash( with_duplicates, algorithm, &handle, NULL, 0, secret, secretlen, 0 ); 1346 | if (status != STATUS_SUCCESS) 1347 | { 1348 | return status; 1349 | } 1350 | 1351 | status = BCryptHashData( handle, input, inputlen, 0 ); 1352 | if (status != STATUS_SUCCESS) 1353 | { 1354 | BCryptDestroyHash( handle ); 1355 | return status; 1356 | } 1357 | 1358 | status = BCryptFinishHash( handle, output, outputlen, 0 ); 1359 | if (status != STATUS_SUCCESS) 1360 | { 1361 | BCryptDestroyHash( handle ); 1362 | return status; 1363 | } 1364 | 1365 | return BCryptDestroyHash( handle ); 1366 | } 1367 | 1368 | BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) 1369 | { 1370 | switch (reason) 1371 | { 1372 | case DLL_PROCESS_ATTACH: 1373 | instance = hinst; 1374 | DisableThreadLibraryCalls( hinst ); 1375 | #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) 1376 | gnutls_initialize(); 1377 | #endif 1378 | break; 1379 | 1380 | case DLL_PROCESS_DETACH: 1381 | if (reserved) break; 1382 | #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) 1383 | gnutls_uninitialize(); 1384 | #endif 1385 | break; 1386 | } 1387 | return TRUE; 1388 | } 1389 | -------------------------------------------------------------------------------- /winecfg.sh: -------------------------------------------------------------------------------- 1 | cd wine-2.0-rc1-64-build 2 | 3 | WINEPREFIX="/games/wine/steam/wineprefix" ./wine winecfg 4 | --------------------------------------------------------------------------------