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 WINE_DEFAULT_DEBUG_CHANNEL(dssenh
);
38 #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0')
44 BCRYPT_ALG_HANDLE alg_handle
;
45 BCRYPT_KEY_HANDLE handle
;
48 #define MAGIC_CONTAINER (('C' << 24) | ('O' << 16) | ('N' << 8) | 'T')
58 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
62 BCRYPT_HASH_HANDLE handle
;
68 static const char dss_path_fmt
[] = "Software\\Wine\\Crypto\\DSS\\%s";
70 static BOOL
create_container_regkey( struct container
*container
, REGSAM sam
, HKEY
*hkey
)
72 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
75 sprintf( path
, dss_path_fmt
, container
->name
);
77 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
78 rootkey
= HKEY_LOCAL_MACHINE
;
80 rootkey
= HKEY_CURRENT_USER
;
82 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
83 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
84 return !RegCreateKeyExA( rootkey
, path
, 0, NULL
, REG_OPTION_NON_VOLATILE
, sam
, NULL
, hkey
, NULL
);
87 static struct container
*create_key_container( const char *name
, DWORD flags
)
89 struct container
*ret
;
91 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
92 ret
->magic
= MAGIC_CONTAINER
;
94 if (name
) strcpy( ret
->name
, name
);
96 if (!(flags
& CRYPT_VERIFYCONTEXT
))
99 if (create_container_regkey( ret
, KEY_WRITE
, &hkey
)) RegCloseKey( hkey
);
104 static BOOL
open_container_regkey( const char *name
, DWORD flags
, REGSAM access
, HKEY
*hkey
)
106 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
109 sprintf( path
, dss_path_fmt
, name
);
111 if (flags
& CRYPT_MACHINE_KEYSET
)
112 rootkey
= HKEY_LOCAL_MACHINE
;
114 rootkey
= HKEY_CURRENT_USER
;
116 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
117 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
118 return !RegOpenKeyExA( rootkey
, path
, 0, access
, hkey
);
121 static const WCHAR
*map_keyspec_to_keypair_name( DWORD keyspec
)
128 name
= L
"KeyExchangeKeyPair";
131 name
= L
"SignatureKeyPair";
134 ERR( "invalid key spec %lu\n", keyspec
);
140 static struct key
*create_key( ALG_ID algid
, DWORD flags
)
149 alg
= BCRYPT_DSA_ALGORITHM
;
153 FIXME( "unhandled algorithm %08x\n", algid
);
157 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
159 ret
->magic
= MAGIC_KEY
;
162 if (BCryptOpenAlgorithmProvider( &ret
->alg_handle
, alg
, MS_PRIMITIVE_PROVIDER
, 0 ))
170 static void destroy_key( struct key
*key
)
173 BCryptDestroyKey( key
->handle
);
174 BCryptCloseAlgorithmProvider( key
->alg_handle
, 0 );
179 static struct key
*import_key( DWORD keyspec
, BYTE
*data
, DWORD len
)
183 if (!(ret
= create_key( keyspec
, 0 ))) return NULL
;
185 if (BCryptImportKeyPair( ret
->alg_handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, &ret
->handle
, data
, len
, 0 ))
187 WARN( "failed to import key\n" );
194 static struct key
*read_key( HKEY hkey
, DWORD keyspec
, DWORD flags
)
199 DATA_BLOB blob_in
, blob_out
;
200 struct key
*ret
= NULL
;
202 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return NULL
;
203 if (RegQueryValueExW( hkey
, value
, 0, &type
, NULL
, &len
)) return NULL
;
204 if (!(data
= heap_alloc( len
))) return NULL
;
206 if (!RegQueryValueExW( hkey
, value
, 0, &type
, data
, &len
))
208 blob_in
.pbData
= data
;
209 blob_in
.cbData
= len
;
210 if (CryptUnprotectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
))
212 ret
= import_key( keyspec
, blob_out
.pbData
, blob_out
.cbData
);
213 LocalFree( blob_out
.pbData
);
221 static void destroy_container( struct container
*container
)
223 if (!container
) return;
224 destroy_key( container
->exch_key
);
225 destroy_key( container
->sign_key
);
226 container
->magic
= 0;
227 heap_free( container
);
230 static struct container
*read_key_container( const char *name
, DWORD flags
)
232 DWORD protect_flags
= (flags
& CRYPT_MACHINE_KEYSET
) ? CRYPTPROTECT_LOCAL_MACHINE
: 0;
233 struct container
*ret
;
236 if (!open_container_regkey( name
, flags
, KEY_READ
, &hkey
)) return NULL
;
238 if ((ret
= create_key_container( name
, flags
)))
240 ret
->exch_key
= read_key( hkey
, AT_KEYEXCHANGE
, protect_flags
);
241 ret
->sign_key
= read_key( hkey
, AT_SIGNATURE
, protect_flags
);
248 static void delete_key_container( const char *name
, DWORD flags
)
250 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
253 sprintf( path
, dss_path_fmt
, name
);
255 if (flags
& CRYPT_MACHINE_KEYSET
)
256 rootkey
= HKEY_LOCAL_MACHINE
;
258 rootkey
= HKEY_CURRENT_USER
;
260 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
261 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
262 RegDeleteKeyExA( rootkey
, path
, 0, 0 );
265 BOOL WINAPI
CPAcquireContext( HCRYPTPROV
*ret_prov
, LPSTR container
, DWORD flags
, PVTableProvStruc vtable
)
267 struct container
*ret
;
270 TRACE( "%p, %s, %08lx, %p\n", ret_prov
, debugstr_a(container
), flags
, vtable
);
272 if (container
&& *container
)
274 if (lstrlenA( container
) >= sizeof(name
)) return FALSE
;
275 lstrcpyA( name
, container
);
279 DWORD len
= sizeof(name
);
280 if (!GetUserNameA( name
, &len
)) return FALSE
;
286 case 0 | CRYPT_MACHINE_KEYSET
:
287 if (!(ret
= read_key_container( name
, flags
)))
288 SetLastError( NTE_BAD_KEYSET
);
291 case CRYPT_NEWKEYSET
:
292 case CRYPT_NEWKEYSET
| CRYPT_MACHINE_KEYSET
:
293 if ((ret
= read_key_container( name
, flags
)))
296 SetLastError( NTE_EXISTS
);
299 ret
= create_key_container( name
, flags
);
302 case CRYPT_VERIFYCONTEXT
:
303 case CRYPT_VERIFYCONTEXT
| CRYPT_MACHINE_KEYSET
:
304 ret
= create_key_container( "", flags
);
307 case CRYPT_DELETEKEYSET
:
308 case CRYPT_DELETEKEYSET
| CRYPT_MACHINE_KEYSET
:
309 delete_key_container( name
, flags
);
314 FIXME( "unsupported flags %08lx\n", flags
);
318 if (!ret
) return FALSE
;
319 *ret_prov
= (HCRYPTPROV
)ret
;
323 BOOL WINAPI
CPReleaseContext( HCRYPTPROV hprov
, DWORD flags
)
325 struct container
*container
= (struct container
*)hprov
;
327 TRACE( "%p, %08lx\n", (void *)hprov
, flags
);
329 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
330 destroy_container( container
);
334 BOOL WINAPI
CPGetProvParam( HCRYPTPROV hprov
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
339 static BOOL
store_key_pair( struct key
*key
, HKEY hkey
, DWORD keyspec
, DWORD flags
)
342 DATA_BLOB blob_in
, blob_out
;
347 if (!key
) return TRUE
;
348 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return FALSE
;
350 if (BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, NULL
, 0, &len
, 0 )) return FALSE
;
351 if (!(data
= heap_alloc( len
))) return FALSE
;
353 if (!BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, data
, len
, &len
, 0 ))
355 blob_in
.pbData
= data
;
356 blob_in
.cbData
= len
;
357 if ((ret
= CryptProtectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
)))
359 ret
= !RegSetValueExW( hkey
, value
, 0, REG_BINARY
, blob_out
.pbData
, blob_out
.cbData
);
360 LocalFree( blob_out
.pbData
);
368 static BOOL
store_key_container_keys( struct container
*container
)
374 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
375 flags
= CRYPTPROTECT_LOCAL_MACHINE
;
379 if (!create_container_regkey( container
, KEY_WRITE
, &hkey
)) return FALSE
;
381 ret
= store_key_pair( container
->exch_key
, hkey
, AT_KEYEXCHANGE
, flags
);
382 if (ret
) store_key_pair( container
->sign_key
, hkey
, AT_SIGNATURE
, flags
);
387 static struct key
*duplicate_key( const struct key
*key
)
391 if (!(ret
= create_key( key
->algid
, key
->flags
))) return NULL
;
393 if (BCryptDuplicateKey( key
->handle
, &ret
->handle
, NULL
, 0, 0 ))
401 static BOOL
generate_key( struct container
*container
, ALG_ID algid
, DWORD bitlen
, DWORD flags
, HCRYPTKEY
*ret_key
)
403 struct key
*key
, *sign_key
;
406 if (!(key
= create_key( algid
, flags
))) return FALSE
;
408 if ((status
= BCryptGenerateKeyPair( key
->alg_handle
, &key
->handle
, bitlen
, 0 )))
410 ERR( "failed to generate key %08lx\n", status
);
414 if ((status
= BCryptFinalizeKeyPair( key
->handle
, 0 )))
416 ERR( "failed to finalize key %08lx\n", status
);
425 if (!(sign_key
= duplicate_key( key
)))
430 destroy_key( container
->sign_key
);
431 container
->sign_key
= sign_key
;
435 FIXME( "unhandled algorithm %08x\n", algid
);
439 if (!store_key_container_keys( container
)) return FALSE
;
441 *ret_key
= (HCRYPTKEY
)key
;
445 BOOL WINAPI
CPGenKey( HCRYPTPROV hprov
, ALG_ID algid
, DWORD flags
, HCRYPTKEY
*ret_key
)
447 static const unsigned int supported_key_lengths
[] = { 512, 768, 1024 };
448 struct container
*container
= (struct container
*)hprov
;
449 ULONG i
, bitlen
= HIWORD(flags
) ? HIWORD(flags
) : 1024;
451 TRACE( "%p, %08x, %08lx, %p\n", (void *)hprov
, algid
, flags
, ret_key
);
453 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
457 SetLastError( STATUS_INVALID_PARAMETER
);
460 for (i
= 0; i
< ARRAY_SIZE(supported_key_lengths
); i
++)
462 if (bitlen
== supported_key_lengths
[i
]) break;
464 if (i
>= ARRAY_SIZE(supported_key_lengths
))
466 SetLastError( NTE_BAD_FLAGS
);
470 return generate_key( container
, algid
, bitlen
, LOWORD(flags
), ret_key
);
473 BOOL WINAPI
CPDestroyKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
)
475 struct key
*key
= (struct key
*)hkey
;
477 TRACE( "%p, %p\n", (void *)hprov
, (void *)hkey
);
479 if (key
->magic
!= MAGIC_KEY
)
481 SetLastError( NTE_BAD_KEY
);
489 #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
490 #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
491 #define MAGIC_DSS3 ('D' | ('S' << 8) | ('S' << 16) | ('3' << 24))
493 static BOOL
import_key_dss2( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
496 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
497 const DSSPUBKEY
*pubkey
= (const DSSPUBKEY
*)(hdr
+ 1);
499 struct key
*key
, *exch_key
, *sign_key
;
502 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
504 switch (pubkey
->magic
)
507 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
511 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
515 FIXME( "unsupported key magic %08lx\n", pubkey
->magic
);
519 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
521 if ((status
= BCryptImportKeyPair( key
->alg_handle
, NULL
, type
, &key
->handle
, (UCHAR
*)data
, len
, 0 )))
523 TRACE( "failed to import key %08lx\n", status
);
528 if (!wcscmp(type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
534 if (!(exch_key
= duplicate_key( key
)))
539 destroy_key( container
->exch_key
);
540 container
->exch_key
= exch_key
;
545 if (!(sign_key
= duplicate_key( key
)))
550 destroy_key( container
->sign_key
);
551 container
->sign_key
= sign_key
;
555 FIXME( "unhandled key algorithm %u\n", algid
);
560 if (!store_key_container_keys( container
)) return FALSE
;
563 *ret_key
= (HCRYPTKEY
)key
;
567 static BOOL
import_key_dss3( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
570 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
571 const DSSPUBKEY_VER3
*pubkey
= (const DSSPUBKEY_VER3
*)(hdr
+ 1);
572 BCRYPT_DSA_KEY_BLOB
*blob
;
575 ULONG i
, size
, size_q
;
578 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
580 switch (pubkey
->magic
)
586 FIXME( "unsupported key magic %08lx\n", pubkey
->magic
);
590 if ((size_q
= pubkey
->bitlenQ
/ 8) > sizeof(blob
->q
))
592 FIXME( "q too large\n" );
596 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
598 size
= sizeof(*blob
) + (pubkey
->bitlenP
/ 8) * 3;
599 if (!(blob
= heap_alloc_zero( size
)))
604 blob
->dwMagic
= BCRYPT_DSA_PUBLIC_MAGIC
;
605 blob
->cbKey
= pubkey
->bitlenP
/ 8;
606 memcpy( blob
->Count
, &pubkey
->DSSSeed
.counter
, sizeof(blob
->Count
) );
607 memcpy( blob
->Seed
, pubkey
->DSSSeed
.seed
, sizeof(blob
->Seed
) );
610 src
= (BYTE
*)(pubkey
+ 1) + blob
->cbKey
;
611 for (i
= 0; i
< size_q
; i
++) blob
->q
[i
] = src
[size_q
- i
- 1];
615 dst
= (BYTE
*)(blob
+ 1);
616 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
619 src
+= blob
->cbKey
+ size_q
;
621 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
624 src
+= blob
->cbKey
+ pubkey
->bitlenJ
/ 8;
626 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
628 if ((status
= BCryptImportKeyPair( key
->alg_handle
, NULL
, BCRYPT_DSA_PUBLIC_BLOB
, &key
->handle
, (UCHAR
*)blob
,
631 WARN( "failed to import key %08lx\n", status
);
638 *ret_key
= (HCRYPTKEY
)key
;
642 BOOL WINAPI
CPImportKey( HCRYPTPROV hprov
, const BYTE
*data
, DWORD len
, HCRYPTKEY hpubkey
, DWORD flags
,
645 struct container
*container
= (struct container
*)hprov
;
646 const BLOBHEADER
*hdr
;
649 TRACE( "%p, %p, %lu, %p, %08lx, %p\n", (void *)hprov
, data
, len
, (void *)hpubkey
, flags
, ret_key
);
651 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
652 if (len
< sizeof(*hdr
)) return FALSE
;
654 hdr
= (const BLOBHEADER
*)data
;
655 if ((hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bType
!= PUBLICKEYBLOB
) || hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
657 FIXME( "bType %u aiKeyAlg %08x not supported\n", hdr
->bType
, hdr
->aiKeyAlg
);
661 switch (hdr
->bVersion
)
664 ret
= import_key_dss2( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
668 ret
= import_key_dss3( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
672 FIXME( "version %u not supported\n", hdr
->bVersion
);
679 BOOL WINAPI
CPExportKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, HCRYPTKEY hexpkey
, DWORD blobtype
, DWORD flags
,
680 BYTE
*data
, DWORD
*len
)
682 struct key
*key
= (struct key
*)hkey
;
685 TRACE( "%p, %p, %p, %08lx, %08lx, %p, %p\n", (void *)hprov
, (void *)hkey
, (void *)hexpkey
, blobtype
, flags
,
688 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
691 FIXME( "export key not supported\n" );
696 FIXME( "flags %08lx not supported\n", flags
);
703 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
707 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
711 FIXME( "blob type %lu not supported\n", blobtype
);
715 return !BCryptExportKey( key
->handle
, NULL
, type
, data
, *len
, len
, 0 );
718 BOOL WINAPI
CPDuplicateKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, DWORD
*reserved
, DWORD flags
, HCRYPTKEY
*ret_key
)
720 struct key
*key
= (struct key
*)hkey
, *ret
;
722 TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov
, (void *)hkey
, reserved
, flags
, ret_key
);
724 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
726 if (!(ret
= duplicate_key( key
))) return FALSE
;
727 *ret_key
= (HCRYPTKEY
)ret
;
731 BOOL WINAPI
CPGetUserKey( HCRYPTPROV hprov
, DWORD keyspec
, HCRYPTKEY
*ret_key
)
733 struct container
*container
= (struct container
*)hprov
;
736 TRACE( "%p, %08lx, %p\n", (void *)hprov
, keyspec
, ret_key
);
738 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
743 if (!container
->exch_key
) SetLastError( NTE_NO_KEY
);
744 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->exch_key
))) ret
= TRUE
;
748 if (!container
->sign_key
) SetLastError( NTE_NO_KEY
);
749 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->sign_key
))) ret
= TRUE
;
753 SetLastError( NTE_NO_KEY
);
760 BOOL WINAPI
CPGenRandom( HCRYPTPROV hprov
, DWORD len
, BYTE
*buffer
)
762 struct container
*container
= (struct container
*)hprov
;
764 TRACE( "%p, %lu, %p\n", (void *)hprov
, len
, buffer
);
766 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
768 return RtlGenRandom( buffer
, len
);
771 static struct hash
*create_hash( ALG_ID algid
)
774 BCRYPT_ALG_HANDLE alg_handle
;
781 alg
= BCRYPT_MD5_ALGORITHM
;
786 alg
= BCRYPT_SHA1_ALGORITHM
;
791 FIXME( "unhandled algorithm %u\n", algid
);
795 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
797 ret
->magic
= MAGIC_HASH
;
799 if (BCryptOpenAlgorithmProvider( &alg_handle
, alg
, MS_PRIMITIVE_PROVIDER
, 0 ))
804 if (BCryptCreateHash( alg_handle
, &ret
->handle
, NULL
, 0, NULL
, 0, 0 ))
806 BCryptCloseAlgorithmProvider( alg_handle
, 0 );
811 BCryptCloseAlgorithmProvider( alg_handle
, 0 );
815 BOOL WINAPI
CPCreateHash( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTKEY hkey
, DWORD flags
, HCRYPTHASH
*ret_hash
)
819 TRACE( "%p, %08x, %p, %08lx, %p\n", (void *)hprov
, algid
, (void *)hkey
, flags
, ret_hash
);
828 FIXME( "algorithm %u not supported\n", algid
);
829 SetLastError( NTE_BAD_ALGID
);
833 if (!(hash
= create_hash( algid
))) return FALSE
;
835 *ret_hash
= (HCRYPTHASH
)hash
;
839 static void destroy_hash( struct hash
*hash
)
842 BCryptDestroyHash( hash
->handle
);
847 BOOL WINAPI
CPDestroyHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
)
849 struct hash
*hash
= (struct hash
*)hhash
;
851 TRACE( "%p, %p\n", (void *)hprov
, (void *)hhash
);
853 if (hash
->magic
!= MAGIC_HASH
)
855 SetLastError( NTE_BAD_HASH
);
859 destroy_hash( hash
);
863 static struct hash
*duplicate_hash( const struct hash
*hash
)
867 if (!(ret
= heap_alloc( sizeof(*ret
) ))) return NULL
;
869 ret
->magic
= hash
->magic
;
870 ret
->len
= hash
->len
;
871 if (BCryptDuplicateHash( hash
->handle
, &ret
->handle
, NULL
, 0, 0 ))
876 memcpy( ret
->value
, hash
->value
, sizeof(hash
->value
) );
877 ret
->finished
= hash
->finished
;
881 BOOL WINAPI
CPDuplicateHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD
*reserved
, DWORD flags
, HCRYPTHASH
*ret_hash
)
883 struct hash
*hash
= (struct hash
*)hhash
, *ret
;
885 TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov
, (void *)hhash
, reserved
, flags
, ret_hash
);
887 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
889 if (!(ret
= duplicate_hash( hash
))) return FALSE
;
890 *ret_hash
= (HCRYPTHASH
)ret
;
894 BOOL WINAPI
CPHashData( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*data
, DWORD len
, DWORD flags
)
896 struct hash
*hash
= (struct hash
*)hhash
;
898 TRACE("%p, %p, %p, %lu, %08lx\n", (void *)hprov
, (void *)hhash
, data
, len
, flags
);
900 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
904 SetLastError( NTE_BAD_HASH_STATE
);
907 return !BCryptHashData( hash
->handle
, (UCHAR
*)data
, len
, 0 );
910 BOOL WINAPI
CPGetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
912 struct hash
*hash
= (struct hash
*)hhash
;
914 TRACE( "%p, %p, %08lx, %p, %p, %08lx\n", (void *)hprov
, (void *)hhash
, param
, data
, len
, flags
);
916 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
921 if (sizeof(hash
->len
) > *len
)
923 *len
= sizeof(hash
->len
);
924 SetLastError( ERROR_MORE_DATA
);
927 *(DWORD
*)data
= hash
->len
;
928 *len
= sizeof(hash
->len
);
934 if (BCryptFinishHash( hash
->handle
, hash
->value
, hash
->len
, 0 )) return FALSE
;
935 hash
->finished
= TRUE
;
937 if (hash
->len
> *len
)
940 SetLastError( ERROR_MORE_DATA
);
943 if (data
) memcpy( data
, hash
->value
, hash
->len
);
948 SetLastError( NTE_BAD_TYPE
);
953 BOOL WINAPI
CPSetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, const BYTE
*data
, DWORD flags
)
955 struct hash
*hash
= (struct hash
*)hhash
;
957 TRACE( "%p, %p, %08lx, %p, %08lx\n", (void *)hprov
, (void *)hhash
, param
, data
, flags
);
959 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
964 memcpy( hash
->value
, data
, hash
->len
);
968 FIXME( "param %lu not supported\n", param
);
969 SetLastError( NTE_BAD_TYPE
);
974 BOOL WINAPI
CPDeriveKey( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTHASH hhash
, DWORD flags
, HCRYPTKEY
*ret_key
)
979 static DWORD
get_signature_length( DWORD algid
)
984 case CALG_DSS_SIGN
: return 40;
986 FIXME( "unhandled algorithm %lu\n", algid
);
991 #define MAX_HASH_LEN 20
992 BOOL WINAPI
CPSignHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD keyspec
, const WCHAR
*desc
, DWORD flags
, BYTE
*sig
,
995 struct container
*container
= (struct container
*)hprov
;
996 struct hash
*hash
= (struct hash
*)hhash
;
999 TRACE( "%p, %p, %lu, %s, %08lx, %p, %p\n", (void *)hprov
, (void *)hhash
, keyspec
, debugstr_w(desc
), flags
, sig
,
1002 if (container
->magic
!= MAGIC_CONTAINER
|| !container
->sign_key
) return FALSE
;
1003 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
1005 if (!(len
= get_signature_length( container
->sign_key
->algid
))) return FALSE
;
1012 return !BCryptSignHash( container
->sign_key
->handle
, NULL
, hash
->value
, hash
->len
, sig
, *siglen
, siglen
, 0 );
1015 BOOL WINAPI
CPVerifySignature( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*sig
, DWORD siglen
, HCRYPTKEY hpubkey
,
1016 const WCHAR
*desc
, DWORD flags
)
1018 struct hash
*hash
= (struct hash
*)hhash
;
1019 struct key
*key
= (struct key
*)hpubkey
;
1021 TRACE( "%p, %p, %p, %lu %p, %s, %08lx\n", (void *)hprov
, (void *)hhash
, sig
, siglen
, (void *)hpubkey
,
1022 debugstr_w(desc
), flags
);
1024 if (hash
->magic
!= MAGIC_HASH
|| key
->magic
!= MAGIC_KEY
) return FALSE
;
1027 FIXME( "flags %08lx not supported\n", flags
);
1031 return !BCryptVerifySignature( key
->handle
, NULL
, hash
->value
, hash
->len
, (UCHAR
*)sig
, siglen
, 0 );