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 %u\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, %08x, %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 ret
= read_key_container( name
, flags
);
290 case CRYPT_NEWKEYSET
:
291 case CRYPT_NEWKEYSET
| CRYPT_MACHINE_KEYSET
:
292 if ((ret
= read_key_container( name
, flags
)))
295 SetLastError( NTE_EXISTS
);
298 ret
= create_key_container( name
, flags
);
301 case CRYPT_VERIFYCONTEXT
:
302 case CRYPT_VERIFYCONTEXT
| CRYPT_MACHINE_KEYSET
:
303 ret
= create_key_container( "", flags
);
306 case CRYPT_DELETEKEYSET
:
307 case CRYPT_DELETEKEYSET
| CRYPT_MACHINE_KEYSET
:
308 delete_key_container( name
, flags
);
313 FIXME( "unsupported flags %08x\n", flags
);
317 if (!ret
) return FALSE
;
318 *ret_prov
= (HCRYPTPROV
)ret
;
322 BOOL WINAPI
CPReleaseContext( HCRYPTPROV hprov
, DWORD flags
)
324 struct container
*container
= (struct container
*)hprov
;
326 TRACE( "%p, %08x\n", (void *)hprov
, flags
);
328 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
329 destroy_container( container
);
333 BOOL WINAPI
CPGetProvParam( HCRYPTPROV hprov
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
338 static BOOL
store_key_pair( struct key
*key
, HKEY hkey
, DWORD keyspec
, DWORD flags
)
341 DATA_BLOB blob_in
, blob_out
;
346 if (!key
) return TRUE
;
347 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return FALSE
;
349 if (BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, NULL
, 0, &len
, 0 )) return FALSE
;
350 if (!(data
= heap_alloc( len
))) return FALSE
;
352 if (!BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, data
, len
, &len
, 0 ))
354 blob_in
.pbData
= data
;
355 blob_in
.cbData
= len
;
356 if ((ret
= CryptProtectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
)))
358 ret
= !RegSetValueExW( hkey
, value
, 0, REG_BINARY
, blob_out
.pbData
, blob_out
.cbData
);
359 LocalFree( blob_out
.pbData
);
367 static BOOL
store_key_container_keys( struct container
*container
)
373 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
374 flags
= CRYPTPROTECT_LOCAL_MACHINE
;
378 if (!create_container_regkey( container
, KEY_WRITE
, &hkey
)) return FALSE
;
380 ret
= store_key_pair( container
->exch_key
, hkey
, AT_KEYEXCHANGE
, flags
);
381 if (ret
) store_key_pair( container
->sign_key
, hkey
, AT_SIGNATURE
, flags
);
386 static struct key
*duplicate_key( const struct key
*key
)
390 if (!(ret
= create_key( key
->algid
, key
->flags
))) return NULL
;
392 if (BCryptDuplicateKey( key
->handle
, &ret
->handle
, NULL
, 0, 0 ))
400 static BOOL
generate_key( struct container
*container
, ALG_ID algid
, DWORD bitlen
, DWORD flags
, HCRYPTKEY
*ret_key
)
402 struct key
*key
, *sign_key
;
405 if (!(key
= create_key( algid
, flags
))) return FALSE
;
407 if ((status
= BCryptGenerateKeyPair( key
->alg_handle
, &key
->handle
, bitlen
, 0 )))
409 ERR( "failed to generate key %08x\n", status
);
413 if ((status
= BCryptFinalizeKeyPair( key
->handle
, 0 )))
415 ERR( "failed to finalize key %08x\n", status
);
424 if (!(sign_key
= duplicate_key( key
)))
429 destroy_key( container
->sign_key
);
430 container
->sign_key
= sign_key
;
434 FIXME( "unhandled algorithm %08x\n", algid
);
438 if (!store_key_container_keys( container
)) return FALSE
;
440 *ret_key
= (HCRYPTKEY
)key
;
444 BOOL WINAPI
CPGenKey( HCRYPTPROV hprov
, ALG_ID algid
, DWORD flags
, HCRYPTKEY
*ret_key
)
446 static const unsigned int supported_key_lengths
[] = { 512, 768, 1024 };
447 struct container
*container
= (struct container
*)hprov
;
448 ULONG i
, bitlen
= HIWORD(flags
) ? HIWORD(flags
) : 1024;
450 TRACE( "%p, %08x, %08x, %p\n", (void *)hprov
, algid
, flags
, ret_key
);
452 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
456 SetLastError( STATUS_INVALID_PARAMETER
);
459 for (i
= 0; i
< ARRAY_SIZE(supported_key_lengths
); i
++)
461 if (bitlen
== supported_key_lengths
[i
]) break;
463 if (i
>= ARRAY_SIZE(supported_key_lengths
))
465 SetLastError( NTE_BAD_FLAGS
);
469 return generate_key( container
, algid
, bitlen
, LOWORD(flags
), ret_key
);
472 BOOL WINAPI
CPDestroyKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
)
474 struct key
*key
= (struct key
*)hkey
;
476 TRACE( "%p, %p\n", (void *)hprov
, (void *)hkey
);
478 if (key
->magic
!= MAGIC_KEY
)
480 SetLastError( NTE_BAD_KEY
);
488 #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
489 #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
490 #define MAGIC_DSS3 ('D' | ('S' << 8) | ('S' << 16) | ('3' << 24))
492 static BOOL
import_key_dss2( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
495 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
496 const DSSPUBKEY
*pubkey
= (const DSSPUBKEY
*)(hdr
+ 1);
498 struct key
*key
, *exch_key
, *sign_key
;
501 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
503 switch (pubkey
->magic
)
506 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
510 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
514 FIXME( "unsupported key magic %08x\n", pubkey
->magic
);
518 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
520 if ((status
= BCryptImportKeyPair( key
->alg_handle
, NULL
, type
, &key
->handle
, (UCHAR
*)data
, len
, 0 )))
522 TRACE( "failed to import key %08x\n", status
);
527 if (!wcscmp(type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
533 if (!(exch_key
= duplicate_key( key
)))
538 destroy_key( container
->exch_key
);
539 container
->exch_key
= exch_key
;
544 if (!(sign_key
= duplicate_key( key
)))
549 destroy_key( container
->sign_key
);
550 container
->sign_key
= sign_key
;
554 FIXME( "unhandled key algorithm %u\n", algid
);
559 if (!store_key_container_keys( container
)) return FALSE
;
562 *ret_key
= (HCRYPTKEY
)key
;
566 static BOOL
import_key_dss3( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
569 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
570 const DSSPUBKEY_VER3
*pubkey
= (const DSSPUBKEY_VER3
*)(hdr
+ 1);
571 BCRYPT_DSA_KEY_BLOB
*blob
;
574 ULONG i
, size
, size_q
;
577 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
579 switch (pubkey
->magic
)
585 FIXME( "unsupported key magic %08x\n", pubkey
->magic
);
589 if ((size_q
= pubkey
->bitlenQ
/ 8) > sizeof(blob
->q
))
591 FIXME( "q too large\n" );
595 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
597 size
= sizeof(*blob
) + (pubkey
->bitlenP
/ 8) * 3;
598 if (!(blob
= heap_alloc_zero( size
)))
603 blob
->dwMagic
= BCRYPT_DSA_PUBLIC_MAGIC
;
604 blob
->cbKey
= pubkey
->bitlenP
/ 8;
605 memcpy( blob
->Count
, &pubkey
->DSSSeed
.counter
, sizeof(blob
->Count
) );
606 memcpy( blob
->Seed
, pubkey
->DSSSeed
.seed
, sizeof(blob
->Seed
) );
609 src
= (BYTE
*)(pubkey
+ 1) + blob
->cbKey
;
610 for (i
= 0; i
< size_q
; i
++) blob
->q
[i
] = src
[size_q
- i
- 1];
614 dst
= (BYTE
*)(blob
+ 1);
615 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
618 src
+= blob
->cbKey
+ size_q
;
620 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
623 src
+= blob
->cbKey
+ pubkey
->bitlenJ
/ 8;
625 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
627 if ((status
= BCryptImportKeyPair( key
->alg_handle
, NULL
, BCRYPT_DSA_PUBLIC_BLOB
, &key
->handle
, (UCHAR
*)blob
,
630 WARN( "failed to import key %08x\n", status
);
637 *ret_key
= (HCRYPTKEY
)key
;
641 BOOL WINAPI
CPImportKey( HCRYPTPROV hprov
, const BYTE
*data
, DWORD len
, HCRYPTKEY hpubkey
, DWORD flags
,
644 struct container
*container
= (struct container
*)hprov
;
645 const BLOBHEADER
*hdr
;
648 TRACE( "%p, %p, %u, %p, %08x, %p\n", (void *)hprov
, data
, len
, (void *)hpubkey
, flags
, ret_key
);
650 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
651 if (len
< sizeof(*hdr
)) return FALSE
;
653 hdr
= (const BLOBHEADER
*)data
;
654 if ((hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bType
!= PUBLICKEYBLOB
) || hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
656 FIXME( "bType %u aiKeyAlg %08x not supported\n", hdr
->bType
, hdr
->aiKeyAlg
);
660 switch (hdr
->bVersion
)
663 ret
= import_key_dss2( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
667 ret
= import_key_dss3( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
671 FIXME( "version %u not supported\n", hdr
->bVersion
);
678 BOOL WINAPI
CPExportKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, HCRYPTKEY hexpkey
, DWORD blobtype
, DWORD flags
,
679 BYTE
*data
, DWORD
*len
)
681 struct key
*key
= (struct key
*)hkey
;
684 TRACE( "%p, %p, %p, %08x, %08x, %p, %p\n", (void *)hprov
, (void *)hkey
, (void *)hexpkey
, blobtype
, flags
,
687 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
690 FIXME( "export key not supported\n" );
695 FIXME( "flags %08x not supported\n", flags
);
702 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
706 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
710 FIXME( "blob type %u not supported\n", blobtype
);
714 return !BCryptExportKey( key
->handle
, NULL
, type
, data
, *len
, len
, 0 );
717 BOOL WINAPI
CPDuplicateKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, DWORD
*reserved
, DWORD flags
, HCRYPTKEY
*ret_key
)
719 struct key
*key
= (struct key
*)hkey
, *ret
;
721 TRACE( "%p, %p, %p, %08x, %p\n", (void *)hprov
, (void *)hkey
, reserved
, flags
, ret_key
);
723 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
725 if (!(ret
= duplicate_key( key
))) return FALSE
;
726 *ret_key
= (HCRYPTKEY
)ret
;
730 BOOL WINAPI
CPGetUserKey( HCRYPTPROV hprov
, DWORD keyspec
, HCRYPTKEY
*ret_key
)
732 struct container
*container
= (struct container
*)hprov
;
735 TRACE( "%p, %08x, %p\n", (void *)hprov
, keyspec
, ret_key
);
737 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
742 if (!container
->exch_key
) SetLastError( NTE_NO_KEY
);
743 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->exch_key
))) ret
= TRUE
;
747 if (!container
->sign_key
) SetLastError( NTE_NO_KEY
);
748 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->sign_key
))) ret
= TRUE
;
752 SetLastError( NTE_NO_KEY
);
759 BOOL WINAPI
CPGenRandom( HCRYPTPROV hprov
, DWORD len
, BYTE
*buffer
)
761 struct container
*container
= (struct container
*)hprov
;
763 TRACE( "%p, %u, %p\n", (void *)hprov
, len
, buffer
);
765 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
767 return RtlGenRandom( buffer
, len
);
770 static struct hash
*create_hash( ALG_ID algid
)
773 BCRYPT_ALG_HANDLE alg_handle
;
780 alg
= BCRYPT_MD5_ALGORITHM
;
785 alg
= BCRYPT_SHA1_ALGORITHM
;
790 FIXME( "unhandled algorithm %u\n", algid
);
794 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
796 ret
->magic
= MAGIC_HASH
;
798 if (BCryptOpenAlgorithmProvider( &alg_handle
, alg
, MS_PRIMITIVE_PROVIDER
, 0 ))
803 if (BCryptCreateHash( alg_handle
, &ret
->handle
, NULL
, 0, NULL
, 0, 0 ))
805 BCryptCloseAlgorithmProvider( alg_handle
, 0 );
810 BCryptCloseAlgorithmProvider( alg_handle
, 0 );
814 BOOL WINAPI
CPCreateHash( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTKEY hkey
, DWORD flags
, HCRYPTHASH
*ret_hash
)
818 TRACE( "%p, %08x, %p, %08x, %p\n", (void *)hprov
, algid
, (void *)hkey
, flags
, ret_hash
);
827 FIXME( "algorithm %u not supported\n", algid
);
828 SetLastError( NTE_BAD_ALGID
);
832 if (!(hash
= create_hash( algid
))) return FALSE
;
834 *ret_hash
= (HCRYPTHASH
)hash
;
838 static void destroy_hash( struct hash
*hash
)
841 BCryptDestroyHash( hash
->handle
);
846 BOOL WINAPI
CPDestroyHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
)
848 struct hash
*hash
= (struct hash
*)hhash
;
850 TRACE( "%p, %p\n", (void *)hprov
, (void *)hhash
);
852 if (hash
->magic
!= MAGIC_HASH
)
854 SetLastError( NTE_BAD_HASH
);
858 destroy_hash( hash
);
862 static struct hash
*duplicate_hash( const struct hash
*hash
)
866 if (!(ret
= heap_alloc( sizeof(*ret
) ))) return NULL
;
868 ret
->magic
= hash
->magic
;
869 ret
->len
= hash
->len
;
870 if (BCryptDuplicateHash( hash
->handle
, &ret
->handle
, NULL
, 0, 0 ))
875 memcpy( ret
->value
, hash
->value
, sizeof(hash
->value
) );
876 ret
->finished
= hash
->finished
;
880 BOOL WINAPI
CPDuplicateHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD
*reserved
, DWORD flags
, HCRYPTHASH
*ret_hash
)
882 struct hash
*hash
= (struct hash
*)hhash
, *ret
;
884 TRACE( "%p, %p, %p, %08x, %p\n", (void *)hprov
, (void *)hhash
, reserved
, flags
, ret_hash
);
886 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
888 if (!(ret
= duplicate_hash( hash
))) return FALSE
;
889 *ret_hash
= (HCRYPTHASH
)ret
;
893 BOOL WINAPI
CPHashData( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*data
, DWORD len
, DWORD flags
)
895 struct hash
*hash
= (struct hash
*)hhash
;
897 TRACE("%p, %p, %p, %u, %08x\n", (void *)hprov
, (void *)hhash
, data
, len
, flags
);
899 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
903 SetLastError( NTE_BAD_HASH_STATE
);
906 return !BCryptHashData( hash
->handle
, (UCHAR
*)data
, len
, 0 );
909 BOOL WINAPI
CPGetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
911 struct hash
*hash
= (struct hash
*)hhash
;
913 TRACE( "%p, %p, %08x, %p, %p, %08x\n", (void *)hprov
, (void *)hhash
, param
, data
, len
, flags
);
915 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
920 if (sizeof(hash
->len
) > *len
)
922 *len
= sizeof(hash
->len
);
923 SetLastError( ERROR_MORE_DATA
);
926 *(DWORD
*)data
= hash
->len
;
927 *len
= sizeof(hash
->len
);
933 if (BCryptFinishHash( hash
->handle
, hash
->value
, hash
->len
, 0 )) return FALSE
;
934 hash
->finished
= TRUE
;
936 if (hash
->len
> *len
)
939 SetLastError( ERROR_MORE_DATA
);
942 memcpy( data
, hash
->value
, hash
->len
);
947 SetLastError( NTE_BAD_TYPE
);
952 BOOL WINAPI
CPSetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, const BYTE
*data
, DWORD flags
)
954 struct hash
*hash
= (struct hash
*)hhash
;
956 TRACE( "%p, %p, %08x, %p, %08x\n", (void *)hprov
, (void *)hhash
, param
, data
, flags
);
958 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
963 memcpy( hash
->value
, data
, hash
->len
);
967 FIXME( "param %u not supported\n", param
);
968 SetLastError( NTE_BAD_TYPE
);
973 BOOL WINAPI
CPDeriveKey( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTHASH hhash
, DWORD flags
, HCRYPTKEY
*ret_key
)
978 static DWORD
get_signature_length( DWORD algid
)
983 case CALG_DSS_SIGN
: return 40;
985 FIXME( "unhandled algorithm %u\n", algid
);
990 #define MAX_HASH_LEN 20
991 BOOL WINAPI
CPSignHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD keyspec
, const WCHAR
*desc
, DWORD flags
, BYTE
*sig
,
994 struct container
*container
= (struct container
*)hprov
;
995 struct hash
*hash
= (struct hash
*)hhash
;
998 TRACE( "%p, %p, %u, %s, %08x, %p, %p\n", (void *)hprov
, (void *)hhash
, keyspec
, debugstr_w(desc
), flags
, sig
,
1001 if (container
->magic
!= MAGIC_CONTAINER
|| !container
->sign_key
) return FALSE
;
1002 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
1004 if (!(len
= get_signature_length( container
->sign_key
->algid
))) return FALSE
;
1011 return !BCryptSignHash( container
->sign_key
->handle
, NULL
, hash
->value
, hash
->len
, sig
, *siglen
, siglen
, 0 );
1014 BOOL WINAPI
CPVerifySignature( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*sig
, DWORD siglen
, HCRYPTKEY hpubkey
,
1015 const WCHAR
*desc
, DWORD flags
)
1017 struct hash
*hash
= (struct hash
*)hhash
;
1018 struct key
*key
= (struct key
*)hpubkey
;
1020 TRACE( "%p, %p, %p, %u %p, %s, %08x\n", (void *)hprov
, (void *)hhash
, sig
, siglen
, (void *)hpubkey
,
1021 debugstr_w(desc
), flags
);
1023 if (hash
->magic
!= MAGIC_HASH
|| key
->magic
!= MAGIC_KEY
) return FALSE
;
1026 FIXME( "flags %08x not supported\n", flags
);
1030 return !BCryptVerifySignature( key
->handle
, NULL
, hash
->value
, hash
->len
, (UCHAR
*)sig
, siglen
, 0 );