2 * Copyright 2008 Maarten Lankhorst
3 * Copyright 2020 Hans Leidekker for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
34 #include "wine/heap.h"
36 static HINSTANCE instance
;
38 WINE_DEFAULT_DEBUG_CHANNEL(dssenh
);
40 #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0')
46 BCRYPT_ALG_HANDLE alg_handle
;
47 BCRYPT_KEY_HANDLE handle
;
50 #define MAGIC_CONTAINER (('C' << 24) | ('O' << 16) | ('N' << 8) | 'T')
60 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
64 BCRYPT_HASH_HANDLE handle
;
70 static const char dss_path_fmt
[] = "Software\\Wine\\Crypto\\DSS\\%s";
72 static BOOL
create_container_regkey( struct container
*container
, REGSAM sam
, HKEY
*hkey
)
74 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
77 sprintf( path
, dss_path_fmt
, container
->name
);
79 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
80 rootkey
= HKEY_LOCAL_MACHINE
;
82 rootkey
= HKEY_CURRENT_USER
;
84 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
85 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
86 return !RegCreateKeyExA( rootkey
, path
, 0, NULL
, REG_OPTION_NON_VOLATILE
, sam
, NULL
, hkey
, NULL
);
89 static struct container
*create_key_container( const char *name
, DWORD flags
)
91 struct container
*ret
;
93 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
94 ret
->magic
= MAGIC_CONTAINER
;
96 if (name
) strcpy( ret
->name
, name
);
98 if (!(flags
& CRYPT_VERIFYCONTEXT
))
101 if (create_container_regkey( ret
, KEY_WRITE
, &hkey
)) RegCloseKey( hkey
);
106 static BOOL
open_container_regkey( const char *name
, DWORD flags
, REGSAM access
, HKEY
*hkey
)
108 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
111 sprintf( path
, dss_path_fmt
, name
);
113 if (flags
& CRYPT_MACHINE_KEYSET
)
114 rootkey
= HKEY_LOCAL_MACHINE
;
116 rootkey
= HKEY_CURRENT_USER
;
118 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
119 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
120 return !RegOpenKeyExA( rootkey
, path
, 0, access
, hkey
);
123 static const WCHAR
*map_keyspec_to_keypair_name( DWORD keyspec
)
130 name
= L
"KeyExchangeKeyPair";
133 name
= L
"SignatureKeyPair";
136 ERR( "invalid key spec %u\n", keyspec
);
142 static struct key
*create_key( ALG_ID algid
, DWORD flags
)
151 alg
= BCRYPT_DSA_ALGORITHM
;
155 FIXME( "unhandled algorithm %08x\n", algid
);
159 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
161 ret
->magic
= MAGIC_KEY
;
164 if (BCryptOpenAlgorithmProvider( &ret
->alg_handle
, alg
, MS_PRIMITIVE_PROVIDER
, 0 ))
172 static void destroy_key( struct key
*key
)
175 BCryptDestroyKey( key
->handle
);
176 BCryptCloseAlgorithmProvider( key
->alg_handle
, 0 );
181 static struct key
*import_key( DWORD keyspec
, BYTE
*data
, DWORD len
)
185 if (!(ret
= create_key( keyspec
, 0 ))) return NULL
;
187 if (BCryptImportKeyPair( ret
->alg_handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, &ret
->handle
, data
, len
, 0 ))
189 WARN( "failed to import key\n" );
196 static struct key
*read_key( HKEY hkey
, DWORD keyspec
, DWORD flags
)
201 DATA_BLOB blob_in
, blob_out
;
202 struct key
*ret
= NULL
;
204 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return NULL
;
205 if (RegQueryValueExW( hkey
, value
, 0, &type
, NULL
, &len
)) return NULL
;
206 if (!(data
= heap_alloc( len
))) return NULL
;
208 if (!RegQueryValueExW( hkey
, value
, 0, &type
, data
, &len
))
210 blob_in
.pbData
= data
;
211 blob_in
.cbData
= len
;
212 if (CryptUnprotectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
))
214 ret
= import_key( keyspec
, blob_out
.pbData
, blob_out
.cbData
);
215 LocalFree( blob_out
.pbData
);
223 static void destroy_container( struct container
*container
)
225 if (!container
) return;
226 destroy_key( container
->exch_key
);
227 destroy_key( container
->sign_key
);
228 container
->magic
= 0;
229 heap_free( container
);
232 static struct container
*read_key_container( const char *name
, DWORD flags
)
234 DWORD protect_flags
= (flags
& CRYPT_MACHINE_KEYSET
) ? CRYPTPROTECT_LOCAL_MACHINE
: 0;
235 struct container
*ret
;
238 if (!open_container_regkey( name
, flags
, KEY_READ
, &hkey
)) return NULL
;
240 if ((ret
= create_key_container( name
, flags
)))
242 ret
->exch_key
= read_key( hkey
, AT_KEYEXCHANGE
, protect_flags
);
243 ret
->sign_key
= read_key( hkey
, AT_SIGNATURE
, protect_flags
);
250 static void delete_key_container( const char *name
, DWORD flags
)
252 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
255 sprintf( path
, dss_path_fmt
, name
);
257 if (flags
& CRYPT_MACHINE_KEYSET
)
258 rootkey
= HKEY_LOCAL_MACHINE
;
260 rootkey
= HKEY_CURRENT_USER
;
262 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
263 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
264 RegDeleteKeyExA( rootkey
, path
, 0, 0 );
267 BOOL WINAPI
CPAcquireContext( HCRYPTPROV
*ret_prov
, LPSTR container
, DWORD flags
, PVTableProvStruc vtable
)
269 struct container
*ret
;
272 TRACE( "%p, %s, %08x, %p\n", ret_prov
, debugstr_a(container
), flags
, vtable
);
274 if (container
&& *container
)
276 if (lstrlenA( container
) >= sizeof(name
)) return FALSE
;
277 lstrcpyA( name
, container
);
281 DWORD len
= sizeof(name
);
282 if (!GetUserNameA( name
, &len
)) return FALSE
;
288 case 0 | CRYPT_MACHINE_KEYSET
:
289 ret
= read_key_container( name
, flags
);
292 case CRYPT_NEWKEYSET
:
293 case CRYPT_NEWKEYSET
| CRYPT_MACHINE_KEYSET
:
294 if ((ret
= read_key_container( name
, flags
)))
297 SetLastError( NTE_EXISTS
);
300 ret
= create_key_container( name
, flags
);
303 case CRYPT_VERIFYCONTEXT
:
304 case CRYPT_VERIFYCONTEXT
| CRYPT_MACHINE_KEYSET
:
305 ret
= create_key_container( "", flags
);
308 case CRYPT_DELETEKEYSET
:
309 case CRYPT_DELETEKEYSET
| CRYPT_MACHINE_KEYSET
:
310 delete_key_container( name
, flags
);
315 FIXME( "unsupported flags %08x\n", flags
);
319 if (!ret
) return FALSE
;
320 *ret_prov
= (HCRYPTPROV
)ret
;
324 BOOL WINAPI
CPReleaseContext( HCRYPTPROV hprov
, DWORD flags
)
326 struct container
*container
= (struct container
*)hprov
;
328 TRACE( "%p, %08x\n", (void *)hprov
, flags
);
330 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
331 destroy_container( container
);
335 BOOL WINAPI
CPGetProvParam( HCRYPTPROV hprov
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
340 static BOOL
store_key_pair( struct key
*key
, HKEY hkey
, DWORD keyspec
, DWORD flags
)
343 DATA_BLOB blob_in
, blob_out
;
348 if (!key
) return TRUE
;
349 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return FALSE
;
351 if (BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, NULL
, 0, &len
, 0 )) return FALSE
;
352 if (!(data
= heap_alloc( len
))) return FALSE
;
354 if (!BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, data
, len
, &len
, 0 ))
356 blob_in
.pbData
= data
;
357 blob_in
.cbData
= len
;
358 if ((ret
= CryptProtectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
)))
360 ret
= !RegSetValueExW( hkey
, value
, 0, REG_BINARY
, blob_out
.pbData
, blob_out
.cbData
);
361 LocalFree( blob_out
.pbData
);
369 static BOOL
store_key_container_keys( struct container
*container
)
375 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
376 flags
= CRYPTPROTECT_LOCAL_MACHINE
;
380 if (!create_container_regkey( container
, KEY_WRITE
, &hkey
)) return FALSE
;
382 ret
= store_key_pair( container
->exch_key
, hkey
, AT_KEYEXCHANGE
, flags
);
383 if (ret
) store_key_pair( container
->sign_key
, hkey
, AT_SIGNATURE
, flags
);
388 static struct key
*duplicate_key( const struct key
*key
)
392 if (!(ret
= create_key( key
->algid
, key
->flags
))) return NULL
;
394 if (BCryptDuplicateKey( key
->handle
, &ret
->handle
, NULL
, 0, 0 ))
402 static BOOL
generate_key( struct container
*container
, ALG_ID algid
, DWORD bitlen
, DWORD flags
, HCRYPTKEY
*ret_key
)
404 struct key
*key
, *sign_key
;
407 if (!(key
= create_key( algid
, flags
))) return FALSE
;
409 if ((status
= BCryptGenerateKeyPair( key
->alg_handle
, &key
->handle
, bitlen
, 0 )))
411 ERR( "failed to generate key %08x\n", status
);
415 if ((status
= BCryptFinalizeKeyPair( key
->handle
, 0 )))
417 ERR( "failed to finalize key %08x\n", status
);
426 if (!(sign_key
= duplicate_key( key
)))
431 destroy_key( container
->sign_key
);
432 container
->sign_key
= sign_key
;
436 FIXME( "unhandled algorithm %08x\n", algid
);
440 if (!store_key_container_keys( container
)) return FALSE
;
442 *ret_key
= (HCRYPTKEY
)key
;
446 BOOL WINAPI
CPGenKey( HCRYPTPROV hprov
, ALG_ID algid
, DWORD flags
, HCRYPTKEY
*ret_key
)
448 static const unsigned int supported_key_lengths
[] = { 512, 768, 1024 };
449 struct container
*container
= (struct container
*)hprov
;
450 ULONG i
, bitlen
= HIWORD(flags
) ? HIWORD(flags
) : 1024;
452 TRACE( "%p, %08x, %08x, %p\n", (void *)hprov
, algid
, flags
, ret_key
);
454 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
458 SetLastError( STATUS_INVALID_PARAMETER
);
461 for (i
= 0; i
< ARRAY_SIZE(supported_key_lengths
); i
++)
463 if (bitlen
== supported_key_lengths
[i
]) break;
465 if (i
>= ARRAY_SIZE(supported_key_lengths
))
467 SetLastError( NTE_BAD_FLAGS
);
471 return generate_key( container
, algid
, bitlen
, LOWORD(flags
), ret_key
);
474 BOOL WINAPI
CPDestroyKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
)
476 struct key
*key
= (struct key
*)hkey
;
478 TRACE( "%p, %p\n", (void *)hprov
, (void *)hkey
);
480 if (key
->magic
!= MAGIC_KEY
)
482 SetLastError( NTE_BAD_KEY
);
490 #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
491 #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
492 #define MAGIC_DSS3 ('D' | ('S' << 8) | ('S' << 16) | ('3' << 24))
494 static BOOL
import_key_dss2( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
497 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
498 const DSSPUBKEY
*pubkey
= (const DSSPUBKEY
*)(hdr
+ 1);
500 struct key
*key
, *exch_key
, *sign_key
;
503 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
505 switch (pubkey
->magic
)
508 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
512 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
516 FIXME( "unsupported key magic %08x\n", pubkey
->magic
);
520 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
522 if ((status
= BCryptImportKeyPair( key
->alg_handle
, NULL
, type
, &key
->handle
, (UCHAR
*)data
, len
, 0 )))
524 TRACE( "failed to import key %08x\n", status
);
529 if (!wcscmp(type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
535 if (!(exch_key
= duplicate_key( key
)))
540 destroy_key( container
->exch_key
);
541 container
->exch_key
= exch_key
;
546 if (!(sign_key
= duplicate_key( key
)))
551 destroy_key( container
->sign_key
);
552 container
->sign_key
= sign_key
;
556 FIXME( "unhandled key algorithm %u\n", algid
);
561 if (!store_key_container_keys( container
)) return FALSE
;
564 *ret_key
= (HCRYPTKEY
)key
;
568 static BOOL
import_key_dss3( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
571 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
572 const DSSPUBKEY_VER3
*pubkey
= (const DSSPUBKEY_VER3
*)(hdr
+ 1);
573 BCRYPT_DSA_KEY_BLOB
*blob
;
576 ULONG i
, size
, size_q
;
579 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
581 switch (pubkey
->magic
)
587 FIXME( "unsupported key magic %08x\n", pubkey
->magic
);
591 if ((size_q
= pubkey
->bitlenQ
/ 8) > sizeof(blob
->q
))
593 FIXME( "q too large\n" );
597 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
599 size
= sizeof(*blob
) + (pubkey
->bitlenP
/ 8) * 3;
600 if (!(blob
= heap_alloc_zero( size
)))
605 blob
->dwMagic
= BCRYPT_DSA_PUBLIC_MAGIC
;
606 blob
->cbKey
= pubkey
->bitlenP
/ 8;
607 memcpy( blob
->Count
, &pubkey
->DSSSeed
.counter
, sizeof(blob
->Count
) );
608 memcpy( blob
->Seed
, pubkey
->DSSSeed
.seed
, sizeof(blob
->Seed
) );
611 src
= (BYTE
*)(pubkey
+ 1) + blob
->cbKey
;
612 for (i
= 0; i
< size_q
; i
++) blob
->q
[i
] = src
[size_q
- i
- 1];
616 dst
= (BYTE
*)(blob
+ 1);
617 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
620 src
+= blob
->cbKey
+ size_q
;
622 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
625 src
+= blob
->cbKey
+ pubkey
->bitlenJ
/ 8;
627 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
629 if ((status
= BCryptImportKeyPair( key
->alg_handle
, NULL
, BCRYPT_DSA_PUBLIC_BLOB
, &key
->handle
, (UCHAR
*)blob
,
632 WARN( "failed to import key %08x\n", status
);
639 *ret_key
= (HCRYPTKEY
)key
;
643 BOOL WINAPI
CPImportKey( HCRYPTPROV hprov
, const BYTE
*data
, DWORD len
, HCRYPTKEY hpubkey
, DWORD flags
,
646 struct container
*container
= (struct container
*)hprov
;
647 const BLOBHEADER
*hdr
;
650 TRACE( "%p, %p, %u, %p, %08x, %p\n", (void *)hprov
, data
, len
, (void *)hpubkey
, flags
, ret_key
);
652 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
653 if (len
< sizeof(*hdr
)) return FALSE
;
655 hdr
= (const BLOBHEADER
*)data
;
656 if ((hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bType
!= PUBLICKEYBLOB
) || hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
658 FIXME( "bType %u aiKeyAlg %08x not supported\n", hdr
->bType
, hdr
->aiKeyAlg
);
662 switch (hdr
->bVersion
)
665 ret
= import_key_dss2( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
669 ret
= import_key_dss3( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
673 FIXME( "version %u not supported\n", hdr
->bVersion
);
680 BOOL WINAPI
CPExportKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, HCRYPTKEY hexpkey
, DWORD blobtype
, DWORD flags
,
681 BYTE
*data
, DWORD
*len
)
683 struct key
*key
= (struct key
*)hkey
;
686 TRACE( "%p, %p, %p, %08x, %08x, %p, %p\n", (void *)hprov
, (void *)hkey
, (void *)hexpkey
, blobtype
, flags
,
689 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
692 FIXME( "export key not supported\n" );
697 FIXME( "flags %08x not supported\n", flags
);
704 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
708 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
712 FIXME( "blob type %u not supported\n", blobtype
);
716 return !BCryptExportKey( key
->handle
, NULL
, type
, data
, *len
, len
, 0 );
719 BOOL WINAPI
CPDuplicateKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, DWORD
*reserved
, DWORD flags
, HCRYPTKEY
*ret_key
)
721 struct key
*key
= (struct key
*)hkey
, *ret
;
723 TRACE( "%p, %p, %p, %08x, %p\n", (void *)hprov
, (void *)hkey
, reserved
, flags
, ret_key
);
725 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
727 if (!(ret
= duplicate_key( key
))) return FALSE
;
728 *ret_key
= (HCRYPTKEY
)ret
;
732 BOOL WINAPI
CPGetUserKey( HCRYPTPROV hprov
, DWORD keyspec
, HCRYPTKEY
*ret_key
)
734 struct container
*container
= (struct container
*)hprov
;
737 TRACE( "%p, %08x, %p\n", (void *)hprov
, keyspec
, ret_key
);
739 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
744 if (!container
->exch_key
) SetLastError( NTE_NO_KEY
);
745 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->exch_key
))) ret
= TRUE
;
749 if (!container
->sign_key
) SetLastError( NTE_NO_KEY
);
750 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->sign_key
))) ret
= TRUE
;
754 SetLastError( NTE_NO_KEY
);
761 BOOL WINAPI
CPGenRandom( HCRYPTPROV hprov
, DWORD len
, BYTE
*buffer
)
763 struct container
*container
= (struct container
*)hprov
;
765 TRACE( "%p, %u, %p\n", (void *)hprov
, len
, buffer
);
767 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
769 return RtlGenRandom( buffer
, len
);
772 static struct hash
*create_hash( ALG_ID algid
)
775 BCRYPT_ALG_HANDLE alg_handle
;
782 alg
= BCRYPT_MD5_ALGORITHM
;
787 alg
= BCRYPT_SHA1_ALGORITHM
;
792 FIXME( "unhandled algorithm %u\n", algid
);
796 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
798 ret
->magic
= MAGIC_HASH
;
800 if (BCryptOpenAlgorithmProvider( &alg_handle
, alg
, MS_PRIMITIVE_PROVIDER
, 0 ))
805 if (BCryptCreateHash( alg_handle
, &ret
->handle
, NULL
, 0, NULL
, 0, 0 ))
807 BCryptCloseAlgorithmProvider( alg_handle
, 0 );
812 BCryptCloseAlgorithmProvider( alg_handle
, 0 );
816 BOOL WINAPI
CPCreateHash( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTKEY hkey
, DWORD flags
, HCRYPTHASH
*ret_hash
)
820 TRACE( "%p, %08x, %p, %08x, %p\n", (void *)hprov
, algid
, (void *)hkey
, flags
, ret_hash
);
829 FIXME( "algorithm %u not supported\n", algid
);
830 SetLastError( NTE_BAD_ALGID
);
834 if (!(hash
= create_hash( algid
))) return FALSE
;
836 *ret_hash
= (HCRYPTHASH
)hash
;
840 static void destroy_hash( struct hash
*hash
)
843 BCryptDestroyHash( hash
->handle
);
848 BOOL WINAPI
CPDestroyHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
)
850 struct hash
*hash
= (struct hash
*)hhash
;
852 TRACE( "%p, %p\n", (void *)hprov
, (void *)hhash
);
854 if (hash
->magic
!= MAGIC_HASH
)
856 SetLastError( NTE_BAD_HASH
);
860 destroy_hash( hash
);
864 static struct hash
*duplicate_hash( const struct hash
*hash
)
868 if (!(ret
= heap_alloc( sizeof(*ret
) ))) return NULL
;
870 ret
->magic
= hash
->magic
;
871 ret
->len
= hash
->len
;
872 if (BCryptDuplicateHash( hash
->handle
, &ret
->handle
, NULL
, 0, 0 ))
877 memcpy( ret
->value
, hash
->value
, sizeof(hash
->value
) );
878 ret
->finished
= hash
->finished
;
882 BOOL WINAPI
CPDuplicateHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD
*reserved
, DWORD flags
, HCRYPTHASH
*ret_hash
)
884 struct hash
*hash
= (struct hash
*)hhash
, *ret
;
886 TRACE( "%p, %p, %p, %08x, %p\n", (void *)hprov
, (void *)hhash
, reserved
, flags
, ret_hash
);
888 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
890 if (!(ret
= duplicate_hash( hash
))) return FALSE
;
891 *ret_hash
= (HCRYPTHASH
)ret
;
895 BOOL WINAPI
CPHashData( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*data
, DWORD len
, DWORD flags
)
897 struct hash
*hash
= (struct hash
*)hhash
;
899 TRACE("%p, %p, %p, %u, %08x\n", (void *)hprov
, (void *)hhash
, data
, len
, flags
);
901 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
905 SetLastError( NTE_BAD_HASH_STATE
);
908 return !BCryptHashData( hash
->handle
, (UCHAR
*)data
, len
, 0 );
911 BOOL WINAPI
CPGetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
913 struct hash
*hash
= (struct hash
*)hhash
;
915 TRACE( "%p, %p, %08x, %p, %p, %08x\n", (void *)hprov
, (void *)hhash
, param
, data
, len
, flags
);
917 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
922 if (sizeof(hash
->len
) > *len
)
924 *len
= sizeof(hash
->len
);
925 SetLastError( ERROR_MORE_DATA
);
928 *(DWORD
*)data
= hash
->len
;
929 *len
= sizeof(hash
->len
);
935 if (BCryptFinishHash( hash
->handle
, hash
->value
, hash
->len
, 0 )) return FALSE
;
936 hash
->finished
= TRUE
;
938 if (hash
->len
> *len
)
941 SetLastError( ERROR_MORE_DATA
);
944 memcpy( data
, hash
->value
, hash
->len
);
949 SetLastError( NTE_BAD_TYPE
);
954 BOOL WINAPI
CPSetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, const BYTE
*data
, DWORD flags
)
956 struct hash
*hash
= (struct hash
*)hhash
;
958 TRACE( "%p, %p, %08x, %p, %08x\n", (void *)hprov
, (void *)hhash
, param
, data
, flags
);
960 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
965 memcpy( hash
->value
, data
, hash
->len
);
969 FIXME( "param %u not supported\n", param
);
970 SetLastError( NTE_BAD_TYPE
);
975 BOOL WINAPI
CPDeriveKey( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTHASH hhash
, DWORD flags
, HCRYPTKEY
*ret_key
)
980 static DWORD
get_signature_length( DWORD algid
)
985 case CALG_DSS_SIGN
: return 40;
987 FIXME( "unhandled algorithm %u\n", algid
);
992 #define MAX_HASH_LEN 20
993 BOOL WINAPI
CPSignHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD keyspec
, const WCHAR
*desc
, DWORD flags
, BYTE
*sig
,
996 struct container
*container
= (struct container
*)hprov
;
997 struct hash
*hash
= (struct hash
*)hhash
;
1000 TRACE( "%p, %p, %u, %s, %08x, %p, %p\n", (void *)hprov
, (void *)hhash
, keyspec
, debugstr_w(desc
), flags
, sig
,
1003 if (container
->magic
!= MAGIC_CONTAINER
|| !container
->sign_key
) return FALSE
;
1004 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
1006 if (!(len
= get_signature_length( container
->sign_key
->algid
))) return FALSE
;
1013 return !BCryptSignHash( container
->sign_key
->handle
, NULL
, hash
->value
, hash
->len
, sig
, *siglen
, siglen
, 0 );
1016 BOOL WINAPI
CPVerifySignature( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*sig
, DWORD siglen
, HCRYPTKEY hpubkey
,
1017 const WCHAR
*desc
, DWORD flags
)
1019 struct hash
*hash
= (struct hash
*)hhash
;
1020 struct key
*key
= (struct key
*)hpubkey
;
1022 TRACE( "%p, %p, %p, %u %p, %s, %08x\n", (void *)hprov
, (void *)hhash
, sig
, siglen
, (void *)hpubkey
,
1023 debugstr_w(desc
), flags
);
1025 if (hash
->magic
!= MAGIC_HASH
|| key
->magic
!= MAGIC_KEY
) return FALSE
;
1028 FIXME( "flags %08x not supported\n", flags
);
1032 return !BCryptVerifySignature( key
->handle
, NULL
, hash
->value
, hash
->len
, (UCHAR
*)sig
, siglen
, 0 );
1035 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1037 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
1041 case DLL_PROCESS_ATTACH
:
1042 instance
= hinstDLL
;
1043 DisableThreadLibraryCalls(hinstDLL
);
1049 /*****************************************************
1050 * DllRegisterServer (DSSENH.@)
1052 HRESULT WINAPI
DllRegisterServer(void)
1054 return __wine_register_resources( instance
);
1057 /*****************************************************
1058 * DllUnregisterServer (DSSENH.@)
1060 HRESULT WINAPI
DllUnregisterServer(void)
1062 return __wine_unregister_resources( instance
);