[BCRYPT] Sync with Wine Staging 1.9.23. The mbedtls code paths are brought to you...
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 17 Nov 2016 22:13:28 +0000 (22:13 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 17 Nov 2016 22:13:28 +0000 (22:13 +0000)
svn path=/trunk/; revision=73261

reactos/dll/win32/bcrypt/bcrypt.spec
reactos/dll/win32/bcrypt/bcrypt_main.c
reactos/media/doc/README.WINE

index c52d89f..e299fe0 100644 (file)
@@ -29,6 +29,7 @@
 @ stub BCryptGenerateSymmetricKey
 @ stdcall BCryptGetFipsAlgorithmMode(ptr)
 @ stdcall BCryptGetProperty(ptr wstr ptr long ptr long)
+@ stdcall BCryptHash(ptr ptr long ptr long ptr long)
 @ stdcall BCryptHashData(ptr ptr long long)
 @ stub BCryptImportKey
 @ stub BCryptImportKeyPair
index 5212af9..1452313 100644 (file)
@@ -32,6 +32,8 @@
 #include <wine/library.h>
 
 #ifdef SONAME_LIBMBEDTLS
+#include <mbedtls/md.h>
+#include <mbedtls/md5.h>
 #include <mbedtls/sha1.h>
 #include <mbedtls/sha256.h>
 #include <mbedtls/sha512.h>
@@ -53,6 +55,9 @@ MAKE_FUNCPTR(gnutls_global_set_log_level);
 MAKE_FUNCPTR(gnutls_hash);
 MAKE_FUNCPTR(gnutls_hash_deinit);
 MAKE_FUNCPTR(gnutls_hash_init);
+MAKE_FUNCPTR(gnutls_hmac);
+MAKE_FUNCPTR(gnutls_hmac_deinit);
+MAKE_FUNCPTR(gnutls_hmac_init);
 MAKE_FUNCPTR(gnutls_perror);
 #undef MAKE_FUNCPTR
 
@@ -85,6 +90,9 @@ static BOOL gnutls_initialize(void)
     LOAD_FUNCPTR(gnutls_hash);
     LOAD_FUNCPTR(gnutls_hash_deinit);
     LOAD_FUNCPTR(gnutls_hash_init);
+    LOAD_FUNCPTR(gnutls_hmac);
+    LOAD_FUNCPTR(gnutls_hmac_deinit);
+    LOAD_FUNCPTR(gnutls_hmac_init);
     LOAD_FUNCPTR(gnutls_perror)
 #undef LOAD_FUNCPTR
 
@@ -120,6 +128,17 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 void *libmbedtls_handle;
 
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(mbedtls_md_init);
+MAKE_FUNCPTR(mbedtls_md_setup);
+MAKE_FUNCPTR(mbedtls_md_update);
+MAKE_FUNCPTR(mbedtls_md_hmac_starts);
+MAKE_FUNCPTR(mbedtls_md_hmac_finish);
+MAKE_FUNCPTR(mbedtls_md_free);
+MAKE_FUNCPTR(mbedtls_md5_init);
+MAKE_FUNCPTR(mbedtls_md5_starts);
+MAKE_FUNCPTR(mbedtls_md5_update);
+MAKE_FUNCPTR(mbedtls_md5_finish);
+MAKE_FUNCPTR(mbedtls_md5_free);
 MAKE_FUNCPTR(mbedtls_sha1_init);
 MAKE_FUNCPTR(mbedtls_sha1_starts);
 MAKE_FUNCPTR(mbedtls_sha1_update);
@@ -137,6 +156,17 @@ MAKE_FUNCPTR(mbedtls_sha512_finish);
 MAKE_FUNCPTR(mbedtls_sha512_free);
 #undef MAKE_FUNCPTR
 
+#define mbedtls_md_init             pmbedtls_md_init
+#define mbedtls_md_setup            pmbedtls_md_setup
+#define mbedtls_md_update           pmbedtls_md_update
+#define mbedtls_md_hmac_starts      pmbedtls_md_hmac_starts
+#define mbedtls_md_hmac_finish      pmbedtls_md_hmac_finish
+#define mbedtls_md_free             pmbedtls_md_free
+#define mbedtls_md5_init            pmbedtls_md5_init
+#define mbedtls_md5_starts          pmbedtls_md5_starts
+#define mbedtls_md5_update          pmbedtls_md5_update
+#define mbedtls_md5_finish          pmbedtls_md5_finish
+#define mbedtls_md5_free            pmbedtls_md5_free
 #define mbedtls_sha1_init           pmbedtls_sha1_init
 #define mbedtls_sha1_starts         pmbedtls_sha1_starts
 #define mbedtls_sha1_update         pmbedtls_sha1_update
@@ -168,6 +198,17 @@ static BOOL mbedtls_initialize(void)
         goto fail; \
     }
 
+    LOAD_FUNCPTR(mbedtls_md_init)
+    LOAD_FUNCPTR(mbedtls_md_setup)
+    LOAD_FUNCPTR(mbedtls_md_update)
+    LOAD_FUNCPTR(mbedtls_md_hmac_starts)
+    LOAD_FUNCPTR(mbedtls_md_hmac_finish)
+    LOAD_FUNCPTR(mbedtls_md_free);
+    LOAD_FUNCPTR(mbedtls_md5_init)
+    LOAD_FUNCPTR(mbedtls_md5_starts)
+    LOAD_FUNCPTR(mbedtls_md5_update)
+    LOAD_FUNCPTR(mbedtls_md5_finish)
+    LOAD_FUNCPTR(mbedtls_md5_free);
     LOAD_FUNCPTR(mbedtls_sha1_init)
     LOAD_FUNCPTR(mbedtls_sha1_starts)
     LOAD_FUNCPTR(mbedtls_sha1_update)
@@ -211,10 +252,48 @@ NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULONG count, ULONG flags)
+#define MAGIC_ALG  (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
+#define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
+struct object
+{
+    ULONG magic;
+};
+
+enum alg_id
+{
+    ALG_ID_MD5,
+    ALG_ID_RNG,
+    ALG_ID_SHA1,
+    ALG_ID_SHA256,
+    ALG_ID_SHA384,
+    ALG_ID_SHA512
+};
+
+static const struct {
+    ULONG hash_length;
+    const WCHAR *alg_name;
+} alg_props[] = {
+    /* ALG_ID_MD5    */ { 16, BCRYPT_MD5_ALGORITHM },
+    /* ALG_ID_RNG    */ {  0, BCRYPT_RNG_ALGORITHM },
+    /* ALG_ID_SHA1   */ { 20, BCRYPT_SHA1_ALGORITHM },
+    /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
+    /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
+    /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM }
+};
+
+struct algorithm
+{
+    struct object hdr;
+    enum alg_id   id;
+    BOOL hmac;
+};
+
+NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
 {
     const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
-    TRACE("%p, %p, %u, %08x - semi-stub\n", algorithm, buffer, count, flags);
+    struct algorithm *algorithm = handle;
+
+    TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags);
 
     if (!algorithm)
     {
@@ -224,6 +303,9 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULON
         if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
             return STATUS_INVALID_HANDLE;
     }
+    else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
+        return STATUS_INVALID_HANDLE;
+
     if (!buffer)
         return STATUS_INVALID_PARAMETER;
 
@@ -237,7 +319,7 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULON
     if (!count)
         return STATUS_SUCCESS;
 
-    if (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)
+    if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
     {
         if (RtlGenRandom(buffer, count))
             return STATUS_SUCCESS;
@@ -247,52 +329,25 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULON
     return STATUS_NOT_IMPLEMENTED;
 }
 
-#define MAGIC_ALG  (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
-#define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
-struct object
-{
-    ULONG magic;
-};
-
-enum alg_id
-{
-    ALG_ID_SHA1,
-    ALG_ID_SHA256,
-    ALG_ID_SHA384,
-    ALG_ID_SHA512
-};
-
-static const struct {
-    ULONG hash_length;
-    const WCHAR *alg_name;
-} alg_props[] = {
-    /* ALG_ID_SHA1   */ { 20, BCRYPT_SHA1_ALGORITHM },
-    /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
-    /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
-    /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM }
-};
-
-struct algorithm
-{
-    struct object hdr;
-    enum alg_id   id;
-};
-
 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
 {
     struct algorithm *alg;
     enum alg_id alg_id;
 
+    const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
+
     TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
 
     if (!handle || !id) return STATUS_INVALID_PARAMETER;
-    if (flags)
+    if (flags & ~supported_flags)
     {
-        FIXME( "unimplemented flags %08x\n", flags );
+        FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
         return STATUS_NOT_IMPLEMENTED;
     }
 
     if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
+    else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
+    else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG;
     else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
     else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
     else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
@@ -310,6 +365,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR
     if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY;
     alg->hdr.magic = MAGIC_ALG;
     alg->id        = alg_id;
+    alg->hmac      = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG;
 
     *handle = alg;
     return STATUS_SUCCESS;
@@ -342,11 +398,14 @@ struct hash
 {
     struct object hdr;
     enum alg_id   alg_id;
+    BOOL hmac;
     union
     {
+        CC_MD5_CTX    md5_ctx;
         CC_SHA1_CTX   sha1_ctx;
         CC_SHA256_CTX sha256_ctx;
         CC_SHA512_CTX sha512_ctx;
+        CCHmacContext hmac_ctx;
     } u;
 };
 
@@ -354,6 +413,10 @@ static NTSTATUS hash_init( struct hash *hash )
 {
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        CC_MD5_Init( &hash->u.md5_ctx );
+        break;
+
     case ALG_ID_SHA1:
         CC_SHA1_Init( &hash->u.sha1_ctx );
         break;
@@ -377,10 +440,49 @@ static NTSTATUS hash_init( struct hash *hash )
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
+{
+    CCHmacAlgorithm cc_algorithm;
+    switch (hash->alg_id)
+    {
+    case ALG_ID_MD5:
+        cc_algorithm = kCCHmacAlgMD5;
+        break;
+
+    case ALG_ID_SHA1:
+        cc_algorithm = kCCHmacAlgSHA1;
+        break;
+
+    case ALG_ID_SHA256:
+        cc_algorithm = kCCHmacAlgSHA256;
+        break;
+
+    case ALG_ID_SHA384:
+        cc_algorithm = kCCHmacAlgSHA384;
+        break;
+
+    case ALG_ID_SHA512:
+        cc_algorithm = kCCHmacAlgSHA512;
+        break;
+
+    default:
+        ERR( "unhandled id %u\n", hash->alg_id );
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size );
+    return STATUS_SUCCESS;
+}
+
+
 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
 {
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        CC_MD5_Update( &hash->u.md5_ctx, input, size );
+        break;
+
     case ALG_ID_SHA1:
         CC_SHA1_Update( &hash->u.sha1_ctx, input, size );
         break;
@@ -404,10 +506,20 @@ static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
+{
+    CCHmacUpdate( &hash->u.hmac_ctx, input, size );
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
 {
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        CC_MD5_Final( output, &hash->u.md5_ctx );
+        break;
+
     case ALG_ID_SHA1:
         CC_SHA1_Final( output, &hash->u.sha1_ctx );
         break;
@@ -430,12 +542,24 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
     }
     return STATUS_SUCCESS;
 }
+
+static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
+{
+    CCHmacFinal( &hash->u.hmac_ctx, output );
+
+    return STATUS_SUCCESS;
+}
 #elif defined(HAVE_GNUTLS_HASH)
 struct hash
 {
     struct object    hdr;
     enum alg_id      alg_id;
-    gnutls_hash_hd_t handle;
+    BOOL hmac;
+    union
+    {
+        gnutls_hash_hd_t hash_handle;
+        gnutls_hmac_hd_t hmac_handle;
+    } u;
 };
 
 static NTSTATUS hash_init( struct hash *hash )
@@ -446,6 +570,9 @@ static NTSTATUS hash_init( struct hash *hash )
 
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        alg = GNUTLS_DIG_MD5;
+        break;
     case ALG_ID_SHA1:
         alg = GNUTLS_DIG_SHA1;
         break;
@@ -467,31 +594,82 @@ static NTSTATUS hash_init( struct hash *hash )
         return STATUS_NOT_IMPLEMENTED;
     }
 
-    if (pgnutls_hash_init( &hash->handle, alg )) return STATUS_INTERNAL_ERROR;
+    if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR;
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
+{
+    gnutls_mac_algorithm_t alg;
+
+    if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
+
+    switch (hash->alg_id)
+    {
+    case ALG_ID_MD5:
+        alg = GNUTLS_MAC_MD5;
+        break;
+    case ALG_ID_SHA1:
+        alg = GNUTLS_MAC_SHA1;
+        break;
+
+    case ALG_ID_SHA256:
+        alg = GNUTLS_MAC_SHA256;
+        break;
+
+    case ALG_ID_SHA384:
+        alg = GNUTLS_MAC_SHA384;
+        break;
+
+    case ALG_ID_SHA512:
+        alg = GNUTLS_MAC_SHA512;
+        break;
+
+    default:
+        ERR( "unhandled id %u\n", hash->alg_id );
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR;
     return STATUS_SUCCESS;
 }
 
 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
 {
-    if (pgnutls_hash( hash->handle, input, size )) return STATUS_INTERNAL_ERROR;
+    if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR;
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
+{
+    if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR;
     return STATUS_SUCCESS;
 }
 
 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
 {
-    pgnutls_hash_deinit( hash->handle, output );
+    pgnutls_hash_deinit( hash->u.hash_handle, output );
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
+{
+    pgnutls_hmac_deinit( hash->u.hmac_handle, output );
     return STATUS_SUCCESS;
 }
 #elif defined(SONAME_LIBMBEDTLS)
 struct hash
 {
-    struct object    hdr;
-    enum alg_id      alg_id;
+    struct object hdr;
+    BOOL hmac;
+    enum alg_id   alg_id;
     union
     {
+        mbedtls_md5_context    md5_ctx;
         mbedtls_sha1_context   sha1_ctx;
         mbedtls_sha256_context sha256_ctx;
         mbedtls_sha512_context sha512_ctx;
+        mbedtls_md_context_t   hmac_ctx;
     } u;
 };
 
@@ -502,6 +680,11 @@ static NTSTATUS hash_init( struct hash *hash )
 #endif
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        mbedtls_md5_init(&hash->u.md5_ctx);
+        mbedtls_md5_starts(&hash->u.md5_ctx);
+        break;
+
     case ALG_ID_SHA1:
         mbedtls_sha1_init(&hash->u.sha1_ctx);
         mbedtls_sha1_starts(&hash->u.sha1_ctx);
@@ -526,6 +709,58 @@ static NTSTATUS hash_init( struct hash *hash )
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
+{
+    const mbedtls_md_info_t *md_info;
+    mbedtls_md_type_t md_type;
+    int ret;
+#ifndef __REACTOS__
+    if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
+#endif
+    mbedtls_md_init(&hash->u.hmac_ctx);
+    switch (hash->alg_id)
+    {
+    case ALG_ID_MD5:
+        md_type = MBEDTLS_MD_MD5;
+        break;
+
+    case ALG_ID_SHA1:
+        md_type = MBEDTLS_MD_SHA1;
+        break;
+
+    case ALG_ID_SHA256:
+        md_type = MBEDTLS_MD_SHA256;
+        break;
+
+    case ALG_ID_SHA384:
+        md_type = MBEDTLS_MD_SHA384;
+        break;
+
+    case ALG_ID_SHA512:
+        md_type = MBEDTLS_MD_SHA512;
+        break;
+
+    default:
+        ERR("unhandled id %u\n", hash->alg_id);
+        return STATUS_NOT_IMPLEMENTED;
+    }
+    if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL)
+    {
+        mbedtls_md_free(&hash->u.hmac_ctx);
+        return STATUS_INTERNAL_ERROR;
+    }
+
+    if ((ret = mbedtls_md_setup(&hash->u.hmac_ctx, md_info, 1)) != 0)
+    {
+        mbedtls_md_free(&hash->u.hmac_ctx);
+        return STATUS_INTERNAL_ERROR;
+    }
+
+    mbedtls_md_hmac_starts(&hash->u.hmac_ctx, key, key_size);
+
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
 {
 #ifndef __REACTOS__
@@ -533,6 +768,10 @@ static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
 #endif
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        mbedtls_md5_update(&hash->u.md5_ctx, input, size);
+        break;
+
     case ALG_ID_SHA1:
         mbedtls_sha1_update(&hash->u.sha1_ctx, input, size);
         break;
@@ -554,6 +793,16 @@ static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
+{
+#ifndef __REACTOS__
+    if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
+#endif
+    mbedtls_md_update(&hash->u.hmac_ctx, input, size);
+
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
 {
 #ifndef __REACTOS__
@@ -561,6 +810,11 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
 #endif
     switch (hash->alg_id)
     {
+    case ALG_ID_MD5:
+        mbedtls_md5_finish(&hash->u.md5_ctx, output);
+        mbedtls_md5_free(&hash->u.md5_ctx);
+        break;
+
     case ALG_ID_SHA1:
         mbedtls_sha1_finish(&hash->u.sha1_ctx, output);
         mbedtls_sha1_free(&hash->u.sha1_ctx);
@@ -584,32 +838,20 @@ static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
 
     return STATUS_SUCCESS;
 }
-#else
-struct hash
-{
-    struct object hdr;
-    enum alg_id   alg_id;
-};
 
-static NTSTATUS hash_init( struct hash *hash )
+static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
 {
-    ERR( "support for hashes not available at build time\n" );
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
-{
-    ERR( "support for hashes not available at build time\n" );
-    return STATUS_NOT_IMPLEMENTED;
-}
+#ifndef __REACTOS__
+    if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
+#endif
+    mbedtls_md_hmac_finish(&hash->u.hmac_ctx, output);
+    mbedtls_md_free(&hash->u.hmac_ctx);
 
-static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
-{
-    ERR( "support for hashes not available at build time\n" );
-    return STATUS_NOT_IMPLEMENTED;
+    return STATUS_SUCCESS;
 }
 #endif
 
+#define OBJECT_LENGTH_MD5       274
 #define OBJECT_LENGTH_SHA1      278
 #define OBJECT_LENGTH_SHA256    286
 #define OBJECT_LENGTH_SHA384    382
@@ -651,6 +893,20 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf,
 
     switch (id)
     {
+    case ALG_ID_MD5:
+        if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
+        {
+            value = OBJECT_LENGTH_MD5;
+            break;
+        }
+        FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) );
+        return STATUS_NOT_IMPLEMENTED;
+
+    case ALG_ID_RNG:
+        if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED;
+        FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) );
+        return STATUS_NOT_IMPLEMENTED;
+
     case ALG_ID_SHA1:
         if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
         {
@@ -761,7 +1017,18 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDL
     if (!(hash = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash) ))) return STATUS_NO_MEMORY;
     hash->hdr.magic = MAGIC_HASH;
     hash->alg_id    = alg->id;
-    if ((status = hash_init( hash )) != STATUS_SUCCESS)
+    hash->hmac      = alg->hmac;
+
+    if (hash->hmac)
+    {
+        status = hmac_init( hash, secret, secretlen );
+    }
+    else
+    {
+        status = hash_init( hash );
+    }
+
+    if (status != STATUS_SUCCESS)
     {
         HeapFree( GetProcessHeap(), 0, hash );
         return status;
@@ -789,9 +1056,16 @@ NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG s
     TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
 
     if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
-    if (!input) return STATUS_INVALID_PARAMETER;
+    if (!input) return STATUS_SUCCESS;
 
-    return hash_update( hash, input, size );
+    if (hash->hmac)
+    {
+        return hmac_update( hash, input, size );
+    }
+    else
+    {
+        return hash_update( hash, input, size );
+    }
 }
 
 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
@@ -803,7 +1077,46 @@ NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULON
     if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
     if (!output) return STATUS_INVALID_PARAMETER;
 
-    return hash_finish( hash, output, size );
+    if (hash->hmac)
+    {
+        return hmac_finish( hash, output, size );
+    }
+    else
+    {
+        return hash_finish( hash, output, size );
+    }
+}
+
+NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
+                            UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
+{
+    NTSTATUS status;
+    BCRYPT_HASH_HANDLE handle;
+
+    TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
+           input, inputlen, output, outputlen );
+
+    status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
+    if (status != STATUS_SUCCESS)
+    {
+        return status;
+    }
+
+    status = BCryptHashData( handle, input, inputlen, 0 );
+    if (status != STATUS_SUCCESS)
+    {
+        BCryptDestroyHash( handle );
+        return status;
+    }
+
+    status = BCryptFinishHash( handle, output, outputlen, 0 );
+    if (status != STATUS_SUCCESS)
+    {
+        BCryptDestroyHash( handle );
+        return status;
+    }
+
+    return BCryptDestroyHash( handle );
 }
 
 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
index 543b883..6f611fc 100644 (file)
@@ -49,7 +49,7 @@ reactos/dll/win32/atl                 # Synced to WineStaging-1.9.16
 reactos/dll/win32/atl80               # Synced to WineStaging-1.9.11
 reactos/dll/win32/atl100              # Synced to WineStaging-1.9.11
 reactos/dll/win32/avifil32            # Synced to WineStaging-1.9.23
-reactos/dll/win32/bcrypt              # Synced to WineStaging-1.9.4
+reactos/dll/win32/bcrypt              # Synced to WineStaging-1.9.23
 reactos/dll/win32/browseui            # Out of sync
 reactos/dll/win32/cabinet             # Synced to WineStaging-1.9.16
 reactos/dll/win32/clusapi             # Synced to WineStaging-1.9.11