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
24 #define WIN32_NO_STATUS
32 #include "wine/debug.h"
33 #include "bcrypt_internal.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
37 static unixlib_handle_t bcrypt_handle
;
39 #define UNIX_CALL( func, params ) __wine_unix_call( bcrypt_handle, unix_ ## func, params )
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_3DES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 522, 0, 0 },
105 { BCRYPT_AES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 654, 0, 0 },
106 { BCRYPT_SHA256_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 286, 32, 512 },
107 { BCRYPT_SHA384_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 48, 1024 },
108 { BCRYPT_SHA512_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 64, 1024 },
109 { BCRYPT_SHA1_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 278, 20, 512 },
110 { BCRYPT_MD5_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 274, 16, 512 },
111 { BCRYPT_MD4_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 512 },
112 { BCRYPT_MD2_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 128 },
113 { BCRYPT_RSA_ALGORITHM
, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
, 0, 0, 0 },
114 { BCRYPT_ECDH_P256_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
115 { BCRYPT_RSA_SIGN_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
116 { BCRYPT_ECDSA_P256_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
117 { BCRYPT_ECDSA_P384_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
118 { BCRYPT_DSA_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
119 { BCRYPT_RNG_ALGORITHM
, BCRYPT_RNG_INTERFACE
, 0, 0, 0 },
122 static BOOL
match_operation_type( ULONG type
, ULONG
class )
124 if (!type
) return TRUE
;
127 case BCRYPT_CIPHER_INTERFACE
: return type
& BCRYPT_CIPHER_OPERATION
;
128 case BCRYPT_HASH_INTERFACE
: return type
& BCRYPT_HASH_OPERATION
;
129 case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
: return type
& BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
;
130 case BCRYPT_SECRET_AGREEMENT_INTERFACE
: return type
& BCRYPT_SECRET_AGREEMENT_OPERATION
;
131 case BCRYPT_SIGNATURE_INTERFACE
: return type
& BCRYPT_SIGNATURE_OPERATION
;
132 case BCRYPT_RNG_INTERFACE
: return type
& BCRYPT_RNG_OPERATION
;
138 NTSTATUS WINAPI
BCryptEnumAlgorithms( ULONG type
, ULONG
*ret_count
, BCRYPT_ALGORITHM_IDENTIFIER
**ret_list
, ULONG flags
)
140 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
141 BCRYPT_HASH_OPERATION
|\
142 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
143 BCRYPT_SECRET_AGREEMENT_OPERATION
|\
144 BCRYPT_SIGNATURE_OPERATION
|\
145 BCRYPT_RNG_OPERATION
;
146 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
149 TRACE( "%08x, %p, %p, %08x\n", type
, ret_count
, ret_list
, flags
);
151 if (!ret_count
|| !ret_list
|| (type
& ~supported
)) return STATUS_INVALID_PARAMETER
;
153 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
155 if (match_operation_type( type
, builtin_algorithms
[i
].class )) count
++;
158 if (!(list
= malloc( count
* sizeof(*list
) ))) return STATUS_NO_MEMORY
;
160 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
162 if (!match_operation_type( type
, builtin_algorithms
[i
].class )) continue;
163 list
[i
].pszName
= (WCHAR
*)builtin_algorithms
[i
].name
;
164 list
[i
].dwClass
= builtin_algorithms
[i
].class;
170 return STATUS_SUCCESS
;
173 NTSTATUS WINAPI
BCryptGenRandom(BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
175 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
176 struct algorithm
*algorithm
= handle
;
178 TRACE("%p, %p, %u, %08x - semi-stub\n", handle
, buffer
, count
, flags
);
182 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
183 * is set. In this case the preferred system RNG is used.
185 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
186 return STATUS_INVALID_HANDLE
;
188 else if (algorithm
->hdr
.magic
!= MAGIC_ALG
|| algorithm
->id
!= ALG_ID_RNG
)
189 return STATUS_INVALID_HANDLE
;
192 return STATUS_INVALID_PARAMETER
;
194 if (flags
& ~supported_flags
)
195 FIXME("unsupported flags %08x\n", flags
& ~supported_flags
);
198 FIXME("ignoring selected algorithm\n");
200 /* When zero bytes are requested the function returns success too. */
202 return STATUS_SUCCESS
;
204 if (algorithm
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
206 if (RtlGenRandom(buffer
, count
))
207 return STATUS_SUCCESS
;
210 FIXME("called with unsupported parameters, returning error\n");
211 return STATUS_NOT_IMPLEMENTED
;
214 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, LPCWSTR id
, LPCWSTR implementation
, DWORD flags
)
216 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
| BCRYPT_HASH_REUSABLE_FLAG
;
217 struct algorithm
*alg
;
221 TRACE( "%p, %s, %s, %08x\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
223 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
224 if (flags
& ~supported_flags
)
226 FIXME( "unsupported flags %08x\n", flags
& ~supported_flags
);
227 return STATUS_NOT_IMPLEMENTED
;
230 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
232 if (!wcscmp( id
, builtin_algorithms
[i
].name
))
238 if (i
== ARRAY_SIZE( builtin_algorithms
))
240 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
241 return STATUS_NOT_IMPLEMENTED
;
244 if (implementation
&& wcscmp( implementation
, MS_PRIMITIVE_PROVIDER
))
246 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
247 return STATUS_NOT_IMPLEMENTED
;
250 if (!(alg
= malloc( sizeof(*alg
) ))) return STATUS_NO_MEMORY
;
251 alg
->hdr
.magic
= MAGIC_ALG
;
253 alg
->mode
= MODE_ID_CBC
;
257 return STATUS_SUCCESS
;
260 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
262 struct algorithm
*alg
= handle
;
264 TRACE( "%p, %08x\n", handle
, flags
);
266 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
269 return STATUS_SUCCESS
;
272 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
274 FIXME("%p - semi-stub\n", enabled
);
277 return STATUS_INVALID_PARAMETER
;
280 return STATUS_SUCCESS
;
296 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
301 md2_init( &hash
->u
.md2
);
305 MD4Init( &hash
->u
.md4
);
309 MD5Init( &hash
->u
.md5
);
313 A_SHAInit( &hash
->u
.sha1
);
317 sha256_init( &hash
->u
.sha256
);
321 sha384_init( &hash
->u
.sha512
);
325 sha512_init( &hash
->u
.sha512
);
329 ERR( "unhandled id %u\n", alg_id
);
330 return STATUS_NOT_IMPLEMENTED
;
332 return STATUS_SUCCESS
;
335 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
,
336 UCHAR
*input
, ULONG size
)
341 md2_update( &hash
->u
.md2
, input
, size
);
345 MD4Update( &hash
->u
.md4
, input
, size
);
349 MD5Update( &hash
->u
.md5
, input
, size
);
353 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
357 sha256_update( &hash
->u
.sha256
, input
, size
);
361 sha384_update( &hash
->u
.sha512
, input
, size
);
365 sha512_update( &hash
->u
.sha512
, input
, size
);
369 ERR( "unhandled id %u\n", alg_id
);
370 return STATUS_NOT_IMPLEMENTED
;
372 return STATUS_SUCCESS
;
375 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
,
376 UCHAR
*output
, ULONG size
)
381 md2_finalize( &hash
->u
.md2
, output
);
385 MD4Final( &hash
->u
.md4
);
386 memcpy( output
, hash
->u
.md4
.digest
, 16 );
390 MD5Final( &hash
->u
.md5
);
391 memcpy( output
, hash
->u
.md5
.digest
, 16 );
395 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
399 sha256_finalize( &hash
->u
.sha256
, output
);
403 sha384_finalize( &hash
->u
.sha512
, output
);
407 sha512_finalize( &hash
->u
.sha512
, output
);
411 ERR( "unhandled id %u\n", alg_id
);
412 return STATUS_NOT_IMPLEMENTED
;
414 return STATUS_SUCCESS
;
417 #define HASH_FLAG_HMAC 0x01
418 #define HASH_FLAG_REUSABLE 0x02
426 struct hash_impl outer
;
427 struct hash_impl inner
;
430 #define BLOCK_LENGTH_3DES 8
431 #define BLOCK_LENGTH_AES 16
433 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
435 if (!wcscmp( prop
, BCRYPT_OBJECT_LENGTH
))
437 if (!builtin_algorithms
[id
].object_length
)
438 return STATUS_NOT_SUPPORTED
;
439 *ret_size
= sizeof(ULONG
);
440 if (size
< sizeof(ULONG
))
441 return STATUS_BUFFER_TOO_SMALL
;
443 *(ULONG
*)buf
= builtin_algorithms
[id
].object_length
;
444 return STATUS_SUCCESS
;
447 if (!wcscmp( prop
, BCRYPT_HASH_LENGTH
))
449 if (!builtin_algorithms
[id
].hash_length
)
450 return STATUS_NOT_SUPPORTED
;
451 *ret_size
= sizeof(ULONG
);
452 if (size
< sizeof(ULONG
))
453 return STATUS_BUFFER_TOO_SMALL
;
455 *(ULONG
*)buf
= builtin_algorithms
[id
].hash_length
;
456 return STATUS_SUCCESS
;
459 if (!wcscmp( prop
, BCRYPT_ALGORITHM_NAME
))
461 *ret_size
= (lstrlenW(builtin_algorithms
[id
].name
) + 1) * sizeof(WCHAR
);
462 if (size
< *ret_size
)
463 return STATUS_BUFFER_TOO_SMALL
;
465 memcpy(buf
, builtin_algorithms
[id
].name
, *ret_size
);
466 return STATUS_SUCCESS
;
469 return STATUS_NOT_IMPLEMENTED
;
472 static NTSTATUS
get_3des_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
474 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
476 *ret_size
= sizeof(ULONG
);
477 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
478 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_3DES
;
479 return STATUS_SUCCESS
;
481 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
486 case MODE_ID_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; 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
= 192;
503 key_lengths
->dwMaxLength
= 192;
504 key_lengths
->dwIncrement
= 0;
506 return STATUS_SUCCESS
;
508 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
509 return STATUS_NOT_IMPLEMENTED
;
512 static NTSTATUS
get_aes_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
514 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
516 *ret_size
= sizeof(ULONG
);
517 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
518 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
519 return STATUS_SUCCESS
;
521 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
526 case MODE_ID_ECB
: str
= BCRYPT_CHAIN_MODE_ECB
; break;
527 case MODE_ID_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
528 case MODE_ID_GCM
: str
= BCRYPT_CHAIN_MODE_GCM
; break;
529 default: return STATUS_NOT_IMPLEMENTED
;
533 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
534 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
535 return STATUS_SUCCESS
;
537 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
539 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
540 *ret_size
= sizeof(*key_lengths
);
541 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
544 key_lengths
->dwMinLength
= 128;
545 key_lengths
->dwMaxLength
= 256;
546 key_lengths
->dwIncrement
= 64;
548 return STATUS_SUCCESS
;
550 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
))
552 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
553 if (mode
!= MODE_ID_GCM
) return STATUS_NOT_SUPPORTED
;
554 *ret_size
= sizeof(*tag_length
);
555 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
558 tag_length
->dwMinLength
= 12;
559 tag_length
->dwMaxLength
= 16;
560 tag_length
->dwIncrement
= 1;
562 return STATUS_SUCCESS
;
565 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
566 return STATUS_NOT_IMPLEMENTED
;
569 static NTSTATUS
get_rsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
571 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
))
573 *ret_size
= sizeof(ULONG
);
574 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
575 if (buf
) *(ULONG
*)buf
= BCRYPT_SUPPORTED_PAD_PKCS1_SIG
;
576 return STATUS_SUCCESS
;
579 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
580 return STATUS_NOT_IMPLEMENTED
;
583 static NTSTATUS
get_dsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
585 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
)) return STATUS_NOT_SUPPORTED
;
586 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
587 return STATUS_NOT_IMPLEMENTED
;
590 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
,
591 UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
595 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
596 if (status
!= STATUS_NOT_IMPLEMENTED
)
602 return get_3des_property( alg
->mode
, prop
, buf
, size
, ret_size
);
605 return get_aes_property( alg
->mode
, prop
, buf
, size
, ret_size
);
608 return get_rsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
611 return get_dsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
617 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop
), alg
->id
);
618 return STATUS_NOT_IMPLEMENTED
;
621 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
626 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
628 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
630 alg
->mode
= MODE_ID_CBC
;
631 return STATUS_SUCCESS
;
635 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
636 return STATUS_NOT_SUPPORTED
;
639 FIXME( "unsupported 3des algorithm property %s\n", debugstr_w(prop
) );
640 return STATUS_NOT_IMPLEMENTED
;
643 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
645 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
647 alg
->mode
= MODE_ID_ECB
;
648 return STATUS_SUCCESS
;
650 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
652 alg
->mode
= MODE_ID_CBC
;
653 return STATUS_SUCCESS
;
655 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
657 alg
->mode
= MODE_ID_GCM
;
658 return STATUS_SUCCESS
;
662 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
663 return STATUS_NOT_IMPLEMENTED
;
666 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
667 return STATUS_NOT_IMPLEMENTED
;
670 FIXME( "unsupported algorithm %u\n", alg
->id
);
671 return STATUS_NOT_IMPLEMENTED
;
675 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
677 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
679 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
681 key
->u
.s
.mode
= MODE_ID_ECB
;
682 return STATUS_SUCCESS
;
684 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
686 key
->u
.s
.mode
= MODE_ID_CBC
;
687 return STATUS_SUCCESS
;
689 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
691 key
->u
.s
.mode
= MODE_ID_GCM
;
692 return STATUS_SUCCESS
;
696 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
697 return STATUS_NOT_IMPLEMENTED
;
701 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
702 return STATUS_NOT_IMPLEMENTED
;
705 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
709 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
710 if (status
== STATUS_NOT_IMPLEMENTED
)
711 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
715 static NTSTATUS
get_key_property( const struct key
*key
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
720 return get_3des_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
723 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
)) return STATUS_NOT_SUPPORTED
;
724 return get_aes_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
727 FIXME( "unsupported algorithm %u\n", key
->alg_id
);
728 return STATUS_NOT_IMPLEMENTED
;
732 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, LPCWSTR prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
, ULONG flags
)
734 struct object
*object
= handle
;
736 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
738 if (!object
) return STATUS_INVALID_HANDLE
;
739 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
741 switch (object
->magic
)
745 const struct algorithm
*alg
= (const struct algorithm
*)object
;
746 return get_alg_property( alg
, prop
, buffer
, count
, res
);
750 const struct key
*key
= (const struct key
*)object
;
751 return get_key_property( key
, prop
, buffer
, count
, res
);
755 const struct hash
*hash
= (const struct hash
*)object
;
756 return get_hash_property( hash
, prop
, buffer
, count
, res
);
759 WARN( "unknown magic %08x\n", object
->magic
);
760 return STATUS_INVALID_HANDLE
;
764 static NTSTATUS
hash_prepare( struct hash
*hash
)
766 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
770 /* initialize hash */
771 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) return status
;
772 if (!(hash
->flags
& HASH_FLAG_HMAC
)) return STATUS_SUCCESS
;
774 /* initialize hmac */
775 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) return status
;
776 block_bytes
= builtin_algorithms
[hash
->alg_id
].block_bits
/ 8;
777 if (hash
->secret_len
> block_bytes
)
779 struct hash_impl temp
;
780 if ((status
= hash_init( &temp
, hash
->alg_id
))) return status
;
781 if ((status
= hash_update( &temp
, hash
->alg_id
, hash
->secret
, hash
->secret_len
))) return status
;
782 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
783 builtin_algorithms
[hash
->alg_id
].hash_length
))) return status
;
785 else memcpy( buffer
, hash
->secret
, hash
->secret_len
);
787 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
788 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) return status
;
789 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
790 return hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
793 static NTSTATUS
hash_create( const struct algorithm
*alg
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
,
794 struct hash
**ret_hash
)
799 if (!(hash
= calloc( 1, sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
800 hash
->hdr
.magic
= MAGIC_HASH
;
801 hash
->alg_id
= alg
->id
;
802 if (alg
->flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
) hash
->flags
= HASH_FLAG_HMAC
;
803 if ((alg
->flags
& BCRYPT_HASH_REUSABLE_FLAG
) || (flags
& BCRYPT_HASH_REUSABLE_FLAG
))
804 hash
->flags
|= HASH_FLAG_REUSABLE
;
806 if (secret_len
&& !(hash
->secret
= malloc( secret_len
)))
809 return STATUS_NO_MEMORY
;
811 memcpy( hash
->secret
, secret
, secret_len
);
812 hash
->secret_len
= secret_len
;
814 if ((status
= hash_prepare( hash
)))
816 free( hash
->secret
);
822 return STATUS_SUCCESS
;
825 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_HASH_HANDLE
*handle
, UCHAR
*object
,
826 ULONG object_len
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
)
828 struct algorithm
*alg
= algorithm
;
832 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm
, handle
, object
, object_len
,
833 secret
, secret_len
, flags
);
834 if (flags
& ~BCRYPT_HASH_REUSABLE_FLAG
)
836 FIXME( "unimplemented flags %08x\n", flags
);
837 return STATUS_NOT_IMPLEMENTED
;
840 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
841 if (object
) FIXME( "ignoring object buffer\n" );
843 if ((status
= hash_create( alg
, secret
, secret_len
, flags
, &hash
))) return status
;
845 return STATUS_SUCCESS
;
848 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
849 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
851 struct hash
*hash_orig
= handle
;
852 struct hash
*hash_copy
;
854 TRACE( "%p, %p, %p, %u, %u\n", handle
, handle_copy
, object
, objectlen
, flags
);
856 if (!hash_orig
|| hash_orig
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
857 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
858 if (object
) FIXME( "ignoring object buffer\n" );
860 if (!(hash_copy
= malloc( sizeof(*hash_copy
) ))) return STATUS_NO_MEMORY
;
862 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
863 if (hash_orig
->secret
&& !(hash_copy
->secret
= malloc( hash_orig
->secret_len
)))
866 return STATUS_NO_MEMORY
;
868 memcpy( hash_copy
->secret
, hash_orig
->secret
, hash_orig
->secret_len
);
870 *handle_copy
= hash_copy
;
871 return STATUS_SUCCESS
;
874 static void hash_destroy( struct hash
*hash
)
878 free( hash
->secret
);
882 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
884 struct hash
*hash
= handle
;
886 TRACE( "%p\n", handle
);
888 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_PARAMETER
;
889 hash_destroy( hash
);
890 return STATUS_SUCCESS
;
893 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
895 struct hash
*hash
= handle
;
897 TRACE( "%p, %p, %u, %08x\n", handle
, input
, size
, flags
);
899 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
900 if (!input
) return STATUS_SUCCESS
;
902 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
905 static NTSTATUS
hash_finalize( struct hash
*hash
, UCHAR
*output
, ULONG size
)
907 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
911 if (!(hash
->flags
& HASH_FLAG_HMAC
))
913 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
))) return status
;
914 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
915 return STATUS_SUCCESS
;
918 hash_length
= builtin_algorithms
[hash
->alg_id
].hash_length
;
919 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
920 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
921 if ((status
= hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
))) return status
;
923 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
924 return STATUS_SUCCESS
;
927 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
929 struct hash
*hash
= handle
;
931 TRACE( "%p, %p, %u, %08x\n", handle
, output
, size
, flags
);
933 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
934 if (!output
) return STATUS_INVALID_PARAMETER
;
936 return hash_finalize( hash
, output
, size
);
939 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE algorithm
, UCHAR
*secret
, ULONG secret_len
,
940 UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
942 struct algorithm
*alg
= algorithm
;
946 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm
, secret
, secret_len
, input
, input_len
, output
, output_len
);
948 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
950 if ((status
= hash_create( alg
, secret
, secret_len
, 0, &hash
))) return status
;
951 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, input
, input_len
)))
953 hash_destroy( hash
);
956 status
= hash_finalize( hash
, output
, output_len
);
957 hash_destroy( hash
);
961 static NTSTATUS
key_asymmetric_create( struct key
**ret_key
, struct algorithm
*alg
, ULONG bitlen
,
962 const UCHAR
*pubkey
, ULONG pubkey_len
)
968 ERR( "no encryption support\n" );
969 return STATUS_NOT_IMPLEMENTED
;
972 if (!(key
= calloc( 1, sizeof(*key
) ))) return STATUS_NO_MEMORY
;
973 key
->hdr
.magic
= MAGIC_KEY
;
974 key
->alg_id
= alg
->id
;
975 key
->u
.a
.bitlen
= bitlen
;
976 key
->u
.a
.pubkey_len
= pubkey_len
;
978 if (!(key
->u
.a
.pubkey
= malloc( pubkey_len
)))
981 return STATUS_NO_MEMORY
;
983 if (pubkey
) memcpy( key
->u
.a
.pubkey
, pubkey
, pubkey_len
);
986 return STATUS_SUCCESS
;
989 static BOOL
key_is_symmetric( struct key
*key
)
991 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_CIPHER_INTERFACE
;
994 static BOOL
is_zero_vector( const UCHAR
*vector
, ULONG len
)
997 if (!vector
) return FALSE
;
998 for (i
= 0; i
< len
; i
++) if (vector
[i
]) return FALSE
;
1002 static BOOL
is_equal_vector( const UCHAR
*vector
, ULONG len
, const UCHAR
*vector2
, ULONG len2
)
1004 if (!vector
&& !vector2
) return TRUE
;
1005 if (len
!= len2
) return FALSE
;
1006 return !memcmp( vector
, vector2
, len
);
1009 static NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
)
1011 BOOL needs_reset
= (!is_zero_vector( vector
, vector_len
) ||
1012 !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
));
1014 free( key
->u
.s
.vector
);
1015 key
->u
.s
.vector
= NULL
;
1016 key
->u
.s
.vector_len
= 0;
1019 if (!(key
->u
.s
.vector
= malloc( vector_len
))) return STATUS_NO_MEMORY
;
1020 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
1021 key
->u
.s
.vector_len
= vector_len
;
1023 if (needs_reset
) UNIX_CALL( key_symmetric_vector_reset
, key
);
1024 return STATUS_SUCCESS
;
1027 static NTSTATUS
key_import( BCRYPT_ALG_HANDLE algorithm
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
1028 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
1032 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1034 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
1036 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
)) return STATUS_BUFFER_TOO_SMALL
;
1037 if (header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
) return STATUS_INVALID_PARAMETER
;
1038 if (header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
1040 FIXME( "unknown key data blob version %u\n", header
->dwVersion
);
1041 return STATUS_INVALID_PARAMETER
;
1043 len
= header
->cbKeyData
;
1044 if (len
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
) return STATUS_INVALID_PARAMETER
;
1046 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, (UCHAR
*)&header
[1], len
, 0 );
1048 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1050 if (input_len
< sizeof(len
)) return STATUS_BUFFER_TOO_SMALL
;
1051 len
= *(ULONG
*)input
;
1052 if (len
+ sizeof(len
) > input_len
) return STATUS_INVALID_PARAMETER
;
1054 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, input
+ sizeof(len
), len
, 0 );
1057 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1058 return STATUS_NOT_IMPLEMENTED
;
1061 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1063 struct key_export_params params
;
1065 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1067 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
1068 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
1071 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1074 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
1075 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
1076 header
->cbKeyData
= key
->u
.s
.secret_len
;
1077 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1079 return STATUS_SUCCESS
;
1081 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1083 ULONG len
, req_size
= sizeof(len
) + key
->u
.s
.secret_len
;
1086 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1089 *(ULONG
*)output
= key
->u
.s
.secret_len
;
1090 memcpy( output
+ sizeof(len
), key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1092 return STATUS_SUCCESS
;
1094 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
) || !wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
) ||
1095 !wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
))
1097 *size
= key
->u
.a
.pubkey_len
;
1098 if (output_len
< key
->u
.a
.pubkey_len
) return STATUS_SUCCESS
;
1099 if (output
) memcpy( output
, key
->u
.a
.pubkey
, key
->u
.a
.pubkey_len
);
1100 return STATUS_SUCCESS
;
1102 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1105 params
.buf
= output
;
1106 params
.len
= output_len
;
1107 params
.ret_len
= size
;
1108 params
.full
= wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
);
1109 return UNIX_CALL( key_export_rsa
, ¶ms
);
1111 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1114 params
.buf
= output
;
1115 params
.len
= output_len
;
1116 params
.ret_len
= size
;
1117 return UNIX_CALL( key_export_ecc
, ¶ms
);
1119 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1122 params
.buf
= output
;
1123 params
.len
= output_len
;
1124 params
.ret_len
= size
;
1125 return UNIX_CALL( key_export_dsa_capi
, ¶ms
);
1128 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1129 return STATUS_NOT_IMPLEMENTED
;
1132 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1133 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1135 struct key_symmetric_set_auth_data_params auth_params
;
1136 struct key_symmetric_encrypt_params encrypt_params
;
1137 struct key_symmetric_get_tag_params tag_params
;
1138 ULONG bytes_left
= input_len
;
1142 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1144 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1146 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1147 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1148 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1149 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1150 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1151 FIXME( "call chaining not implemented\n" );
1153 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1156 *ret_len
= input_len
;
1157 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1158 if (input
&& !output
) return STATUS_SUCCESS
;
1159 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1161 auth_params
.key
= key
;
1162 auth_params
.auth_data
= auth_info
->pbAuthData
;
1163 auth_params
.len
= auth_info
->cbAuthData
;
1164 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1166 encrypt_params
.key
= key
;
1167 encrypt_params
.input
= input
;
1168 encrypt_params
.input_len
= input_len
;
1169 encrypt_params
.output
= output
;
1170 encrypt_params
.output_len
= output_len
;
1171 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
))) return status
;
1173 tag_params
.key
= key
;
1174 tag_params
.tag
= auth_info
->pbTag
;
1175 tag_params
.len
= auth_info
->cbTag
;
1176 return UNIX_CALL( key_symmetric_get_tag
, &tag_params
);
1179 *ret_len
= input_len
;
1181 if (flags
& BCRYPT_BLOCK_PADDING
)
1182 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1183 else if (input_len
& (key
->u
.s
.block_size
- 1))
1184 return STATUS_INVALID_BUFFER_SIZE
;
1186 if (!output
) return STATUS_SUCCESS
;
1187 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1188 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1189 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1191 encrypt_params
.key
= key
;
1192 encrypt_params
.input
= input
;
1193 encrypt_params
.input_len
= key
->u
.s
.block_size
;
1194 encrypt_params
.output
= output
;
1195 encrypt_params
.output_len
= key
->u
.s
.block_size
;
1196 while (bytes_left
>= key
->u
.s
.block_size
)
1198 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
)))
1200 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 )))
1202 bytes_left
-= key
->u
.s
.block_size
;
1203 encrypt_params
.input
+= key
->u
.s
.block_size
;
1204 encrypt_params
.output
+= key
->u
.s
.block_size
;
1207 if (flags
& BCRYPT_BLOCK_PADDING
)
1209 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1210 memcpy( buf
, encrypt_params
.input
, bytes_left
);
1211 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1212 encrypt_params
.input
= buf
;
1213 status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
);
1220 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1221 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1223 struct key_symmetric_set_auth_data_params auth_params
;
1224 struct key_symmetric_decrypt_params decrypt_params
;
1225 struct key_symmetric_get_tag_params tag_params
;
1226 ULONG bytes_left
= input_len
;
1229 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1231 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1234 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1235 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1236 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1237 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1239 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1242 *ret_len
= input_len
;
1243 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1244 if (!output
) return STATUS_SUCCESS
;
1245 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1247 auth_params
.key
= key
;
1248 auth_params
.auth_data
= auth_info
->pbAuthData
;
1249 auth_params
.len
= auth_info
->cbAuthData
;
1250 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1252 decrypt_params
.key
= key
;
1253 decrypt_params
.input
= input
;
1254 decrypt_params
.input_len
= input_len
;
1255 decrypt_params
.output
= output
;
1256 decrypt_params
.output_len
= output_len
;
1257 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1259 tag_params
.key
= key
;
1260 tag_params
.tag
= tag
;
1261 tag_params
.len
= sizeof(tag
);
1262 if ((status
= UNIX_CALL( key_symmetric_get_tag
, &tag_params
))) return status
;
1263 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1265 return STATUS_SUCCESS
;
1268 *ret_len
= input_len
;
1270 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1271 if (!output
) return STATUS_SUCCESS
;
1272 if (flags
& BCRYPT_BLOCK_PADDING
)
1274 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1275 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1276 bytes_left
-= key
->u
.s
.block_size
;
1278 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1280 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1281 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1283 decrypt_params
.key
= key
;
1284 decrypt_params
.input
= input
;
1285 decrypt_params
.input_len
= key
->u
.s
.block_size
;
1286 decrypt_params
.output
= output
;
1287 decrypt_params
.output_len
= key
->u
.s
.block_size
;
1288 while (bytes_left
>= key
->u
.s
.block_size
)
1290 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1291 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 )))
1293 bytes_left
-= key
->u
.s
.block_size
;
1294 decrypt_params
.input
+= key
->u
.s
.block_size
;
1295 decrypt_params
.output
+= key
->u
.s
.block_size
;
1298 if (flags
& BCRYPT_BLOCK_PADDING
)
1300 UCHAR
*buf
, *dst
= decrypt_params
.output
;
1301 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1302 decrypt_params
.output
= buf
;
1303 status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
);
1304 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1306 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1307 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1308 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1310 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1317 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1320 struct key_import_params params
;
1325 if (!wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
))
1327 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1328 DWORD key_size
, magic
;
1330 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1334 case ALG_ID_ECDH_P256
:
1336 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
1339 case ALG_ID_ECDSA_P256
:
1341 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
1344 case ALG_ID_ECDSA_P384
:
1346 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
1350 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1351 return STATUS_NOT_SUPPORTED
;
1354 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1355 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2)
1356 return STATUS_INVALID_PARAMETER
;
1358 size
= sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2;
1359 return key_asymmetric_create( (struct key
**)ret_key
, alg
, key_size
* 8, (BYTE
*)ecc_blob
, size
);
1361 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1363 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1364 DWORD key_size
, magic
;
1366 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1370 case ALG_ID_ECDH_P256
:
1372 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
1374 case ALG_ID_ECDSA_P256
:
1376 magic
= BCRYPT_ECDSA_PRIVATE_P256_MAGIC
;
1380 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1381 return STATUS_NOT_SUPPORTED
;
1384 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1385 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 3)
1386 return STATUS_INVALID_PARAMETER
;
1388 size
= sizeof(*ecc_blob
) + key_size
* 2;
1389 if ((status
= key_asymmetric_create( &key
, alg
, key_size
* 8, NULL
, size
))) return status
;
1393 params
.len
= input_len
;
1394 if ((status
= UNIX_CALL( key_import_ecc
, ¶ms
)))
1396 BCryptDestroyKey( key
);
1401 return STATUS_SUCCESS
;
1403 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1405 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1407 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1408 if ((alg
->id
!= ALG_ID_RSA
&& alg
->id
!= ALG_ID_RSA_SIGN
) || rsa_blob
->Magic
!= BCRYPT_RSAPUBLIC_MAGIC
)
1409 return STATUS_NOT_SUPPORTED
;
1411 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1412 return key_asymmetric_create( (struct key
**)ret_key
, alg
, rsa_blob
->BitLength
, (BYTE
*)rsa_blob
, size
);
1414 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1416 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1418 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1419 if (alg
->id
!= ALG_ID_RSA
|| (rsa_blob
->Magic
!= BCRYPT_RSAPRIVATE_MAGIC
&&
1420 rsa_blob
->Magic
!= BCRYPT_RSAFULLPRIVATE_MAGIC
)) return STATUS_NOT_SUPPORTED
;
1422 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1423 if ((status
= key_asymmetric_create( &key
, alg
, rsa_blob
->BitLength
, (BYTE
*)rsa_blob
, size
)))
1427 params
.len
= input_len
;
1428 if ((status
= UNIX_CALL( key_import_rsa
, ¶ms
)))
1430 BCryptDestroyKey( key
);
1435 return STATUS_SUCCESS
;
1437 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
))
1439 BCRYPT_DSA_KEY_BLOB
*dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)input
;
1441 if (input_len
< sizeof(*dsa_blob
)) return STATUS_INVALID_PARAMETER
;
1442 if ((alg
->id
!= ALG_ID_DSA
) || dsa_blob
->dwMagic
!= BCRYPT_DSA_PUBLIC_MAGIC
)
1443 return STATUS_NOT_SUPPORTED
;
1445 size
= sizeof(*dsa_blob
) + dsa_blob
->cbKey
* 3;
1446 return key_asymmetric_create( (struct key
**)ret_key
, alg
, dsa_blob
->cbKey
* 8, (BYTE
*)dsa_blob
, size
);
1448 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1450 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1453 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1455 if (hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1457 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1458 return STATUS_NOT_SUPPORTED
;
1460 if (alg
->id
!= ALG_ID_DSA
)
1462 FIXME( "algorithm %u does not support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1463 return STATUS_NOT_SUPPORTED
;
1466 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1467 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1468 if (pubkey
->magic
!= MAGIC_DSS2
) return STATUS_NOT_SUPPORTED
;
1470 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 2 + 40 + sizeof(DSSSEED
))
1471 return STATUS_INVALID_PARAMETER
;
1473 size
= sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 3 + 20 + sizeof(DSSSEED
);
1474 if ((status
= key_asymmetric_create( &key
, alg
, pubkey
->bitlen
, NULL
, size
))) return status
;
1478 params
.len
= input_len
;
1479 if ((status
= UNIX_CALL( key_import_dsa_capi
, ¶ms
)))
1481 BCryptDestroyKey( key
);
1486 return STATUS_SUCCESS
;
1488 else if (!wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
)) /* not supported on native */
1490 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1493 if (alg
->id
!= ALG_ID_DSA
) return STATUS_NOT_SUPPORTED
;
1494 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1496 if (hdr
->bType
!= PUBLICKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1498 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1499 return STATUS_NOT_SUPPORTED
;
1502 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1503 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1504 if (pubkey
->magic
!= MAGIC_DSS1
) return STATUS_NOT_SUPPORTED
;
1506 size
= sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 3 + 20 + sizeof(DSSSEED
);
1507 if (input_len
< size
) return STATUS_INVALID_PARAMETER
;
1509 if ((status
= key_asymmetric_create( &key
, alg
, pubkey
->bitlen
, (BYTE
*)hdr
, size
))) return status
;
1510 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1513 return STATUS_SUCCESS
;
1516 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1517 return STATUS_NOT_SUPPORTED
;
1520 static ULONG
get_block_size( struct algorithm
*alg
)
1522 ULONG ret
= 0, size
= sizeof(ret
);
1523 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
1527 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1528 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1531 BCRYPT_KEY_LENGTHS_STRUCT key_lengths
;
1532 struct algorithm
*alg
= algorithm
;
1533 ULONG block_size
, size
;
1536 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
1538 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1539 if (object
) FIXME( "ignoring object buffer\n" );
1543 ERR( "no encryption support\n" );
1544 return STATUS_NOT_IMPLEMENTED
;
1547 if (!(block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1549 if (!get_alg_property( alg
, BCRYPT_KEY_LENGTHS
, (UCHAR
*)&key_lengths
, sizeof(key_lengths
), &size
))
1551 if (secret_len
> (size
= key_lengths
.dwMaxLength
/ 8))
1553 WARN( "secret_len %u exceeds key max length %u, setting to maximum.\n", secret_len
, size
);
1556 else if (secret_len
< (size
= key_lengths
.dwMinLength
/ 8))
1558 WARN( "secret_len %u is less than minimum key length %u.\n", secret_len
, size
);
1559 return STATUS_INVALID_PARAMETER
;
1561 else if (key_lengths
.dwIncrement
&& (secret_len
* 8 - key_lengths
.dwMinLength
) % key_lengths
.dwIncrement
)
1563 WARN( "secret_len %u is not a valid key length.\n", secret_len
);
1564 return STATUS_INVALID_PARAMETER
;
1568 if (!(key
= calloc( 1, sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1569 InitializeCriticalSection( &key
->u
.s
.cs
);
1570 key
->hdr
.magic
= MAGIC_KEY
;
1571 key
->alg_id
= alg
->id
;
1572 key
->u
.s
.mode
= alg
->mode
;
1573 key
->u
.s
.block_size
= block_size
;
1575 if (!(key
->u
.s
.secret
= malloc( secret_len
)))
1578 return STATUS_NO_MEMORY
;
1580 memcpy( key
->u
.s
.secret
, secret
, secret_len
);
1581 key
->u
.s
.secret_len
= secret_len
;
1584 return STATUS_SUCCESS
;
1587 NTSTATUS WINAPI
BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
, ULONG key_len
,
1590 struct algorithm
*alg
= algorithm
;
1595 TRACE( "%p, %p, %u, %08x\n", algorithm
, handle
, key_len
, flags
);
1597 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1598 if (!handle
) return STATUS_INVALID_PARAMETER
;
1602 case ALG_ID_ECDH_P256
:
1603 case ALG_ID_ECDSA_P256
:
1604 size
= sizeof(BCRYPT_ECCKEY_BLOB
) + 2 * 256 / 8;
1606 case ALG_ID_ECDSA_P384
:
1607 size
= sizeof(BCRYPT_ECCKEY_BLOB
) + 2 * 384 / 8;
1610 case ALG_ID_RSA_SIGN
:
1611 size
= sizeof(BCRYPT_RSAKEY_BLOB
) + 2 * key_len
/ 8;
1614 size
= sizeof(BCRYPT_DSA_KEY_BLOB
) + 3 * key_len
/ 8;
1617 FIXME( "algorithm %u not supported\n", alg
->id
);
1618 return STATUS_NOT_SUPPORTED
;
1621 if (!(status
= key_asymmetric_create( &key
, alg
, key_len
, NULL
, size
))) *handle
= key
;
1625 NTSTATUS WINAPI
BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle
, ULONG flags
)
1627 struct key
*key
= handle
;
1629 TRACE( "%p, %08x\n", key
, flags
);
1630 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1632 return UNIX_CALL( key_asymmetric_generate
, key
);
1635 NTSTATUS WINAPI
BCryptImportKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, LPCWSTR type
,
1636 BCRYPT_KEY_HANDLE
*key
, PUCHAR object
, ULONG object_len
, PUCHAR input
,
1637 ULONG input_len
, ULONG flags
)
1639 struct algorithm
*alg
= algorithm
;
1641 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm
, decrypt_key
, debugstr_w(type
), key
, object
,
1642 object_len
, input
, input_len
, flags
);
1644 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1645 if (!key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1649 FIXME( "decryption of key not yet supported\n" );
1650 return STATUS_NOT_IMPLEMENTED
;
1653 return key_import( algorithm
, type
, key
, object
, object_len
, input
, input_len
);
1656 NTSTATUS WINAPI
BCryptExportKey( BCRYPT_KEY_HANDLE export_key
, BCRYPT_KEY_HANDLE encrypt_key
, LPCWSTR type
,
1657 PUCHAR output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1659 struct key
*key
= export_key
;
1661 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key
, encrypt_key
, debugstr_w(type
), output
, output_len
, size
, flags
);
1663 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1664 if (!type
|| !size
) return STATUS_INVALID_PARAMETER
;
1668 FIXME( "encryption of key not yet supported\n" );
1669 return STATUS_NOT_IMPLEMENTED
;
1672 return key_export( key
, type
, output
, output_len
, size
);
1675 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
1680 memset( key_copy
, 0, sizeof(*key_copy
) );
1681 key_copy
->hdr
= key_orig
->hdr
;
1682 key_copy
->alg_id
= key_orig
->alg_id
;
1684 if (key_is_symmetric( key_orig
))
1686 if (!(buffer
= malloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
1687 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
1689 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
1690 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
1691 key_copy
->u
.s
.secret
= buffer
;
1692 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
1693 InitializeCriticalSection( &key_copy
->u
.s
.cs
);
1697 struct key_asymmetric_duplicate_params params
;
1699 if (!(buffer
= malloc( key_orig
->u
.a
.pubkey_len
))) return STATUS_NO_MEMORY
;
1700 memcpy( buffer
, key_orig
->u
.a
.pubkey
, key_orig
->u
.a
.pubkey_len
);
1702 key_copy
->u
.a
.bitlen
= key_orig
->u
.a
.bitlen
;
1703 key_copy
->u
.a
.flags
= key_orig
->u
.a
.flags
;
1704 key_copy
->u
.a
.pubkey
= buffer
;
1705 key_copy
->u
.a
.pubkey_len
= key_orig
->u
.a
.pubkey_len
;
1706 key_copy
->u
.a
.dss_seed
= key_orig
->u
.a
.dss_seed
;
1708 params
.key_orig
= key_orig
;
1709 params
.key_copy
= key_copy
;
1710 if ((status
= UNIX_CALL( key_asymmetric_duplicate
, ¶ms
))) return status
;
1713 return STATUS_SUCCESS
;
1716 static void key_destroy( struct key
*key
)
1718 if (key_is_symmetric( key
))
1720 UNIX_CALL( key_symmetric_destroy
, key
);
1721 free( key
->u
.s
.vector
);
1722 free( key
->u
.s
.secret
);
1723 DeleteCriticalSection( &key
->u
.s
.cs
);
1727 UNIX_CALL( key_asymmetric_destroy
, key
);
1728 free( key
->u
.a
.pubkey
);
1734 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
1735 UCHAR
*object
, ULONG object_len
, ULONG flags
)
1737 struct key
*key_orig
= handle
;
1738 struct key
*key_copy
;
1741 TRACE( "%p, %p, %p, %u, %08x\n", handle
, handle_copy
, object
, object_len
, flags
);
1742 if (object
) FIXME( "ignoring object buffer\n" );
1744 if (!key_orig
|| key_orig
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1745 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1746 if (!(key_copy
= malloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
1748 if ((status
= key_duplicate( key_orig
, key_copy
)))
1750 key_destroy( key_copy
);
1754 *handle_copy
= key_copy
;
1755 return STATUS_SUCCESS
;
1758 NTSTATUS WINAPI
BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1759 BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
, ULONG input_len
, ULONG flags
)
1761 struct algorithm
*alg
= algorithm
;
1763 TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm
, decrypt_key
, debugstr_w(type
), ret_key
, input
,
1766 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1767 if (!ret_key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1770 FIXME( "decryption of key not yet supported\n" );
1771 return STATUS_NOT_IMPLEMENTED
;
1774 return key_import_pair( alg
, type
, ret_key
, input
, input_len
);
1777 NTSTATUS WINAPI
BCryptSignHash( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*input
, ULONG input_len
,
1778 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1780 struct key_asymmetric_sign_params params
;
1781 struct key
*key
= handle
;
1783 TRACE( "%p, %p, %p, %u, %p, %u, %p, %08x\n", handle
, padding
, input
, input_len
, output
, output_len
,
1786 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1787 if (key_is_symmetric( key
))
1789 FIXME( "signing with symmetric keys not yet supported\n" );
1790 return STATUS_NOT_IMPLEMENTED
;
1794 params
.padding
= padding
;
1795 params
.input
= input
;
1796 params
.input_len
= input_len
;
1797 params
.output
= output
;
1798 params
.output_len
= output_len
;
1799 params
.ret_len
= ret_len
;
1800 params
.flags
= flags
;
1801 return UNIX_CALL( key_asymmetric_sign
, ¶ms
);
1804 NTSTATUS WINAPI
BCryptVerifySignature( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*hash
, ULONG hash_len
,
1805 UCHAR
*signature
, ULONG signature_len
, ULONG flags
)
1807 struct key_asymmetric_verify_params params
;
1808 struct key
*key
= handle
;
1810 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
1812 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1813 if (!hash
|| !hash_len
|| !signature
|| !signature_len
) return STATUS_INVALID_PARAMETER
;
1814 if (key_is_symmetric( key
)) return STATUS_NOT_SUPPORTED
;
1817 params
.padding
= padding
;
1819 params
.hash_len
= hash_len
;
1820 params
.signature
= signature
;
1821 params
.signature_len
= signature_len
;
1822 params
.flags
= flags
;
1823 return UNIX_CALL( key_asymmetric_verify
, ¶ms
);
1826 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
1828 struct key
*key
= handle
;
1830 TRACE( "%p\n", handle
);
1832 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1835 return STATUS_SUCCESS
;
1838 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1839 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1841 struct key
*key
= handle
;
1844 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1845 output_len
, ret_len
, flags
);
1847 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1848 if (!key_is_symmetric( key
))
1850 FIXME( "encryption with asymmetric keys not yet supported\n" );
1851 return STATUS_NOT_IMPLEMENTED
;
1853 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1855 FIXME( "flags %08x not implemented\n", flags
);
1856 return STATUS_NOT_IMPLEMENTED
;
1859 EnterCriticalSection( &key
->u
.s
.cs
);
1860 ret
= key_symmetric_encrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1861 LeaveCriticalSection( &key
->u
.s
.cs
);
1865 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1866 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1868 struct key_asymmetric_decrypt_params params
;
1869 struct key
*key
= handle
;
1871 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1872 output_len
, ret_len
, flags
);
1874 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1875 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1877 FIXME( "flags %08x not supported\n", flags
);
1878 return STATUS_NOT_IMPLEMENTED
;
1881 if (key_is_symmetric( key
))
1884 EnterCriticalSection( &key
->u
.s
.cs
);
1885 ret
= key_symmetric_decrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1886 LeaveCriticalSection( &key
->u
.s
.cs
);
1891 params
.input
= input
;
1892 params
.input_len
= input_len
;
1893 params
.output
= output
;
1894 params
.output_len
= output_len
;
1895 params
.ret_len
= ret_len
;
1896 return UNIX_CALL( key_asymmetric_decrypt
, ¶ms
);
1899 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1901 struct object
*object
= handle
;
1903 TRACE( "%p, %s, %p, %u, %08x\n", handle
, debugstr_w(prop
), value
, size
, flags
);
1905 if (!object
) return STATUS_INVALID_HANDLE
;
1907 switch (object
->magic
)
1911 struct algorithm
*alg
= (struct algorithm
*)object
;
1912 return set_alg_property( alg
, prop
, value
, size
, flags
);
1916 struct key
*key
= (struct key
*)object
;
1917 return set_key_property( key
, prop
, value
, size
, flags
);
1920 WARN( "unknown magic %08x\n", object
->magic
);
1921 return STATUS_INVALID_HANDLE
;
1925 #define HMAC_PAD_LEN 64
1926 NTSTATUS WINAPI
BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle
, BCRYPT_ALG_HANDLE halg
, UCHAR
*key
, ULONG keylen
, ULONG flags
)
1928 struct hash
*hash
= handle
;
1929 UCHAR buf
[MAX_HASH_OUTPUT_BYTES
* 2];
1933 TRACE( "%p, %p, %p, %u, %08x\n", handle
, halg
, key
, keylen
, flags
);
1935 if (!key
|| !keylen
) return STATUS_INVALID_PARAMETER
;
1936 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
1937 if (keylen
> builtin_algorithms
[hash
->alg_id
].hash_length
* 2) return STATUS_INVALID_PARAMETER
;
1941 FIXME( "algorithm handle not supported\n" );
1942 return STATUS_NOT_IMPLEMENTED
;
1945 len
= builtin_algorithms
[hash
->alg_id
].hash_length
;
1946 if ((status
= hash_finalize( hash
, buf
, len
))) return status
;
1950 UCHAR pad1
[HMAC_PAD_LEN
], pad2
[HMAC_PAD_LEN
];
1953 for (i
= 0; i
< sizeof(pad1
); i
++)
1955 pad1
[i
] = 0x36 ^ (i
< len
? buf
[i
] : 0);
1956 pad2
[i
] = 0x5c ^ (i
< len
? buf
[i
] : 0);
1959 if ((status
= hash_prepare( hash
)) ||
1960 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad1
, sizeof(pad1
) )) ||
1961 (status
= hash_finalize( hash
, buf
, len
))) return status
;
1963 if ((status
= hash_prepare( hash
)) ||
1964 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad2
, sizeof(pad2
) )) ||
1965 (status
= hash_finalize( hash
, buf
+ len
, len
))) return status
;
1968 memcpy( key
, buf
, keylen
);
1969 return STATUS_SUCCESS
;
1972 static NTSTATUS
pbkdf2( struct hash
*hash
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
1973 ULONGLONG iterations
, ULONG i
, UCHAR
*dst
, ULONG hash_len
)
1975 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
1976 UCHAR bytes
[4], *buf
;
1979 if (!(buf
= malloc( hash_len
))) return STATUS_NO_MEMORY
;
1981 for (j
= 0; j
< iterations
; j
++)
1985 /* use salt || INT(i) */
1986 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, salt
, salt_len
)))
1991 bytes
[0] = (i
>> 24) & 0xff;
1992 bytes
[1] = (i
>> 16) & 0xff;
1993 bytes
[2] = (i
>> 8) & 0xff;
1994 bytes
[3] = i
& 0xff;
1995 status
= hash_update( &hash
->inner
, hash
->alg_id
, bytes
, 4 );
1997 else status
= hash_update( &hash
->inner
, hash
->alg_id
, buf
, hash_len
); /* use U_j */
2005 if ((status
= hash_finalize( hash
, buf
, hash_len
)))
2011 if (j
== 0) memcpy( dst
, buf
, hash_len
);
2012 else for (k
= 0; k
< hash_len
; k
++) dst
[k
] ^= buf
[k
];
2019 NTSTATUS WINAPI
BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2020 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
, ULONG flags
)
2022 struct algorithm
*alg
= handle
;
2023 ULONG hash_len
, block_count
, bytes_left
, i
;
2028 TRACE( "%p, %p, %u, %p, %u, %s, %p, %u, %08x\n", handle
, pwd
, pwd_len
, salt
, salt_len
,
2029 wine_dbgstr_longlong(iterations
), dk
, dk_len
, flags
);
2031 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
2033 hash_len
= builtin_algorithms
[alg
->id
].hash_length
;
2034 if (dk_len
<= 0 || dk_len
> ((((ULONGLONG
)1) << 32) - 1) * hash_len
) return STATUS_INVALID_PARAMETER
;
2036 block_count
= 1 + ((dk_len
- 1) / hash_len
); /* ceil(dk_len / hash_len) */
2037 bytes_left
= dk_len
- (block_count
- 1) * hash_len
;
2039 if ((status
= hash_create( alg
, pwd
, pwd_len
, BCRYPT_HASH_REUSABLE_FLAG
, &hash
))) return status
;
2042 for (i
= 1; i
< block_count
; i
++)
2044 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, i
, dk
+ ((i
- 1) * hash_len
), hash_len
)))
2046 hash_destroy( hash
);
2051 /* final partial block */
2052 if (!(partial
= malloc( hash_len
)))
2054 hash_destroy( hash
);
2055 return STATUS_NO_MEMORY
;
2058 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, block_count
, partial
, hash_len
)))
2060 hash_destroy( hash
);
2064 memcpy( dk
+ ((block_count
- 1) * hash_len
), partial
, bytes_left
);
2066 hash_destroy( hash
);
2068 return STATUS_SUCCESS
;
2071 NTSTATUS WINAPI
BCryptSecretAgreement(BCRYPT_KEY_HANDLE privatekey
, BCRYPT_KEY_HANDLE publickey
, BCRYPT_SECRET_HANDLE
*handle
, ULONG flags
)
2073 struct key
*privkey
= privatekey
;
2074 struct key
*pubkey
= publickey
;
2075 struct secret
*secret
;
2077 FIXME( "%p, %p, %p, %08x\n", privatekey
, publickey
, handle
, flags
);
2079 if (!privkey
|| privkey
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
2080 if (!pubkey
|| pubkey
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
2081 if (!handle
) return STATUS_INVALID_PARAMETER
;
2083 if (!(secret
= calloc( 1, sizeof(*secret
) ))) return STATUS_NO_MEMORY
;
2084 secret
->hdr
.magic
= MAGIC_SECRET
;
2087 return STATUS_SUCCESS
;
2090 NTSTATUS WINAPI
BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle
)
2092 struct secret
*secret
= handle
;
2094 FIXME( "%p\n", handle
);
2096 if (!secret
|| secret
->hdr
.magic
!= MAGIC_SECRET
) return STATUS_INVALID_HANDLE
;
2097 secret
->hdr
.magic
= 0;
2099 return STATUS_SUCCESS
;
2102 NTSTATUS WINAPI
BCryptDeriveKey(BCRYPT_SECRET_HANDLE handle
, LPCWSTR kdf
, BCryptBufferDesc
*parameter
,
2103 PUCHAR derived
, ULONG derived_size
, ULONG
*result
, ULONG flags
)
2105 struct secret
*secret
= handle
;
2107 FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret
, debugstr_w(kdf
), parameter
, derived
, derived_size
, result
, flags
);
2109 if (!secret
|| secret
->hdr
.magic
!= MAGIC_SECRET
) return STATUS_INVALID_HANDLE
;
2110 if (!kdf
) return STATUS_INVALID_PARAMETER
;
2112 return STATUS_INTERNAL_ERROR
;
2115 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
2119 case DLL_PROCESS_ATTACH
:
2120 DisableThreadLibraryCalls( hinst
);
2121 if (!NtQueryVirtualMemory( GetCurrentProcess(), hinst
, MemoryWineUnixFuncs
,
2122 &bcrypt_handle
, sizeof(bcrypt_handle
), NULL
))
2124 if (UNIX_CALL( process_attach
, NULL
)) bcrypt_handle
= 0;
2127 case DLL_PROCESS_DETACH
:
2128 if (reserved
) break;
2129 if (bcrypt_handle
) UNIX_CALL( process_detach
, NULL
);