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"
35 WINE_DEFAULT_DEBUG_CHANNEL(dssenh
);
37 #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0')
43 BCRYPT_KEY_HANDLE handle
;
46 #define MAGIC_CONTAINER (('C' << 24) | ('O' << 16) | ('N' << 8) | 'T')
56 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
60 BCRYPT_HASH_HANDLE handle
;
66 static const char dss_path_fmt
[] = "Software\\Wine\\Crypto\\DSS\\%s";
68 static BOOL
create_container_regkey( struct container
*container
, REGSAM sam
, HKEY
*hkey
)
70 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
73 sprintf( path
, dss_path_fmt
, container
->name
);
75 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
76 rootkey
= HKEY_LOCAL_MACHINE
;
78 rootkey
= HKEY_CURRENT_USER
;
80 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
81 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
82 return !RegCreateKeyExA( rootkey
, path
, 0, NULL
, REG_OPTION_NON_VOLATILE
, sam
, NULL
, hkey
, NULL
);
85 static struct container
*create_key_container( const char *name
, DWORD flags
)
87 struct container
*ret
;
89 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
90 ret
->magic
= MAGIC_CONTAINER
;
92 if (name
) strcpy( ret
->name
, name
);
94 if (!(flags
& CRYPT_VERIFYCONTEXT
))
97 if (create_container_regkey( ret
, KEY_WRITE
, &hkey
)) RegCloseKey( hkey
);
102 static BOOL
open_container_regkey( const char *name
, DWORD flags
, REGSAM access
, HKEY
*hkey
)
104 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
107 sprintf( path
, dss_path_fmt
, name
);
109 if (flags
& CRYPT_MACHINE_KEYSET
)
110 rootkey
= HKEY_LOCAL_MACHINE
;
112 rootkey
= HKEY_CURRENT_USER
;
114 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
115 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
116 return !RegOpenKeyExA( rootkey
, path
, 0, access
, hkey
);
119 static const WCHAR
*map_keyspec_to_keypair_name( DWORD keyspec
)
126 name
= L
"KeyExchangeKeyPair";
129 name
= L
"SignatureKeyPair";
132 ERR( "invalid key spec %lu\n", keyspec
);
138 static struct key
*create_key( ALG_ID algid
, DWORD flags
)
149 FIXME( "unhandled algorithm %08x\n", algid
);
153 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
155 ret
->magic
= MAGIC_KEY
;
161 static void destroy_key( struct key
*key
)
164 BCryptDestroyKey( key
->handle
);
165 /* Ensure compiler doesn't optimize out the assignment with 0. */
166 SecureZeroMemory( &key
->magic
, sizeof(key
->magic
) );
170 static struct key
*import_key( DWORD keyspec
, BYTE
*data
, DWORD len
)
174 if (!(ret
= create_key( keyspec
, 0 ))) return NULL
;
176 if (BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, &ret
->handle
, data
, len
, 0 ))
178 WARN( "failed to import key\n" );
185 static struct key
*read_key( HKEY hkey
, DWORD keyspec
, DWORD flags
)
190 DATA_BLOB blob_in
, blob_out
;
191 struct key
*ret
= NULL
;
193 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return NULL
;
194 if (RegQueryValueExW( hkey
, value
, 0, &type
, NULL
, &len
)) return NULL
;
195 if (!(data
= malloc( len
))) return NULL
;
197 if (!RegQueryValueExW( hkey
, value
, 0, &type
, data
, &len
))
199 blob_in
.pbData
= data
;
200 blob_in
.cbData
= len
;
201 if (CryptUnprotectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
))
203 ret
= import_key( keyspec
, blob_out
.pbData
, blob_out
.cbData
);
204 LocalFree( blob_out
.pbData
);
212 static void destroy_container( struct container
*container
)
214 if (!container
) return;
215 destroy_key( container
->exch_key
);
216 destroy_key( container
->sign_key
);
217 /* Ensure compiler doesn't optimize out the assignment with 0. */
218 SecureZeroMemory( &container
->magic
, sizeof(container
->magic
) );
222 static struct container
*read_key_container( const char *name
, DWORD flags
)
224 DWORD protect_flags
= (flags
& CRYPT_MACHINE_KEYSET
) ? CRYPTPROTECT_LOCAL_MACHINE
: 0;
225 struct container
*ret
;
228 if (!open_container_regkey( name
, flags
, KEY_READ
, &hkey
)) return NULL
;
230 if ((ret
= create_key_container( name
, flags
)))
232 ret
->exch_key
= read_key( hkey
, AT_KEYEXCHANGE
, protect_flags
);
233 ret
->sign_key
= read_key( hkey
, AT_SIGNATURE
, protect_flags
);
240 static void delete_key_container( const char *name
, DWORD flags
)
242 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
245 sprintf( path
, dss_path_fmt
, name
);
247 if (flags
& CRYPT_MACHINE_KEYSET
)
248 rootkey
= HKEY_LOCAL_MACHINE
;
250 rootkey
= HKEY_CURRENT_USER
;
252 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
253 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
254 RegDeleteKeyExA( rootkey
, path
, 0, 0 );
257 BOOL WINAPI
CPAcquireContext( HCRYPTPROV
*ret_prov
, LPSTR container
, DWORD flags
, PVTableProvStruc vtable
)
259 struct container
*ret
;
262 TRACE( "%p, %s, %08lx, %p\n", ret_prov
, debugstr_a(container
), flags
, vtable
);
264 if (container
&& *container
)
266 if (lstrlenA( container
) >= sizeof(name
)) return FALSE
;
267 lstrcpyA( name
, container
);
271 DWORD len
= sizeof(name
);
272 if (!GetUserNameA( name
, &len
)) return FALSE
;
278 case 0 | CRYPT_MACHINE_KEYSET
:
279 if (!(ret
= read_key_container( name
, flags
)))
280 SetLastError( NTE_BAD_KEYSET
);
283 case CRYPT_NEWKEYSET
:
284 case CRYPT_NEWKEYSET
| CRYPT_MACHINE_KEYSET
:
285 if ((ret
= read_key_container( name
, flags
)))
288 SetLastError( NTE_EXISTS
);
291 ret
= create_key_container( name
, flags
);
294 case CRYPT_VERIFYCONTEXT
:
295 case CRYPT_VERIFYCONTEXT
| CRYPT_MACHINE_KEYSET
:
296 ret
= create_key_container( "", flags
);
299 case CRYPT_DELETEKEYSET
:
300 case CRYPT_DELETEKEYSET
| CRYPT_MACHINE_KEYSET
:
301 delete_key_container( name
, flags
);
306 FIXME( "unsupported flags %08lx\n", flags
);
310 if (!ret
) return FALSE
;
311 *ret_prov
= (HCRYPTPROV
)ret
;
315 BOOL WINAPI
CPReleaseContext( HCRYPTPROV hprov
, DWORD flags
)
317 struct container
*container
= (struct container
*)hprov
;
319 TRACE( "%p, %08lx\n", (void *)hprov
, flags
);
321 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
322 destroy_container( container
);
326 BOOL WINAPI
CPGetProvParam( HCRYPTPROV hprov
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
331 static BOOL
store_key_pair( struct key
*key
, HKEY hkey
, DWORD keyspec
, DWORD flags
)
334 DATA_BLOB blob_in
, blob_out
;
339 if (!key
) return TRUE
;
340 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return FALSE
;
342 if (BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, NULL
, 0, &len
, 0 )) return FALSE
;
343 if (!(data
= malloc( len
))) return FALSE
;
345 if (!BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, data
, len
, &len
, 0 ))
347 blob_in
.pbData
= data
;
348 blob_in
.cbData
= len
;
349 if ((ret
= CryptProtectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
)))
351 ret
= !RegSetValueExW( hkey
, value
, 0, REG_BINARY
, blob_out
.pbData
, blob_out
.cbData
);
352 LocalFree( blob_out
.pbData
);
360 static BOOL
store_key_container_keys( struct container
*container
)
366 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
367 flags
= CRYPTPROTECT_LOCAL_MACHINE
;
371 if (!create_container_regkey( container
, KEY_WRITE
, &hkey
)) return FALSE
;
373 ret
= store_key_pair( container
->exch_key
, hkey
, AT_KEYEXCHANGE
, flags
);
374 if (ret
) store_key_pair( container
->sign_key
, hkey
, AT_SIGNATURE
, flags
);
379 static struct key
*duplicate_key( const struct key
*key
)
383 if (!(ret
= create_key( key
->algid
, key
->flags
))) return NULL
;
385 if (BCryptDuplicateKey( key
->handle
, &ret
->handle
, NULL
, 0, 0 ))
393 static BOOL
generate_key( struct container
*container
, ALG_ID algid
, DWORD bitlen
, DWORD flags
, HCRYPTKEY
*ret_key
)
395 struct key
*key
, *sign_key
;
398 if (!(key
= create_key( algid
, flags
))) return FALSE
;
400 if ((status
= BCryptGenerateKeyPair( BCRYPT_DSA_ALG_HANDLE
, &key
->handle
, bitlen
, 0 )))
402 ERR( "failed to generate key %08lx\n", status
);
406 if ((status
= BCryptFinalizeKeyPair( key
->handle
, 0 )))
408 ERR( "failed to finalize key %08lx\n", status
);
417 if (!(sign_key
= duplicate_key( key
)))
422 destroy_key( container
->sign_key
);
423 container
->sign_key
= sign_key
;
427 FIXME( "unhandled algorithm %08x\n", algid
);
431 if (!store_key_container_keys( container
)) return FALSE
;
433 *ret_key
= (HCRYPTKEY
)key
;
437 BOOL WINAPI
CPGenKey( HCRYPTPROV hprov
, ALG_ID algid
, DWORD flags
, HCRYPTKEY
*ret_key
)
439 static const unsigned int supported_key_lengths
[] = { 512, 768, 1024 };
440 struct container
*container
= (struct container
*)hprov
;
441 ULONG i
, bitlen
= HIWORD(flags
) ? HIWORD(flags
) : 1024;
443 TRACE( "%p, %08x, %08lx, %p\n", (void *)hprov
, algid
, flags
, ret_key
);
445 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
449 SetLastError( STATUS_INVALID_PARAMETER
);
452 for (i
= 0; i
< ARRAY_SIZE(supported_key_lengths
); i
++)
454 if (bitlen
== supported_key_lengths
[i
]) break;
456 if (i
>= ARRAY_SIZE(supported_key_lengths
))
458 SetLastError( NTE_BAD_FLAGS
);
462 return generate_key( container
, algid
, bitlen
, LOWORD(flags
), ret_key
);
465 BOOL WINAPI
CPDestroyKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
)
467 struct key
*key
= (struct key
*)hkey
;
469 TRACE( "%p, %p\n", (void *)hprov
, (void *)hkey
);
471 if (key
->magic
!= MAGIC_KEY
)
473 SetLastError( NTE_BAD_KEY
);
481 #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
482 #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
483 #define MAGIC_DSS3 ('D' | ('S' << 8) | ('S' << 16) | ('3' << 24))
485 static BOOL
import_key_dss2( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
488 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
489 const DSSPUBKEY
*pubkey
= (const DSSPUBKEY
*)(hdr
+ 1);
491 struct key
*key
, *exch_key
, *sign_key
;
494 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
496 switch (pubkey
->magic
)
499 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
503 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
507 FIXME( "unsupported key magic %08lx\n", pubkey
->magic
);
511 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
513 if ((status
= BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE
, NULL
, type
, &key
->handle
, (UCHAR
*)data
, len
, 0 )))
515 TRACE( "failed to import key %08lx\n", status
);
520 if (!wcscmp(type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
526 if (!(exch_key
= duplicate_key( key
)))
531 destroy_key( container
->exch_key
);
532 container
->exch_key
= exch_key
;
537 if (!(sign_key
= duplicate_key( key
)))
542 destroy_key( container
->sign_key
);
543 container
->sign_key
= sign_key
;
547 FIXME( "unhandled key algorithm %u\n", algid
);
552 if (!store_key_container_keys( container
)) return FALSE
;
555 *ret_key
= (HCRYPTKEY
)key
;
559 static BOOL
import_key_dss3( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
562 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
563 const DSSPUBKEY_VER3
*pubkey
= (const DSSPUBKEY_VER3
*)(hdr
+ 1);
564 BCRYPT_DSA_KEY_BLOB
*blob
;
567 ULONG i
, size
, size_q
;
570 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
572 switch (pubkey
->magic
)
578 FIXME( "unsupported key magic %08lx\n", pubkey
->magic
);
582 if ((size_q
= pubkey
->bitlenQ
/ 8) > sizeof(blob
->q
))
584 FIXME( "q too large\n" );
588 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
590 size
= sizeof(*blob
) + (pubkey
->bitlenP
/ 8) * 3;
591 if (!(blob
= calloc( 1, size
)))
596 blob
->dwMagic
= BCRYPT_DSA_PUBLIC_MAGIC
;
597 blob
->cbKey
= pubkey
->bitlenP
/ 8;
598 memcpy( blob
->Count
, &pubkey
->DSSSeed
.counter
, sizeof(blob
->Count
) );
599 memcpy( blob
->Seed
, pubkey
->DSSSeed
.seed
, sizeof(blob
->Seed
) );
602 src
= (BYTE
*)(pubkey
+ 1) + blob
->cbKey
;
603 for (i
= 0; i
< size_q
; i
++) blob
->q
[i
] = src
[size_q
- i
- 1];
607 dst
= (BYTE
*)(blob
+ 1);
608 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
611 src
+= blob
->cbKey
+ size_q
;
613 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
616 src
+= blob
->cbKey
+ pubkey
->bitlenJ
/ 8;
618 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
620 if ((status
= BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE
, NULL
, BCRYPT_DSA_PUBLIC_BLOB
, &key
->handle
,
621 (UCHAR
*)blob
, size
, 0 )))
623 WARN( "failed to import key %08lx\n", status
);
630 *ret_key
= (HCRYPTKEY
)key
;
634 BOOL WINAPI
CPImportKey( HCRYPTPROV hprov
, const BYTE
*data
, DWORD len
, HCRYPTKEY hpubkey
, DWORD flags
,
637 struct container
*container
= (struct container
*)hprov
;
638 const BLOBHEADER
*hdr
;
641 TRACE( "%p, %p, %lu, %p, %08lx, %p\n", (void *)hprov
, data
, len
, (void *)hpubkey
, flags
, ret_key
);
643 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
644 if (len
< sizeof(*hdr
)) return FALSE
;
646 hdr
= (const BLOBHEADER
*)data
;
647 if ((hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bType
!= PUBLICKEYBLOB
) || hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
649 FIXME( "bType %u aiKeyAlg %08x not supported\n", hdr
->bType
, hdr
->aiKeyAlg
);
653 switch (hdr
->bVersion
)
656 ret
= import_key_dss2( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
660 ret
= import_key_dss3( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
664 FIXME( "version %u not supported\n", hdr
->bVersion
);
671 BOOL WINAPI
CPExportKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, HCRYPTKEY hexpkey
, DWORD blobtype
, DWORD flags
,
672 BYTE
*data
, DWORD
*len
)
674 struct key
*key
= (struct key
*)hkey
;
677 TRACE( "%p, %p, %p, %08lx, %08lx, %p, %p\n", (void *)hprov
, (void *)hkey
, (void *)hexpkey
, blobtype
, flags
,
680 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
683 FIXME( "export key not supported\n" );
688 FIXME( "flags %08lx not supported\n", flags
);
695 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
699 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
703 FIXME( "blob type %lu not supported\n", blobtype
);
707 return !BCryptExportKey( key
->handle
, NULL
, type
, data
, *len
, len
, 0 );
710 BOOL WINAPI
CPDuplicateKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, DWORD
*reserved
, DWORD flags
, HCRYPTKEY
*ret_key
)
712 struct key
*key
= (struct key
*)hkey
, *ret
;
714 TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov
, (void *)hkey
, reserved
, flags
, ret_key
);
716 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
718 if (!(ret
= duplicate_key( key
))) return FALSE
;
719 *ret_key
= (HCRYPTKEY
)ret
;
723 BOOL WINAPI
CPGetUserKey( HCRYPTPROV hprov
, DWORD keyspec
, HCRYPTKEY
*ret_key
)
725 struct container
*container
= (struct container
*)hprov
;
728 TRACE( "%p, %08lx, %p\n", (void *)hprov
, keyspec
, ret_key
);
730 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
735 if (!container
->exch_key
) SetLastError( NTE_NO_KEY
);
736 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->exch_key
))) ret
= TRUE
;
740 if (!container
->sign_key
) SetLastError( NTE_NO_KEY
);
741 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->sign_key
))) ret
= TRUE
;
745 SetLastError( NTE_NO_KEY
);
752 BOOL WINAPI
CPGenRandom( HCRYPTPROV hprov
, DWORD len
, BYTE
*buffer
)
754 struct container
*container
= (struct container
*)hprov
;
756 TRACE( "%p, %lu, %p\n", (void *)hprov
, len
, buffer
);
758 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
760 return RtlGenRandom( buffer
, len
);
763 static struct hash
*create_hash( ALG_ID algid
)
766 BCRYPT_ALG_HANDLE alg_handle
;
772 alg_handle
= BCRYPT_MD5_ALG_HANDLE
;
777 alg_handle
= BCRYPT_SHA1_ALG_HANDLE
;
782 FIXME( "unhandled algorithm %u\n", algid
);
786 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
788 ret
->magic
= MAGIC_HASH
;
790 if (BCryptCreateHash( alg_handle
, &ret
->handle
, NULL
, 0, NULL
, 0, 0 ))
798 BOOL WINAPI
CPCreateHash( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTKEY hkey
, DWORD flags
, HCRYPTHASH
*ret_hash
)
802 TRACE( "%p, %08x, %p, %08lx, %p\n", (void *)hprov
, algid
, (void *)hkey
, flags
, ret_hash
);
811 FIXME( "algorithm %u not supported\n", algid
);
812 SetLastError( NTE_BAD_ALGID
);
816 if (!(hash
= create_hash( algid
))) return FALSE
;
818 *ret_hash
= (HCRYPTHASH
)hash
;
822 static void destroy_hash( struct hash
*hash
)
825 BCryptDestroyHash( hash
->handle
);
826 /* Ensure compiler doesn't optimize out the assignment with 0. */
827 SecureZeroMemory( &hash
->magic
, sizeof(hash
->magic
) );
831 BOOL WINAPI
CPDestroyHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
)
833 struct hash
*hash
= (struct hash
*)hhash
;
835 TRACE( "%p, %p\n", (void *)hprov
, (void *)hhash
);
837 if (hash
->magic
!= MAGIC_HASH
)
839 SetLastError( NTE_BAD_HASH
);
843 destroy_hash( hash
);
847 static struct hash
*duplicate_hash( const struct hash
*hash
)
851 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
853 ret
->magic
= hash
->magic
;
854 ret
->len
= hash
->len
;
855 if (BCryptDuplicateHash( hash
->handle
, &ret
->handle
, NULL
, 0, 0 ))
860 memcpy( ret
->value
, hash
->value
, sizeof(hash
->value
) );
861 ret
->finished
= hash
->finished
;
865 BOOL WINAPI
CPDuplicateHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD
*reserved
, DWORD flags
, HCRYPTHASH
*ret_hash
)
867 struct hash
*hash
= (struct hash
*)hhash
, *ret
;
869 TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov
, (void *)hhash
, reserved
, flags
, ret_hash
);
871 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
873 if (!(ret
= duplicate_hash( hash
))) return FALSE
;
874 *ret_hash
= (HCRYPTHASH
)ret
;
878 BOOL WINAPI
CPHashData( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*data
, DWORD len
, DWORD flags
)
880 struct hash
*hash
= (struct hash
*)hhash
;
882 TRACE("%p, %p, %p, %lu, %08lx\n", (void *)hprov
, (void *)hhash
, data
, len
, flags
);
884 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
888 SetLastError( NTE_BAD_HASH_STATE
);
891 return !BCryptHashData( hash
->handle
, (UCHAR
*)data
, len
, 0 );
894 BOOL WINAPI
CPGetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
896 struct hash
*hash
= (struct hash
*)hhash
;
898 TRACE( "%p, %p, %08lx, %p, %p, %08lx\n", (void *)hprov
, (void *)hhash
, param
, data
, len
, flags
);
900 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
905 if (sizeof(hash
->len
) > *len
)
907 *len
= sizeof(hash
->len
);
908 SetLastError( ERROR_MORE_DATA
);
911 *(DWORD
*)data
= hash
->len
;
912 *len
= sizeof(hash
->len
);
918 if (BCryptFinishHash( hash
->handle
, hash
->value
, hash
->len
, 0 )) return FALSE
;
919 hash
->finished
= TRUE
;
921 if (hash
->len
> *len
)
924 SetLastError( ERROR_MORE_DATA
);
927 if (data
) memcpy( data
, hash
->value
, hash
->len
);
932 SetLastError( NTE_BAD_TYPE
);
937 BOOL WINAPI
CPSetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, const BYTE
*data
, DWORD flags
)
939 struct hash
*hash
= (struct hash
*)hhash
;
941 TRACE( "%p, %p, %08lx, %p, %08lx\n", (void *)hprov
, (void *)hhash
, param
, data
, flags
);
943 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
948 memcpy( hash
->value
, data
, hash
->len
);
952 FIXME( "param %lu not supported\n", param
);
953 SetLastError( NTE_BAD_TYPE
);
958 BOOL WINAPI
CPDeriveKey( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTHASH hhash
, DWORD flags
, HCRYPTKEY
*ret_key
)
963 static DWORD
get_signature_length( DWORD algid
)
968 case CALG_DSS_SIGN
: return 40;
970 FIXME( "unhandled algorithm %lu\n", algid
);
975 #define MAX_HASH_LEN 20
976 BOOL WINAPI
CPSignHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD keyspec
, const WCHAR
*desc
, DWORD flags
, BYTE
*sig
,
979 struct container
*container
= (struct container
*)hprov
;
980 struct hash
*hash
= (struct hash
*)hhash
;
983 TRACE( "%p, %p, %lu, %s, %08lx, %p, %p\n", (void *)hprov
, (void *)hhash
, keyspec
, debugstr_w(desc
), flags
, sig
,
986 if (container
->magic
!= MAGIC_CONTAINER
|| !container
->sign_key
) return FALSE
;
987 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
989 if (!(len
= get_signature_length( container
->sign_key
->algid
))) return FALSE
;
996 return !BCryptSignHash( container
->sign_key
->handle
, NULL
, hash
->value
, hash
->len
, sig
, *siglen
, siglen
, 0 );
999 BOOL WINAPI
CPVerifySignature( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*sig
, DWORD siglen
, HCRYPTKEY hpubkey
,
1000 const WCHAR
*desc
, DWORD flags
)
1002 struct hash
*hash
= (struct hash
*)hhash
;
1003 struct key
*key
= (struct key
*)hpubkey
;
1005 TRACE( "%p, %p, %p, %lu %p, %s, %08lx\n", (void *)hprov
, (void *)hhash
, sig
, siglen
, (void *)hpubkey
,
1006 debugstr_w(desc
), flags
);
1008 if (hash
->magic
!= MAGIC_HASH
|| key
->magic
!= MAGIC_KEY
) return FALSE
;
1011 FIXME( "flags %08lx not supported\n", flags
);
1015 if (!hash
->finished
)
1017 if (BCryptFinishHash( hash
->handle
, hash
->value
, hash
->len
, 0 )) return FALSE
;
1018 hash
->finished
= TRUE
;
1021 return !BCryptVerifySignature( key
->handle
, NULL
, hash
->value
, hash
->len
, (UCHAR
*)sig
, siglen
, 0 );