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 <wine/config.h> 21 #include <wine/port.h> 22 23 #include <ntstatus.h> 24 #define WIN32_NO_STATUS 25 #include <windef.h> 26 #include <winbase.h> 27 #include <ntsecapi.h> 28 #include <bcrypt.h> 29 30 #include <wine/debug.h> 31 #include <wine/unicode.h> 32 #include <wine/library.h> 33 34 #ifdef SONAME_LIBMBEDTLS 35 #include <mbedtls/md.h> 36 #include <mbedtls/md5.h> 37 #include <mbedtls/sha1.h> 38 #include <mbedtls/sha256.h> 39 #include <mbedtls/sha512.h> 40 #endif 41 42 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt); 43 44 static HINSTANCE instance; 45 46 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) 47 WINE_DECLARE_DEBUG_CHANNEL(winediag); 48 49 static void *libgnutls_handle; 50 #define MAKE_FUNCPTR(f) static typeof(f) * p##f 51 MAKE_FUNCPTR(gnutls_global_deinit); 52 MAKE_FUNCPTR(gnutls_global_init); 53 MAKE_FUNCPTR(gnutls_global_set_log_function); 54 MAKE_FUNCPTR(gnutls_global_set_log_level); 55 MAKE_FUNCPTR(gnutls_hash); 56 MAKE_FUNCPTR(gnutls_hash_deinit); 57 MAKE_FUNCPTR(gnutls_hash_init); 58 MAKE_FUNCPTR(gnutls_hmac); 59 MAKE_FUNCPTR(gnutls_hmac_deinit); 60 MAKE_FUNCPTR(gnutls_hmac_init); 61 MAKE_FUNCPTR(gnutls_perror); 62 #undef MAKE_FUNCPTR 63 64 static void gnutls_log( int level, const char *msg ) 65 { 66 TRACE( "<%d> %s", level, msg ); 67 } 68 69 static BOOL gnutls_initialize(void) 70 { 71 int ret; 72 73 if (!(libgnutls_handle = wine_dlopen( SONAME_LIBGNUTLS, RTLD_NOW, NULL, 0 ))) 74 { 75 ERR_(winediag)( "failed to load libgnutls, no support for crypto hashes\n" ); 76 return FALSE; 77 } 78 79 #define LOAD_FUNCPTR(f) \ 80 if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \ 81 { \ 82 ERR( "failed to load %s\n", #f ); \ 83 goto fail; \ 84 } 85 86 LOAD_FUNCPTR(gnutls_global_deinit) 87 LOAD_FUNCPTR(gnutls_global_init) 88 LOAD_FUNCPTR(gnutls_global_set_log_function) 89 LOAD_FUNCPTR(gnutls_global_set_log_level) 90 LOAD_FUNCPTR(gnutls_hash); 91 LOAD_FUNCPTR(gnutls_hash_deinit); 92 LOAD_FUNCPTR(gnutls_hash_init); 93 LOAD_FUNCPTR(gnutls_hmac); 94 LOAD_FUNCPTR(gnutls_hmac_deinit); 95 LOAD_FUNCPTR(gnutls_hmac_init); 96 LOAD_FUNCPTR(gnutls_perror) 97 #undef LOAD_FUNCPTR 98 99 if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS) 100 { 101 pgnutls_perror( ret ); 102 goto fail; 103 } 104 105 if (TRACE_ON( bcrypt )) 106 { 107 pgnutls_global_set_log_level( 4 ); 108 pgnutls_global_set_log_function( gnutls_log ); 109 } 110 111 return TRUE; 112 113 fail: 114 wine_dlclose( libgnutls_handle, NULL, 0 ); 115 libgnutls_handle = NULL; 116 return FALSE; 117 } 118 119 static void gnutls_uninitialize(void) 120 { 121 pgnutls_global_deinit(); 122 wine_dlclose( libgnutls_handle, NULL, 0 ); 123 libgnutls_handle = NULL; 124 } 125 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__) 126 WINE_DECLARE_DEBUG_CHANNEL(winediag); 127 128 void *libmbedtls_handle; 129 130 #define MAKE_FUNCPTR(f) static typeof(f) * p##f 131 MAKE_FUNCPTR(mbedtls_md_init); 132 MAKE_FUNCPTR(mbedtls_md_setup); 133 MAKE_FUNCPTR(mbedtls_md_update); 134 MAKE_FUNCPTR(mbedtls_md_hmac_starts); 135 MAKE_FUNCPTR(mbedtls_md_hmac_finish); 136 MAKE_FUNCPTR(mbedtls_md_free); 137 MAKE_FUNCPTR(mbedtls_md5_init); 138 MAKE_FUNCPTR(mbedtls_md5_starts); 139 MAKE_FUNCPTR(mbedtls_md5_update); 140 MAKE_FUNCPTR(mbedtls_md5_finish); 141 MAKE_FUNCPTR(mbedtls_md5_free); 142 MAKE_FUNCPTR(mbedtls_sha1_init); 143 MAKE_FUNCPTR(mbedtls_sha1_starts); 144 MAKE_FUNCPTR(mbedtls_sha1_update); 145 MAKE_FUNCPTR(mbedtls_sha1_finish); 146 MAKE_FUNCPTR(mbedtls_sha1_free); 147 MAKE_FUNCPTR(mbedtls_sha256_init); 148 MAKE_FUNCPTR(mbedtls_sha256_starts); 149 MAKE_FUNCPTR(mbedtls_sha256_update); 150 MAKE_FUNCPTR(mbedtls_sha256_finish); 151 MAKE_FUNCPTR(mbedtls_sha256_free); 152 MAKE_FUNCPTR(mbedtls_sha512_init); 153 MAKE_FUNCPTR(mbedtls_sha512_starts); 154 MAKE_FUNCPTR(mbedtls_sha512_update); 155 MAKE_FUNCPTR(mbedtls_sha512_finish); 156 MAKE_FUNCPTR(mbedtls_sha512_free); 157 #undef MAKE_FUNCPTR 158 159 #define mbedtls_md_init pmbedtls_md_init 160 #define mbedtls_md_setup pmbedtls_md_setup 161 #define mbedtls_md_update pmbedtls_md_update 162 #define mbedtls_md_hmac_starts pmbedtls_md_hmac_starts 163 #define mbedtls_md_hmac_finish pmbedtls_md_hmac_finish 164 #define mbedtls_md_free pmbedtls_md_free 165 #define mbedtls_md5_init pmbedtls_md5_init 166 #define mbedtls_md5_starts pmbedtls_md5_starts 167 #define mbedtls_md5_update pmbedtls_md5_update 168 #define mbedtls_md5_finish pmbedtls_md5_finish 169 #define mbedtls_md5_free pmbedtls_md5_free 170 #define mbedtls_sha1_init pmbedtls_sha1_init 171 #define mbedtls_sha1_starts pmbedtls_sha1_starts 172 #define mbedtls_sha1_update pmbedtls_sha1_update 173 #define mbedtls_sha1_finish pmbedtls_sha1_finish 174 #define mbedtls_sha1_free pmbedtls_sha1_free 175 #define mbedtls_sha256_init pmbedtls_sha256_init 176 #define mbedtls_sha256_starts pmbedtls_sha256_starts 177 #define mbedtls_sha256_update pmbedtls_sha256_update 178 #define mbedtls_sha256_finish pmbedtls_sha256_finish 179 #define mbedtls_sha256_free pmbedtls_sha256_free 180 #define mbedtls_sha512_init pmbedtls_sha512_init 181 #define mbedtls_sha512_starts pmbedtls_sha512_starts 182 #define mbedtls_sha512_update pmbedtls_sha512_update 183 #define mbedtls_sha512_finish pmbedtls_sha512_finish 184 #define mbedtls_sha512_free pmbedtls_sha512_free 185 186 static BOOL mbedtls_initialize(void) 187 { 188 if (!(libmbedtls_handle = wine_dlopen( SONAME_LIBMBEDTLS, RTLD_NOW, NULL, 0 ))) 189 { 190 ERR_(winediag)( "failed to load libmbedtls, no support for crypto hashes\n" ); 191 return FALSE; 192 } 193 194 #define LOAD_FUNCPTR(f) \ 195 if (!(p##f = wine_dlsym( libmbedtls_handle, #f, NULL, 0 ))) \ 196 { \ 197 ERR( "failed to load %s\n", #f ); \ 198 goto fail; \ 199 } 200 201 LOAD_FUNCPTR(mbedtls_md_init) 202 LOAD_FUNCPTR(mbedtls_md_setup) 203 LOAD_FUNCPTR(mbedtls_md_update) 204 LOAD_FUNCPTR(mbedtls_md_hmac_starts) 205 LOAD_FUNCPTR(mbedtls_md_hmac_finish) 206 LOAD_FUNCPTR(mbedtls_md_free); 207 LOAD_FUNCPTR(mbedtls_md5_init) 208 LOAD_FUNCPTR(mbedtls_md5_starts) 209 LOAD_FUNCPTR(mbedtls_md5_update) 210 LOAD_FUNCPTR(mbedtls_md5_finish) 211 LOAD_FUNCPTR(mbedtls_md5_free); 212 LOAD_FUNCPTR(mbedtls_sha1_init) 213 LOAD_FUNCPTR(mbedtls_sha1_starts) 214 LOAD_FUNCPTR(mbedtls_sha1_update) 215 LOAD_FUNCPTR(mbedtls_sha1_finish) 216 LOAD_FUNCPTR(mbedtls_sha1_free); 217 LOAD_FUNCPTR(mbedtls_sha256_init) 218 LOAD_FUNCPTR(mbedtls_sha256_starts) 219 LOAD_FUNCPTR(mbedtls_sha256_update) 220 LOAD_FUNCPTR(mbedtls_sha256_finish) 221 LOAD_FUNCPTR(mbedtls_sha256_free); 222 LOAD_FUNCPTR(mbedtls_sha512_init) 223 LOAD_FUNCPTR(mbedtls_sha512_starts) 224 LOAD_FUNCPTR(mbedtls_sha512_update) 225 LOAD_FUNCPTR(mbedtls_sha512_finish) 226 LOAD_FUNCPTR(mbedtls_sha512_free); 227 #undef LOAD_FUNCPTR 228 229 return TRUE; 230 231 fail: 232 wine_dlclose( libmbedtls_handle, NULL, 0 ); 233 libmbedtls_handle = NULL; 234 return FALSE; 235 } 236 237 static void mbedtls_uninitialize(void) 238 { 239 wine_dlclose( libmbedtls_handle, NULL, 0 ); 240 libmbedtls_handle = NULL; 241 } 242 #endif /* SONAME_LIBMBEDTLS && !HAVE_COMMONCRYPTO_COMMONDIGEST_H && !__REACTOS__ */ 243 244 NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount, 245 BCRYPT_ALGORITHM_IDENTIFIER **ppAlgList, ULONG dwFlags) 246 { 247 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations, pAlgCount, ppAlgList, dwFlags); 248 249 *ppAlgList=NULL; 250 *pAlgCount=0; 251 252 return STATUS_NOT_IMPLEMENTED; 253 } 254 255 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0') 256 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H') 257 struct object 258 { 259 ULONG magic; 260 }; 261 262 enum alg_id 263 { 264 ALG_ID_MD5, 265 ALG_ID_RNG, 266 ALG_ID_SHA1, 267 ALG_ID_SHA256, 268 ALG_ID_SHA384, 269 ALG_ID_SHA512, 270 ALG_ID_ECDSA_P256, 271 ALG_ID_ECDSA_P384, 272 }; 273 274 static const struct { 275 ULONG hash_length; 276 const WCHAR *alg_name; 277 } alg_props[] = { 278 /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM }, 279 /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM }, 280 /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM }, 281 /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM }, 282 /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM }, 283 /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM }, 284 /* ALG_ID_ECDSA_P256 */ { 0, BCRYPT_ECDSA_P256_ALGORITHM }, 285 /* ALG_ID_ECDSA_P384 */ { 0, BCRYPT_ECDSA_P384_ALGORITHM }, 286 }; 287 288 struct algorithm 289 { 290 struct object hdr; 291 enum alg_id id; 292 BOOL hmac; 293 }; 294 295 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags) 296 { 297 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG; 298 struct algorithm *algorithm = handle; 299 300 TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags); 301 302 if (!algorithm) 303 { 304 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG 305 * is set. In this case the preferred system RNG is used. 306 */ 307 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)) 308 return STATUS_INVALID_HANDLE; 309 } 310 else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG) 311 return STATUS_INVALID_HANDLE; 312 313 if (!buffer) 314 return STATUS_INVALID_PARAMETER; 315 316 if (flags & ~supported_flags) 317 FIXME("unsupported flags %08x\n", flags & ~supported_flags); 318 319 if (algorithm) 320 FIXME("ignoring selected algorithm\n"); 321 322 /* When zero bytes are requested the function returns success too. */ 323 if (!count) 324 return STATUS_SUCCESS; 325 326 if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)) 327 { 328 if (RtlGenRandom(buffer, count)) 329 return STATUS_SUCCESS; 330 } 331 332 FIXME("called with unsupported parameters, returning error\n"); 333 return STATUS_NOT_IMPLEMENTED; 334 } 335 336 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags ) 337 { 338 struct algorithm *alg; 339 enum alg_id alg_id; 340 341 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG; 342 343 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags ); 344 345 if (!handle || !id) return STATUS_INVALID_PARAMETER; 346 if (flags & ~supported_flags) 347 { 348 FIXME( "unsupported flags %08x\n", flags & ~supported_flags); 349 return STATUS_NOT_IMPLEMENTED; 350 } 351 352 if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1; 353 else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5; 354 else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG; 355 else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256; 356 else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384; 357 else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512; 358 else if (!strcmpW( id, BCRYPT_ECDSA_P256_ALGORITHM )) alg_id = ALG_ID_ECDSA_P256; 359 else if (!strcmpW( id, BCRYPT_ECDSA_P384_ALGORITHM )) alg_id = ALG_ID_ECDSA_P384; 360 else 361 { 362 FIXME( "algorithm %s not supported\n", debugstr_w(id) ); 363 return STATUS_NOT_IMPLEMENTED; 364 } 365 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER )) 366 { 367 FIXME( "implementation %s not supported\n", debugstr_w(implementation) ); 368 return STATUS_NOT_IMPLEMENTED; 369 } 370 371 if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY; 372 alg->hdr.magic = MAGIC_ALG; 373 alg->id = alg_id; 374 alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG; 375 376 *handle = alg; 377 return STATUS_SUCCESS; 378 } 379 380 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags ) 381 { 382 struct algorithm *alg = handle; 383 384 TRACE( "%p, %08x\n", handle, flags ); 385 386 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; 387 HeapFree( GetProcessHeap(), 0, alg ); 388 return STATUS_SUCCESS; 389 } 390 391 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled) 392 { 393 FIXME("%p - semi-stub\n", enabled); 394 395 if (!enabled) 396 return STATUS_INVALID_PARAMETER; 397 398 *enabled = FALSE; 399 return STATUS_SUCCESS; 400 } 401 402 #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H 403 struct hash 404 { 405 struct object hdr; 406 enum alg_id alg_id; 407 BOOL hmac; 408 union 409 { 410 CC_MD5_CTX md5_ctx; 411 CC_SHA1_CTX sha1_ctx; 412 CC_SHA256_CTX sha256_ctx; 413 CC_SHA512_CTX sha512_ctx; 414 CCHmacContext hmac_ctx; 415 } u; 416 }; 417 418 static NTSTATUS hash_init( struct hash *hash ) 419 { 420 switch (hash->alg_id) 421 { 422 case ALG_ID_MD5: 423 CC_MD5_Init( &hash->u.md5_ctx ); 424 break; 425 426 case ALG_ID_SHA1: 427 CC_SHA1_Init( &hash->u.sha1_ctx ); 428 break; 429 430 case ALG_ID_SHA256: 431 CC_SHA256_Init( &hash->u.sha256_ctx ); 432 break; 433 434 case ALG_ID_SHA384: 435 CC_SHA384_Init( &hash->u.sha512_ctx ); 436 break; 437 438 case ALG_ID_SHA512: 439 CC_SHA512_Init( &hash->u.sha512_ctx ); 440 break; 441 442 default: 443 ERR( "unhandled id %u\n", hash->alg_id ); 444 return STATUS_NOT_IMPLEMENTED; 445 } 446 return STATUS_SUCCESS; 447 } 448 449 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) 450 { 451 CCHmacAlgorithm cc_algorithm; 452 switch (hash->alg_id) 453 { 454 case ALG_ID_MD5: 455 cc_algorithm = kCCHmacAlgMD5; 456 break; 457 458 case ALG_ID_SHA1: 459 cc_algorithm = kCCHmacAlgSHA1; 460 break; 461 462 case ALG_ID_SHA256: 463 cc_algorithm = kCCHmacAlgSHA256; 464 break; 465 466 case ALG_ID_SHA384: 467 cc_algorithm = kCCHmacAlgSHA384; 468 break; 469 470 case ALG_ID_SHA512: 471 cc_algorithm = kCCHmacAlgSHA512; 472 break; 473 474 default: 475 ERR( "unhandled id %u\n", hash->alg_id ); 476 return STATUS_NOT_IMPLEMENTED; 477 } 478 479 CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size ); 480 return STATUS_SUCCESS; 481 } 482 483 484 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) 485 { 486 switch (hash->alg_id) 487 { 488 case ALG_ID_MD5: 489 CC_MD5_Update( &hash->u.md5_ctx, input, size ); 490 break; 491 492 case ALG_ID_SHA1: 493 CC_SHA1_Update( &hash->u.sha1_ctx, input, size ); 494 break; 495 496 case ALG_ID_SHA256: 497 CC_SHA256_Update( &hash->u.sha256_ctx, input, size ); 498 break; 499 500 case ALG_ID_SHA384: 501 CC_SHA384_Update( &hash->u.sha512_ctx, input, size ); 502 break; 503 504 case ALG_ID_SHA512: 505 CC_SHA512_Update( &hash->u.sha512_ctx, input, size ); 506 break; 507 508 default: 509 ERR( "unhandled id %u\n", hash->alg_id ); 510 return STATUS_NOT_IMPLEMENTED; 511 } 512 return STATUS_SUCCESS; 513 } 514 515 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) 516 { 517 CCHmacUpdate( &hash->u.hmac_ctx, input, size ); 518 return STATUS_SUCCESS; 519 } 520 521 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) 522 { 523 switch (hash->alg_id) 524 { 525 case ALG_ID_MD5: 526 CC_MD5_Final( output, &hash->u.md5_ctx ); 527 break; 528 529 case ALG_ID_SHA1: 530 CC_SHA1_Final( output, &hash->u.sha1_ctx ); 531 break; 532 533 case ALG_ID_SHA256: 534 CC_SHA256_Final( output, &hash->u.sha256_ctx ); 535 break; 536 537 case ALG_ID_SHA384: 538 CC_SHA384_Final( output, &hash->u.sha512_ctx ); 539 break; 540 541 case ALG_ID_SHA512: 542 CC_SHA512_Final( output, &hash->u.sha512_ctx ); 543 break; 544 545 default: 546 ERR( "unhandled id %u\n", hash->alg_id ); 547 break; 548 } 549 return STATUS_SUCCESS; 550 } 551 552 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) 553 { 554 CCHmacFinal( &hash->u.hmac_ctx, output ); 555 556 return STATUS_SUCCESS; 557 } 558 #elif defined(HAVE_GNUTLS_HASH) 559 struct hash 560 { 561 struct object hdr; 562 enum alg_id alg_id; 563 BOOL hmac; 564 union 565 { 566 gnutls_hash_hd_t hash_handle; 567 gnutls_hmac_hd_t hmac_handle; 568 } u; 569 }; 570 571 static NTSTATUS hash_init( struct hash *hash ) 572 { 573 gnutls_digest_algorithm_t alg; 574 575 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; 576 577 switch (hash->alg_id) 578 { 579 case ALG_ID_MD5: 580 alg = GNUTLS_DIG_MD5; 581 break; 582 case ALG_ID_SHA1: 583 alg = GNUTLS_DIG_SHA1; 584 break; 585 586 case ALG_ID_SHA256: 587 alg = GNUTLS_DIG_SHA256; 588 break; 589 590 case ALG_ID_SHA384: 591 alg = GNUTLS_DIG_SHA384; 592 break; 593 594 case ALG_ID_SHA512: 595 alg = GNUTLS_DIG_SHA512; 596 break; 597 598 default: 599 ERR( "unhandled id %u\n", hash->alg_id ); 600 return STATUS_NOT_IMPLEMENTED; 601 } 602 603 if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR; 604 return STATUS_SUCCESS; 605 } 606 607 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) 608 { 609 gnutls_mac_algorithm_t alg; 610 611 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; 612 613 switch (hash->alg_id) 614 { 615 case ALG_ID_MD5: 616 alg = GNUTLS_MAC_MD5; 617 break; 618 case ALG_ID_SHA1: 619 alg = GNUTLS_MAC_SHA1; 620 break; 621 622 case ALG_ID_SHA256: 623 alg = GNUTLS_MAC_SHA256; 624 break; 625 626 case ALG_ID_SHA384: 627 alg = GNUTLS_MAC_SHA384; 628 break; 629 630 case ALG_ID_SHA512: 631 alg = GNUTLS_MAC_SHA512; 632 break; 633 634 default: 635 ERR( "unhandled id %u\n", hash->alg_id ); 636 return STATUS_NOT_IMPLEMENTED; 637 } 638 639 if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR; 640 return STATUS_SUCCESS; 641 } 642 643 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) 644 { 645 if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR; 646 return STATUS_SUCCESS; 647 } 648 649 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) 650 { 651 if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR; 652 return STATUS_SUCCESS; 653 } 654 655 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) 656 { 657 pgnutls_hash_deinit( hash->u.hash_handle, output ); 658 return STATUS_SUCCESS; 659 } 660 661 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) 662 { 663 pgnutls_hmac_deinit( hash->u.hmac_handle, output ); 664 return STATUS_SUCCESS; 665 } 666 #elif defined(SONAME_LIBMBEDTLS) 667 struct hash 668 { 669 struct object hdr; 670 BOOL hmac; 671 enum alg_id alg_id; 672 union 673 { 674 mbedtls_md5_context md5_ctx; 675 mbedtls_sha1_context sha1_ctx; 676 mbedtls_sha256_context sha256_ctx; 677 mbedtls_sha512_context sha512_ctx; 678 mbedtls_md_context_t hmac_ctx; 679 } u; 680 }; 681 682 static NTSTATUS hash_init( struct hash *hash ) 683 { 684 #ifndef __REACTOS__ 685 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR; 686 #endif 687 switch (hash->alg_id) 688 { 689 case ALG_ID_MD5: 690 mbedtls_md5_init(&hash->u.md5_ctx); 691 mbedtls_md5_starts(&hash->u.md5_ctx); 692 break; 693 694 case ALG_ID_SHA1: 695 mbedtls_sha1_init(&hash->u.sha1_ctx); 696 mbedtls_sha1_starts(&hash->u.sha1_ctx); 697 break; 698 699 case ALG_ID_SHA256: 700 mbedtls_sha256_init(&hash->u.sha256_ctx); 701 mbedtls_sha256_starts(&hash->u.sha256_ctx, FALSE); 702 break; 703 704 case ALG_ID_SHA384: 705 case ALG_ID_SHA512: 706 mbedtls_sha512_init(&hash->u.sha512_ctx); 707 mbedtls_sha512_starts(&hash->u.sha512_ctx, hash->alg_id==ALG_ID_SHA384); 708 break; 709 710 default: 711 ERR( "unhandled id %u\n", hash->alg_id ); 712 return STATUS_NOT_IMPLEMENTED; 713 } 714 715 return STATUS_SUCCESS; 716 } 717 718 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size ) 719 { 720 const mbedtls_md_info_t *md_info; 721 mbedtls_md_type_t md_type; 722 int ret; 723 #ifndef __REACTOS__ 724 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR; 725 #endif 726 mbedtls_md_init(&hash->u.hmac_ctx); 727 switch (hash->alg_id) 728 { 729 case ALG_ID_MD5: 730 md_type = MBEDTLS_MD_MD5; 731 break; 732 733 case ALG_ID_SHA1: 734 md_type = MBEDTLS_MD_SHA1; 735 break; 736 737 case ALG_ID_SHA256: 738 md_type = MBEDTLS_MD_SHA256; 739 break; 740 741 case ALG_ID_SHA384: 742 md_type = MBEDTLS_MD_SHA384; 743 break; 744 745 case ALG_ID_SHA512: 746 md_type = MBEDTLS_MD_SHA512; 747 break; 748 749 default: 750 ERR("unhandled id %u\n", hash->alg_id); 751 return STATUS_NOT_IMPLEMENTED; 752 } 753 if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) 754 { 755 mbedtls_md_free(&hash->u.hmac_ctx); 756 return STATUS_INTERNAL_ERROR; 757 } 758 759 if ((ret = mbedtls_md_setup(&hash->u.hmac_ctx, md_info, 1)) != 0) 760 { 761 mbedtls_md_free(&hash->u.hmac_ctx); 762 return STATUS_INTERNAL_ERROR; 763 } 764 765 mbedtls_md_hmac_starts(&hash->u.hmac_ctx, key, key_size); 766 767 return STATUS_SUCCESS; 768 } 769 770 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size ) 771 { 772 #ifndef __REACTOS__ 773 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR; 774 #endif 775 switch (hash->alg_id) 776 { 777 case ALG_ID_MD5: 778 mbedtls_md5_update(&hash->u.md5_ctx, input, size); 779 break; 780 781 case ALG_ID_SHA1: 782 mbedtls_sha1_update(&hash->u.sha1_ctx, input, size); 783 break; 784 785 case ALG_ID_SHA256: 786 mbedtls_sha256_update(&hash->u.sha256_ctx, input, size); 787 break; 788 789 case ALG_ID_SHA384: 790 case ALG_ID_SHA512: 791 mbedtls_sha512_update(&hash->u.sha512_ctx, input, size); 792 break; 793 794 default: 795 ERR( "unhandled id %u\n", hash->alg_id ); 796 return STATUS_NOT_IMPLEMENTED; 797 } 798 799 return STATUS_SUCCESS; 800 } 801 802 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size ) 803 { 804 #ifndef __REACTOS__ 805 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR; 806 #endif 807 mbedtls_md_update(&hash->u.hmac_ctx, input, size); 808 809 return STATUS_SUCCESS; 810 } 811 812 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size ) 813 { 814 #ifndef __REACTOS__ 815 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR; 816 #endif 817 switch (hash->alg_id) 818 { 819 case ALG_ID_MD5: 820 mbedtls_md5_finish(&hash->u.md5_ctx, output); 821 mbedtls_md5_free(&hash->u.md5_ctx); 822 break; 823 824 case ALG_ID_SHA1: 825 mbedtls_sha1_finish(&hash->u.sha1_ctx, output); 826 mbedtls_sha1_free(&hash->u.sha1_ctx); 827 break; 828 829 case ALG_ID_SHA256: 830 mbedtls_sha256_finish(&hash->u.sha256_ctx, output); 831 mbedtls_sha256_free(&hash->u.sha256_ctx); 832 break; 833 834 case ALG_ID_SHA384: 835 case ALG_ID_SHA512: 836 mbedtls_sha512_finish(&hash->u.sha512_ctx, output); 837 mbedtls_sha512_free(&hash->u.sha512_ctx); 838 break; 839 840 default: 841 ERR( "unhandled id %u\n", hash->alg_id ); 842 return STATUS_NOT_IMPLEMENTED; 843 } 844 845 return STATUS_SUCCESS; 846 } 847 848 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size ) 849 { 850 #ifndef __REACTOS__ 851 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR; 852 #endif 853 mbedtls_md_hmac_finish(&hash->u.hmac_ctx, output); 854 mbedtls_md_free(&hash->u.hmac_ctx); 855 856 return STATUS_SUCCESS; 857 } 858 #endif 859 860 #define OBJECT_LENGTH_MD5 274 861 #define OBJECT_LENGTH_SHA1 278 862 #define OBJECT_LENGTH_SHA256 286 863 #define OBJECT_LENGTH_SHA384 382 864 #define OBJECT_LENGTH_SHA512 382 865 866 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) 867 { 868 if (!strcmpW( prop, BCRYPT_HASH_LENGTH )) 869 { 870 *ret_size = sizeof(ULONG); 871 if (size < sizeof(ULONG)) 872 return STATUS_BUFFER_TOO_SMALL; 873 if(buf) 874 *(ULONG*)buf = alg_props[id].hash_length; 875 return STATUS_SUCCESS; 876 } 877 878 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME )) 879 { 880 *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR); 881 if (size < *ret_size) 882 return STATUS_BUFFER_TOO_SMALL; 883 if(buf) 884 memcpy(buf, alg_props[id].alg_name, *ret_size); 885 return STATUS_SUCCESS; 886 } 887 888 return STATUS_NOT_IMPLEMENTED; 889 } 890 891 static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) 892 { 893 NTSTATUS status; 894 ULONG value; 895 896 status = generic_alg_property( id, prop, buf, size, ret_size ); 897 if (status != STATUS_NOT_IMPLEMENTED) 898 return status; 899 900 switch (id) 901 { 902 case ALG_ID_MD5: 903 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 904 { 905 value = OBJECT_LENGTH_MD5; 906 break; 907 } 908 FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) ); 909 return STATUS_NOT_IMPLEMENTED; 910 911 case ALG_ID_RNG: 912 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED; 913 FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) ); 914 return STATUS_NOT_IMPLEMENTED; 915 916 case ALG_ID_SHA1: 917 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 918 { 919 value = OBJECT_LENGTH_SHA1; 920 break; 921 } 922 FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) ); 923 return STATUS_NOT_IMPLEMENTED; 924 925 case ALG_ID_SHA256: 926 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 927 { 928 value = OBJECT_LENGTH_SHA256; 929 break; 930 } 931 FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) ); 932 return STATUS_NOT_IMPLEMENTED; 933 934 case ALG_ID_SHA384: 935 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 936 { 937 value = OBJECT_LENGTH_SHA384; 938 break; 939 } 940 FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) ); 941 return STATUS_NOT_IMPLEMENTED; 942 943 case ALG_ID_SHA512: 944 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) 945 { 946 value = OBJECT_LENGTH_SHA512; 947 break; 948 } 949 FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) ); 950 return STATUS_NOT_IMPLEMENTED; 951 952 default: 953 FIXME( "unsupported algorithm %u\n", id ); 954 return STATUS_NOT_IMPLEMENTED; 955 } 956 957 if (size < sizeof(ULONG)) 958 { 959 *ret_size = sizeof(ULONG); 960 return STATUS_BUFFER_TOO_SMALL; 961 } 962 if (buf) *(ULONG *)buf = value; 963 *ret_size = sizeof(ULONG); 964 965 return STATUS_SUCCESS; 966 } 967 968 static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) 969 { 970 NTSTATUS status; 971 972 status = generic_alg_property( id, prop, buf, size, ret_size ); 973 if (status == STATUS_NOT_IMPLEMENTED) 974 FIXME( "unsupported property %s\n", debugstr_w(prop) ); 975 return status; 976 } 977 978 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags ) 979 { 980 struct object *object = handle; 981 982 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags ); 983 984 if (!object) return STATUS_INVALID_HANDLE; 985 if (!prop || !res) return STATUS_INVALID_PARAMETER; 986 987 switch (object->magic) 988 { 989 case MAGIC_ALG: 990 { 991 const struct algorithm *alg = (const struct algorithm *)object; 992 return get_alg_property( alg->id, prop, buffer, count, res ); 993 } 994 case MAGIC_HASH: 995 { 996 const struct hash *hash = (const struct hash *)object; 997 return get_hash_property( hash->alg_id, prop, buffer, count, res ); 998 } 999 default: 1000 WARN( "unknown magic %08x\n", object->magic ); 1001 return STATUS_INVALID_HANDLE; 1002 } 1003 } 1004 1005 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, 1006 UCHAR *secret, ULONG secretlen, ULONG flags ) 1007 { 1008 struct algorithm *alg = algorithm; 1009 struct hash *hash; 1010 NTSTATUS status; 1011 1012 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen, 1013 secret, secretlen, flags ); 1014 if (flags) 1015 { 1016 FIXME( "unimplemented flags %08x\n", flags ); 1017 return STATUS_NOT_IMPLEMENTED; 1018 } 1019 1020 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; 1021 if (object) FIXME( "ignoring object buffer\n" ); 1022 1023 if (!(hash = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash) ))) return STATUS_NO_MEMORY; 1024 hash->hdr.magic = MAGIC_HASH; 1025 hash->alg_id = alg->id; 1026 hash->hmac = alg->hmac; 1027 1028 if (hash->hmac) 1029 { 1030 status = hmac_init( hash, secret, secretlen ); 1031 } 1032 else 1033 { 1034 status = hash_init( hash ); 1035 } 1036 1037 if (status != STATUS_SUCCESS) 1038 { 1039 HeapFree( GetProcessHeap(), 0, hash ); 1040 return status; 1041 } 1042 1043 *handle = hash; 1044 return STATUS_SUCCESS; 1045 } 1046 1047 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle ) 1048 { 1049 struct hash *hash = handle; 1050 1051 TRACE( "%p\n", handle ); 1052 1053 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1054 HeapFree( GetProcessHeap(), 0, hash ); 1055 return STATUS_SUCCESS; 1056 } 1057 1058 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags ) 1059 { 1060 struct hash *hash = handle; 1061 1062 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags ); 1063 1064 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1065 if (!input) return STATUS_SUCCESS; 1066 1067 if (hash->hmac) 1068 { 1069 return hmac_update( hash, input, size ); 1070 } 1071 else 1072 { 1073 return hash_update( hash, input, size ); 1074 } 1075 } 1076 1077 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags ) 1078 { 1079 struct hash *hash = handle; 1080 1081 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags ); 1082 1083 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; 1084 if (!output) return STATUS_INVALID_PARAMETER; 1085 1086 if (hash->hmac) 1087 { 1088 return hmac_finish( hash, output, size ); 1089 } 1090 else 1091 { 1092 return hash_finish( hash, output, size ); 1093 } 1094 } 1095 1096 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen, 1097 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen ) 1098 { 1099 NTSTATUS status; 1100 BCRYPT_HASH_HANDLE handle; 1101 1102 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen, 1103 input, inputlen, output, outputlen ); 1104 1105 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0); 1106 if (status != STATUS_SUCCESS) 1107 { 1108 return status; 1109 } 1110 1111 status = BCryptHashData( handle, input, inputlen, 0 ); 1112 if (status != STATUS_SUCCESS) 1113 { 1114 BCryptDestroyHash( handle ); 1115 return status; 1116 } 1117 1118 status = BCryptFinishHash( handle, output, outputlen, 0 ); 1119 if (status != STATUS_SUCCESS) 1120 { 1121 BCryptDestroyHash( handle ); 1122 return status; 1123 } 1124 1125 return BCryptDestroyHash( handle ); 1126 } 1127 1128 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) 1129 { 1130 switch (reason) 1131 { 1132 case DLL_PROCESS_ATTACH: 1133 instance = hinst; 1134 DisableThreadLibraryCalls( hinst ); 1135 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) 1136 gnutls_initialize(); 1137 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__) 1138 mbedtls_initialize(); 1139 #endif 1140 break; 1141 1142 case DLL_PROCESS_DETACH: 1143 if (reserved) break; 1144 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) 1145 gnutls_uninitialize(); 1146 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__) 1147 mbedtls_uninitialize(); 1148 #endif 1149 break; 1150 } 1151 return TRUE; 1152 } 1153