2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/port.h"
24 #ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
25 #include <AvailabilityMacros.h>
26 #include <CommonCrypto/CommonCryptor.h>
30 #define WIN32_NO_STATUS
37 #include "bcrypt_internal.h"
39 #include "wine/debug.h"
40 #include "wine/heap.h"
41 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
45 static HINSTANCE instance
;
47 NTSTATUS WINAPI
BCryptAddContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, ULONG pos
)
49 FIXME("%08x, %s, %08x, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), pos
);
50 return STATUS_SUCCESS
;
53 NTSTATUS WINAPI
BCryptAddContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
, ULONG pos
)
55 FIXME("%08x, %s, %08x, %s, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
), pos
);
56 return STATUS_SUCCESS
;
59 NTSTATUS WINAPI
BCryptRemoveContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
)
61 FIXME("%08x, %s, %08x, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
));
62 return STATUS_NOT_IMPLEMENTED
;
65 NTSTATUS WINAPI
BCryptRemoveContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
)
67 FIXME("%08x, %s, %08x, %s, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
));
68 return STATUS_NOT_IMPLEMENTED
;
71 NTSTATUS WINAPI
BCryptEnumContextFunctions( ULONG table
, const WCHAR
*ctx
, ULONG iface
, ULONG
*buflen
,
72 CRYPT_CONTEXT_FUNCTIONS
**buffer
)
74 FIXME( "%u, %s, %u, %p, %p\n", table
, debugstr_w(ctx
), iface
, buflen
, buffer
);
75 return STATUS_NOT_IMPLEMENTED
;
78 void WINAPI
BCryptFreeBuffer( void *buffer
)
80 FIXME( "%p\n", buffer
);
83 NTSTATUS WINAPI
BCryptRegisterProvider(LPCWSTR provider
, ULONG flags
, PCRYPT_PROVIDER_REG reg
)
85 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider
), flags
, reg
);
86 return STATUS_SUCCESS
;
89 NTSTATUS WINAPI
BCryptUnregisterProvider(LPCWSTR provider
)
91 FIXME("%s: stub\n", debugstr_w(provider
));
92 return STATUS_NOT_IMPLEMENTED
;
95 #define MAX_HASH_OUTPUT_BYTES 64
96 #define MAX_HASH_BLOCK_BITS 1024
98 /* ordered by class, keep in sync with enum alg_id */
107 builtin_algorithms
[] =
109 { BCRYPT_AES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 654, 0, 0 },
110 { BCRYPT_SHA256_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 286, 32, 512 },
111 { BCRYPT_SHA384_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 48, 1024 },
112 { BCRYPT_SHA512_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 64, 1024 },
113 { BCRYPT_SHA1_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 278, 20, 512 },
114 { BCRYPT_MD5_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 274, 16, 512 },
115 { BCRYPT_MD4_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 512 },
116 { BCRYPT_MD2_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 128 },
117 { BCRYPT_RSA_ALGORITHM
, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
, 0, 0, 0 },
118 { BCRYPT_ECDH_P256_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
119 { BCRYPT_RSA_SIGN_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
120 { BCRYPT_ECDSA_P256_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
121 { BCRYPT_ECDSA_P384_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
122 { BCRYPT_DSA_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
123 { BCRYPT_RNG_ALGORITHM
, BCRYPT_RNG_INTERFACE
, 0, 0, 0 },
126 static BOOL
match_operation_type( ULONG type
, ULONG
class )
128 if (!type
) return TRUE
;
131 case BCRYPT_CIPHER_INTERFACE
: return type
& BCRYPT_CIPHER_OPERATION
;
132 case BCRYPT_HASH_INTERFACE
: return type
& BCRYPT_HASH_OPERATION
;
133 case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
: return type
& BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
;
134 case BCRYPT_SECRET_AGREEMENT_INTERFACE
: return type
& BCRYPT_SECRET_AGREEMENT_OPERATION
;
135 case BCRYPT_SIGNATURE_INTERFACE
: return type
& BCRYPT_SIGNATURE_OPERATION
;
136 case BCRYPT_RNG_INTERFACE
: return type
& BCRYPT_RNG_OPERATION
;
142 NTSTATUS WINAPI
BCryptEnumAlgorithms( ULONG type
, ULONG
*ret_count
, BCRYPT_ALGORITHM_IDENTIFIER
**ret_list
, ULONG flags
)
144 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
145 BCRYPT_HASH_OPERATION
|\
146 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
147 BCRYPT_SECRET_AGREEMENT_OPERATION
|\
148 BCRYPT_SIGNATURE_OPERATION
|\
149 BCRYPT_RNG_OPERATION
;
150 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
153 TRACE( "%08x, %p, %p, %08x\n", type
, ret_count
, ret_list
, flags
);
155 if (!ret_count
|| !ret_list
|| (type
& ~supported
)) return STATUS_INVALID_PARAMETER
;
157 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
159 if (match_operation_type( type
, builtin_algorithms
[i
].class )) count
++;
162 if (!(list
= heap_alloc( count
* sizeof(*list
) ))) return STATUS_NO_MEMORY
;
164 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
166 if (!match_operation_type( type
, builtin_algorithms
[i
].class )) continue;
167 list
[i
].pszName
= (WCHAR
*)builtin_algorithms
[i
].name
;
168 list
[i
].dwClass
= builtin_algorithms
[i
].class;
174 return STATUS_SUCCESS
;
177 NTSTATUS WINAPI
BCryptGenRandom(BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
179 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
180 struct algorithm
*algorithm
= handle
;
182 TRACE("%p, %p, %u, %08x - semi-stub\n", handle
, buffer
, count
, flags
);
186 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
187 * is set. In this case the preferred system RNG is used.
189 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
190 return STATUS_INVALID_HANDLE
;
192 else if (algorithm
->hdr
.magic
!= MAGIC_ALG
|| algorithm
->id
!= ALG_ID_RNG
)
193 return STATUS_INVALID_HANDLE
;
196 return STATUS_INVALID_PARAMETER
;
198 if (flags
& ~supported_flags
)
199 FIXME("unsupported flags %08x\n", flags
& ~supported_flags
);
202 FIXME("ignoring selected algorithm\n");
204 /* When zero bytes are requested the function returns success too. */
206 return STATUS_SUCCESS
;
208 if (algorithm
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
210 if (RtlGenRandom(buffer
, count
))
211 return STATUS_SUCCESS
;
214 FIXME("called with unsupported parameters, returning error\n");
215 return STATUS_NOT_IMPLEMENTED
;
218 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, LPCWSTR id
, LPCWSTR implementation
, DWORD flags
)
220 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
| BCRYPT_HASH_REUSABLE_FLAG
;
221 struct algorithm
*alg
;
225 TRACE( "%p, %s, %s, %08x\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
227 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
228 if (flags
& ~supported_flags
)
230 FIXME( "unsupported flags %08x\n", flags
& ~supported_flags
);
231 return STATUS_NOT_IMPLEMENTED
;
234 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
236 if (!strcmpW( id
, builtin_algorithms
[i
].name
))
242 if (i
== ARRAY_SIZE( builtin_algorithms
))
244 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
245 return STATUS_NOT_IMPLEMENTED
;
248 if (implementation
&& strcmpW( implementation
, MS_PRIMITIVE_PROVIDER
))
250 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
251 return STATUS_NOT_IMPLEMENTED
;
254 if (!(alg
= heap_alloc( sizeof(*alg
) ))) return STATUS_NO_MEMORY
;
255 alg
->hdr
.magic
= MAGIC_ALG
;
257 alg
->mode
= MODE_ID_CBC
;
261 return STATUS_SUCCESS
;
264 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
266 struct algorithm
*alg
= handle
;
268 TRACE( "%p, %08x\n", handle
, flags
);
270 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
273 return STATUS_SUCCESS
;
276 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
278 FIXME("%p - semi-stub\n", enabled
);
281 return STATUS_INVALID_PARAMETER
;
284 return STATUS_SUCCESS
;
300 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
305 md2_init( &hash
->u
.md2
);
309 MD4Init( &hash
->u
.md4
);
313 MD5Init( &hash
->u
.md5
);
317 A_SHAInit( &hash
->u
.sha1
);
321 sha256_init( &hash
->u
.sha256
);
325 sha384_init( &hash
->u
.sha512
);
329 sha512_init( &hash
->u
.sha512
);
333 ERR( "unhandled id %u\n", alg_id
);
334 return STATUS_NOT_IMPLEMENTED
;
336 return STATUS_SUCCESS
;
339 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
,
340 UCHAR
*input
, ULONG size
)
345 md2_update( &hash
->u
.md2
, input
, size
);
349 MD4Update( &hash
->u
.md4
, input
, size
);
353 MD5Update( &hash
->u
.md5
, input
, size
);
357 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
361 sha256_update( &hash
->u
.sha256
, input
, size
);
365 sha384_update( &hash
->u
.sha512
, input
, size
);
369 sha512_update( &hash
->u
.sha512
, input
, size
);
373 ERR( "unhandled id %u\n", alg_id
);
374 return STATUS_NOT_IMPLEMENTED
;
376 return STATUS_SUCCESS
;
379 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
,
380 UCHAR
*output
, ULONG size
)
385 md2_finalize( &hash
->u
.md2
, output
);
389 MD4Final( &hash
->u
.md4
);
390 memcpy( output
, hash
->u
.md4
.digest
, 16 );
394 MD5Final( &hash
->u
.md5
);
395 memcpy( output
, hash
->u
.md5
.digest
, 16 );
399 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
403 sha256_finalize( &hash
->u
.sha256
, output
);
407 sha384_finalize( &hash
->u
.sha512
, output
);
411 sha512_finalize( &hash
->u
.sha512
, output
);
415 ERR( "unhandled id %u\n", alg_id
);
416 return STATUS_NOT_IMPLEMENTED
;
418 return STATUS_SUCCESS
;
421 #define HASH_FLAG_HMAC 0x01
422 #define HASH_FLAG_REUSABLE 0x02
430 struct hash_impl outer
;
431 struct hash_impl inner
;
434 #define BLOCK_LENGTH_AES 16
436 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
438 if (!strcmpW( prop
, BCRYPT_OBJECT_LENGTH
))
440 if (!builtin_algorithms
[id
].object_length
)
441 return STATUS_NOT_SUPPORTED
;
442 *ret_size
= sizeof(ULONG
);
443 if (size
< sizeof(ULONG
))
444 return STATUS_BUFFER_TOO_SMALL
;
446 *(ULONG
*)buf
= builtin_algorithms
[id
].object_length
;
447 return STATUS_SUCCESS
;
450 if (!strcmpW( prop
, BCRYPT_HASH_LENGTH
))
452 if (!builtin_algorithms
[id
].hash_length
)
453 return STATUS_NOT_SUPPORTED
;
454 *ret_size
= sizeof(ULONG
);
455 if (size
< sizeof(ULONG
))
456 return STATUS_BUFFER_TOO_SMALL
;
458 *(ULONG
*)buf
= builtin_algorithms
[id
].hash_length
;
459 return STATUS_SUCCESS
;
462 if (!strcmpW( prop
, BCRYPT_ALGORITHM_NAME
))
464 *ret_size
= (strlenW(builtin_algorithms
[id
].name
) + 1) * sizeof(WCHAR
);
465 if (size
< *ret_size
)
466 return STATUS_BUFFER_TOO_SMALL
;
468 memcpy(buf
, builtin_algorithms
[id
].name
, *ret_size
);
469 return STATUS_SUCCESS
;
472 return STATUS_NOT_IMPLEMENTED
;
475 static NTSTATUS
get_aes_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
477 if (!strcmpW( prop
, BCRYPT_BLOCK_LENGTH
))
479 *ret_size
= sizeof(ULONG
);
480 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
481 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
482 return STATUS_SUCCESS
;
484 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
489 case MODE_ID_ECB
: str
= BCRYPT_CHAIN_MODE_ECB
; break;
490 case MODE_ID_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
491 case MODE_ID_GCM
: str
= BCRYPT_CHAIN_MODE_GCM
; break;
492 default: return STATUS_NOT_IMPLEMENTED
;
496 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
497 memcpy( buf
, str
, (strlenW(str
) + 1) * sizeof(WCHAR
) );
498 return STATUS_SUCCESS
;
500 if (!strcmpW( prop
, BCRYPT_KEY_LENGTHS
))
502 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
503 *ret_size
= sizeof(*key_lengths
);
504 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
507 key_lengths
->dwMinLength
= 128;
508 key_lengths
->dwMaxLength
= 256;
509 key_lengths
->dwIncrement
= 64;
511 return STATUS_SUCCESS
;
513 if (!strcmpW( prop
, BCRYPT_AUTH_TAG_LENGTH
))
515 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
516 if (mode
!= MODE_ID_GCM
) return STATUS_NOT_SUPPORTED
;
517 *ret_size
= sizeof(*tag_length
);
518 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
521 tag_length
->dwMinLength
= 12;
522 tag_length
->dwMaxLength
= 16;
523 tag_length
->dwIncrement
= 1;
525 return STATUS_SUCCESS
;
528 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
529 return STATUS_NOT_IMPLEMENTED
;
532 static NTSTATUS
get_rsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
534 if (!strcmpW( prop
, BCRYPT_PADDING_SCHEMES
))
536 *ret_size
= sizeof(ULONG
);
537 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
538 if (buf
) *(ULONG
*)buf
= BCRYPT_SUPPORTED_PAD_PKCS1_SIG
;
539 return STATUS_SUCCESS
;
542 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
543 return STATUS_NOT_IMPLEMENTED
;
546 static NTSTATUS
get_dsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
548 if (!strcmpW( prop
, BCRYPT_PADDING_SCHEMES
)) return STATUS_NOT_SUPPORTED
;
549 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
550 return STATUS_NOT_IMPLEMENTED
;
553 NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
557 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
558 if (status
!= STATUS_NOT_IMPLEMENTED
)
564 return get_aes_property( alg
->mode
, prop
, buf
, size
, ret_size
);
567 return get_rsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
570 return get_dsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
576 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop
), alg
->id
);
577 return STATUS_NOT_IMPLEMENTED
;
580 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
585 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
587 if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
589 alg
->mode
= MODE_ID_ECB
;
590 return STATUS_SUCCESS
;
592 else if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
594 alg
->mode
= MODE_ID_CBC
;
595 return STATUS_SUCCESS
;
597 else if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
599 alg
->mode
= MODE_ID_GCM
;
600 return STATUS_SUCCESS
;
604 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
605 return STATUS_NOT_IMPLEMENTED
;
608 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
609 return STATUS_NOT_IMPLEMENTED
;
612 FIXME( "unsupported algorithm %u\n", alg
->id
);
613 return STATUS_NOT_IMPLEMENTED
;
617 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
621 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
622 if (status
== STATUS_NOT_IMPLEMENTED
)
623 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
627 static NTSTATUS
get_key_property( const struct key
*key
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
632 if (!strcmpW( prop
, BCRYPT_AUTH_TAG_LENGTH
)) return STATUS_NOT_SUPPORTED
;
633 return get_aes_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
636 FIXME( "unsupported algorithm %u\n", key
->alg_id
);
637 return STATUS_NOT_IMPLEMENTED
;
641 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, LPCWSTR prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
, ULONG flags
)
643 struct object
*object
= handle
;
645 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
647 if (!object
) return STATUS_INVALID_HANDLE
;
648 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
650 switch (object
->magic
)
654 const struct algorithm
*alg
= (const struct algorithm
*)object
;
655 return get_alg_property( alg
, prop
, buffer
, count
, res
);
659 const struct key
*key
= (const struct key
*)object
;
660 return get_key_property( key
, prop
, buffer
, count
, res
);
664 const struct hash
*hash
= (const struct hash
*)object
;
665 return get_hash_property( hash
, prop
, buffer
, count
, res
);
668 WARN( "unknown magic %08x\n", object
->magic
);
669 return STATUS_INVALID_HANDLE
;
673 static NTSTATUS
prepare_hash( struct hash
*hash
)
675 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
679 /* initialize hash */
680 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) return status
;
681 if (!(hash
->flags
& HASH_FLAG_HMAC
)) return STATUS_SUCCESS
;
683 /* initialize hmac */
684 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) return status
;
685 block_bytes
= builtin_algorithms
[hash
->alg_id
].block_bits
/ 8;
686 if (hash
->secret_len
> block_bytes
)
688 struct hash_impl temp
;
689 if ((status
= hash_init( &temp
, hash
->alg_id
))) return status
;
690 if ((status
= hash_update( &temp
, hash
->alg_id
, hash
->secret
, hash
->secret_len
))) return status
;
691 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
692 builtin_algorithms
[hash
->alg_id
].hash_length
))) return status
;
694 else memcpy( buffer
, hash
->secret
, hash
->secret_len
);
696 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
697 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) return status
;
698 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
699 return hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
702 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_HASH_HANDLE
*handle
, UCHAR
*object
, ULONG objectlen
,
703 UCHAR
*secret
, ULONG secretlen
, ULONG flags
)
705 struct algorithm
*alg
= algorithm
;
709 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm
, handle
, object
, objectlen
,
710 secret
, secretlen
, flags
);
711 if (flags
& ~BCRYPT_HASH_REUSABLE_FLAG
)
713 FIXME( "unimplemented flags %08x\n", flags
);
714 return STATUS_NOT_IMPLEMENTED
;
717 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
718 if (object
) FIXME( "ignoring object buffer\n" );
720 if (!(hash
= heap_alloc_zero( sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
721 hash
->hdr
.magic
= MAGIC_HASH
;
722 hash
->alg_id
= alg
->id
;
723 if (alg
->flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
) hash
->flags
= HASH_FLAG_HMAC
;
724 if ((alg
->flags
& BCRYPT_HASH_REUSABLE_FLAG
) || (flags
& BCRYPT_HASH_REUSABLE_FLAG
))
725 hash
->flags
|= HASH_FLAG_REUSABLE
;
727 if (secretlen
&& !(hash
->secret
= heap_alloc( secretlen
)))
730 return STATUS_NO_MEMORY
;
732 memcpy( hash
->secret
, secret
, secretlen
);
733 hash
->secret_len
= secretlen
;
735 if ((status
= prepare_hash( hash
)) != STATUS_SUCCESS
)
737 heap_free( hash
->secret
);
743 return STATUS_SUCCESS
;
746 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
747 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
749 struct hash
*hash_orig
= handle
;
750 struct hash
*hash_copy
;
752 TRACE( "%p, %p, %p, %u, %u\n", handle
, handle_copy
, object
, objectlen
, flags
);
754 if (!hash_orig
|| hash_orig
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
755 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
756 if (object
) FIXME( "ignoring object buffer\n" );
758 if (!(hash_copy
= heap_alloc( sizeof(*hash_copy
) )))
759 return STATUS_NO_MEMORY
;
761 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
762 if (hash_orig
->secret
&& !(hash_copy
->secret
= heap_alloc( hash_orig
->secret_len
)))
764 heap_free( hash_copy
);
765 return STATUS_NO_MEMORY
;
767 memcpy( hash_copy
->secret
, hash_orig
->secret
, hash_orig
->secret_len
);
769 *handle_copy
= hash_copy
;
770 return STATUS_SUCCESS
;
773 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
775 struct hash
*hash
= handle
;
777 TRACE( "%p\n", handle
);
779 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_PARAMETER
;
781 heap_free( hash
->secret
);
783 return STATUS_SUCCESS
;
786 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
788 struct hash
*hash
= handle
;
790 TRACE( "%p, %p, %u, %08x\n", handle
, input
, size
, flags
);
792 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
793 if (!input
) return STATUS_SUCCESS
;
795 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
798 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
800 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
801 struct hash
*hash
= handle
;
805 TRACE( "%p, %p, %u, %08x\n", handle
, output
, size
, flags
);
807 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
808 if (!output
) return STATUS_INVALID_PARAMETER
;
810 if (!(hash
->flags
& HASH_FLAG_HMAC
))
812 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
))) return status
;
813 if (hash
->flags
& HASH_FLAG_REUSABLE
) return prepare_hash( hash
);
814 return STATUS_SUCCESS
;
817 hash_length
= builtin_algorithms
[hash
->alg_id
].hash_length
;
818 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
819 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
820 if ((status
= hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
))) return status
;
821 if (hash
->flags
& HASH_FLAG_REUSABLE
) return prepare_hash( hash
);
822 return STATUS_SUCCESS
;
825 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE algorithm
, UCHAR
*secret
, ULONG secretlen
,
826 UCHAR
*input
, ULONG inputlen
, UCHAR
*output
, ULONG outputlen
)
829 BCRYPT_HASH_HANDLE handle
;
831 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm
, secret
, secretlen
,
832 input
, inputlen
, output
, outputlen
);
834 status
= BCryptCreateHash( algorithm
, &handle
, NULL
, 0, secret
, secretlen
, 0);
835 if (status
!= STATUS_SUCCESS
)
840 status
= BCryptHashData( handle
, input
, inputlen
, 0 );
841 if (status
!= STATUS_SUCCESS
)
843 BCryptDestroyHash( handle
);
847 status
= BCryptFinishHash( handle
, output
, outputlen
, 0 );
848 if (status
!= STATUS_SUCCESS
)
850 BCryptDestroyHash( handle
);
854 return BCryptDestroyHash( handle
);
857 #if defined(HAVE_GNUTLS_CIPHER_INIT) || defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
858 BOOL
key_is_symmetric( struct key
*key
)
860 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_CIPHER_INTERFACE
;
863 BOOL
is_zero_vector( const UCHAR
*vector
, ULONG len
)
866 if (!vector
) return FALSE
;
867 for (i
= 0; i
< len
; i
++) if (vector
[i
]) return FALSE
;
871 BOOL
is_equal_vector( const UCHAR
*vector
, ULONG len
, const UCHAR
*vector2
, ULONG len2
)
873 if (!vector
&& !vector2
) return TRUE
;
874 if (len
!= len2
) return FALSE
;
875 return !memcmp( vector
, vector2
, len
);
878 static NTSTATUS
key_import( BCRYPT_ALG_HANDLE algorithm
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
879 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
883 if (!strcmpW( type
, BCRYPT_KEY_DATA_BLOB
))
885 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
887 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
)) return STATUS_BUFFER_TOO_SMALL
;
888 if (header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
) return STATUS_INVALID_PARAMETER
;
889 if (header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
891 FIXME( "unknown key data blob version %u\n", header
->dwVersion
);
892 return STATUS_INVALID_PARAMETER
;
894 len
= header
->cbKeyData
;
895 if (len
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
) return STATUS_INVALID_PARAMETER
;
897 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, (UCHAR
*)&header
[1], len
, 0 );
899 else if (!strcmpW( type
, BCRYPT_OPAQUE_KEY_BLOB
))
901 if (input_len
< sizeof(len
)) return STATUS_BUFFER_TOO_SMALL
;
902 len
= *(ULONG
*)input
;
903 if (len
+ sizeof(len
) > input_len
) return STATUS_INVALID_PARAMETER
;
905 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, input
+ sizeof(len
), len
, 0 );
908 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
909 return STATUS_NOT_IMPLEMENTED
;
912 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
914 if (!strcmpW( type
, BCRYPT_KEY_DATA_BLOB
))
916 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
917 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
920 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
922 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
923 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
924 header
->cbKeyData
= key
->u
.s
.secret_len
;
925 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
926 return STATUS_SUCCESS
;
928 else if (!strcmpW( type
, BCRYPT_OPAQUE_KEY_BLOB
))
930 ULONG len
, req_size
= sizeof(len
) + key
->u
.s
.secret_len
;
933 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
935 *(ULONG
*)output
= key
->u
.s
.secret_len
;
936 memcpy( output
+ sizeof(len
), key
->u
.s
.secret
, key
->u
.s
.secret_len
);
937 return STATUS_SUCCESS
;
939 else if (!strcmpW( type
, BCRYPT_RSAPUBLIC_BLOB
) || !strcmpW( type
, BCRYPT_DSA_PUBLIC_BLOB
) ||
940 !strcmpW( type
, BCRYPT_ECCPUBLIC_BLOB
))
942 *size
= key
->u
.a
.pubkey_len
;
943 if (output_len
< key
->u
.a
.pubkey_len
) return STATUS_SUCCESS
;
945 memcpy( output
, key
->u
.a
.pubkey
, key
->u
.a
.pubkey_len
);
946 return STATUS_SUCCESS
;
948 else if (!strcmpW( type
, BCRYPT_ECCPRIVATE_BLOB
))
950 return key_export_ecc( key
, output
, output_len
, size
);
952 else if (!strcmpW( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
954 return key_export_dsa_capi( key
, output
, output_len
, size
);
957 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
958 return STATUS_NOT_IMPLEMENTED
;
961 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
965 memset( key_copy
, 0, sizeof(*key_copy
) );
966 key_copy
->hdr
= key_orig
->hdr
;
967 key_copy
->alg_id
= key_orig
->alg_id
;
969 if (key_is_symmetric( key_orig
))
971 if (!(buffer
= heap_alloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
972 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
974 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
975 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
976 key_copy
->u
.s
.secret
= buffer
;
977 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
981 if (!(buffer
= heap_alloc( key_orig
->u
.a
.pubkey_len
))) return STATUS_NO_MEMORY
;
982 memcpy( buffer
, key_orig
->u
.a
.pubkey
, key_orig
->u
.a
.pubkey_len
);
984 key_copy
->u
.a
.pubkey
= buffer
;
985 key_copy
->u
.a
.pubkey_len
= key_orig
->u
.a
.pubkey_len
;
988 return STATUS_SUCCESS
;
991 static NTSTATUS
key_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
992 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
994 ULONG bytes_left
= input_len
;
995 UCHAR
*buf
, *src
, *dst
;
998 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1000 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1002 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1003 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1004 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1005 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1006 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1007 FIXME( "call chaining not implemented\n" );
1009 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1012 *ret_len
= input_len
;
1013 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1014 if (input
&& !output
) return STATUS_SUCCESS
;
1015 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1017 if ((status
= key_symmetric_set_auth_data( key
, auth_info
->pbAuthData
, auth_info
->cbAuthData
)))
1019 if ((status
= key_symmetric_encrypt( key
, input
, input_len
, output
, output_len
))) return status
;
1021 return key_symmetric_get_tag( key
, auth_info
->pbTag
, auth_info
->cbTag
);
1024 *ret_len
= input_len
;
1026 if (flags
& BCRYPT_BLOCK_PADDING
)
1027 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1028 else if (input_len
& (key
->u
.s
.block_size
- 1))
1029 return STATUS_INVALID_BUFFER_SIZE
;
1031 if (!output
) return STATUS_SUCCESS
;
1032 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1033 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1034 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1038 while (bytes_left
>= key
->u
.s
.block_size
)
1040 if ((status
= key_symmetric_encrypt( key
, src
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
)))
1042 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 ))) return status
;
1043 bytes_left
-= key
->u
.s
.block_size
;
1044 src
+= key
->u
.s
.block_size
;
1045 dst
+= key
->u
.s
.block_size
;
1048 if (flags
& BCRYPT_BLOCK_PADDING
)
1050 if (!(buf
= heap_alloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1051 memcpy( buf
, src
, bytes_left
);
1052 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1053 status
= key_symmetric_encrypt( key
, buf
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
);
1060 static NTSTATUS
key_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1061 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1063 ULONG bytes_left
= input_len
;
1064 UCHAR
*buf
, *src
, *dst
;
1067 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1069 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1072 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1073 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1074 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1075 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1077 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1080 *ret_len
= input_len
;
1081 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1082 if (!output
) return STATUS_SUCCESS
;
1083 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1085 if ((status
= key_symmetric_set_auth_data( key
, auth_info
->pbAuthData
, auth_info
->cbAuthData
)))
1087 if ((status
= key_symmetric_decrypt( key
, input
, input_len
, output
, output_len
))) return status
;
1089 if ((status
= key_symmetric_get_tag( key
, tag
, sizeof(tag
) ))) return status
;
1090 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1092 return STATUS_SUCCESS
;
1095 *ret_len
= input_len
;
1097 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1098 if (!output
) return STATUS_SUCCESS
;
1099 if (flags
& BCRYPT_BLOCK_PADDING
)
1101 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1102 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1103 bytes_left
-= key
->u
.s
.block_size
;
1105 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1107 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1108 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1112 while (bytes_left
>= key
->u
.s
.block_size
)
1114 if ((status
= key_symmetric_decrypt( key
, src
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
)))
1116 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 ))) return status
;
1117 bytes_left
-= key
->u
.s
.block_size
;
1118 src
+= key
->u
.s
.block_size
;
1119 dst
+= key
->u
.s
.block_size
;
1122 if (flags
& BCRYPT_BLOCK_PADDING
)
1124 if (!(buf
= heap_alloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1125 status
= key_symmetric_decrypt( key
, src
, key
->u
.s
.block_size
, buf
, key
->u
.s
.block_size
);
1126 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1128 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1129 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1130 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1132 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1139 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1145 if (!strcmpW( type
, BCRYPT_ECCPUBLIC_BLOB
))
1147 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1148 DWORD key_size
, magic
, size
;
1150 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1154 case ALG_ID_ECDH_P256
:
1156 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
1159 case ALG_ID_ECDSA_P256
:
1161 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
1164 case ALG_ID_ECDSA_P384
:
1166 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
1170 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1171 return STATUS_NOT_SUPPORTED
;
1174 if (ecc_blob
->dwMagic
!= magic
) return STATUS_NOT_SUPPORTED
;
1175 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2)
1176 return STATUS_INVALID_PARAMETER
;
1178 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1179 key
->hdr
.magic
= MAGIC_KEY
;
1181 size
= sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2;
1182 if ((status
= key_asymmetric_init( key
, alg
, key_size
* 8, (BYTE
*)ecc_blob
, size
)))
1189 return STATUS_SUCCESS
;
1191 else if (!strcmpW( type
, BCRYPT_ECCPRIVATE_BLOB
))
1193 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1194 DWORD key_size
, magic
;
1196 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1200 case ALG_ID_ECDH_P256
:
1202 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
1206 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1207 return STATUS_NOT_SUPPORTED
;
1210 if (ecc_blob
->dwMagic
!= magic
) return STATUS_NOT_SUPPORTED
;
1211 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 3)
1212 return STATUS_INVALID_PARAMETER
;
1214 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1215 key
->hdr
.magic
= MAGIC_KEY
;
1217 if ((status
= key_asymmetric_init( key
, alg
, key_size
* 8, NULL
, 0 )))
1222 if ((status
= key_import_ecc( key
, input
, input_len
)))
1229 return STATUS_SUCCESS
;
1231 else if (!strcmpW( type
, BCRYPT_RSAPUBLIC_BLOB
))
1233 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1236 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1237 if ((alg
->id
!= ALG_ID_RSA
&& alg
->id
!= ALG_ID_RSA_SIGN
) || rsa_blob
->Magic
!= BCRYPT_RSAPUBLIC_MAGIC
)
1238 return STATUS_NOT_SUPPORTED
;
1240 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1241 key
->hdr
.magic
= MAGIC_KEY
;
1243 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1244 if ((status
= key_asymmetric_init( key
, alg
, rsa_blob
->BitLength
, (BYTE
*)rsa_blob
, size
)))
1251 return STATUS_SUCCESS
;
1253 else if (!strcmpW( type
, BCRYPT_DSA_PUBLIC_BLOB
))
1255 BCRYPT_DSA_KEY_BLOB
*dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)input
;
1258 if (input_len
< sizeof(*dsa_blob
)) return STATUS_INVALID_PARAMETER
;
1259 if ((alg
->id
!= ALG_ID_DSA
) || dsa_blob
->dwMagic
!= BCRYPT_DSA_PUBLIC_MAGIC
)
1260 return STATUS_NOT_SUPPORTED
;
1262 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1263 key
->hdr
.magic
= MAGIC_KEY
;
1265 size
= sizeof(*dsa_blob
) + dsa_blob
->cbKey
* 3;
1266 if ((status
= key_asymmetric_init( key
, alg
, dsa_blob
->cbKey
* 8, (BYTE
*)dsa_blob
, size
)))
1273 return STATUS_SUCCESS
;
1275 else if (!strcmpW( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1277 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1280 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1282 if (hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1284 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1285 return STATUS_NOT_SUPPORTED
;
1287 if (alg
->id
!= ALG_ID_DSA
)
1289 FIXME( "algorithm %u does not support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1290 return STATUS_NOT_SUPPORTED
;
1293 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1294 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1295 if (pubkey
->magic
!= MAGIC_DSS2
) return STATUS_NOT_SUPPORTED
;
1297 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 2 + 40 + sizeof(DSSSEED
))
1298 return STATUS_INVALID_PARAMETER
;
1300 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1301 key
->hdr
.magic
= MAGIC_KEY
;
1303 if ((status
= key_asymmetric_init( key
, alg
, pubkey
->bitlen
, NULL
, 0 )))
1308 if ((status
= key_import_dsa_capi( key
, input
, input_len
)))
1315 return STATUS_SUCCESS
;
1318 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1319 return STATUS_NOT_SUPPORTED
;
1322 NTSTATUS
key_symmetric_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
1324 ERR( "support for keys not available at build time\n" );
1325 return STATUS_NOT_IMPLEMENTED
;
1328 BOOL
key_is_symmetric( struct key
*key
)
1330 ERR( "support for keys not available at build time\n" );
1334 NTSTATUS
key_set_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1336 ERR( "support for keys not available at build time\n" );
1337 return STATUS_NOT_IMPLEMENTED
;
1340 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
1342 ERR( "support for keys not available at build time\n" );
1343 return STATUS_NOT_IMPLEMENTED
;
1346 NTSTATUS
key_asymmetric_init( struct key
*key
, struct algorithm
*alg
, ULONG bitlen
, const UCHAR
*pubkey
,
1349 ERR( "support for keys not available at build time\n" );
1350 return STATUS_NOT_IMPLEMENTED
;
1353 NTSTATUS
key_asymmetric_generate( struct key
*key
)
1355 ERR( "support for keys not available at build time\n" );
1356 return STATUS_NOT_IMPLEMENTED
;
1359 NTSTATUS
key_asymmetric_sign( struct key
*key
, void *padding
, UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1360 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1362 ERR( "support for keys not available at build time\n" );
1363 return STATUS_NOT_IMPLEMENTED
;
1366 NTSTATUS
key_asymmetric_verify( struct key
*key
, void *padding
, UCHAR
*hash
, ULONG hash_len
, UCHAR
*signature
,
1367 ULONG signature_len
, DWORD flags
)
1369 ERR( "support for keys not available at build time\n" );
1370 return STATUS_NOT_IMPLEMENTED
;
1373 static NTSTATUS
key_import( BCRYPT_ALG_HANDLE algorithm
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
1374 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
1376 ERR( "support for keys not available at build time\n" );
1377 return STATUS_NOT_IMPLEMENTED
;
1380 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1382 ERR( "support for keys not available at build time\n" );
1383 return STATUS_NOT_IMPLEMENTED
;
1386 NTSTATUS
key_destroy( struct key
*key
)
1388 ERR( "support for keys not available at build time\n" );
1389 return STATUS_NOT_IMPLEMENTED
;
1392 static NTSTATUS
key_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1393 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1395 ERR( "support for keys not available at build time\n" );
1396 return STATUS_NOT_IMPLEMENTED
;
1399 static NTSTATUS
key_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1400 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1402 ERR( "support for keys not available at build time\n" );
1403 return STATUS_NOT_IMPLEMENTED
;
1406 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1409 ERR( "support for keys not available at build time\n" );
1410 return STATUS_NOT_IMPLEMENTED
;
1413 NTSTATUS
key_export_ecc( struct key
*key
, UCHAR
*output
, ULONG len
, ULONG
*ret_len
)
1415 ERR( "support for keys not available at build time\n" );
1416 return STATUS_NOT_IMPLEMENTED
;
1419 NTSTATUS
key_import_ecc( struct key
*key
, UCHAR
*input
, ULONG len
)
1421 ERR( "support for keys not available at build time\n" );
1422 return STATUS_NOT_IMPLEMENTED
;
1426 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1427 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1430 struct algorithm
*alg
= algorithm
;
1434 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
1436 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1437 if (object
) FIXME( "ignoring object buffer\n" );
1439 if (!(key
= heap_alloc( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1440 key
->hdr
.magic
= MAGIC_KEY
;
1442 if ((status
= key_symmetric_init( key
, alg
, secret
, secret_len
)))
1449 return STATUS_SUCCESS
;
1452 NTSTATUS WINAPI
BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
, ULONG key_len
,
1455 struct algorithm
*alg
= algorithm
;
1459 TRACE( "%p, %p, %u, %08x\n", algorithm
, handle
, key_len
, flags
);
1461 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1462 if (!handle
) return STATUS_INVALID_PARAMETER
;
1464 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1465 key
->hdr
.magic
= MAGIC_KEY
;
1467 if ((status
= key_asymmetric_init( key
, alg
, key_len
, NULL
, 0 )))
1474 return STATUS_SUCCESS
;
1477 NTSTATUS WINAPI
BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle
, ULONG flags
)
1479 struct key
*key
= handle
;
1481 TRACE( "%p, %08x\n", key
, flags
);
1482 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1484 return key_asymmetric_generate( key
);
1487 NTSTATUS WINAPI
BCryptImportKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, LPCWSTR type
,
1488 BCRYPT_KEY_HANDLE
*key
, PUCHAR object
, ULONG object_len
, PUCHAR input
,
1489 ULONG input_len
, ULONG flags
)
1491 struct algorithm
*alg
= algorithm
;
1493 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm
, decrypt_key
, debugstr_w(type
), key
, object
,
1494 object_len
, input
, input_len
, flags
);
1496 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1497 if (!key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1501 FIXME( "decryption of key not yet supported\n" );
1502 return STATUS_NOT_IMPLEMENTED
;
1505 return key_import( algorithm
, type
, key
, object
, object_len
, input
, input_len
);
1508 NTSTATUS WINAPI
BCryptExportKey( BCRYPT_KEY_HANDLE export_key
, BCRYPT_KEY_HANDLE encrypt_key
, LPCWSTR type
,
1509 PUCHAR output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1511 struct key
*key
= export_key
;
1513 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key
, encrypt_key
, debugstr_w(type
), output
, output_len
, size
, flags
);
1515 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1516 if (!type
|| !size
) return STATUS_INVALID_PARAMETER
;
1520 FIXME( "encryption of key not yet supported\n" );
1521 return STATUS_NOT_IMPLEMENTED
;
1524 return key_export( key
, type
, output
, output_len
, size
);
1527 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
1528 UCHAR
*object
, ULONG object_len
, ULONG flags
)
1530 struct key
*key_orig
= handle
;
1531 struct key
*key_copy
;
1534 TRACE( "%p, %p, %p, %u, %08x\n", handle
, handle_copy
, object
, object_len
, flags
);
1535 if (object
) FIXME( "ignoring object buffer\n" );
1537 if (!key_orig
|| key_orig
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1538 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1539 if (!(key_copy
= heap_alloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
1541 if ((status
= key_duplicate( key_orig
, key_copy
)))
1543 heap_free( key_copy
);
1547 *handle_copy
= key_copy
;
1548 return STATUS_SUCCESS
;
1551 NTSTATUS WINAPI
BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1552 BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
, ULONG input_len
, ULONG flags
)
1554 struct algorithm
*alg
= algorithm
;
1556 TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm
, decrypt_key
, debugstr_w(type
), ret_key
, input
,
1559 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1560 if (!ret_key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1563 FIXME( "decryption of key not yet supported\n" );
1564 return STATUS_NOT_IMPLEMENTED
;
1567 return key_import_pair( alg
, type
, ret_key
, input
, input_len
);
1570 NTSTATUS WINAPI
BCryptSignHash( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*input
, ULONG input_len
,
1571 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1573 struct key
*key
= handle
;
1575 TRACE( "%p, %p, %p, %u, %p, %u, %p, %08x\n", handle
, padding
, input
, input_len
, output
, output_len
,
1578 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1579 if (key_is_symmetric( key
))
1581 FIXME( "signing with symmetric keys not yet supported\n" );
1582 return STATUS_NOT_IMPLEMENTED
;
1585 return key_asymmetric_sign( key
, padding
, input
, input_len
, output
, output_len
, ret_len
, flags
);
1588 NTSTATUS WINAPI
BCryptVerifySignature( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*hash
, ULONG hash_len
,
1589 UCHAR
*signature
, ULONG signature_len
, ULONG flags
)
1591 struct key
*key
= handle
;
1593 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
1595 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1596 if (!hash
|| !hash_len
|| !signature
|| !signature_len
) return STATUS_INVALID_PARAMETER
;
1597 if (key_is_symmetric( key
)) return STATUS_NOT_SUPPORTED
;
1599 return key_asymmetric_verify( key
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
1602 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
1604 struct key
*key
= handle
;
1606 TRACE( "%p\n", handle
);
1608 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1610 return key_destroy( key
);
1613 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1614 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1616 struct key
*key
= handle
;
1618 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1619 output_len
, ret_len
, flags
);
1621 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1622 if (!key_is_symmetric( key
))
1624 FIXME( "encryption with asymmetric keys not yet supported\n" );
1625 return STATUS_NOT_IMPLEMENTED
;
1627 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1629 FIXME( "flags %08x not implemented\n", flags
);
1630 return STATUS_NOT_IMPLEMENTED
;
1633 return key_encrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1636 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1637 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1639 struct key
*key
= handle
;
1641 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1642 output_len
, ret_len
, flags
);
1644 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1645 if (!key_is_symmetric( key
))
1647 FIXME( "decryption with asymmetric keys not yet supported\n" );
1648 return STATUS_NOT_IMPLEMENTED
;
1650 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1652 FIXME( "flags %08x not supported\n", flags
);
1653 return STATUS_NOT_IMPLEMENTED
;
1656 return key_decrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1659 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1661 struct object
*object
= handle
;
1663 TRACE( "%p, %s, %p, %u, %08x\n", handle
, debugstr_w(prop
), value
, size
, flags
);
1665 if (!object
) return STATUS_INVALID_HANDLE
;
1667 switch (object
->magic
)
1671 struct algorithm
*alg
= (struct algorithm
*)object
;
1672 return set_alg_property( alg
, prop
, value
, size
, flags
);
1676 struct key
*key
= (struct key
*)object
;
1677 return key_set_property( key
, prop
, value
, size
, flags
);
1680 WARN( "unknown magic %08x\n", object
->magic
);
1681 return STATUS_INVALID_HANDLE
;
1685 #define HMAC_PAD_LEN 64
1686 NTSTATUS WINAPI
BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle
, BCRYPT_ALG_HANDLE halg
, UCHAR
*key
, ULONG keylen
, ULONG flags
)
1688 struct hash
*hash
= handle
;
1689 UCHAR buf
[MAX_HASH_OUTPUT_BYTES
* 2];
1693 TRACE( "%p, %p, %p, %u, %08x\n", handle
, halg
, key
, keylen
, flags
);
1695 if (!key
|| !keylen
) return STATUS_INVALID_PARAMETER
;
1696 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
1697 if (keylen
> builtin_algorithms
[hash
->alg_id
].hash_length
* 2) return STATUS_INVALID_PARAMETER
;
1701 FIXME( "algorithm handle not supported\n" );
1702 return STATUS_NOT_IMPLEMENTED
;
1705 len
= builtin_algorithms
[hash
->alg_id
].hash_length
;
1706 if ((status
= BCryptFinishHash( handle
, buf
, len
, 0 ))) return status
;
1710 UCHAR pad1
[HMAC_PAD_LEN
], pad2
[HMAC_PAD_LEN
];
1713 for (i
= 0; i
< sizeof(pad1
); i
++)
1715 pad1
[i
] = 0x36 ^ (i
< len
? buf
[i
] : 0);
1716 pad2
[i
] = 0x5c ^ (i
< len
? buf
[i
] : 0);
1719 if ((status
= prepare_hash( hash
)) ||
1720 (status
= BCryptHashData( handle
, pad1
, sizeof(pad1
), 0 )) ||
1721 (status
= BCryptFinishHash( handle
, buf
, len
, 0 ))) return status
;
1723 if ((status
= prepare_hash( hash
)) ||
1724 (status
= BCryptHashData( handle
, pad2
, sizeof(pad2
), 0 )) ||
1725 (status
= BCryptFinishHash( handle
, buf
+ len
, len
, 0 ))) return status
;
1728 memcpy( key
, buf
, keylen
);
1729 return STATUS_SUCCESS
;
1732 static NTSTATUS
pbkdf2( BCRYPT_HASH_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
1733 ULONGLONG iterations
, ULONG i
, UCHAR
*dst
, ULONG hash_len
)
1735 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
1736 UCHAR bytes
[4], *buf
;
1739 if (!(buf
= heap_alloc( hash_len
))) return STATUS_NO_MEMORY
;
1741 for (j
= 0; j
< iterations
; j
++)
1745 /* use salt || INT(i) */
1746 status
= BCryptHashData( handle
, salt
, salt_len
, 0 );
1747 if (status
!= STATUS_SUCCESS
)
1752 bytes
[0] = (i
>> 24) & 0xff;
1753 bytes
[1] = (i
>> 16) & 0xff;
1754 bytes
[2] = (i
>> 8) & 0xff;
1755 bytes
[3] = i
& 0xff;
1756 status
= BCryptHashData( handle
, bytes
, 4, 0 );
1758 else status
= BCryptHashData( handle
, buf
, hash_len
, 0 ); /* use U_j */
1759 if (status
!= STATUS_SUCCESS
)
1765 status
= BCryptFinishHash( handle
, buf
, hash_len
, 0 );
1766 if (status
!= STATUS_SUCCESS
)
1772 if (j
== 0) memcpy( dst
, buf
, hash_len
);
1773 else for (k
= 0; k
< hash_len
; k
++) dst
[k
] ^= buf
[k
];
1780 NTSTATUS WINAPI
BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
1781 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
, ULONG flags
)
1783 struct algorithm
*alg
= handle
;
1784 ULONG hash_len
, block_count
, bytes_left
, i
;
1785 BCRYPT_HASH_HANDLE hash
;
1789 TRACE( "%p, %p, %u, %p, %u, %s, %p, %u, %08x\n", handle
, pwd
, pwd_len
, salt
, salt_len
,
1790 wine_dbgstr_longlong(iterations
), dk
, dk_len
, flags
);
1792 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1794 hash_len
= builtin_algorithms
[alg
->id
].hash_length
;
1795 if (dk_len
<= 0 || dk_len
> ((((ULONGLONG
)1) << 32) - 1) * hash_len
) return STATUS_INVALID_PARAMETER
;
1797 block_count
= 1 + ((dk_len
- 1) / hash_len
); /* ceil(dk_len / hash_len) */
1798 bytes_left
= dk_len
- (block_count
- 1) * hash_len
;
1800 status
= BCryptCreateHash( handle
, &hash
, NULL
, 0, pwd
, pwd_len
, BCRYPT_HASH_REUSABLE_FLAG
);
1801 if (status
!= STATUS_SUCCESS
)
1805 for (i
= 1; i
< block_count
; i
++)
1807 status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, i
, dk
+ ((i
- 1) * hash_len
), hash_len
);
1808 if (status
!= STATUS_SUCCESS
)
1810 BCryptDestroyHash( hash
);
1815 /* final partial block */
1816 if (!(partial
= heap_alloc( hash_len
)))
1818 BCryptDestroyHash( hash
);
1819 return STATUS_NO_MEMORY
;
1822 status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, block_count
, partial
, hash_len
);
1823 if (status
!= STATUS_SUCCESS
)
1825 BCryptDestroyHash( hash
);
1826 heap_free( partial
);
1829 memcpy( dk
+ ((block_count
- 1) * hash_len
), partial
, bytes_left
);
1831 BCryptDestroyHash( hash
);
1832 heap_free( partial
);
1833 return STATUS_SUCCESS
;
1836 NTSTATUS WINAPI
BCryptSecretAgreement(BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE key
, BCRYPT_SECRET_HANDLE
*secret
, ULONG flags
)
1838 FIXME( "%p, %p, %p, %08x\n", handle
, key
, secret
, flags
);
1841 *secret
= (BCRYPT_SECRET_HANDLE
*)0xDEADFEED;
1843 return STATUS_SUCCESS
;
1846 NTSTATUS WINAPI
BCryptDestroySecret(BCRYPT_SECRET_HANDLE secret
)
1848 FIXME( "%p\n", secret
);
1849 return STATUS_SUCCESS
;
1852 NTSTATUS WINAPI
BCryptDeriveKey(BCRYPT_SECRET_HANDLE secret
, LPCWSTR kdf
, BCryptBufferDesc
*parameter
,
1853 PUCHAR derived
, ULONG derived_size
, ULONG
*result
, ULONG flags
)
1855 FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret
, debugstr_w(kdf
), parameter
, derived
, derived_size
, result
, flags
);
1856 return STATUS_INTERNAL_ERROR
;
1859 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
1863 case DLL_PROCESS_ATTACH
:
1865 DisableThreadLibraryCalls( hinst
);
1866 #ifdef HAVE_GNUTLS_CIPHER_INIT
1867 gnutls_initialize();
1871 case DLL_PROCESS_DETACH
:
1872 if (reserved
) break;
1873 #ifdef HAVE_GNUTLS_CIPHER_INIT
1874 gnutls_uninitialize();