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
23 #define WIN32_NO_STATUS
31 #include "bcrypt_internal.h"
33 #include "wine/debug.h"
34 #include "wine/heap.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
38 static HINSTANCE instance
;
40 static const struct key_funcs
*key_funcs
;
42 NTSTATUS WINAPI
BCryptAddContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, ULONG pos
)
44 FIXME("%08x, %s, %08x, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), pos
);
45 return STATUS_SUCCESS
;
48 NTSTATUS WINAPI
BCryptAddContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
, ULONG pos
)
50 FIXME("%08x, %s, %08x, %s, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
), pos
);
51 return STATUS_SUCCESS
;
54 NTSTATUS WINAPI
BCryptRemoveContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
)
56 FIXME("%08x, %s, %08x, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
));
57 return STATUS_NOT_IMPLEMENTED
;
60 NTSTATUS WINAPI
BCryptRemoveContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
)
62 FIXME("%08x, %s, %08x, %s, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
));
63 return STATUS_NOT_IMPLEMENTED
;
66 NTSTATUS WINAPI
BCryptEnumContextFunctions( ULONG table
, const WCHAR
*ctx
, ULONG iface
, ULONG
*buflen
,
67 CRYPT_CONTEXT_FUNCTIONS
**buffer
)
69 FIXME( "%u, %s, %u, %p, %p\n", table
, debugstr_w(ctx
), iface
, buflen
, buffer
);
70 return STATUS_NOT_IMPLEMENTED
;
73 void WINAPI
BCryptFreeBuffer( void *buffer
)
75 FIXME( "%p\n", buffer
);
78 NTSTATUS WINAPI
BCryptRegisterProvider(LPCWSTR provider
, ULONG flags
, PCRYPT_PROVIDER_REG reg
)
80 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider
), flags
, reg
);
81 return STATUS_SUCCESS
;
84 NTSTATUS WINAPI
BCryptUnregisterProvider(LPCWSTR provider
)
86 FIXME("%s: stub\n", debugstr_w(provider
));
87 return STATUS_NOT_IMPLEMENTED
;
90 #define MAX_HASH_OUTPUT_BYTES 64
91 #define MAX_HASH_BLOCK_BITS 1024
93 /* ordered by class, keep in sync with enum alg_id */
102 builtin_algorithms
[] =
104 { BCRYPT_AES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 654, 0, 0 },
105 { BCRYPT_SHA256_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 286, 32, 512 },
106 { BCRYPT_SHA384_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 48, 1024 },
107 { BCRYPT_SHA512_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 64, 1024 },
108 { BCRYPT_SHA1_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 278, 20, 512 },
109 { BCRYPT_MD5_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 274, 16, 512 },
110 { BCRYPT_MD4_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 512 },
111 { BCRYPT_MD2_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 128 },
112 { BCRYPT_RSA_ALGORITHM
, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
, 0, 0, 0 },
113 { BCRYPT_ECDH_P256_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
114 { BCRYPT_RSA_SIGN_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
115 { BCRYPT_ECDSA_P256_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
116 { BCRYPT_ECDSA_P384_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
117 { BCRYPT_DSA_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
118 { BCRYPT_RNG_ALGORITHM
, BCRYPT_RNG_INTERFACE
, 0, 0, 0 },
121 static BOOL
match_operation_type( ULONG type
, ULONG
class )
123 if (!type
) return TRUE
;
126 case BCRYPT_CIPHER_INTERFACE
: return type
& BCRYPT_CIPHER_OPERATION
;
127 case BCRYPT_HASH_INTERFACE
: return type
& BCRYPT_HASH_OPERATION
;
128 case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
: return type
& BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
;
129 case BCRYPT_SECRET_AGREEMENT_INTERFACE
: return type
& BCRYPT_SECRET_AGREEMENT_OPERATION
;
130 case BCRYPT_SIGNATURE_INTERFACE
: return type
& BCRYPT_SIGNATURE_OPERATION
;
131 case BCRYPT_RNG_INTERFACE
: return type
& BCRYPT_RNG_OPERATION
;
137 NTSTATUS WINAPI
BCryptEnumAlgorithms( ULONG type
, ULONG
*ret_count
, BCRYPT_ALGORITHM_IDENTIFIER
**ret_list
, ULONG flags
)
139 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
140 BCRYPT_HASH_OPERATION
|\
141 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
142 BCRYPT_SECRET_AGREEMENT_OPERATION
|\
143 BCRYPT_SIGNATURE_OPERATION
|\
144 BCRYPT_RNG_OPERATION
;
145 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
148 TRACE( "%08x, %p, %p, %08x\n", type
, ret_count
, ret_list
, flags
);
150 if (!ret_count
|| !ret_list
|| (type
& ~supported
)) return STATUS_INVALID_PARAMETER
;
152 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
154 if (match_operation_type( type
, builtin_algorithms
[i
].class )) count
++;
157 if (!(list
= heap_alloc( count
* sizeof(*list
) ))) return STATUS_NO_MEMORY
;
159 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
161 if (!match_operation_type( type
, builtin_algorithms
[i
].class )) continue;
162 list
[i
].pszName
= (WCHAR
*)builtin_algorithms
[i
].name
;
163 list
[i
].dwClass
= builtin_algorithms
[i
].class;
169 return STATUS_SUCCESS
;
172 NTSTATUS WINAPI
BCryptGenRandom(BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
174 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
175 struct algorithm
*algorithm
= handle
;
177 TRACE("%p, %p, %u, %08x - semi-stub\n", handle
, buffer
, count
, flags
);
181 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
182 * is set. In this case the preferred system RNG is used.
184 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
185 return STATUS_INVALID_HANDLE
;
187 else if (algorithm
->hdr
.magic
!= MAGIC_ALG
|| algorithm
->id
!= ALG_ID_RNG
)
188 return STATUS_INVALID_HANDLE
;
191 return STATUS_INVALID_PARAMETER
;
193 if (flags
& ~supported_flags
)
194 FIXME("unsupported flags %08x\n", flags
& ~supported_flags
);
197 FIXME("ignoring selected algorithm\n");
199 /* When zero bytes are requested the function returns success too. */
201 return STATUS_SUCCESS
;
203 if (algorithm
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
205 if (RtlGenRandom(buffer
, count
))
206 return STATUS_SUCCESS
;
209 FIXME("called with unsupported parameters, returning error\n");
210 return STATUS_NOT_IMPLEMENTED
;
213 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, LPCWSTR id
, LPCWSTR implementation
, DWORD flags
)
215 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
| BCRYPT_HASH_REUSABLE_FLAG
;
216 struct algorithm
*alg
;
220 TRACE( "%p, %s, %s, %08x\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
222 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
223 if (flags
& ~supported_flags
)
225 FIXME( "unsupported flags %08x\n", flags
& ~supported_flags
);
226 return STATUS_NOT_IMPLEMENTED
;
229 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
231 if (!wcscmp( id
, builtin_algorithms
[i
].name
))
237 if (i
== ARRAY_SIZE( builtin_algorithms
))
239 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
240 return STATUS_NOT_IMPLEMENTED
;
243 if (implementation
&& wcscmp( implementation
, MS_PRIMITIVE_PROVIDER
))
245 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
246 return STATUS_NOT_IMPLEMENTED
;
249 if (!(alg
= heap_alloc( sizeof(*alg
) ))) return STATUS_NO_MEMORY
;
250 alg
->hdr
.magic
= MAGIC_ALG
;
252 alg
->mode
= MODE_ID_CBC
;
256 return STATUS_SUCCESS
;
259 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
261 struct algorithm
*alg
= handle
;
263 TRACE( "%p, %08x\n", handle
, flags
);
265 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
268 return STATUS_SUCCESS
;
271 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
273 FIXME("%p - semi-stub\n", enabled
);
276 return STATUS_INVALID_PARAMETER
;
279 return STATUS_SUCCESS
;
295 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
300 md2_init( &hash
->u
.md2
);
304 MD4Init( &hash
->u
.md4
);
308 MD5Init( &hash
->u
.md5
);
312 A_SHAInit( &hash
->u
.sha1
);
316 sha256_init( &hash
->u
.sha256
);
320 sha384_init( &hash
->u
.sha512
);
324 sha512_init( &hash
->u
.sha512
);
328 ERR( "unhandled id %u\n", alg_id
);
329 return STATUS_NOT_IMPLEMENTED
;
331 return STATUS_SUCCESS
;
334 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
,
335 UCHAR
*input
, ULONG size
)
340 md2_update( &hash
->u
.md2
, input
, size
);
344 MD4Update( &hash
->u
.md4
, input
, size
);
348 MD5Update( &hash
->u
.md5
, input
, size
);
352 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
356 sha256_update( &hash
->u
.sha256
, input
, size
);
360 sha384_update( &hash
->u
.sha512
, input
, size
);
364 sha512_update( &hash
->u
.sha512
, input
, size
);
368 ERR( "unhandled id %u\n", alg_id
);
369 return STATUS_NOT_IMPLEMENTED
;
371 return STATUS_SUCCESS
;
374 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
,
375 UCHAR
*output
, ULONG size
)
380 md2_finalize( &hash
->u
.md2
, output
);
384 MD4Final( &hash
->u
.md4
);
385 memcpy( output
, hash
->u
.md4
.digest
, 16 );
389 MD5Final( &hash
->u
.md5
);
390 memcpy( output
, hash
->u
.md5
.digest
, 16 );
394 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
398 sha256_finalize( &hash
->u
.sha256
, output
);
402 sha384_finalize( &hash
->u
.sha512
, output
);
406 sha512_finalize( &hash
->u
.sha512
, output
);
410 ERR( "unhandled id %u\n", alg_id
);
411 return STATUS_NOT_IMPLEMENTED
;
413 return STATUS_SUCCESS
;
416 #define HASH_FLAG_HMAC 0x01
417 #define HASH_FLAG_REUSABLE 0x02
425 struct hash_impl outer
;
426 struct hash_impl inner
;
429 #define BLOCK_LENGTH_AES 16
431 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
433 if (!wcscmp( prop
, BCRYPT_OBJECT_LENGTH
))
435 if (!builtin_algorithms
[id
].object_length
)
436 return STATUS_NOT_SUPPORTED
;
437 *ret_size
= sizeof(ULONG
);
438 if (size
< sizeof(ULONG
))
439 return STATUS_BUFFER_TOO_SMALL
;
441 *(ULONG
*)buf
= builtin_algorithms
[id
].object_length
;
442 return STATUS_SUCCESS
;
445 if (!wcscmp( prop
, BCRYPT_HASH_LENGTH
))
447 if (!builtin_algorithms
[id
].hash_length
)
448 return STATUS_NOT_SUPPORTED
;
449 *ret_size
= sizeof(ULONG
);
450 if (size
< sizeof(ULONG
))
451 return STATUS_BUFFER_TOO_SMALL
;
453 *(ULONG
*)buf
= builtin_algorithms
[id
].hash_length
;
454 return STATUS_SUCCESS
;
457 if (!wcscmp( prop
, BCRYPT_ALGORITHM_NAME
))
459 *ret_size
= (lstrlenW(builtin_algorithms
[id
].name
) + 1) * sizeof(WCHAR
);
460 if (size
< *ret_size
)
461 return STATUS_BUFFER_TOO_SMALL
;
463 memcpy(buf
, builtin_algorithms
[id
].name
, *ret_size
);
464 return STATUS_SUCCESS
;
467 return STATUS_NOT_IMPLEMENTED
;
470 static NTSTATUS
get_aes_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
472 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
474 *ret_size
= sizeof(ULONG
);
475 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
476 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
477 return STATUS_SUCCESS
;
479 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
484 case MODE_ID_ECB
: str
= BCRYPT_CHAIN_MODE_ECB
; break;
485 case MODE_ID_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
486 case MODE_ID_GCM
: str
= BCRYPT_CHAIN_MODE_GCM
; break;
487 default: return STATUS_NOT_IMPLEMENTED
;
491 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
492 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
493 return STATUS_SUCCESS
;
495 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
497 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
498 *ret_size
= sizeof(*key_lengths
);
499 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
502 key_lengths
->dwMinLength
= 128;
503 key_lengths
->dwMaxLength
= 256;
504 key_lengths
->dwIncrement
= 64;
506 return STATUS_SUCCESS
;
508 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
))
510 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
511 if (mode
!= MODE_ID_GCM
) return STATUS_NOT_SUPPORTED
;
512 *ret_size
= sizeof(*tag_length
);
513 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
516 tag_length
->dwMinLength
= 12;
517 tag_length
->dwMaxLength
= 16;
518 tag_length
->dwIncrement
= 1;
520 return STATUS_SUCCESS
;
523 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
524 return STATUS_NOT_IMPLEMENTED
;
527 static NTSTATUS
get_rsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
529 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
))
531 *ret_size
= sizeof(ULONG
);
532 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
533 if (buf
) *(ULONG
*)buf
= BCRYPT_SUPPORTED_PAD_PKCS1_SIG
;
534 return STATUS_SUCCESS
;
537 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
538 return STATUS_NOT_IMPLEMENTED
;
541 static NTSTATUS
get_dsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
543 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
)) return STATUS_NOT_SUPPORTED
;
544 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
545 return STATUS_NOT_IMPLEMENTED
;
548 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
,
549 UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
553 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
554 if (status
!= STATUS_NOT_IMPLEMENTED
)
560 return get_aes_property( alg
->mode
, prop
, buf
, size
, ret_size
);
563 return get_rsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
566 return get_dsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
572 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop
), alg
->id
);
573 return STATUS_NOT_IMPLEMENTED
;
576 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
581 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
583 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
585 alg
->mode
= MODE_ID_ECB
;
586 return STATUS_SUCCESS
;
588 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
590 alg
->mode
= MODE_ID_CBC
;
591 return STATUS_SUCCESS
;
593 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
595 alg
->mode
= MODE_ID_GCM
;
596 return STATUS_SUCCESS
;
600 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
601 return STATUS_NOT_IMPLEMENTED
;
604 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
605 return STATUS_NOT_IMPLEMENTED
;
608 FIXME( "unsupported algorithm %u\n", alg
->id
);
609 return STATUS_NOT_IMPLEMENTED
;
613 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
617 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
618 if (status
== STATUS_NOT_IMPLEMENTED
)
619 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
623 static NTSTATUS
get_key_property( const struct key
*key
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
628 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
)) return STATUS_NOT_SUPPORTED
;
629 return get_aes_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
632 FIXME( "unsupported algorithm %u\n", key
->alg_id
);
633 return STATUS_NOT_IMPLEMENTED
;
637 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, LPCWSTR prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
, ULONG flags
)
639 struct object
*object
= handle
;
641 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
643 if (!object
) return STATUS_INVALID_HANDLE
;
644 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
646 switch (object
->magic
)
650 const struct algorithm
*alg
= (const struct algorithm
*)object
;
651 return get_alg_property( alg
, prop
, buffer
, count
, res
);
655 const struct key
*key
= (const struct key
*)object
;
656 return get_key_property( key
, prop
, buffer
, count
, res
);
660 const struct hash
*hash
= (const struct hash
*)object
;
661 return get_hash_property( hash
, prop
, buffer
, count
, res
);
664 WARN( "unknown magic %08x\n", object
->magic
);
665 return STATUS_INVALID_HANDLE
;
669 static NTSTATUS
prepare_hash( struct hash
*hash
)
671 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
675 /* initialize hash */
676 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) return status
;
677 if (!(hash
->flags
& HASH_FLAG_HMAC
)) return STATUS_SUCCESS
;
679 /* initialize hmac */
680 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) return status
;
681 block_bytes
= builtin_algorithms
[hash
->alg_id
].block_bits
/ 8;
682 if (hash
->secret_len
> block_bytes
)
684 struct hash_impl temp
;
685 if ((status
= hash_init( &temp
, hash
->alg_id
))) return status
;
686 if ((status
= hash_update( &temp
, hash
->alg_id
, hash
->secret
, hash
->secret_len
))) return status
;
687 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
688 builtin_algorithms
[hash
->alg_id
].hash_length
))) return status
;
690 else memcpy( buffer
, hash
->secret
, hash
->secret_len
);
692 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
693 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) return status
;
694 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
695 return hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
698 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_HASH_HANDLE
*handle
, UCHAR
*object
, ULONG objectlen
,
699 UCHAR
*secret
, ULONG secretlen
, ULONG flags
)
701 struct algorithm
*alg
= algorithm
;
705 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm
, handle
, object
, objectlen
,
706 secret
, secretlen
, flags
);
707 if (flags
& ~BCRYPT_HASH_REUSABLE_FLAG
)
709 FIXME( "unimplemented flags %08x\n", flags
);
710 return STATUS_NOT_IMPLEMENTED
;
713 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
714 if (object
) FIXME( "ignoring object buffer\n" );
716 if (!(hash
= heap_alloc_zero( sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
717 hash
->hdr
.magic
= MAGIC_HASH
;
718 hash
->alg_id
= alg
->id
;
719 if (alg
->flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
) hash
->flags
= HASH_FLAG_HMAC
;
720 if ((alg
->flags
& BCRYPT_HASH_REUSABLE_FLAG
) || (flags
& BCRYPT_HASH_REUSABLE_FLAG
))
721 hash
->flags
|= HASH_FLAG_REUSABLE
;
723 if (secretlen
&& !(hash
->secret
= heap_alloc( secretlen
)))
726 return STATUS_NO_MEMORY
;
728 memcpy( hash
->secret
, secret
, secretlen
);
729 hash
->secret_len
= secretlen
;
731 if ((status
= prepare_hash( hash
)) != STATUS_SUCCESS
)
733 heap_free( hash
->secret
);
739 return STATUS_SUCCESS
;
742 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
743 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
745 struct hash
*hash_orig
= handle
;
746 struct hash
*hash_copy
;
748 TRACE( "%p, %p, %p, %u, %u\n", handle
, handle_copy
, object
, objectlen
, flags
);
750 if (!hash_orig
|| hash_orig
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
751 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
752 if (object
) FIXME( "ignoring object buffer\n" );
754 if (!(hash_copy
= heap_alloc( sizeof(*hash_copy
) )))
755 return STATUS_NO_MEMORY
;
757 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
758 if (hash_orig
->secret
&& !(hash_copy
->secret
= heap_alloc( hash_orig
->secret_len
)))
760 heap_free( hash_copy
);
761 return STATUS_NO_MEMORY
;
763 memcpy( hash_copy
->secret
, hash_orig
->secret
, hash_orig
->secret_len
);
765 *handle_copy
= hash_copy
;
766 return STATUS_SUCCESS
;
769 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
771 struct hash
*hash
= handle
;
773 TRACE( "%p\n", handle
);
775 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_PARAMETER
;
777 heap_free( hash
->secret
);
779 return STATUS_SUCCESS
;
782 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
784 struct hash
*hash
= handle
;
786 TRACE( "%p, %p, %u, %08x\n", handle
, input
, size
, flags
);
788 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
789 if (!input
) return STATUS_SUCCESS
;
791 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
794 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
796 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
797 struct hash
*hash
= handle
;
801 TRACE( "%p, %p, %u, %08x\n", handle
, output
, size
, flags
);
803 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
804 if (!output
) return STATUS_INVALID_PARAMETER
;
806 if (!(hash
->flags
& HASH_FLAG_HMAC
))
808 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
))) return status
;
809 if (hash
->flags
& HASH_FLAG_REUSABLE
) return prepare_hash( hash
);
810 return STATUS_SUCCESS
;
813 hash_length
= builtin_algorithms
[hash
->alg_id
].hash_length
;
814 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
815 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
816 if ((status
= hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
))) return status
;
817 if (hash
->flags
& HASH_FLAG_REUSABLE
) return prepare_hash( hash
);
818 return STATUS_SUCCESS
;
821 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE algorithm
, UCHAR
*secret
, ULONG secretlen
,
822 UCHAR
*input
, ULONG inputlen
, UCHAR
*output
, ULONG outputlen
)
825 BCRYPT_HASH_HANDLE handle
;
827 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm
, secret
, secretlen
,
828 input
, inputlen
, output
, outputlen
);
830 status
= BCryptCreateHash( algorithm
, &handle
, NULL
, 0, secret
, secretlen
, 0);
831 if (status
!= STATUS_SUCCESS
)
836 status
= BCryptHashData( handle
, input
, inputlen
, 0 );
837 if (status
!= STATUS_SUCCESS
)
839 BCryptDestroyHash( handle
);
843 status
= BCryptFinishHash( handle
, output
, outputlen
, 0 );
844 if (status
!= STATUS_SUCCESS
)
846 BCryptDestroyHash( handle
);
850 return BCryptDestroyHash( handle
);
853 static NTSTATUS
key_asymmetric_create( struct key
**ret_key
, struct algorithm
*alg
, ULONG bitlen
,
854 const UCHAR
*pubkey
, ULONG pubkey_len
)
861 ERR( "no encryption support\n" );
862 return STATUS_NOT_IMPLEMENTED
;
865 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
866 key
->hdr
.magic
= MAGIC_KEY
;
867 key
->alg_id
= alg
->id
;
868 key
->u
.a
.bitlen
= bitlen
;
872 if (!(key
->u
.a
.pubkey
= heap_alloc( pubkey_len
)))
875 return STATUS_NO_MEMORY
;
877 memcpy( key
->u
.a
.pubkey
, pubkey
, pubkey_len
);
878 key
->u
.a
.pubkey_len
= pubkey_len
;
880 if ((status
= key_funcs
->key_asymmetric_init( key
)))
882 heap_free( key
->u
.a
.pubkey
);
887 return STATUS_SUCCESS
;
890 static BOOL
key_is_symmetric( struct key
*key
)
892 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_CIPHER_INTERFACE
;
895 static BOOL
is_zero_vector( const UCHAR
*vector
, ULONG len
)
898 if (!vector
) return FALSE
;
899 for (i
= 0; i
< len
; i
++) if (vector
[i
]) return FALSE
;
903 static BOOL
is_equal_vector( const UCHAR
*vector
, ULONG len
, const UCHAR
*vector2
, ULONG len2
)
905 if (!vector
&& !vector2
) return TRUE
;
906 if (len
!= len2
) return FALSE
;
907 return !memcmp( vector
, vector2
, len
);
910 static NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
)
912 BOOL needs_reset
= (!is_zero_vector( vector
, vector_len
) ||
913 !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
));
915 heap_free( key
->u
.s
.vector
);
916 key
->u
.s
.vector
= NULL
;
917 key
->u
.s
.vector_len
= 0;
920 if (!(key
->u
.s
.vector
= heap_alloc( vector_len
))) return STATUS_NO_MEMORY
;
921 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
922 key
->u
.s
.vector_len
= vector_len
;
924 if (needs_reset
) key_funcs
->key_symmetric_vector_reset( key
);
925 return STATUS_SUCCESS
;
928 static NTSTATUS
key_import( BCRYPT_ALG_HANDLE algorithm
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
929 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
933 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
935 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
937 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
)) return STATUS_BUFFER_TOO_SMALL
;
938 if (header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
) return STATUS_INVALID_PARAMETER
;
939 if (header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
941 FIXME( "unknown key data blob version %u\n", header
->dwVersion
);
942 return STATUS_INVALID_PARAMETER
;
944 len
= header
->cbKeyData
;
945 if (len
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
) return STATUS_INVALID_PARAMETER
;
947 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, (UCHAR
*)&header
[1], len
, 0 );
949 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
951 if (input_len
< sizeof(len
)) return STATUS_BUFFER_TOO_SMALL
;
952 len
= *(ULONG
*)input
;
953 if (len
+ sizeof(len
) > input_len
) return STATUS_INVALID_PARAMETER
;
955 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, input
+ sizeof(len
), len
, 0 );
958 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
959 return STATUS_NOT_IMPLEMENTED
;
962 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
964 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
966 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
967 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
970 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
973 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
974 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
975 header
->cbKeyData
= key
->u
.s
.secret_len
;
976 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
978 return STATUS_SUCCESS
;
980 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
982 ULONG len
, req_size
= sizeof(len
) + key
->u
.s
.secret_len
;
985 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
988 *(ULONG
*)output
= key
->u
.s
.secret_len
;
989 memcpy( output
+ sizeof(len
), key
->u
.s
.secret
, key
->u
.s
.secret_len
);
991 return STATUS_SUCCESS
;
993 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
) || !wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
) ||
994 !wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
))
996 *size
= key
->u
.a
.pubkey_len
;
997 if (output_len
< key
->u
.a
.pubkey_len
) return STATUS_SUCCESS
;
998 if (output
) memcpy( output
, key
->u
.a
.pubkey
, key
->u
.a
.pubkey_len
);
999 return STATUS_SUCCESS
;
1001 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1003 return key_funcs
->key_export_ecc( key
, output
, output_len
, size
);
1005 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1007 return key_funcs
->key_export_dsa_capi( key
, output
, output_len
, size
);
1010 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1011 return STATUS_NOT_IMPLEMENTED
;
1014 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
1018 memset( key_copy
, 0, sizeof(*key_copy
) );
1019 key_copy
->hdr
= key_orig
->hdr
;
1020 key_copy
->alg_id
= key_orig
->alg_id
;
1022 if (key_is_symmetric( key_orig
))
1024 if (!(buffer
= heap_alloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
1025 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
1027 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
1028 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
1029 key_copy
->u
.s
.secret
= buffer
;
1030 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
1034 if (!(buffer
= heap_alloc( key_orig
->u
.a
.pubkey_len
))) return STATUS_NO_MEMORY
;
1035 memcpy( buffer
, key_orig
->u
.a
.pubkey
, key_orig
->u
.a
.pubkey_len
);
1037 key_copy
->u
.a
.pubkey
= buffer
;
1038 key_copy
->u
.a
.pubkey_len
= key_orig
->u
.a
.pubkey_len
;
1041 return STATUS_SUCCESS
;
1044 static NTSTATUS
key_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1045 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1047 ULONG bytes_left
= input_len
;
1048 UCHAR
*buf
, *src
, *dst
;
1051 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1053 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1055 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1056 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1057 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1058 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1059 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1060 FIXME( "call chaining not implemented\n" );
1062 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1065 *ret_len
= input_len
;
1066 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1067 if (input
&& !output
) return STATUS_SUCCESS
;
1068 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1070 if ((status
= key_funcs
->key_symmetric_set_auth_data( key
, auth_info
->pbAuthData
, auth_info
->cbAuthData
)))
1072 if ((status
= key_funcs
->key_symmetric_encrypt( key
, input
, input_len
, output
, output_len
))) return status
;
1074 return key_funcs
->key_symmetric_get_tag( key
, auth_info
->pbTag
, auth_info
->cbTag
);
1077 *ret_len
= input_len
;
1079 if (flags
& BCRYPT_BLOCK_PADDING
)
1080 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1081 else if (input_len
& (key
->u
.s
.block_size
- 1))
1082 return STATUS_INVALID_BUFFER_SIZE
;
1084 if (!output
) return STATUS_SUCCESS
;
1085 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1086 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1087 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1091 while (bytes_left
>= key
->u
.s
.block_size
)
1093 if ((status
= key_funcs
->key_symmetric_encrypt( key
, src
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
)))
1095 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 )))
1097 bytes_left
-= key
->u
.s
.block_size
;
1098 src
+= key
->u
.s
.block_size
;
1099 dst
+= key
->u
.s
.block_size
;
1102 if (flags
& BCRYPT_BLOCK_PADDING
)
1104 if (!(buf
= heap_alloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1105 memcpy( buf
, src
, bytes_left
);
1106 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1107 status
= key_funcs
->key_symmetric_encrypt( key
, buf
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
);
1114 static NTSTATUS
key_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1115 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1117 ULONG bytes_left
= input_len
;
1118 UCHAR
*buf
, *src
, *dst
;
1121 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1123 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1126 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1127 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1128 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1129 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1131 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1134 *ret_len
= input_len
;
1135 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1136 if (!output
) return STATUS_SUCCESS
;
1137 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1139 if ((status
= key_funcs
->key_symmetric_set_auth_data( key
, auth_info
->pbAuthData
, auth_info
->cbAuthData
)))
1141 if ((status
= key_funcs
->key_symmetric_decrypt( key
, input
, input_len
, output
, output_len
))) return status
;
1143 if ((status
= key_funcs
->key_symmetric_get_tag( key
, tag
, sizeof(tag
) ))) return status
;
1144 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1146 return STATUS_SUCCESS
;
1149 *ret_len
= input_len
;
1151 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1152 if (!output
) return STATUS_SUCCESS
;
1153 if (flags
& BCRYPT_BLOCK_PADDING
)
1155 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1156 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1157 bytes_left
-= key
->u
.s
.block_size
;
1159 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1161 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1162 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1166 while (bytes_left
>= key
->u
.s
.block_size
)
1168 if ((status
= key_funcs
->key_symmetric_decrypt( key
, src
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
)))
1170 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 )))
1172 bytes_left
-= key
->u
.s
.block_size
;
1173 src
+= key
->u
.s
.block_size
;
1174 dst
+= key
->u
.s
.block_size
;
1177 if (flags
& BCRYPT_BLOCK_PADDING
)
1179 if (!(buf
= heap_alloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1180 status
= key_funcs
->key_symmetric_decrypt( key
, src
, key
->u
.s
.block_size
, buf
, key
->u
.s
.block_size
);
1181 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1183 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1184 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1185 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1187 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1194 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1200 if (!wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
))
1202 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1203 DWORD key_size
, magic
, size
;
1205 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1209 case ALG_ID_ECDH_P256
:
1211 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
1214 case ALG_ID_ECDSA_P256
:
1216 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
1219 case ALG_ID_ECDSA_P384
:
1221 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
1225 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1226 return STATUS_NOT_SUPPORTED
;
1229 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1230 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2)
1231 return STATUS_INVALID_PARAMETER
;
1233 size
= sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2;
1234 return key_asymmetric_create( (struct key
**)ret_key
, alg
, key_size
* 8, (BYTE
*)ecc_blob
, size
);
1236 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1238 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1239 DWORD key_size
, magic
;
1241 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1245 case ALG_ID_ECDH_P256
:
1247 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
1249 case ALG_ID_ECDSA_P256
:
1251 magic
= BCRYPT_ECDSA_PRIVATE_P256_MAGIC
;
1255 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1256 return STATUS_NOT_SUPPORTED
;
1259 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1260 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 3)
1261 return STATUS_INVALID_PARAMETER
;
1263 if ((status
= key_asymmetric_create( &key
, alg
, key_size
* 8, NULL
, 0 ))) return status
;
1264 if ((status
= key_funcs
->key_import_ecc( key
, input
, input_len
)))
1266 BCryptDestroyKey( key
);
1271 return STATUS_SUCCESS
;
1273 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1275 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1278 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1279 if ((alg
->id
!= ALG_ID_RSA
&& alg
->id
!= ALG_ID_RSA_SIGN
) || rsa_blob
->Magic
!= BCRYPT_RSAPUBLIC_MAGIC
)
1280 return STATUS_NOT_SUPPORTED
;
1282 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1283 return key_asymmetric_create( (struct key
**)ret_key
, alg
, rsa_blob
->BitLength
, (BYTE
*)rsa_blob
, size
);
1285 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
))
1287 BCRYPT_DSA_KEY_BLOB
*dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)input
;
1290 if (input_len
< sizeof(*dsa_blob
)) return STATUS_INVALID_PARAMETER
;
1291 if ((alg
->id
!= ALG_ID_DSA
) || dsa_blob
->dwMagic
!= BCRYPT_DSA_PUBLIC_MAGIC
)
1292 return STATUS_NOT_SUPPORTED
;
1294 size
= sizeof(*dsa_blob
) + dsa_blob
->cbKey
* 3;
1295 return key_asymmetric_create( (struct key
**)ret_key
, alg
, dsa_blob
->cbKey
* 8, (BYTE
*)dsa_blob
, size
);
1297 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1299 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1302 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1304 if (hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1306 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1307 return STATUS_NOT_SUPPORTED
;
1309 if (alg
->id
!= ALG_ID_DSA
)
1311 FIXME( "algorithm %u does not support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1312 return STATUS_NOT_SUPPORTED
;
1315 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1316 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1317 if (pubkey
->magic
!= MAGIC_DSS2
) return STATUS_NOT_SUPPORTED
;
1319 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 2 + 40 + sizeof(DSSSEED
))
1320 return STATUS_INVALID_PARAMETER
;
1322 if ((status
= key_asymmetric_create( &key
, alg
, pubkey
->bitlen
, NULL
, 0 ))) return status
;
1323 if ((status
= key_funcs
->key_import_dsa_capi( key
, input
, input_len
)))
1325 BCryptDestroyKey( key
);
1330 return STATUS_SUCCESS
;
1332 else if (!wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
)) /* not supported on native */
1334 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1338 if (alg
->id
!= ALG_ID_DSA
) return STATUS_NOT_SUPPORTED
;
1339 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1341 if (hdr
->bType
!= PUBLICKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1343 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1344 return STATUS_NOT_SUPPORTED
;
1347 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1348 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1349 if (pubkey
->magic
!= MAGIC_DSS1
) return STATUS_NOT_SUPPORTED
;
1351 size
= sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 3 + 20 + sizeof(DSSSEED
);
1352 if (input_len
< size
) return STATUS_INVALID_PARAMETER
;
1354 if ((status
= key_asymmetric_create( &key
, alg
, pubkey
->bitlen
, (BYTE
*)hdr
, size
))) return status
;
1355 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1358 return STATUS_SUCCESS
;
1361 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1362 return STATUS_NOT_SUPPORTED
;
1365 static ULONG
get_block_size( struct algorithm
*alg
)
1367 ULONG ret
= 0, size
= sizeof(ret
);
1368 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
1372 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1373 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1376 struct algorithm
*alg
= algorithm
;
1381 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
1383 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1384 if (object
) FIXME( "ignoring object buffer\n" );
1388 ERR( "no encryption support\n" );
1389 return STATUS_NOT_IMPLEMENTED
;
1392 if (!(block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1394 if (!(key
= heap_alloc_zero( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1395 key
->hdr
.magic
= MAGIC_KEY
;
1396 key
->alg_id
= alg
->id
;
1397 key
->u
.s
.mode
= alg
->mode
;
1398 key
->u
.s
.block_size
= block_size
;
1400 if (!(key
->u
.s
.secret
= heap_alloc( secret_len
)))
1403 return STATUS_NO_MEMORY
;
1405 memcpy( key
->u
.s
.secret
, secret
, secret_len
);
1406 key
->u
.s
.secret_len
= secret_len
;
1408 if ((status
= key_funcs
->key_symmetric_init( key
)))
1410 heap_free( key
->u
.s
.secret
);
1416 return STATUS_SUCCESS
;
1419 NTSTATUS WINAPI
BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
, ULONG key_len
,
1422 struct algorithm
*alg
= algorithm
;
1426 TRACE( "%p, %p, %u, %08x\n", algorithm
, handle
, key_len
, flags
);
1428 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1429 if (!handle
) return STATUS_INVALID_PARAMETER
;
1431 if (!(status
= key_asymmetric_create( &key
, alg
, key_len
, NULL
, 0 ))) *handle
= key
;
1435 NTSTATUS WINAPI
BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle
, ULONG flags
)
1437 struct key
*key
= handle
;
1439 TRACE( "%p, %08x\n", key
, flags
);
1440 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1442 return key_funcs
->key_asymmetric_generate( key
);
1445 NTSTATUS WINAPI
BCryptImportKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, LPCWSTR type
,
1446 BCRYPT_KEY_HANDLE
*key
, PUCHAR object
, ULONG object_len
, PUCHAR input
,
1447 ULONG input_len
, ULONG flags
)
1449 struct algorithm
*alg
= algorithm
;
1451 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm
, decrypt_key
, debugstr_w(type
), key
, object
,
1452 object_len
, input
, input_len
, flags
);
1454 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1455 if (!key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1459 FIXME( "decryption of key not yet supported\n" );
1460 return STATUS_NOT_IMPLEMENTED
;
1463 return key_import( algorithm
, type
, key
, object
, object_len
, input
, input_len
);
1466 NTSTATUS WINAPI
BCryptExportKey( BCRYPT_KEY_HANDLE export_key
, BCRYPT_KEY_HANDLE encrypt_key
, LPCWSTR type
,
1467 PUCHAR output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1469 struct key
*key
= export_key
;
1471 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key
, encrypt_key
, debugstr_w(type
), output
, output_len
, size
, flags
);
1473 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1474 if (!type
|| !size
) return STATUS_INVALID_PARAMETER
;
1478 FIXME( "encryption of key not yet supported\n" );
1479 return STATUS_NOT_IMPLEMENTED
;
1482 return key_export( key
, type
, output
, output_len
, size
);
1485 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
1486 UCHAR
*object
, ULONG object_len
, ULONG flags
)
1488 struct key
*key_orig
= handle
;
1489 struct key
*key_copy
;
1492 TRACE( "%p, %p, %p, %u, %08x\n", handle
, handle_copy
, object
, object_len
, flags
);
1493 if (object
) FIXME( "ignoring object buffer\n" );
1495 if (!key_orig
|| key_orig
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1496 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1497 if (!(key_copy
= heap_alloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
1499 if ((status
= key_duplicate( key_orig
, key_copy
)))
1501 heap_free( key_copy
);
1505 *handle_copy
= key_copy
;
1506 return STATUS_SUCCESS
;
1509 NTSTATUS WINAPI
BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1510 BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
, ULONG input_len
, ULONG flags
)
1512 struct algorithm
*alg
= algorithm
;
1514 TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm
, decrypt_key
, debugstr_w(type
), ret_key
, input
,
1517 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1518 if (!ret_key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1521 FIXME( "decryption of key not yet supported\n" );
1522 return STATUS_NOT_IMPLEMENTED
;
1525 return key_import_pair( alg
, type
, ret_key
, input
, input_len
);
1528 NTSTATUS WINAPI
BCryptSignHash( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*input
, ULONG input_len
,
1529 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1531 struct key
*key
= handle
;
1533 TRACE( "%p, %p, %p, %u, %p, %u, %p, %08x\n", handle
, padding
, input
, input_len
, output
, output_len
,
1536 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1537 if (key_is_symmetric( key
))
1539 FIXME( "signing with symmetric keys not yet supported\n" );
1540 return STATUS_NOT_IMPLEMENTED
;
1543 return key_funcs
->key_asymmetric_sign( key
, padding
, input
, input_len
, output
, output_len
, ret_len
, flags
);
1546 NTSTATUS WINAPI
BCryptVerifySignature( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*hash
, ULONG hash_len
,
1547 UCHAR
*signature
, ULONG signature_len
, ULONG flags
)
1549 struct key
*key
= handle
;
1551 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
1553 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1554 if (!hash
|| !hash_len
|| !signature
|| !signature_len
) return STATUS_INVALID_PARAMETER
;
1555 if (key_is_symmetric( key
)) return STATUS_NOT_SUPPORTED
;
1557 return key_funcs
->key_asymmetric_verify( key
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
1560 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
1562 struct key
*key
= handle
;
1564 TRACE( "%p\n", handle
);
1566 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1567 if (key_is_symmetric( key
))
1569 key_funcs
->key_symmetric_destroy( key
);
1570 heap_free( key
->u
.s
.vector
);
1571 heap_free( key
->u
.s
.secret
);
1575 key_funcs
->key_asymmetric_destroy( key
);
1576 heap_free( key
->u
.a
.pubkey
);
1580 return STATUS_SUCCESS
;
1583 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1584 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1586 struct key
*key
= handle
;
1588 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1589 output_len
, ret_len
, flags
);
1591 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1592 if (!key_is_symmetric( key
))
1594 FIXME( "encryption with asymmetric keys not yet supported\n" );
1595 return STATUS_NOT_IMPLEMENTED
;
1597 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1599 FIXME( "flags %08x not implemented\n", flags
);
1600 return STATUS_NOT_IMPLEMENTED
;
1603 return key_encrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1606 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1607 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1609 struct key
*key
= handle
;
1611 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1612 output_len
, ret_len
, flags
);
1614 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1615 if (!key_is_symmetric( key
))
1617 FIXME( "decryption with asymmetric keys not yet supported\n" );
1618 return STATUS_NOT_IMPLEMENTED
;
1620 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1622 FIXME( "flags %08x not supported\n", flags
);
1623 return STATUS_NOT_IMPLEMENTED
;
1626 return key_decrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1629 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1631 struct object
*object
= handle
;
1633 TRACE( "%p, %s, %p, %u, %08x\n", handle
, debugstr_w(prop
), value
, size
, flags
);
1635 if (!object
) return STATUS_INVALID_HANDLE
;
1637 switch (object
->magic
)
1641 struct algorithm
*alg
= (struct algorithm
*)object
;
1642 return set_alg_property( alg
, prop
, value
, size
, flags
);
1646 struct key
*key
= (struct key
*)object
;
1647 return key_funcs
->key_set_property( key
, prop
, value
, size
, flags
);
1650 WARN( "unknown magic %08x\n", object
->magic
);
1651 return STATUS_INVALID_HANDLE
;
1655 #define HMAC_PAD_LEN 64
1656 NTSTATUS WINAPI
BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle
, BCRYPT_ALG_HANDLE halg
, UCHAR
*key
, ULONG keylen
, ULONG flags
)
1658 struct hash
*hash
= handle
;
1659 UCHAR buf
[MAX_HASH_OUTPUT_BYTES
* 2];
1663 TRACE( "%p, %p, %p, %u, %08x\n", handle
, halg
, key
, keylen
, flags
);
1665 if (!key
|| !keylen
) return STATUS_INVALID_PARAMETER
;
1666 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
1667 if (keylen
> builtin_algorithms
[hash
->alg_id
].hash_length
* 2) return STATUS_INVALID_PARAMETER
;
1671 FIXME( "algorithm handle not supported\n" );
1672 return STATUS_NOT_IMPLEMENTED
;
1675 len
= builtin_algorithms
[hash
->alg_id
].hash_length
;
1676 if ((status
= BCryptFinishHash( handle
, buf
, len
, 0 ))) return status
;
1680 UCHAR pad1
[HMAC_PAD_LEN
], pad2
[HMAC_PAD_LEN
];
1683 for (i
= 0; i
< sizeof(pad1
); i
++)
1685 pad1
[i
] = 0x36 ^ (i
< len
? buf
[i
] : 0);
1686 pad2
[i
] = 0x5c ^ (i
< len
? buf
[i
] : 0);
1689 if ((status
= prepare_hash( hash
)) ||
1690 (status
= BCryptHashData( handle
, pad1
, sizeof(pad1
), 0 )) ||
1691 (status
= BCryptFinishHash( handle
, buf
, len
, 0 ))) return status
;
1693 if ((status
= prepare_hash( hash
)) ||
1694 (status
= BCryptHashData( handle
, pad2
, sizeof(pad2
), 0 )) ||
1695 (status
= BCryptFinishHash( handle
, buf
+ len
, len
, 0 ))) return status
;
1698 memcpy( key
, buf
, keylen
);
1699 return STATUS_SUCCESS
;
1702 static NTSTATUS
pbkdf2( BCRYPT_HASH_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
1703 ULONGLONG iterations
, ULONG i
, UCHAR
*dst
, ULONG hash_len
)
1705 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
1706 UCHAR bytes
[4], *buf
;
1709 if (!(buf
= heap_alloc( hash_len
))) return STATUS_NO_MEMORY
;
1711 for (j
= 0; j
< iterations
; j
++)
1715 /* use salt || INT(i) */
1716 status
= BCryptHashData( handle
, salt
, salt_len
, 0 );
1717 if (status
!= STATUS_SUCCESS
)
1722 bytes
[0] = (i
>> 24) & 0xff;
1723 bytes
[1] = (i
>> 16) & 0xff;
1724 bytes
[2] = (i
>> 8) & 0xff;
1725 bytes
[3] = i
& 0xff;
1726 status
= BCryptHashData( handle
, bytes
, 4, 0 );
1728 else status
= BCryptHashData( handle
, buf
, hash_len
, 0 ); /* use U_j */
1729 if (status
!= STATUS_SUCCESS
)
1735 status
= BCryptFinishHash( handle
, buf
, hash_len
, 0 );
1736 if (status
!= STATUS_SUCCESS
)
1742 if (j
== 0) memcpy( dst
, buf
, hash_len
);
1743 else for (k
= 0; k
< hash_len
; k
++) dst
[k
] ^= buf
[k
];
1750 NTSTATUS WINAPI
BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
1751 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
, ULONG flags
)
1753 struct algorithm
*alg
= handle
;
1754 ULONG hash_len
, block_count
, bytes_left
, i
;
1755 BCRYPT_HASH_HANDLE hash
;
1759 TRACE( "%p, %p, %u, %p, %u, %s, %p, %u, %08x\n", handle
, pwd
, pwd_len
, salt
, salt_len
,
1760 wine_dbgstr_longlong(iterations
), dk
, dk_len
, flags
);
1762 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1764 hash_len
= builtin_algorithms
[alg
->id
].hash_length
;
1765 if (dk_len
<= 0 || dk_len
> ((((ULONGLONG
)1) << 32) - 1) * hash_len
) return STATUS_INVALID_PARAMETER
;
1767 block_count
= 1 + ((dk_len
- 1) / hash_len
); /* ceil(dk_len / hash_len) */
1768 bytes_left
= dk_len
- (block_count
- 1) * hash_len
;
1770 status
= BCryptCreateHash( handle
, &hash
, NULL
, 0, pwd
, pwd_len
, BCRYPT_HASH_REUSABLE_FLAG
);
1771 if (status
!= STATUS_SUCCESS
)
1775 for (i
= 1; i
< block_count
; i
++)
1777 status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, i
, dk
+ ((i
- 1) * hash_len
), hash_len
);
1778 if (status
!= STATUS_SUCCESS
)
1780 BCryptDestroyHash( hash
);
1785 /* final partial block */
1786 if (!(partial
= heap_alloc( hash_len
)))
1788 BCryptDestroyHash( hash
);
1789 return STATUS_NO_MEMORY
;
1792 status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, block_count
, partial
, hash_len
);
1793 if (status
!= STATUS_SUCCESS
)
1795 BCryptDestroyHash( hash
);
1796 heap_free( partial
);
1799 memcpy( dk
+ ((block_count
- 1) * hash_len
), partial
, bytes_left
);
1801 BCryptDestroyHash( hash
);
1802 heap_free( partial
);
1803 return STATUS_SUCCESS
;
1806 NTSTATUS WINAPI
BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey
, BCRYPT_KEY_HANDLE publickey
, BCRYPT_SECRET_HANDLE
*handle
, ULONG flags
)
1808 struct key
*privkey
= privatekey
;
1809 struct key
*pubkey
= publickey
;
1810 struct secret
*secret
;
1812 FIXME( "%p, %p, %p, %08x\n", privatekey
, publickey
, handle
, flags
);
1814 if (!privkey
|| privkey
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1815 if (!pubkey
|| pubkey
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1816 if (!handle
) return STATUS_INVALID_PARAMETER
;
1818 if (!(secret
= heap_alloc_zero( sizeof(*secret
) ))) return STATUS_NO_MEMORY
;
1819 secret
->hdr
.magic
= MAGIC_SECRET
;
1822 return STATUS_SUCCESS
;
1825 NTSTATUS WINAPI
BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle
)
1827 struct secret
*secret
= handle
;
1829 FIXME( "%p\n", handle
);
1831 if (!secret
|| secret
->hdr
.magic
!= MAGIC_SECRET
) return STATUS_INVALID_HANDLE
;
1832 secret
->hdr
.magic
= 0;
1833 heap_free( secret
);
1834 return STATUS_SUCCESS
;
1837 NTSTATUS WINAPI
BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle
, LPCWSTR kdf
, BCryptBufferDesc
*parameter
,
1838 PUCHAR derived
, ULONG derived_size
, ULONG
*result
, ULONG flags
)
1840 struct secret
*secret
= handle
;
1842 FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret
, debugstr_w(kdf
), parameter
, derived
, derived_size
, result
, flags
);
1844 if (!secret
|| secret
->hdr
.magic
!= MAGIC_SECRET
) return STATUS_INVALID_HANDLE
;
1845 if (!kdf
) return STATUS_INVALID_PARAMETER
;
1847 return STATUS_INTERNAL_ERROR
;
1850 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
1854 case DLL_PROCESS_ATTACH
:
1856 DisableThreadLibraryCalls( hinst
);
1857 __wine_init_unix_lib( hinst
, reason
, NULL
, &key_funcs
);
1859 case DLL_PROCESS_DETACH
:
1860 if (reserved
) break;
1861 __wine_init_unix_lib( hinst
, reason
, NULL
, NULL
);