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
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
, ULONG pos
)
44 FIXME( "%#lx, %s, %#lx, %s, %lu: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
), pos
);
45 return STATUS_SUCCESS
;
48 NTSTATUS WINAPI
BCryptAddContextFunctionProvider( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
,
49 const WCHAR
*provider
, ULONG pos
)
51 FIXME( "%#lx, %s, %#lx, %s, %s, %lu: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
),
52 debugstr_w(provider
), pos
);
53 return STATUS_SUCCESS
;
56 NTSTATUS WINAPI
BCryptRemoveContextFunction( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
)
58 FIXME( "%#lx, %s, %#lx, %s: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
) );
59 return STATUS_NOT_IMPLEMENTED
;
62 NTSTATUS WINAPI
BCryptRemoveContextFunctionProvider( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
,
63 const WCHAR
*provider
)
65 FIXME( "%#lx, %s, %#lx, %s, %s: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
), debugstr_w(provider
) );
66 return STATUS_NOT_IMPLEMENTED
;
69 NTSTATUS WINAPI
BCryptEnumContextFunctions( ULONG table
, const WCHAR
*ctx
, ULONG iface
, ULONG
*buflen
,
70 CRYPT_CONTEXT_FUNCTIONS
**buffer
)
72 FIXME( "%#lx, %s, %#lx, %p, %p\n", table
, debugstr_w(ctx
), iface
, buflen
, buffer
);
73 return STATUS_NOT_IMPLEMENTED
;
76 void WINAPI
BCryptFreeBuffer( void *buffer
)
81 NTSTATUS WINAPI
BCryptRegisterProvider( const WCHAR
*provider
, ULONG flags
, CRYPT_PROVIDER_REG
*reg
)
83 FIXME( "%s, %#lx, %p: stub\n", debugstr_w(provider
), flags
, reg
);
84 return STATUS_SUCCESS
;
87 NTSTATUS WINAPI
BCryptUnregisterProvider( const WCHAR
*provider
)
89 FIXME( "%s: stub\n", debugstr_w(provider
) );
90 return STATUS_NOT_IMPLEMENTED
;
93 #define MAX_HASH_OUTPUT_BYTES 64
94 #define MAX_HASH_BLOCK_BITS 1024
96 /* ordered by class, keep in sync with enum alg_id */
105 builtin_algorithms
[] =
107 { BCRYPT_3DES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 522, 0, 0 },
108 { BCRYPT_AES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 654, 0, 0 },
109 { BCRYPT_SHA256_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 286, 32, 512 },
110 { BCRYPT_SHA384_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 48, 1024 },
111 { BCRYPT_SHA512_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 64, 1024 },
112 { BCRYPT_SHA1_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 278, 20, 512 },
113 { BCRYPT_MD5_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 274, 16, 512 },
114 { BCRYPT_MD4_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 512 },
115 { BCRYPT_MD2_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 128 },
116 { BCRYPT_RSA_ALGORITHM
, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
, 0, 0, 0 },
117 { BCRYPT_ECDH_P256_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
118 { BCRYPT_RSA_SIGN_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
119 { BCRYPT_ECDSA_P256_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
120 { BCRYPT_ECDSA_P384_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
121 { BCRYPT_DSA_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
122 { BCRYPT_RNG_ALGORITHM
, BCRYPT_RNG_INTERFACE
, 0, 0, 0 },
125 static BOOL
match_operation_type( ULONG type
, ULONG
class )
127 if (!type
) return TRUE
;
130 case BCRYPT_CIPHER_INTERFACE
: return type
& BCRYPT_CIPHER_OPERATION
;
131 case BCRYPT_HASH_INTERFACE
: return type
& BCRYPT_HASH_OPERATION
;
132 case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
: return type
& BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
;
133 case BCRYPT_SECRET_AGREEMENT_INTERFACE
: return type
& BCRYPT_SECRET_AGREEMENT_OPERATION
;
134 case BCRYPT_SIGNATURE_INTERFACE
: return type
& BCRYPT_SIGNATURE_OPERATION
;
135 case BCRYPT_RNG_INTERFACE
: return type
& BCRYPT_RNG_OPERATION
;
141 NTSTATUS WINAPI
BCryptEnumAlgorithms( ULONG type
, ULONG
*ret_count
, BCRYPT_ALGORITHM_IDENTIFIER
**ret_list
, ULONG flags
)
143 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
144 BCRYPT_HASH_OPERATION
|\
145 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
146 BCRYPT_SECRET_AGREEMENT_OPERATION
|\
147 BCRYPT_SIGNATURE_OPERATION
|\
148 BCRYPT_RNG_OPERATION
;
149 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
150 ULONG i
, j
, count
= 0;
152 TRACE( "%#lx, %p, %p, %#lx\n", type
, ret_count
, ret_list
, flags
);
154 if (!ret_count
|| !ret_list
|| (type
& ~supported
)) return STATUS_INVALID_PARAMETER
;
156 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
158 if (match_operation_type( type
, builtin_algorithms
[i
].class )) count
++;
161 if (!(list
= malloc( count
* sizeof(*list
) ))) return STATUS_NO_MEMORY
;
163 for (i
= 0, j
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
165 if (!match_operation_type( type
, builtin_algorithms
[i
].class )) continue;
166 list
[j
].pszName
= (WCHAR
*)builtin_algorithms
[i
].name
;
167 list
[j
].dwClass
= builtin_algorithms
[i
].class;
174 return STATUS_SUCCESS
;
177 NTSTATUS WINAPI
BCryptGenRandom(BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
179 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
180 struct algorithm
*algorithm
= handle
;
182 TRACE("%p, %p, %lu, %#lx - semi-stub\n", handle
, buffer
, count
, flags
);
186 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
187 * is set. In this case the preferred system RNG is used.
189 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
190 return STATUS_INVALID_HANDLE
;
192 else if (algorithm
->hdr
.magic
!= MAGIC_ALG
|| algorithm
->id
!= ALG_ID_RNG
)
193 return STATUS_INVALID_HANDLE
;
196 return STATUS_INVALID_PARAMETER
;
198 if (flags
& ~supported_flags
)
199 FIXME("unsupported flags %#lx\n", flags
& ~supported_flags
);
202 FIXME("ignoring selected algorithm\n");
204 /* When zero bytes are requested the function returns success too. */
206 return STATUS_SUCCESS
;
208 if (algorithm
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
210 if (RtlGenRandom(buffer
, count
))
211 return STATUS_SUCCESS
;
214 FIXME("called with unsupported parameters, returning error\n");
215 return STATUS_NOT_IMPLEMENTED
;
218 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, const WCHAR
*id
, const WCHAR
*implementation
,
221 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
| BCRYPT_HASH_REUSABLE_FLAG
;
222 struct algorithm
*alg
;
226 TRACE( "%p, %s, %s, %#lx\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
228 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
229 if (flags
& ~supported_flags
)
231 FIXME( "unsupported flags %#lx\n", flags
& ~supported_flags
);
232 return STATUS_NOT_IMPLEMENTED
;
235 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
237 if (!wcscmp( id
, builtin_algorithms
[i
].name
))
243 if (i
== ARRAY_SIZE( builtin_algorithms
))
245 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
246 return STATUS_NOT_IMPLEMENTED
;
249 if (implementation
&& wcscmp( implementation
, MS_PRIMITIVE_PROVIDER
))
251 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
252 return STATUS_NOT_IMPLEMENTED
;
255 if (!(alg
= malloc( sizeof(*alg
) ))) return STATUS_NO_MEMORY
;
256 alg
->hdr
.magic
= MAGIC_ALG
;
258 alg
->mode
= MODE_ID_CBC
;
262 return STATUS_SUCCESS
;
265 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
267 struct algorithm
*alg
= handle
;
269 TRACE( "%p, %#lx\n", handle
, flags
);
271 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
274 return STATUS_SUCCESS
;
277 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
279 FIXME("%p - semi-stub\n", enabled
);
282 return STATUS_INVALID_PARAMETER
;
285 return STATUS_SUCCESS
;
301 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
306 md2_init( &hash
->u
.md2
);
310 MD4Init( &hash
->u
.md4
);
314 MD5Init( &hash
->u
.md5
);
318 A_SHAInit( &hash
->u
.sha1
);
322 sha256_init( &hash
->u
.sha256
);
326 sha384_init( &hash
->u
.sha512
);
330 sha512_init( &hash
->u
.sha512
);
334 ERR( "unhandled id %u\n", alg_id
);
335 return STATUS_NOT_IMPLEMENTED
;
337 return STATUS_SUCCESS
;
340 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
,
341 UCHAR
*input
, ULONG size
)
346 md2_update( &hash
->u
.md2
, input
, size
);
350 MD4Update( &hash
->u
.md4
, input
, size
);
354 MD5Update( &hash
->u
.md5
, input
, size
);
358 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
362 sha256_update( &hash
->u
.sha256
, input
, size
);
366 sha384_update( &hash
->u
.sha512
, input
, size
);
370 sha512_update( &hash
->u
.sha512
, input
, size
);
374 ERR( "unhandled id %u\n", alg_id
);
375 return STATUS_NOT_IMPLEMENTED
;
377 return STATUS_SUCCESS
;
380 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
,
381 UCHAR
*output
, ULONG size
)
386 md2_finalize( &hash
->u
.md2
, output
);
390 MD4Final( &hash
->u
.md4
);
391 memcpy( output
, hash
->u
.md4
.digest
, 16 );
395 MD5Final( &hash
->u
.md5
);
396 memcpy( output
, hash
->u
.md5
.digest
, 16 );
400 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
404 sha256_finalize( &hash
->u
.sha256
, output
);
408 sha384_finalize( &hash
->u
.sha512
, output
);
412 sha512_finalize( &hash
->u
.sha512
, output
);
416 ERR( "unhandled id %u\n", alg_id
);
417 return STATUS_NOT_IMPLEMENTED
;
419 return STATUS_SUCCESS
;
422 #define HASH_FLAG_HMAC 0x01
423 #define HASH_FLAG_REUSABLE 0x02
431 struct hash_impl outer
;
432 struct hash_impl inner
;
435 #define BLOCK_LENGTH_3DES 8
436 #define BLOCK_LENGTH_AES 16
438 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
440 if (!wcscmp( prop
, BCRYPT_OBJECT_LENGTH
))
442 if (!builtin_algorithms
[id
].object_length
)
443 return STATUS_NOT_SUPPORTED
;
444 *ret_size
= sizeof(ULONG
);
445 if (size
< sizeof(ULONG
))
446 return STATUS_BUFFER_TOO_SMALL
;
448 *(ULONG
*)buf
= builtin_algorithms
[id
].object_length
;
449 return STATUS_SUCCESS
;
452 if (!wcscmp( prop
, BCRYPT_HASH_LENGTH
))
454 if (!builtin_algorithms
[id
].hash_length
)
455 return STATUS_NOT_SUPPORTED
;
456 *ret_size
= sizeof(ULONG
);
457 if (size
< sizeof(ULONG
))
458 return STATUS_BUFFER_TOO_SMALL
;
460 *(ULONG
*)buf
= builtin_algorithms
[id
].hash_length
;
461 return STATUS_SUCCESS
;
464 if (!wcscmp( prop
, BCRYPT_ALGORITHM_NAME
))
466 *ret_size
= (lstrlenW(builtin_algorithms
[id
].name
) + 1) * sizeof(WCHAR
);
467 if (size
< *ret_size
)
468 return STATUS_BUFFER_TOO_SMALL
;
470 memcpy(buf
, builtin_algorithms
[id
].name
, *ret_size
);
471 return STATUS_SUCCESS
;
474 return STATUS_NOT_IMPLEMENTED
;
477 static NTSTATUS
get_3des_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
479 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
481 *ret_size
= sizeof(ULONG
);
482 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
483 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_3DES
;
484 return STATUS_SUCCESS
;
486 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
491 case MODE_ID_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
492 default: return STATUS_NOT_IMPLEMENTED
;
496 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
497 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
498 return STATUS_SUCCESS
;
500 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
502 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
503 *ret_size
= sizeof(*key_lengths
);
504 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
507 key_lengths
->dwMinLength
= 192;
508 key_lengths
->dwMaxLength
= 192;
509 key_lengths
->dwIncrement
= 0;
511 return STATUS_SUCCESS
;
513 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
514 return STATUS_NOT_IMPLEMENTED
;
517 static NTSTATUS
get_aes_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
519 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
521 *ret_size
= sizeof(ULONG
);
522 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
523 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
524 return STATUS_SUCCESS
;
526 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
531 case MODE_ID_ECB
: str
= BCRYPT_CHAIN_MODE_ECB
; break;
532 case MODE_ID_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
533 case MODE_ID_GCM
: str
= BCRYPT_CHAIN_MODE_GCM
; break;
534 default: return STATUS_NOT_IMPLEMENTED
;
538 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
539 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
540 return STATUS_SUCCESS
;
542 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
544 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
545 *ret_size
= sizeof(*key_lengths
);
546 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
549 key_lengths
->dwMinLength
= 128;
550 key_lengths
->dwMaxLength
= 256;
551 key_lengths
->dwIncrement
= 64;
553 return STATUS_SUCCESS
;
555 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
))
557 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
558 if (mode
!= MODE_ID_GCM
) return STATUS_NOT_SUPPORTED
;
559 *ret_size
= sizeof(*tag_length
);
560 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
563 tag_length
->dwMinLength
= 12;
564 tag_length
->dwMaxLength
= 16;
565 tag_length
->dwIncrement
= 1;
567 return STATUS_SUCCESS
;
570 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
571 return STATUS_NOT_IMPLEMENTED
;
574 static NTSTATUS
get_rsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
576 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
))
578 *ret_size
= sizeof(ULONG
);
579 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
580 if (buf
) *(ULONG
*)buf
= BCRYPT_SUPPORTED_PAD_PKCS1_SIG
;
581 return STATUS_SUCCESS
;
584 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
585 return STATUS_NOT_IMPLEMENTED
;
588 static NTSTATUS
get_dsa_property( enum mode_id mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
590 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
)) return STATUS_NOT_SUPPORTED
;
591 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
592 return STATUS_NOT_IMPLEMENTED
;
595 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
,
596 UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
600 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
601 if (status
!= STATUS_NOT_IMPLEMENTED
)
607 return get_3des_property( alg
->mode
, prop
, buf
, size
, ret_size
);
610 return get_aes_property( alg
->mode
, prop
, buf
, size
, ret_size
);
613 return get_rsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
616 return get_dsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
622 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop
), alg
->id
);
623 return STATUS_NOT_IMPLEMENTED
;
626 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
631 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
633 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
635 alg
->mode
= MODE_ID_CBC
;
636 return STATUS_SUCCESS
;
640 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
641 return STATUS_NOT_SUPPORTED
;
644 FIXME( "unsupported 3des algorithm property %s\n", debugstr_w(prop
) );
645 return STATUS_NOT_IMPLEMENTED
;
648 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
650 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
652 alg
->mode
= MODE_ID_ECB
;
653 return STATUS_SUCCESS
;
655 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
657 alg
->mode
= MODE_ID_CBC
;
658 return STATUS_SUCCESS
;
660 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
662 alg
->mode
= MODE_ID_GCM
;
663 return STATUS_SUCCESS
;
667 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
668 return STATUS_NOT_IMPLEMENTED
;
671 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
672 return STATUS_NOT_IMPLEMENTED
;
675 FIXME( "unsupported algorithm %u\n", alg
->id
);
676 return STATUS_NOT_IMPLEMENTED
;
680 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
682 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
684 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
686 key
->u
.s
.mode
= MODE_ID_ECB
;
687 return STATUS_SUCCESS
;
689 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
691 key
->u
.s
.mode
= MODE_ID_CBC
;
692 return STATUS_SUCCESS
;
694 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
696 key
->u
.s
.mode
= MODE_ID_GCM
;
697 return STATUS_SUCCESS
;
701 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
702 return STATUS_NOT_IMPLEMENTED
;
705 else if (!wcscmp( prop
, BCRYPT_KEY_LENGTH
))
707 if (size
< sizeof(DWORD
)) return STATUS_INVALID_PARAMETER
;
708 key
->u
.a
.bitlen
= *(DWORD
*)value
;
709 return STATUS_SUCCESS
;
712 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
713 return STATUS_NOT_IMPLEMENTED
;
716 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
720 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
721 if (status
== STATUS_NOT_IMPLEMENTED
)
722 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
726 static NTSTATUS
get_key_property( const struct key
*key
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
731 return get_3des_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
734 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
)) return STATUS_NOT_SUPPORTED
;
735 return get_aes_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
738 FIXME( "unsupported algorithm %u\n", key
->alg_id
);
739 return STATUS_NOT_IMPLEMENTED
;
743 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
,
746 struct object
*object
= handle
;
748 TRACE( "%p, %s, %p, %lu, %p, %#lx\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
750 if (!object
) return STATUS_INVALID_HANDLE
;
751 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
753 switch (object
->magic
)
757 const struct algorithm
*alg
= (const struct algorithm
*)object
;
758 return get_alg_property( alg
, prop
, buffer
, count
, res
);
762 const struct key
*key
= (const struct key
*)object
;
763 return get_key_property( key
, prop
, buffer
, count
, res
);
767 const struct hash
*hash
= (const struct hash
*)object
;
768 return get_hash_property( hash
, prop
, buffer
, count
, res
);
771 WARN( "unknown magic %#lx\n", object
->magic
);
772 return STATUS_INVALID_HANDLE
;
776 static NTSTATUS
hash_prepare( struct hash
*hash
)
778 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
782 /* initialize hash */
783 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) return status
;
784 if (!(hash
->flags
& HASH_FLAG_HMAC
)) return STATUS_SUCCESS
;
786 /* initialize hmac */
787 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) return status
;
788 block_bytes
= builtin_algorithms
[hash
->alg_id
].block_bits
/ 8;
789 if (hash
->secret_len
> block_bytes
)
791 struct hash_impl temp
;
792 if ((status
= hash_init( &temp
, hash
->alg_id
))) return status
;
793 if ((status
= hash_update( &temp
, hash
->alg_id
, hash
->secret
, hash
->secret_len
))) return status
;
794 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
795 builtin_algorithms
[hash
->alg_id
].hash_length
))) return status
;
797 else memcpy( buffer
, hash
->secret
, hash
->secret_len
);
799 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
800 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) return status
;
801 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
802 return hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
805 static NTSTATUS
hash_create( const struct algorithm
*alg
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
,
806 struct hash
**ret_hash
)
811 if (!(hash
= calloc( 1, sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
812 hash
->hdr
.magic
= MAGIC_HASH
;
813 hash
->alg_id
= alg
->id
;
814 if (alg
->flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
) hash
->flags
= HASH_FLAG_HMAC
;
815 if ((alg
->flags
& BCRYPT_HASH_REUSABLE_FLAG
) || (flags
& BCRYPT_HASH_REUSABLE_FLAG
))
816 hash
->flags
|= HASH_FLAG_REUSABLE
;
818 if (secret_len
&& !(hash
->secret
= malloc( secret_len
)))
821 return STATUS_NO_MEMORY
;
823 memcpy( hash
->secret
, secret
, secret_len
);
824 hash
->secret_len
= secret_len
;
826 if ((status
= hash_prepare( hash
)))
828 free( hash
->secret
);
834 return STATUS_SUCCESS
;
837 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_HASH_HANDLE
*handle
, UCHAR
*object
,
838 ULONG object_len
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
)
840 struct algorithm
*alg
= algorithm
;
844 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
845 if (flags
& ~BCRYPT_HASH_REUSABLE_FLAG
)
847 FIXME( "unimplemented flags %#lx\n", flags
);
848 return STATUS_NOT_IMPLEMENTED
;
851 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
852 if (object
) FIXME( "ignoring object buffer\n" );
854 if ((status
= hash_create( alg
, secret
, secret_len
, flags
, &hash
))) return status
;
856 return STATUS_SUCCESS
;
859 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
860 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
862 struct hash
*hash_orig
= handle
;
863 struct hash
*hash_copy
;
865 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, handle_copy
, object
, objectlen
, flags
);
867 if (!hash_orig
|| hash_orig
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
868 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
869 if (object
) FIXME( "ignoring object buffer\n" );
871 if (!(hash_copy
= malloc( sizeof(*hash_copy
) ))) return STATUS_NO_MEMORY
;
873 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
874 if (hash_orig
->secret
&& !(hash_copy
->secret
= malloc( hash_orig
->secret_len
)))
877 return STATUS_NO_MEMORY
;
879 memcpy( hash_copy
->secret
, hash_orig
->secret
, hash_orig
->secret_len
);
881 *handle_copy
= hash_copy
;
882 return STATUS_SUCCESS
;
885 static void hash_destroy( struct hash
*hash
)
889 free( hash
->secret
);
893 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
895 struct hash
*hash
= handle
;
897 TRACE( "%p\n", handle
);
899 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_PARAMETER
;
900 hash_destroy( hash
);
901 return STATUS_SUCCESS
;
904 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
906 struct hash
*hash
= handle
;
908 TRACE( "%p, %p, %lu, %#lx\n", handle
, input
, size
, flags
);
910 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
911 if (!input
) return STATUS_SUCCESS
;
913 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
916 static NTSTATUS
hash_finalize( struct hash
*hash
, UCHAR
*output
, ULONG size
)
918 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
922 if (!(hash
->flags
& HASH_FLAG_HMAC
))
924 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
))) return status
;
925 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
926 return STATUS_SUCCESS
;
929 hash_length
= builtin_algorithms
[hash
->alg_id
].hash_length
;
930 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
931 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
932 if ((status
= hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
))) return status
;
934 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
935 return STATUS_SUCCESS
;
938 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
940 struct hash
*hash
= handle
;
942 TRACE( "%p, %p, %lu, %#lx\n", handle
, output
, size
, flags
);
944 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
945 if (!output
) return STATUS_INVALID_PARAMETER
;
947 return hash_finalize( hash
, output
, size
);
950 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE algorithm
, UCHAR
*secret
, ULONG secret_len
,
951 UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
953 struct algorithm
*alg
= algorithm
;
957 TRACE( "%p, %p, %lu, %p, %lu, %p, %lu\n", algorithm
, secret
, secret_len
, input
, input_len
, output
, output_len
);
959 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
961 if ((status
= hash_create( alg
, secret
, secret_len
, 0, &hash
))) return status
;
962 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, input
, input_len
)))
964 hash_destroy( hash
);
967 status
= hash_finalize( hash
, output
, output_len
);
968 hash_destroy( hash
);
972 static NTSTATUS
key_asymmetric_create( enum alg_id alg_id
, ULONG bitlen
, struct key
**ret_key
)
978 ERR( "no encryption support\n" );
979 return STATUS_NOT_IMPLEMENTED
;
982 if (!(key
= calloc( 1, sizeof(*key
) ))) return STATUS_NO_MEMORY
;
983 key
->hdr
.magic
= MAGIC_KEY
;
984 key
->alg_id
= alg_id
;
985 key
->u
.a
.bitlen
= bitlen
;
988 return STATUS_SUCCESS
;
991 static BOOL
key_is_symmetric( struct key
*key
)
993 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_CIPHER_INTERFACE
;
996 static BOOL
is_zero_vector( const UCHAR
*vector
, ULONG len
)
999 if (!vector
) return FALSE
;
1000 for (i
= 0; i
< len
; i
++) if (vector
[i
]) return FALSE
;
1004 static BOOL
is_equal_vector( const UCHAR
*vector
, ULONG len
, const UCHAR
*vector2
, ULONG len2
)
1006 if (!vector
&& !vector2
) return TRUE
;
1007 if (len
!= len2
) return FALSE
;
1008 return !memcmp( vector
, vector2
, len
);
1011 static NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
)
1013 BOOL needs_reset
= (!is_zero_vector( vector
, vector_len
) ||
1014 !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
));
1016 free( key
->u
.s
.vector
);
1017 key
->u
.s
.vector
= NULL
;
1018 key
->u
.s
.vector_len
= 0;
1021 if (!(key
->u
.s
.vector
= malloc( vector_len
))) return STATUS_NO_MEMORY
;
1022 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
1023 key
->u
.s
.vector_len
= vector_len
;
1025 if (needs_reset
) UNIX_CALL( key_symmetric_vector_reset
, key
);
1026 return STATUS_SUCCESS
;
1029 static NTSTATUS
key_import( BCRYPT_ALG_HANDLE algorithm
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
1030 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
1034 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1036 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
1038 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
)) return STATUS_BUFFER_TOO_SMALL
;
1039 if (header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
) return STATUS_INVALID_PARAMETER
;
1040 if (header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
1042 FIXME( "unknown key data blob version %lu\n", header
->dwVersion
);
1043 return STATUS_INVALID_PARAMETER
;
1045 len
= header
->cbKeyData
;
1046 if (len
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
) return STATUS_INVALID_PARAMETER
;
1048 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, (UCHAR
*)&header
[1], len
, 0 );
1050 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1052 if (input_len
< sizeof(len
)) return STATUS_BUFFER_TOO_SMALL
;
1053 len
= *(ULONG
*)input
;
1054 if (len
+ sizeof(len
) > input_len
) return STATUS_INVALID_PARAMETER
;
1056 return BCryptGenerateSymmetricKey( algorithm
, key
, object
, object_len
, input
+ sizeof(len
), len
, 0 );
1059 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1060 return STATUS_NOT_IMPLEMENTED
;
1063 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1065 struct key_asymmetric_export_params params
;
1067 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1069 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
1070 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
1073 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1076 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
1077 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
1078 header
->cbKeyData
= key
->u
.s
.secret_len
;
1079 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1081 return STATUS_SUCCESS
;
1083 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1085 ULONG len
, req_size
= sizeof(len
) + key
->u
.s
.secret_len
;
1088 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1091 *(ULONG
*)output
= key
->u
.s
.secret_len
;
1092 memcpy( output
+ sizeof(len
), key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1094 return STATUS_SUCCESS
;
1096 else if (!wcscmp( type
, BCRYPT_DSA_PRIVATE_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
) ||
1097 !wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1101 params
.buf
= output
;
1102 params
.len
= output_len
;
1103 params
.ret_len
= size
;
1104 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1106 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1109 params
.flags
= (wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
)) ? KEY_EXPORT_FLAG_RSA_FULL
: 0;
1110 params
.buf
= output
;
1111 params
.len
= output_len
;
1112 params
.ret_len
= size
;
1113 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1115 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
) ||
1116 !wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
) || !wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1119 params
.flags
= KEY_EXPORT_FLAG_PUBLIC
;
1120 params
.buf
= output
;
1121 params
.len
= output_len
;
1122 params
.ret_len
= size
;
1123 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1126 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1127 return STATUS_NOT_IMPLEMENTED
;
1130 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1131 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1133 struct key_symmetric_set_auth_data_params auth_params
;
1134 struct key_symmetric_encrypt_params encrypt_params
;
1135 struct key_symmetric_get_tag_params tag_params
;
1136 ULONG bytes_left
= input_len
;
1140 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1142 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1144 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1145 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1146 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1147 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1148 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1149 FIXME( "call chaining not implemented\n" );
1151 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1154 *ret_len
= input_len
;
1155 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1156 if (input
&& !output
) return STATUS_SUCCESS
;
1157 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1159 auth_params
.key
= key
;
1160 auth_params
.auth_data
= auth_info
->pbAuthData
;
1161 auth_params
.len
= auth_info
->cbAuthData
;
1162 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1164 encrypt_params
.key
= key
;
1165 encrypt_params
.input
= input
;
1166 encrypt_params
.input_len
= input_len
;
1167 encrypt_params
.output
= output
;
1168 encrypt_params
.output_len
= output_len
;
1169 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
))) return status
;
1171 tag_params
.key
= key
;
1172 tag_params
.tag
= auth_info
->pbTag
;
1173 tag_params
.len
= auth_info
->cbTag
;
1174 return UNIX_CALL( key_symmetric_get_tag
, &tag_params
);
1177 *ret_len
= input_len
;
1179 if (flags
& BCRYPT_BLOCK_PADDING
)
1180 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1181 else if (input_len
& (key
->u
.s
.block_size
- 1))
1182 return STATUS_INVALID_BUFFER_SIZE
;
1184 if (!output
) return STATUS_SUCCESS
;
1185 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1186 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1187 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1189 encrypt_params
.key
= key
;
1190 encrypt_params
.input
= input
;
1191 encrypt_params
.input_len
= key
->u
.s
.block_size
;
1192 encrypt_params
.output
= output
;
1193 encrypt_params
.output_len
= key
->u
.s
.block_size
;
1194 while (bytes_left
>= key
->u
.s
.block_size
)
1196 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
)))
1198 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 )))
1200 bytes_left
-= key
->u
.s
.block_size
;
1201 encrypt_params
.input
+= key
->u
.s
.block_size
;
1202 encrypt_params
.output
+= key
->u
.s
.block_size
;
1205 if (flags
& BCRYPT_BLOCK_PADDING
)
1207 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1208 memcpy( buf
, encrypt_params
.input
, bytes_left
);
1209 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1210 encrypt_params
.input
= buf
;
1211 status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
);
1218 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1219 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1221 struct key_symmetric_set_auth_data_params auth_params
;
1222 struct key_symmetric_decrypt_params decrypt_params
;
1223 struct key_symmetric_get_tag_params tag_params
;
1224 ULONG bytes_left
= input_len
;
1227 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1229 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1232 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1233 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1234 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1235 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1237 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1240 *ret_len
= input_len
;
1241 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1242 if (!output
) return STATUS_SUCCESS
;
1243 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1245 auth_params
.key
= key
;
1246 auth_params
.auth_data
= auth_info
->pbAuthData
;
1247 auth_params
.len
= auth_info
->cbAuthData
;
1248 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1250 decrypt_params
.key
= key
;
1251 decrypt_params
.input
= input
;
1252 decrypt_params
.input_len
= input_len
;
1253 decrypt_params
.output
= output
;
1254 decrypt_params
.output_len
= output_len
;
1255 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1257 tag_params
.key
= key
;
1258 tag_params
.tag
= tag
;
1259 tag_params
.len
= sizeof(tag
);
1260 if ((status
= UNIX_CALL( key_symmetric_get_tag
, &tag_params
))) return status
;
1261 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1263 return STATUS_SUCCESS
;
1266 *ret_len
= input_len
;
1268 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1269 if (!output
) return STATUS_SUCCESS
;
1270 if (flags
& BCRYPT_BLOCK_PADDING
)
1272 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1273 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1274 bytes_left
-= key
->u
.s
.block_size
;
1276 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1278 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1279 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
))) return status
;
1281 decrypt_params
.key
= key
;
1282 decrypt_params
.input
= input
;
1283 decrypt_params
.input_len
= key
->u
.s
.block_size
;
1284 decrypt_params
.output
= output
;
1285 decrypt_params
.output_len
= key
->u
.s
.block_size
;
1286 while (bytes_left
>= key
->u
.s
.block_size
)
1288 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1289 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0 )))
1291 bytes_left
-= key
->u
.s
.block_size
;
1292 decrypt_params
.input
+= key
->u
.s
.block_size
;
1293 decrypt_params
.output
+= key
->u
.s
.block_size
;
1296 if (flags
& BCRYPT_BLOCK_PADDING
)
1298 UCHAR
*buf
, *dst
= decrypt_params
.output
;
1299 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1300 decrypt_params
.output
= buf
;
1301 status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
);
1302 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1304 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1305 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1306 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1308 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1315 static void key_destroy( struct key
*key
)
1317 if (key_is_symmetric( key
))
1319 UNIX_CALL( key_symmetric_destroy
, key
);
1320 free( key
->u
.s
.vector
);
1321 free( key
->u
.s
.secret
);
1322 DeleteCriticalSection( &key
->u
.s
.cs
);
1325 UNIX_CALL( key_asymmetric_destroy
, key
);
1331 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1334 struct key_asymmetric_import_params params
;
1339 if (!wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
))
1341 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1342 DWORD key_size
, magic
;
1344 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1348 case ALG_ID_ECDH_P256
:
1350 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
1353 case ALG_ID_ECDSA_P256
:
1355 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
1358 case ALG_ID_ECDSA_P384
:
1360 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
1364 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1365 return STATUS_NOT_SUPPORTED
;
1368 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1369 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2)
1370 return STATUS_INVALID_PARAMETER
;
1372 if ((status
= key_asymmetric_create( alg
->id
, key_size
* 8, &key
))) return status
;
1374 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1376 params
.len
= input_len
;
1377 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1384 return STATUS_SUCCESS
;
1386 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1388 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1389 DWORD key_size
, magic
;
1391 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1395 case ALG_ID_ECDH_P256
:
1397 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
1399 case ALG_ID_ECDSA_P256
:
1401 magic
= BCRYPT_ECDSA_PRIVATE_P256_MAGIC
;
1405 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1406 return STATUS_NOT_SUPPORTED
;
1409 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1410 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 3)
1411 return STATUS_INVALID_PARAMETER
;
1413 if ((status
= key_asymmetric_create( alg
->id
, key_size
* 8, &key
))) return status
;
1417 params
.len
= input_len
;
1418 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1425 return STATUS_SUCCESS
;
1427 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1429 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1431 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1432 if ((alg
->id
!= ALG_ID_RSA
&& alg
->id
!= ALG_ID_RSA_SIGN
) || rsa_blob
->Magic
!= BCRYPT_RSAPUBLIC_MAGIC
)
1433 return STATUS_NOT_SUPPORTED
;
1435 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1436 if (size
!= input_len
) return NTE_BAD_DATA
;
1438 if ((status
= key_asymmetric_create( alg
->id
, rsa_blob
->BitLength
, &key
))) return status
;
1440 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1442 params
.len
= input_len
;
1443 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1450 return STATUS_SUCCESS
;
1452 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1454 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1456 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1457 if (alg
->id
!= ALG_ID_RSA
|| (rsa_blob
->Magic
!= BCRYPT_RSAPRIVATE_MAGIC
&&
1458 rsa_blob
->Magic
!= BCRYPT_RSAFULLPRIVATE_MAGIC
)) return STATUS_NOT_SUPPORTED
;
1460 if ((status
= key_asymmetric_create( alg
->id
, rsa_blob
->BitLength
, &key
))) return status
;
1464 params
.len
= input_len
;
1465 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1472 return STATUS_SUCCESS
;
1474 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
))
1476 BCRYPT_DSA_KEY_BLOB
*dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)input
;
1478 if (input_len
< sizeof(*dsa_blob
)) return STATUS_INVALID_PARAMETER
;
1479 if ((alg
->id
!= ALG_ID_DSA
) || dsa_blob
->dwMagic
!= BCRYPT_DSA_PUBLIC_MAGIC
)
1480 return STATUS_NOT_SUPPORTED
;
1482 if ((status
= key_asymmetric_create( alg
->id
, dsa_blob
->cbKey
* 8, &key
))) return status
;
1484 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1486 params
.len
= input_len
;
1487 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1494 return STATUS_SUCCESS
;
1496 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1498 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1501 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1503 if (hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1505 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1506 return STATUS_NOT_SUPPORTED
;
1508 if (alg
->id
!= ALG_ID_DSA
)
1510 FIXME( "algorithm %u does not support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1511 return STATUS_NOT_SUPPORTED
;
1514 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1515 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1516 if (pubkey
->magic
!= MAGIC_DSS2
) return STATUS_NOT_SUPPORTED
;
1518 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 2 + 40 + sizeof(DSSSEED
))
1519 return STATUS_INVALID_PARAMETER
;
1521 if ((status
= key_asymmetric_create( alg
->id
, pubkey
->bitlen
, &key
))) return status
;
1522 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1526 params
.len
= input_len
;
1527 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1534 return STATUS_SUCCESS
;
1536 else if (!wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
)) /* not supported on native */
1538 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1541 if (alg
->id
!= ALG_ID_DSA
) return STATUS_NOT_SUPPORTED
;
1542 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1544 if (hdr
->bType
!= PUBLICKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1546 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1547 return STATUS_NOT_SUPPORTED
;
1550 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1551 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1552 if (pubkey
->magic
!= MAGIC_DSS1
) return STATUS_NOT_SUPPORTED
;
1554 size
= sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 3 + 20 + sizeof(DSSSEED
);
1555 if (input_len
< size
) return STATUS_INVALID_PARAMETER
;
1557 if ((status
= key_asymmetric_create( alg
->id
, pubkey
->bitlen
, &key
))) return status
;
1558 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1560 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1562 params
.len
= input_len
;
1563 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1570 return STATUS_SUCCESS
;
1573 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1574 return STATUS_NOT_SUPPORTED
;
1577 static ULONG
get_block_size( struct algorithm
*alg
)
1579 ULONG ret
= 0, size
= sizeof(ret
);
1580 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
1584 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1585 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1588 BCRYPT_KEY_LENGTHS_STRUCT key_lengths
;
1589 struct algorithm
*alg
= algorithm
;
1590 ULONG block_size
, size
;
1593 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
1595 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1596 if (object
) FIXME( "ignoring object buffer\n" );
1600 ERR( "no encryption support\n" );
1601 return STATUS_NOT_IMPLEMENTED
;
1604 if (!(block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1606 if (!get_alg_property( alg
, BCRYPT_KEY_LENGTHS
, (UCHAR
*)&key_lengths
, sizeof(key_lengths
), &size
))
1608 if (secret_len
> (size
= key_lengths
.dwMaxLength
/ 8))
1610 WARN( "secret_len %lu exceeds key max length %lu, setting to maximum\n", secret_len
, size
);
1613 else if (secret_len
< (size
= key_lengths
.dwMinLength
/ 8))
1615 WARN( "secret_len %lu is less than minimum key length %lu\n", secret_len
, size
);
1616 return STATUS_INVALID_PARAMETER
;
1618 else if (key_lengths
.dwIncrement
&& (secret_len
* 8 - key_lengths
.dwMinLength
) % key_lengths
.dwIncrement
)
1620 WARN( "secret_len %lu is not a valid key length\n", secret_len
);
1621 return STATUS_INVALID_PARAMETER
;
1625 if (!(key
= calloc( 1, sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1626 InitializeCriticalSection( &key
->u
.s
.cs
);
1627 key
->hdr
.magic
= MAGIC_KEY
;
1628 key
->alg_id
= alg
->id
;
1629 key
->u
.s
.mode
= alg
->mode
;
1630 key
->u
.s
.block_size
= block_size
;
1632 if (!(key
->u
.s
.secret
= malloc( secret_len
)))
1635 return STATUS_NO_MEMORY
;
1637 memcpy( key
->u
.s
.secret
, secret
, secret_len
);
1638 key
->u
.s
.secret_len
= secret_len
;
1641 return STATUS_SUCCESS
;
1644 NTSTATUS WINAPI
BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
, ULONG key_len
,
1647 struct algorithm
*alg
= algorithm
;
1651 TRACE( "%p, %p, %lu, %#lx\n", algorithm
, handle
, key_len
, flags
);
1653 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1654 if (!handle
) return STATUS_INVALID_PARAMETER
;
1656 if ((status
= key_asymmetric_create( alg
->id
, key_len
, &key
))) return status
;
1658 return STATUS_SUCCESS
;
1661 NTSTATUS WINAPI
BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle
, ULONG flags
)
1663 struct key
*key
= handle
;
1665 TRACE( "%p, %#lx\n", key
, flags
);
1666 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1668 return UNIX_CALL( key_asymmetric_generate
, key
);
1671 NTSTATUS WINAPI
BCryptImportKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1672 BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
, ULONG object_len
, UCHAR
*input
,
1673 ULONG input_len
, ULONG flags
)
1675 struct algorithm
*alg
= algorithm
;
1677 TRACE( "%p, %p, %s, %p, %p, %lu, %p, %lu, %#lx\n", algorithm
, decrypt_key
, debugstr_w(type
), key
, object
,
1678 object_len
, input
, input_len
, flags
);
1680 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1681 if (!key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1685 FIXME( "decryption of key not yet supported\n" );
1686 return STATUS_NOT_IMPLEMENTED
;
1689 return key_import( algorithm
, type
, key
, object
, object_len
, input
, input_len
);
1692 NTSTATUS WINAPI
BCryptExportKey( BCRYPT_KEY_HANDLE export_key
, BCRYPT_KEY_HANDLE encrypt_key
, const WCHAR
*type
,
1693 UCHAR
*output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1695 struct key
*key
= export_key
;
1697 TRACE( "%p, %p, %s, %p, %lu, %p, %#lx\n", key
, encrypt_key
, debugstr_w(type
), output
, output_len
, size
, flags
);
1699 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1700 if (!type
|| !size
) return STATUS_INVALID_PARAMETER
;
1704 FIXME( "encryption of key not yet supported\n" );
1705 return STATUS_NOT_IMPLEMENTED
;
1708 return key_export( key
, type
, output
, output_len
, size
);
1711 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
1716 memset( key_copy
, 0, sizeof(*key_copy
) );
1717 key_copy
->hdr
= key_orig
->hdr
;
1718 key_copy
->alg_id
= key_orig
->alg_id
;
1720 if (key_is_symmetric( key_orig
))
1722 if (!(buffer
= malloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
1723 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
1725 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
1726 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
1727 key_copy
->u
.s
.secret
= buffer
;
1728 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
1729 InitializeCriticalSection( &key_copy
->u
.s
.cs
);
1733 struct key_asymmetric_duplicate_params params
;
1735 key_copy
->u
.a
.bitlen
= key_orig
->u
.a
.bitlen
;
1736 key_copy
->u
.a
.flags
= key_orig
->u
.a
.flags
;
1737 key_copy
->u
.a
.dss_seed
= key_orig
->u
.a
.dss_seed
;
1739 params
.key_orig
= key_orig
;
1740 params
.key_copy
= key_copy
;
1741 if ((status
= UNIX_CALL( key_asymmetric_duplicate
, ¶ms
))) return status
;
1744 return STATUS_SUCCESS
;
1747 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
1748 UCHAR
*object
, ULONG object_len
, ULONG flags
)
1750 struct key
*key_orig
= handle
;
1751 struct key
*key_copy
;
1754 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, handle_copy
, object
, object_len
, flags
);
1755 if (object
) FIXME( "ignoring object buffer\n" );
1757 if (!key_orig
|| key_orig
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1758 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1759 if (!(key_copy
= malloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
1761 if ((status
= key_duplicate( key_orig
, key_copy
)))
1763 key_destroy( key_copy
);
1767 *handle_copy
= key_copy
;
1768 return STATUS_SUCCESS
;
1771 NTSTATUS WINAPI
BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1772 BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
, ULONG input_len
, ULONG flags
)
1774 struct algorithm
*alg
= algorithm
;
1776 TRACE( "%p, %p, %s, %p, %p, %lu, %#lx\n", algorithm
, decrypt_key
, debugstr_w(type
), ret_key
, input
,
1779 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1780 if (!ret_key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1783 FIXME( "decryption of key not yet supported\n" );
1784 return STATUS_NOT_IMPLEMENTED
;
1787 if (!wcscmp( type
, BCRYPT_PUBLIC_KEY_BLOB
))
1789 BCRYPT_KEY_BLOB
*key_blob
= (BCRYPT_KEY_BLOB
*)input
;
1791 if (input_len
< sizeof(*key_blob
)) return STATUS_INVALID_PARAMETER
;
1793 switch (key_blob
->Magic
)
1795 case BCRYPT_ECDH_PUBLIC_P256_MAGIC
:
1796 case BCRYPT_ECDSA_PUBLIC_P256_MAGIC
:
1797 case BCRYPT_ECDSA_PUBLIC_P384_MAGIC
:
1798 type
= BCRYPT_ECCPUBLIC_BLOB
;
1801 case BCRYPT_RSAPUBLIC_MAGIC
:
1802 type
= BCRYPT_RSAPUBLIC_BLOB
;
1805 case BCRYPT_DSA_PUBLIC_MAGIC
:
1806 type
= BCRYPT_DSA_PUBLIC_BLOB
;
1810 FIXME( "unsupported key magic %#lx\n", key_blob
->Magic
);
1811 return STATUS_NOT_SUPPORTED
;
1815 return key_import_pair( alg
, type
, ret_key
, input
, input_len
);
1818 NTSTATUS WINAPI
BCryptSignHash( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*input
, ULONG input_len
,
1819 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1821 struct key_asymmetric_sign_params params
;
1822 struct key
*key
= handle
;
1824 TRACE( "%p, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, padding
, input
, input_len
, output
, output_len
,
1827 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1828 if (key_is_symmetric( key
))
1830 FIXME( "signing with symmetric keys not yet supported\n" );
1831 return STATUS_NOT_IMPLEMENTED
;
1835 params
.padding
= padding
;
1836 params
.input
= input
;
1837 params
.input_len
= input_len
;
1838 params
.output
= output
;
1839 params
.output_len
= output_len
;
1840 params
.ret_len
= ret_len
;
1841 params
.flags
= flags
;
1842 return UNIX_CALL( key_asymmetric_sign
, ¶ms
);
1845 NTSTATUS WINAPI
BCryptVerifySignature( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*hash
, ULONG hash_len
,
1846 UCHAR
*signature
, ULONG signature_len
, ULONG flags
)
1848 struct key_asymmetric_verify_params params
;
1849 struct key
*key
= handle
;
1851 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
1853 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1854 if (!hash
|| !hash_len
|| !signature
|| !signature_len
) return STATUS_INVALID_PARAMETER
;
1855 if (key_is_symmetric( key
)) return STATUS_NOT_SUPPORTED
;
1858 params
.padding
= padding
;
1860 params
.hash_len
= hash_len
;
1861 params
.signature
= signature
;
1862 params
.signature_len
= signature_len
;
1863 params
.flags
= flags
;
1864 return UNIX_CALL( key_asymmetric_verify
, ¶ms
);
1867 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
1869 struct key
*key
= handle
;
1871 TRACE( "%p\n", handle
);
1873 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1876 return STATUS_SUCCESS
;
1879 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1880 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1882 struct key
*key
= handle
;
1885 TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1886 output_len
, ret_len
, flags
);
1888 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1889 if (!key_is_symmetric( key
))
1891 FIXME( "encryption with asymmetric keys not yet supported\n" );
1892 return STATUS_NOT_IMPLEMENTED
;
1894 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1896 FIXME( "flags %#lx not implemented\n", flags
);
1897 return STATUS_NOT_IMPLEMENTED
;
1900 EnterCriticalSection( &key
->u
.s
.cs
);
1901 ret
= key_symmetric_encrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1902 LeaveCriticalSection( &key
->u
.s
.cs
);
1906 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1907 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1909 struct key_asymmetric_decrypt_params params
;
1910 struct key
*key
= handle
;
1912 TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
1913 output_len
, ret_len
, flags
);
1915 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1916 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1918 FIXME( "flags %#lx not supported\n", flags
);
1919 return STATUS_NOT_IMPLEMENTED
;
1922 if (key_is_symmetric( key
))
1925 EnterCriticalSection( &key
->u
.s
.cs
);
1926 ret
= key_symmetric_decrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1927 LeaveCriticalSection( &key
->u
.s
.cs
);
1932 params
.input
= input
;
1933 params
.input_len
= input_len
;
1934 params
.output
= output
;
1935 params
.output_len
= output_len
;
1936 params
.ret_len
= ret_len
;
1937 return UNIX_CALL( key_asymmetric_decrypt
, ¶ms
);
1940 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1942 struct object
*object
= handle
;
1944 TRACE( "%p, %s, %p, %lu, %#lx\n", handle
, debugstr_w(prop
), value
, size
, flags
);
1946 if (!object
) return STATUS_INVALID_HANDLE
;
1948 switch (object
->magic
)
1952 struct algorithm
*alg
= (struct algorithm
*)object
;
1953 return set_alg_property( alg
, prop
, value
, size
, flags
);
1957 struct key
*key
= (struct key
*)object
;
1958 return set_key_property( key
, prop
, value
, size
, flags
);
1961 WARN( "unknown magic %#lx\n", object
->magic
);
1962 return STATUS_INVALID_HANDLE
;
1966 #define HMAC_PAD_LEN 64
1967 NTSTATUS WINAPI
BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle
, BCRYPT_ALG_HANDLE halg
, UCHAR
*key
, ULONG keylen
, ULONG flags
)
1969 struct hash
*hash
= handle
;
1970 UCHAR buf
[MAX_HASH_OUTPUT_BYTES
* 2];
1974 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, halg
, key
, keylen
, flags
);
1976 if (!key
|| !keylen
) return STATUS_INVALID_PARAMETER
;
1977 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
1978 if (keylen
> builtin_algorithms
[hash
->alg_id
].hash_length
* 2) return STATUS_INVALID_PARAMETER
;
1982 FIXME( "algorithm handle not supported\n" );
1983 return STATUS_NOT_IMPLEMENTED
;
1986 len
= builtin_algorithms
[hash
->alg_id
].hash_length
;
1987 if ((status
= hash_finalize( hash
, buf
, len
))) return status
;
1991 UCHAR pad1
[HMAC_PAD_LEN
], pad2
[HMAC_PAD_LEN
];
1994 for (i
= 0; i
< sizeof(pad1
); i
++)
1996 pad1
[i
] = 0x36 ^ (i
< len
? buf
[i
] : 0);
1997 pad2
[i
] = 0x5c ^ (i
< len
? buf
[i
] : 0);
2000 if ((status
= hash_prepare( hash
)) ||
2001 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad1
, sizeof(pad1
) )) ||
2002 (status
= hash_finalize( hash
, buf
, len
))) return status
;
2004 if ((status
= hash_prepare( hash
)) ||
2005 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad2
, sizeof(pad2
) )) ||
2006 (status
= hash_finalize( hash
, buf
+ len
, len
))) return status
;
2009 memcpy( key
, buf
, keylen
);
2010 return STATUS_SUCCESS
;
2013 static NTSTATUS
pbkdf2( struct hash
*hash
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2014 ULONGLONG iterations
, ULONG i
, UCHAR
*dst
, ULONG hash_len
)
2016 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
2017 UCHAR bytes
[4], *buf
;
2020 if (!(buf
= malloc( hash_len
))) return STATUS_NO_MEMORY
;
2022 for (j
= 0; j
< iterations
; j
++)
2026 /* use salt || INT(i) */
2027 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, salt
, salt_len
)))
2032 bytes
[0] = (i
>> 24) & 0xff;
2033 bytes
[1] = (i
>> 16) & 0xff;
2034 bytes
[2] = (i
>> 8) & 0xff;
2035 bytes
[3] = i
& 0xff;
2036 status
= hash_update( &hash
->inner
, hash
->alg_id
, bytes
, 4 );
2038 else status
= hash_update( &hash
->inner
, hash
->alg_id
, buf
, hash_len
); /* use U_j */
2046 if ((status
= hash_finalize( hash
, buf
, hash_len
)))
2052 if (j
== 0) memcpy( dst
, buf
, hash_len
);
2053 else for (k
= 0; k
< hash_len
; k
++) dst
[k
] ^= buf
[k
];
2060 NTSTATUS WINAPI
BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2061 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
, ULONG flags
)
2063 struct algorithm
*alg
= handle
;
2064 ULONG hash_len
, block_count
, bytes_left
, i
;
2069 TRACE( "%p, %p, %lu, %p, %lu, %s, %p, %lu, %#lx\n", handle
, pwd
, pwd_len
, salt
, salt_len
,
2070 wine_dbgstr_longlong(iterations
), dk
, dk_len
, flags
);
2072 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
2074 hash_len
= builtin_algorithms
[alg
->id
].hash_length
;
2075 if (dk_len
<= 0 || dk_len
> ((((ULONGLONG
)1) << 32) - 1) * hash_len
) return STATUS_INVALID_PARAMETER
;
2077 block_count
= 1 + ((dk_len
- 1) / hash_len
); /* ceil(dk_len / hash_len) */
2078 bytes_left
= dk_len
- (block_count
- 1) * hash_len
;
2080 if ((status
= hash_create( alg
, pwd
, pwd_len
, BCRYPT_HASH_REUSABLE_FLAG
, &hash
))) return status
;
2083 for (i
= 1; i
< block_count
; i
++)
2085 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, i
, dk
+ ((i
- 1) * hash_len
), hash_len
)))
2087 hash_destroy( hash
);
2092 /* final partial block */
2093 if (!(partial
= malloc( hash_len
)))
2095 hash_destroy( hash
);
2096 return STATUS_NO_MEMORY
;
2099 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, block_count
, partial
, hash_len
)))
2101 hash_destroy( hash
);
2105 memcpy( dk
+ ((block_count
- 1) * hash_len
), partial
, bytes_left
);
2107 hash_destroy( hash
);
2109 return STATUS_SUCCESS
;
2112 NTSTATUS WINAPI
BCryptSecretAgreement( BCRYPT_KEY_HANDLE privatekey
, BCRYPT_KEY_HANDLE publickey
,
2113 BCRYPT_SECRET_HANDLE
*handle
, ULONG flags
)
2115 struct key
*privkey
= privatekey
;
2116 struct key
*pubkey
= publickey
;
2117 struct secret
*secret
;
2119 FIXME( "%p, %p, %p, %#lx\n", privatekey
, publickey
, handle
, flags
);
2121 if (!privkey
|| privkey
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
2122 if (!pubkey
|| pubkey
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
2123 if (!handle
) return STATUS_INVALID_PARAMETER
;
2125 if (!(secret
= calloc( 1, sizeof(*secret
) ))) return STATUS_NO_MEMORY
;
2126 secret
->hdr
.magic
= MAGIC_SECRET
;
2129 return STATUS_SUCCESS
;
2132 NTSTATUS WINAPI
BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle
)
2134 struct secret
*secret
= handle
;
2136 FIXME( "%p\n", handle
);
2138 if (!secret
|| secret
->hdr
.magic
!= MAGIC_SECRET
) return STATUS_INVALID_HANDLE
;
2139 secret
->hdr
.magic
= 0;
2141 return STATUS_SUCCESS
;
2144 NTSTATUS WINAPI
BCryptDeriveKey( BCRYPT_SECRET_HANDLE handle
, const WCHAR
*kdf
, BCryptBufferDesc
*parameter
,
2145 UCHAR
*derived
, ULONG derived_size
, ULONG
*result
, ULONG flags
)
2147 struct secret
*secret
= handle
;
2149 FIXME( "%p, %s, %p, %p, %lu, %p, %#lx\n", secret
, debugstr_w(kdf
), parameter
, derived
, derived_size
, result
, flags
);
2151 if (!secret
|| secret
->hdr
.magic
!= MAGIC_SECRET
) return STATUS_INVALID_HANDLE
;
2152 if (!kdf
) return STATUS_INVALID_PARAMETER
;
2154 return STATUS_INTERNAL_ERROR
;
2157 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
2161 case DLL_PROCESS_ATTACH
:
2162 DisableThreadLibraryCalls( hinst
);
2163 if (!NtQueryVirtualMemory( GetCurrentProcess(), hinst
, MemoryWineUnixFuncs
,
2164 &bcrypt_handle
, sizeof(bcrypt_handle
), NULL
))
2166 if (UNIX_CALL( process_attach
, NULL
)) bcrypt_handle
= 0;
2169 case DLL_PROCESS_DETACH
:
2170 if (reserved
) break;
2171 if (bcrypt_handle
) UNIX_CALL( process_detach
, NULL
);