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
);
169 static struct key
*import_key( DWORD keyspec
, BYTE
*data
, DWORD len
)
173 if (!(ret
= create_key( keyspec
, 0 ))) return NULL
;
175 if (BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, &ret
->handle
, data
, len
, 0 ))
177 WARN( "failed to import key\n" );
184 static struct key
*read_key( HKEY hkey
, DWORD keyspec
, DWORD flags
)
189 DATA_BLOB blob_in
, blob_out
;
190 struct key
*ret
= NULL
;
192 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return NULL
;
193 if (RegQueryValueExW( hkey
, value
, 0, &type
, NULL
, &len
)) return NULL
;
194 if (!(data
= malloc( len
))) return NULL
;
196 if (!RegQueryValueExW( hkey
, value
, 0, &type
, data
, &len
))
198 blob_in
.pbData
= data
;
199 blob_in
.cbData
= len
;
200 if (CryptUnprotectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
))
202 ret
= import_key( keyspec
, blob_out
.pbData
, blob_out
.cbData
);
203 LocalFree( blob_out
.pbData
);
211 static void destroy_container( struct container
*container
)
213 if (!container
) return;
214 destroy_key( container
->exch_key
);
215 destroy_key( container
->sign_key
);
216 container
->magic
= 0;
220 static struct container
*read_key_container( const char *name
, DWORD flags
)
222 DWORD protect_flags
= (flags
& CRYPT_MACHINE_KEYSET
) ? CRYPTPROTECT_LOCAL_MACHINE
: 0;
223 struct container
*ret
;
226 if (!open_container_regkey( name
, flags
, KEY_READ
, &hkey
)) return NULL
;
228 if ((ret
= create_key_container( name
, flags
)))
230 ret
->exch_key
= read_key( hkey
, AT_KEYEXCHANGE
, protect_flags
);
231 ret
->sign_key
= read_key( hkey
, AT_SIGNATURE
, protect_flags
);
238 static void delete_key_container( const char *name
, DWORD flags
)
240 char path
[sizeof(dss_path_fmt
) + MAX_PATH
];
243 sprintf( path
, dss_path_fmt
, name
);
245 if (flags
& CRYPT_MACHINE_KEYSET
)
246 rootkey
= HKEY_LOCAL_MACHINE
;
248 rootkey
= HKEY_CURRENT_USER
;
250 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\DSS */
251 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\DSS */
252 RegDeleteKeyExA( rootkey
, path
, 0, 0 );
255 BOOL WINAPI
CPAcquireContext( HCRYPTPROV
*ret_prov
, LPSTR container
, DWORD flags
, PVTableProvStruc vtable
)
257 struct container
*ret
;
260 TRACE( "%p, %s, %08lx, %p\n", ret_prov
, debugstr_a(container
), flags
, vtable
);
262 if (container
&& *container
)
264 if (lstrlenA( container
) >= sizeof(name
)) return FALSE
;
265 lstrcpyA( name
, container
);
269 DWORD len
= sizeof(name
);
270 if (!GetUserNameA( name
, &len
)) return FALSE
;
276 case 0 | CRYPT_MACHINE_KEYSET
:
277 if (!(ret
= read_key_container( name
, flags
)))
278 SetLastError( NTE_BAD_KEYSET
);
281 case CRYPT_NEWKEYSET
:
282 case CRYPT_NEWKEYSET
| CRYPT_MACHINE_KEYSET
:
283 if ((ret
= read_key_container( name
, flags
)))
286 SetLastError( NTE_EXISTS
);
289 ret
= create_key_container( name
, flags
);
292 case CRYPT_VERIFYCONTEXT
:
293 case CRYPT_VERIFYCONTEXT
| CRYPT_MACHINE_KEYSET
:
294 ret
= create_key_container( "", flags
);
297 case CRYPT_DELETEKEYSET
:
298 case CRYPT_DELETEKEYSET
| CRYPT_MACHINE_KEYSET
:
299 delete_key_container( name
, flags
);
304 FIXME( "unsupported flags %08lx\n", flags
);
308 if (!ret
) return FALSE
;
309 *ret_prov
= (HCRYPTPROV
)ret
;
313 BOOL WINAPI
CPReleaseContext( HCRYPTPROV hprov
, DWORD flags
)
315 struct container
*container
= (struct container
*)hprov
;
317 TRACE( "%p, %08lx\n", (void *)hprov
, flags
);
319 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
320 destroy_container( container
);
324 BOOL WINAPI
CPGetProvParam( HCRYPTPROV hprov
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
329 static BOOL
store_key_pair( struct key
*key
, HKEY hkey
, DWORD keyspec
, DWORD flags
)
332 DATA_BLOB blob_in
, blob_out
;
337 if (!key
) return TRUE
;
338 if (!(value
= map_keyspec_to_keypair_name( keyspec
))) return FALSE
;
340 if (BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, NULL
, 0, &len
, 0 )) return FALSE
;
341 if (!(data
= malloc( len
))) return FALSE
;
343 if (!BCryptExportKey( key
->handle
, NULL
, LEGACY_DSA_V2_PRIVATE_BLOB
, data
, len
, &len
, 0 ))
345 blob_in
.pbData
= data
;
346 blob_in
.cbData
= len
;
347 if ((ret
= CryptProtectData( &blob_in
, NULL
, NULL
, NULL
, NULL
, flags
, &blob_out
)))
349 ret
= !RegSetValueExW( hkey
, value
, 0, REG_BINARY
, blob_out
.pbData
, blob_out
.cbData
);
350 LocalFree( blob_out
.pbData
);
358 static BOOL
store_key_container_keys( struct container
*container
)
364 if (container
->flags
& CRYPT_MACHINE_KEYSET
)
365 flags
= CRYPTPROTECT_LOCAL_MACHINE
;
369 if (!create_container_regkey( container
, KEY_WRITE
, &hkey
)) return FALSE
;
371 ret
= store_key_pair( container
->exch_key
, hkey
, AT_KEYEXCHANGE
, flags
);
372 if (ret
) store_key_pair( container
->sign_key
, hkey
, AT_SIGNATURE
, flags
);
377 static struct key
*duplicate_key( const struct key
*key
)
381 if (!(ret
= create_key( key
->algid
, key
->flags
))) return NULL
;
383 if (BCryptDuplicateKey( key
->handle
, &ret
->handle
, NULL
, 0, 0 ))
391 static BOOL
generate_key( struct container
*container
, ALG_ID algid
, DWORD bitlen
, DWORD flags
, HCRYPTKEY
*ret_key
)
393 struct key
*key
, *sign_key
;
396 if (!(key
= create_key( algid
, flags
))) return FALSE
;
398 if ((status
= BCryptGenerateKeyPair( BCRYPT_DSA_ALG_HANDLE
, &key
->handle
, bitlen
, 0 )))
400 ERR( "failed to generate key %08lx\n", status
);
404 if ((status
= BCryptFinalizeKeyPair( key
->handle
, 0 )))
406 ERR( "failed to finalize key %08lx\n", status
);
415 if (!(sign_key
= duplicate_key( key
)))
420 destroy_key( container
->sign_key
);
421 container
->sign_key
= sign_key
;
425 FIXME( "unhandled algorithm %08x\n", algid
);
429 if (!store_key_container_keys( container
)) return FALSE
;
431 *ret_key
= (HCRYPTKEY
)key
;
435 BOOL WINAPI
CPGenKey( HCRYPTPROV hprov
, ALG_ID algid
, DWORD flags
, HCRYPTKEY
*ret_key
)
437 static const unsigned int supported_key_lengths
[] = { 512, 768, 1024 };
438 struct container
*container
= (struct container
*)hprov
;
439 ULONG i
, bitlen
= HIWORD(flags
) ? HIWORD(flags
) : 1024;
441 TRACE( "%p, %08x, %08lx, %p\n", (void *)hprov
, algid
, flags
, ret_key
);
443 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
447 SetLastError( STATUS_INVALID_PARAMETER
);
450 for (i
= 0; i
< ARRAY_SIZE(supported_key_lengths
); i
++)
452 if (bitlen
== supported_key_lengths
[i
]) break;
454 if (i
>= ARRAY_SIZE(supported_key_lengths
))
456 SetLastError( NTE_BAD_FLAGS
);
460 return generate_key( container
, algid
, bitlen
, LOWORD(flags
), ret_key
);
463 BOOL WINAPI
CPDestroyKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
)
465 struct key
*key
= (struct key
*)hkey
;
467 TRACE( "%p, %p\n", (void *)hprov
, (void *)hkey
);
469 if (key
->magic
!= MAGIC_KEY
)
471 SetLastError( NTE_BAD_KEY
);
479 #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
480 #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
481 #define MAGIC_DSS3 ('D' | ('S' << 8) | ('S' << 16) | ('3' << 24))
483 static BOOL
import_key_dss2( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
486 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
487 const DSSPUBKEY
*pubkey
= (const DSSPUBKEY
*)(hdr
+ 1);
489 struct key
*key
, *exch_key
, *sign_key
;
492 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
494 switch (pubkey
->magic
)
497 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
501 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
505 FIXME( "unsupported key magic %08lx\n", pubkey
->magic
);
509 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
511 if ((status
= BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE
, NULL
, type
, &key
->handle
, (UCHAR
*)data
, len
, 0 )))
513 TRACE( "failed to import key %08lx\n", status
);
518 if (!wcscmp(type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
524 if (!(exch_key
= duplicate_key( key
)))
529 destroy_key( container
->exch_key
);
530 container
->exch_key
= exch_key
;
535 if (!(sign_key
= duplicate_key( key
)))
540 destroy_key( container
->sign_key
);
541 container
->sign_key
= sign_key
;
545 FIXME( "unhandled key algorithm %u\n", algid
);
550 if (!store_key_container_keys( container
)) return FALSE
;
553 *ret_key
= (HCRYPTKEY
)key
;
557 static BOOL
import_key_dss3( struct container
*container
, ALG_ID algid
, const BYTE
*data
, DWORD len
, DWORD flags
,
560 const BLOBHEADER
*hdr
= (const BLOBHEADER
*)data
;
561 const DSSPUBKEY_VER3
*pubkey
= (const DSSPUBKEY_VER3
*)(hdr
+ 1);
562 BCRYPT_DSA_KEY_BLOB
*blob
;
565 ULONG i
, size
, size_q
;
568 if (len
< sizeof(*hdr
) + sizeof(*pubkey
)) return FALSE
;
570 switch (pubkey
->magic
)
576 FIXME( "unsupported key magic %08lx\n", pubkey
->magic
);
580 if ((size_q
= pubkey
->bitlenQ
/ 8) > sizeof(blob
->q
))
582 FIXME( "q too large\n" );
586 if (!(key
= create_key( CALG_DSS_SIGN
, flags
))) return FALSE
;
588 size
= sizeof(*blob
) + (pubkey
->bitlenP
/ 8) * 3;
589 if (!(blob
= calloc( 1, size
)))
594 blob
->dwMagic
= BCRYPT_DSA_PUBLIC_MAGIC
;
595 blob
->cbKey
= pubkey
->bitlenP
/ 8;
596 memcpy( blob
->Count
, &pubkey
->DSSSeed
.counter
, sizeof(blob
->Count
) );
597 memcpy( blob
->Seed
, pubkey
->DSSSeed
.seed
, sizeof(blob
->Seed
) );
600 src
= (BYTE
*)(pubkey
+ 1) + blob
->cbKey
;
601 for (i
= 0; i
< size_q
; i
++) blob
->q
[i
] = src
[size_q
- i
- 1];
605 dst
= (BYTE
*)(blob
+ 1);
606 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
609 src
+= blob
->cbKey
+ size_q
;
611 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
614 src
+= blob
->cbKey
+ pubkey
->bitlenJ
/ 8;
616 for (i
= 0; i
< blob
->cbKey
; i
++) dst
[i
] = src
[blob
->cbKey
- i
- 1];
618 if ((status
= BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE
, NULL
, BCRYPT_DSA_PUBLIC_BLOB
, &key
->handle
,
619 (UCHAR
*)blob
, size
, 0 )))
621 WARN( "failed to import key %08lx\n", status
);
628 *ret_key
= (HCRYPTKEY
)key
;
632 BOOL WINAPI
CPImportKey( HCRYPTPROV hprov
, const BYTE
*data
, DWORD len
, HCRYPTKEY hpubkey
, DWORD flags
,
635 struct container
*container
= (struct container
*)hprov
;
636 const BLOBHEADER
*hdr
;
639 TRACE( "%p, %p, %lu, %p, %08lx, %p\n", (void *)hprov
, data
, len
, (void *)hpubkey
, flags
, ret_key
);
641 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
642 if (len
< sizeof(*hdr
)) return FALSE
;
644 hdr
= (const BLOBHEADER
*)data
;
645 if ((hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bType
!= PUBLICKEYBLOB
) || hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
647 FIXME( "bType %u aiKeyAlg %08x not supported\n", hdr
->bType
, hdr
->aiKeyAlg
);
651 switch (hdr
->bVersion
)
654 ret
= import_key_dss2( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
658 ret
= import_key_dss3( container
, hdr
->aiKeyAlg
, data
, len
, flags
, ret_key
);
662 FIXME( "version %u not supported\n", hdr
->bVersion
);
669 BOOL WINAPI
CPExportKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, HCRYPTKEY hexpkey
, DWORD blobtype
, DWORD flags
,
670 BYTE
*data
, DWORD
*len
)
672 struct key
*key
= (struct key
*)hkey
;
675 TRACE( "%p, %p, %p, %08lx, %08lx, %p, %p\n", (void *)hprov
, (void *)hkey
, (void *)hexpkey
, blobtype
, flags
,
678 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
681 FIXME( "export key not supported\n" );
686 FIXME( "flags %08lx not supported\n", flags
);
693 type
= LEGACY_DSA_V2_PUBLIC_BLOB
;
697 type
= LEGACY_DSA_V2_PRIVATE_BLOB
;
701 FIXME( "blob type %lu not supported\n", blobtype
);
705 return !BCryptExportKey( key
->handle
, NULL
, type
, data
, *len
, len
, 0 );
708 BOOL WINAPI
CPDuplicateKey( HCRYPTPROV hprov
, HCRYPTKEY hkey
, DWORD
*reserved
, DWORD flags
, HCRYPTKEY
*ret_key
)
710 struct key
*key
= (struct key
*)hkey
, *ret
;
712 TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov
, (void *)hkey
, reserved
, flags
, ret_key
);
714 if (key
->magic
!= MAGIC_KEY
) return FALSE
;
716 if (!(ret
= duplicate_key( key
))) return FALSE
;
717 *ret_key
= (HCRYPTKEY
)ret
;
721 BOOL WINAPI
CPGetUserKey( HCRYPTPROV hprov
, DWORD keyspec
, HCRYPTKEY
*ret_key
)
723 struct container
*container
= (struct container
*)hprov
;
726 TRACE( "%p, %08lx, %p\n", (void *)hprov
, keyspec
, ret_key
);
728 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
733 if (!container
->exch_key
) SetLastError( NTE_NO_KEY
);
734 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->exch_key
))) ret
= TRUE
;
738 if (!container
->sign_key
) SetLastError( NTE_NO_KEY
);
739 else if ((*ret_key
= (HCRYPTKEY
)duplicate_key( container
->sign_key
))) ret
= TRUE
;
743 SetLastError( NTE_NO_KEY
);
750 BOOL WINAPI
CPGenRandom( HCRYPTPROV hprov
, DWORD len
, BYTE
*buffer
)
752 struct container
*container
= (struct container
*)hprov
;
754 TRACE( "%p, %lu, %p\n", (void *)hprov
, len
, buffer
);
756 if (container
->magic
!= MAGIC_CONTAINER
) return FALSE
;
758 return RtlGenRandom( buffer
, len
);
761 static struct hash
*create_hash( ALG_ID algid
)
764 BCRYPT_ALG_HANDLE alg_handle
;
770 alg_handle
= BCRYPT_MD5_ALG_HANDLE
;
775 alg_handle
= BCRYPT_SHA1_ALG_HANDLE
;
780 FIXME( "unhandled algorithm %u\n", algid
);
784 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
786 ret
->magic
= MAGIC_HASH
;
788 if (BCryptCreateHash( alg_handle
, &ret
->handle
, NULL
, 0, NULL
, 0, 0 ))
796 BOOL WINAPI
CPCreateHash( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTKEY hkey
, DWORD flags
, HCRYPTHASH
*ret_hash
)
800 TRACE( "%p, %08x, %p, %08lx, %p\n", (void *)hprov
, algid
, (void *)hkey
, flags
, ret_hash
);
809 FIXME( "algorithm %u not supported\n", algid
);
810 SetLastError( NTE_BAD_ALGID
);
814 if (!(hash
= create_hash( algid
))) return FALSE
;
816 *ret_hash
= (HCRYPTHASH
)hash
;
820 static void destroy_hash( struct hash
*hash
)
823 BCryptDestroyHash( hash
->handle
);
828 BOOL WINAPI
CPDestroyHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
)
830 struct hash
*hash
= (struct hash
*)hhash
;
832 TRACE( "%p, %p\n", (void *)hprov
, (void *)hhash
);
834 if (hash
->magic
!= MAGIC_HASH
)
836 SetLastError( NTE_BAD_HASH
);
840 destroy_hash( hash
);
844 static struct hash
*duplicate_hash( const struct hash
*hash
)
848 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
850 ret
->magic
= hash
->magic
;
851 ret
->len
= hash
->len
;
852 if (BCryptDuplicateHash( hash
->handle
, &ret
->handle
, NULL
, 0, 0 ))
857 memcpy( ret
->value
, hash
->value
, sizeof(hash
->value
) );
858 ret
->finished
= hash
->finished
;
862 BOOL WINAPI
CPDuplicateHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD
*reserved
, DWORD flags
, HCRYPTHASH
*ret_hash
)
864 struct hash
*hash
= (struct hash
*)hhash
, *ret
;
866 TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov
, (void *)hhash
, reserved
, flags
, ret_hash
);
868 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
870 if (!(ret
= duplicate_hash( hash
))) return FALSE
;
871 *ret_hash
= (HCRYPTHASH
)ret
;
875 BOOL WINAPI
CPHashData( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*data
, DWORD len
, DWORD flags
)
877 struct hash
*hash
= (struct hash
*)hhash
;
879 TRACE("%p, %p, %p, %lu, %08lx\n", (void *)hprov
, (void *)hhash
, data
, len
, flags
);
881 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
885 SetLastError( NTE_BAD_HASH_STATE
);
888 return !BCryptHashData( hash
->handle
, (UCHAR
*)data
, len
, 0 );
891 BOOL WINAPI
CPGetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, BYTE
*data
, DWORD
*len
, DWORD flags
)
893 struct hash
*hash
= (struct hash
*)hhash
;
895 TRACE( "%p, %p, %08lx, %p, %p, %08lx\n", (void *)hprov
, (void *)hhash
, param
, data
, len
, flags
);
897 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
902 if (sizeof(hash
->len
) > *len
)
904 *len
= sizeof(hash
->len
);
905 SetLastError( ERROR_MORE_DATA
);
908 *(DWORD
*)data
= hash
->len
;
909 *len
= sizeof(hash
->len
);
915 if (BCryptFinishHash( hash
->handle
, hash
->value
, hash
->len
, 0 )) return FALSE
;
916 hash
->finished
= TRUE
;
918 if (hash
->len
> *len
)
921 SetLastError( ERROR_MORE_DATA
);
924 if (data
) memcpy( data
, hash
->value
, hash
->len
);
929 SetLastError( NTE_BAD_TYPE
);
934 BOOL WINAPI
CPSetHashParam( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD param
, const BYTE
*data
, DWORD flags
)
936 struct hash
*hash
= (struct hash
*)hhash
;
938 TRACE( "%p, %p, %08lx, %p, %08lx\n", (void *)hprov
, (void *)hhash
, param
, data
, flags
);
940 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
945 memcpy( hash
->value
, data
, hash
->len
);
949 FIXME( "param %lu not supported\n", param
);
950 SetLastError( NTE_BAD_TYPE
);
955 BOOL WINAPI
CPDeriveKey( HCRYPTPROV hprov
, ALG_ID algid
, HCRYPTHASH hhash
, DWORD flags
, HCRYPTKEY
*ret_key
)
960 static DWORD
get_signature_length( DWORD algid
)
965 case CALG_DSS_SIGN
: return 40;
967 FIXME( "unhandled algorithm %lu\n", algid
);
972 #define MAX_HASH_LEN 20
973 BOOL WINAPI
CPSignHash( HCRYPTPROV hprov
, HCRYPTHASH hhash
, DWORD keyspec
, const WCHAR
*desc
, DWORD flags
, BYTE
*sig
,
976 struct container
*container
= (struct container
*)hprov
;
977 struct hash
*hash
= (struct hash
*)hhash
;
980 TRACE( "%p, %p, %lu, %s, %08lx, %p, %p\n", (void *)hprov
, (void *)hhash
, keyspec
, debugstr_w(desc
), flags
, sig
,
983 if (container
->magic
!= MAGIC_CONTAINER
|| !container
->sign_key
) return FALSE
;
984 if (hash
->magic
!= MAGIC_HASH
) return FALSE
;
986 if (!(len
= get_signature_length( container
->sign_key
->algid
))) return FALSE
;
993 return !BCryptSignHash( container
->sign_key
->handle
, NULL
, hash
->value
, hash
->len
, sig
, *siglen
, siglen
, 0 );
996 BOOL WINAPI
CPVerifySignature( HCRYPTPROV hprov
, HCRYPTHASH hhash
, const BYTE
*sig
, DWORD siglen
, HCRYPTKEY hpubkey
,
997 const WCHAR
*desc
, DWORD flags
)
999 struct hash
*hash
= (struct hash
*)hhash
;
1000 struct key
*key
= (struct key
*)hpubkey
;
1002 TRACE( "%p, %p, %p, %lu %p, %s, %08lx\n", (void *)hprov
, (void *)hhash
, sig
, siglen
, (void *)hpubkey
,
1003 debugstr_w(desc
), flags
);
1005 if (hash
->magic
!= MAGIC_HASH
|| key
->magic
!= MAGIC_KEY
) return FALSE
;
1008 FIXME( "flags %08lx not supported\n", flags
);
1012 return !BCryptVerifySignature( key
->handle
, NULL
, hash
->value
, hash
->len
, (UCHAR
*)sig
, siglen
, 0 );