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_ECDH_P384_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
119 { BCRYPT_RSA_SIGN_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
120 { BCRYPT_ECDSA_P256_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
121 { BCRYPT_ECDSA_P384_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
122 { BCRYPT_DSA_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
123 { BCRYPT_RNG_ALGORITHM
, BCRYPT_RNG_INTERFACE
, 0, 0, 0 },
126 static BOOL
match_operation_type( ULONG type
, ULONG
class )
128 if (!type
) return TRUE
;
131 case BCRYPT_CIPHER_INTERFACE
: return type
& BCRYPT_CIPHER_OPERATION
;
132 case BCRYPT_HASH_INTERFACE
: return type
& BCRYPT_HASH_OPERATION
;
133 case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
: return type
& BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
;
134 case BCRYPT_SECRET_AGREEMENT_INTERFACE
: return type
& BCRYPT_SECRET_AGREEMENT_OPERATION
;
135 case BCRYPT_SIGNATURE_INTERFACE
: return type
& BCRYPT_SIGNATURE_OPERATION
;
136 case BCRYPT_RNG_INTERFACE
: return type
& BCRYPT_RNG_OPERATION
;
142 NTSTATUS WINAPI
BCryptEnumAlgorithms( ULONG type
, ULONG
*ret_count
, BCRYPT_ALGORITHM_IDENTIFIER
**ret_list
, ULONG flags
)
144 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
145 BCRYPT_HASH_OPERATION
|\
146 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
147 BCRYPT_SECRET_AGREEMENT_OPERATION
|\
148 BCRYPT_SIGNATURE_OPERATION
|\
149 BCRYPT_RNG_OPERATION
;
150 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
151 ULONG i
, j
, count
= 0;
153 TRACE( "%#lx, %p, %p, %#lx\n", type
, ret_count
, ret_list
, flags
);
155 if (!ret_count
|| !ret_list
|| (type
& ~supported
)) return STATUS_INVALID_PARAMETER
;
157 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
159 if (match_operation_type( type
, builtin_algorithms
[i
].class )) count
++;
162 if (!(list
= malloc( count
* sizeof(*list
) ))) return STATUS_NO_MEMORY
;
164 for (i
= 0, j
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
166 if (!match_operation_type( type
, builtin_algorithms
[i
].class )) continue;
167 list
[j
].pszName
= (WCHAR
*)builtin_algorithms
[i
].name
;
168 list
[j
].dwClass
= builtin_algorithms
[i
].class;
175 return STATUS_SUCCESS
;
178 static const struct algorithm pseudo_algorithms
[] =
180 {{ MAGIC_ALG
}, ALG_ID_MD2
},
181 {{ MAGIC_ALG
}, ALG_ID_MD4
},
182 {{ MAGIC_ALG
}, ALG_ID_MD5
},
183 {{ MAGIC_ALG
}, ALG_ID_SHA1
},
184 {{ MAGIC_ALG
}, ALG_ID_SHA256
},
185 {{ MAGIC_ALG
}, ALG_ID_SHA384
},
186 {{ MAGIC_ALG
}, ALG_ID_SHA512
},
188 {{ MAGIC_ALG
}, ALG_ID_RNG
},
189 {{ MAGIC_ALG
}, ALG_ID_MD5
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
190 {{ MAGIC_ALG
}, ALG_ID_SHA1
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
191 {{ MAGIC_ALG
}, ALG_ID_SHA256
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
192 {{ MAGIC_ALG
}, ALG_ID_SHA384
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
193 {{ MAGIC_ALG
}, ALG_ID_SHA512
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
194 {{ MAGIC_ALG
}, ALG_ID_RSA
},
196 {{ 0 }}, /* AES_CMAC */
197 {{ 0 }}, /* AES_GMAC */
198 {{ MAGIC_ALG
}, ALG_ID_MD2
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
199 {{ MAGIC_ALG
}, ALG_ID_MD4
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
200 {{ MAGIC_ALG
}, ALG_ID_3DES
, CHAIN_MODE_CBC
},
201 {{ MAGIC_ALG
}, ALG_ID_3DES
, CHAIN_MODE_ECB
},
202 {{ MAGIC_ALG
}, ALG_ID_3DES
, CHAIN_MODE_CFB
},
203 {{ 0 }}, /* 3DES_112_CBC */
204 {{ 0 }}, /* 3DES_112_ECB */
205 {{ 0 }}, /* 3DES_112_CFB */
206 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_CBC
},
207 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_ECB
},
208 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_CFB
},
209 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_CCM
},
210 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_GCM
},
211 {{ 0 }}, /* DES_CBC */
212 {{ 0 }}, /* DES_ECB */
213 {{ 0 }}, /* DES_CFB */
214 {{ 0 }}, /* DESX_CBC */
215 {{ 0 }}, /* DESX_ECB */
216 {{ 0 }}, /* DESX_CFB */
217 {{ 0 }}, /* RC2_CBC */
218 {{ 0 }}, /* RC2_ECB */
219 {{ 0 }}, /* RC2_CFB */
222 {{ MAGIC_ALG
}, ALG_ID_ECDH_P256
},
223 {{ MAGIC_ALG
}, ALG_ID_ECDH_P384
},
224 {{ 0 }}, /* ECDH_P512 */
225 {{ MAGIC_ALG
}, ALG_ID_DSA
},
226 {{ MAGIC_ALG
}, ALG_ID_ECDSA_P256
},
227 {{ MAGIC_ALG
}, ALG_ID_ECDSA_P384
},
228 {{ 0 }}, /* ECDSA_P512 */
229 {{ MAGIC_ALG
}, ALG_ID_RSA_SIGN
},
232 /* Algorithm pseudo-handles are denoted by having the lowest bit set.
233 * An aligned algorithm pointer will never have this bit set.
235 static inline BOOL
is_alg_pseudo_handle( BCRYPT_ALG_HANDLE handle
)
237 return (((ULONG_PTR
)handle
& 1) == 1);
240 static struct object
*get_object( BCRYPT_HANDLE handle
, ULONG magic
)
244 if (!handle
) return NULL
;
246 if (!is_alg_pseudo_handle( handle
))
248 struct object
*obj
= handle
;
249 if (magic
&& obj
->magic
!= magic
) return NULL
;
253 idx
= (ULONG_PTR
)handle
>> 4;
254 if (idx
> ARRAY_SIZE(pseudo_algorithms
) || !pseudo_algorithms
[idx
].hdr
.magic
)
256 FIXME( "pseudo-handle %p not supported\n", handle
);
259 return (struct object
*)&pseudo_algorithms
[idx
];
262 static inline struct algorithm
*get_alg_object( BCRYPT_ALG_HANDLE handle
)
264 return (struct algorithm
*)get_object( handle
, MAGIC_ALG
);
267 static inline struct hash
*get_hash_object( BCRYPT_HASH_HANDLE handle
)
269 return (struct hash
*)get_object( handle
, MAGIC_HASH
);
272 static inline struct key
*get_key_object( BCRYPT_KEY_HANDLE handle
)
274 return (struct key
*)get_object( handle
, MAGIC_KEY
);
277 static inline struct secret
*get_secret_object( BCRYPT_SECRET_HANDLE handle
)
279 return (struct secret
*)get_object( handle
, MAGIC_SECRET
);
282 NTSTATUS WINAPI
BCryptGenRandom( BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
284 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
285 struct algorithm
*alg
= get_alg_object( handle
);
287 TRACE("%p, %p, %lu, %#lx - semi-stub\n", handle
, buffer
, count
, flags
);
291 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
292 * is set. In this case the preferred system RNG is used.
294 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
295 return STATUS_INVALID_HANDLE
;
297 else if (is_alg_pseudo_handle( handle
) && handle
!= BCRYPT_RNG_ALG_HANDLE
)
299 FIXME( "pseudo-handle %p not supported\n", handle
);
300 return STATUS_NOT_IMPLEMENTED
;
302 else if (!alg
|| alg
->id
!= ALG_ID_RNG
)
303 return STATUS_INVALID_HANDLE
;
306 return STATUS_INVALID_PARAMETER
;
308 if (flags
& ~supported_flags
)
309 FIXME("unsupported flags %#lx\n", flags
& ~supported_flags
);
312 FIXME("ignoring selected algorithm\n");
314 /* When zero bytes are requested the function returns success too. */
316 return STATUS_SUCCESS
;
318 if (alg
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
320 if (RtlGenRandom(buffer
, count
)) return STATUS_SUCCESS
;
323 FIXME("called with unsupported parameters, returning error\n");
324 return STATUS_NOT_IMPLEMENTED
;
327 static struct algorithm
*create_algorithm( enum alg_id id
, enum chain_mode mode
, DWORD flags
)
329 struct algorithm
*ret
;
330 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
331 ret
->hdr
.magic
= MAGIC_ALG
;
338 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, const WCHAR
*id
, const WCHAR
*implementation
,
341 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
| BCRYPT_HASH_REUSABLE_FLAG
;
342 struct algorithm
*alg
;
346 TRACE( "%p, %s, %s, %#lx\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
348 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
349 if (flags
& ~supported_flags
)
351 FIXME( "unsupported flags %#lx\n", flags
& ~supported_flags
);
352 return STATUS_NOT_IMPLEMENTED
;
355 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
357 if (!wcscmp( id
, builtin_algorithms
[i
].name
))
363 if (i
== ARRAY_SIZE( builtin_algorithms
))
365 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
366 return STATUS_NOT_IMPLEMENTED
;
369 if (implementation
&& wcscmp( implementation
, MS_PRIMITIVE_PROVIDER
))
371 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
372 return STATUS_NOT_IMPLEMENTED
;
375 if (!(alg
= create_algorithm( alg_id
, 0, flags
))) return STATUS_NO_MEMORY
;
377 return STATUS_SUCCESS
;
380 static void destroy_object( struct object
*obj
)
386 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
388 struct algorithm
*alg
= handle
;
390 TRACE( "%p, %#lx\n", handle
, flags
);
392 if (!handle
|| is_alg_pseudo_handle( handle
) || alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
393 destroy_object( &alg
->hdr
);
394 return STATUS_SUCCESS
;
397 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
399 FIXME("%p - semi-stub\n", enabled
);
402 return STATUS_INVALID_PARAMETER
;
405 return STATUS_SUCCESS
;
421 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
426 md2_init( &hash
->u
.md2
);
430 MD4Init( &hash
->u
.md4
);
434 MD5Init( &hash
->u
.md5
);
438 A_SHAInit( &hash
->u
.sha1
);
442 sha256_init( &hash
->u
.sha256
);
446 sha384_init( &hash
->u
.sha512
);
450 sha512_init( &hash
->u
.sha512
);
454 ERR( "unhandled id %u\n", alg_id
);
455 return STATUS_NOT_IMPLEMENTED
;
457 return STATUS_SUCCESS
;
460 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
, UCHAR
*input
, ULONG size
)
465 md2_update( &hash
->u
.md2
, input
, size
);
469 MD4Update( &hash
->u
.md4
, input
, size
);
473 MD5Update( &hash
->u
.md5
, input
, size
);
477 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
481 sha256_update( &hash
->u
.sha256
, input
, size
);
485 sha384_update( &hash
->u
.sha512
, input
, size
);
489 sha512_update( &hash
->u
.sha512
, input
, size
);
493 ERR( "unhandled id %u\n", alg_id
);
494 return STATUS_NOT_IMPLEMENTED
;
496 return STATUS_SUCCESS
;
499 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
, UCHAR
*output
, ULONG size
)
504 md2_finalize( &hash
->u
.md2
, output
);
508 MD4Final( &hash
->u
.md4
);
509 memcpy( output
, hash
->u
.md4
.digest
, 16 );
513 MD5Final( &hash
->u
.md5
);
514 memcpy( output
, hash
->u
.md5
.digest
, 16 );
518 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
522 sha256_finalize( &hash
->u
.sha256
, output
);
526 sha384_finalize( &hash
->u
.sha512
, output
);
530 sha512_finalize( &hash
->u
.sha512
, output
);
534 ERR( "unhandled id %u\n", alg_id
);
535 return STATUS_NOT_IMPLEMENTED
;
537 return STATUS_SUCCESS
;
540 #define HASH_FLAG_HMAC 0x01
541 #define HASH_FLAG_REUSABLE 0x02
549 struct hash_impl outer
;
550 struct hash_impl inner
;
553 #define BLOCK_LENGTH_3DES 8
554 #define BLOCK_LENGTH_AES 16
556 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
558 if (!wcscmp( prop
, BCRYPT_OBJECT_LENGTH
))
560 if (!builtin_algorithms
[id
].object_length
)
561 return STATUS_NOT_SUPPORTED
;
562 *ret_size
= sizeof(ULONG
);
563 if (size
< sizeof(ULONG
))
564 return STATUS_BUFFER_TOO_SMALL
;
566 *(ULONG
*)buf
= builtin_algorithms
[id
].object_length
;
567 return STATUS_SUCCESS
;
570 if (!wcscmp( prop
, BCRYPT_HASH_LENGTH
))
572 if (!builtin_algorithms
[id
].hash_length
)
573 return STATUS_NOT_SUPPORTED
;
574 *ret_size
= sizeof(ULONG
);
575 if (size
< sizeof(ULONG
))
576 return STATUS_BUFFER_TOO_SMALL
;
578 *(ULONG
*)buf
= builtin_algorithms
[id
].hash_length
;
579 return STATUS_SUCCESS
;
582 if (!wcscmp( prop
, BCRYPT_ALGORITHM_NAME
))
584 *ret_size
= (lstrlenW(builtin_algorithms
[id
].name
) + 1) * sizeof(WCHAR
);
585 if (size
< *ret_size
)
586 return STATUS_BUFFER_TOO_SMALL
;
588 memcpy(buf
, builtin_algorithms
[id
].name
, *ret_size
);
589 return STATUS_SUCCESS
;
592 return STATUS_NOT_IMPLEMENTED
;
595 static NTSTATUS
get_3des_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
597 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
599 *ret_size
= sizeof(ULONG
);
600 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
601 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_3DES
;
602 return STATUS_SUCCESS
;
604 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
609 case CHAIN_MODE_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
610 default: return STATUS_NOT_IMPLEMENTED
;
614 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
615 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
616 return STATUS_SUCCESS
;
618 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
620 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
621 *ret_size
= sizeof(*key_lengths
);
622 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
625 key_lengths
->dwMinLength
= 192;
626 key_lengths
->dwMaxLength
= 192;
627 key_lengths
->dwIncrement
= 0;
629 return STATUS_SUCCESS
;
631 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
632 return STATUS_NOT_IMPLEMENTED
;
635 static NTSTATUS
get_aes_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
637 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
639 *ret_size
= sizeof(ULONG
);
640 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
641 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
642 return STATUS_SUCCESS
;
644 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
649 case CHAIN_MODE_ECB
: str
= BCRYPT_CHAIN_MODE_ECB
; break;
650 case CHAIN_MODE_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
651 case CHAIN_MODE_GCM
: str
= BCRYPT_CHAIN_MODE_GCM
; break;
652 case CHAIN_MODE_CFB
: str
= BCRYPT_CHAIN_MODE_CFB
; break;
653 default: return STATUS_NOT_IMPLEMENTED
;
657 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
658 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
659 return STATUS_SUCCESS
;
661 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
663 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
664 *ret_size
= sizeof(*key_lengths
);
665 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
668 key_lengths
->dwMinLength
= 128;
669 key_lengths
->dwMaxLength
= 256;
670 key_lengths
->dwIncrement
= 64;
672 return STATUS_SUCCESS
;
674 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
))
676 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
677 if (mode
!= CHAIN_MODE_GCM
) return STATUS_NOT_SUPPORTED
;
678 *ret_size
= sizeof(*tag_length
);
679 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
682 tag_length
->dwMinLength
= 12;
683 tag_length
->dwMaxLength
= 16;
684 tag_length
->dwIncrement
= 1;
686 return STATUS_SUCCESS
;
689 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
690 return STATUS_NOT_IMPLEMENTED
;
693 static NTSTATUS
get_rsa_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
695 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
))
697 *ret_size
= sizeof(ULONG
);
698 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
699 if (buf
) *(ULONG
*)buf
= BCRYPT_SUPPORTED_PAD_PKCS1_SIG
;
700 return STATUS_SUCCESS
;
703 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
704 return STATUS_NOT_IMPLEMENTED
;
707 static NTSTATUS
get_dsa_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
709 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
)) return STATUS_NOT_SUPPORTED
;
710 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
711 return STATUS_NOT_IMPLEMENTED
;
714 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
,
719 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
720 if (status
!= STATUS_NOT_IMPLEMENTED
)
726 return get_3des_property( alg
->mode
, prop
, buf
, size
, ret_size
);
729 return get_aes_property( alg
->mode
, prop
, buf
, size
, ret_size
);
732 return get_rsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
735 return get_dsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
741 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop
), alg
->id
);
742 return STATUS_NOT_IMPLEMENTED
;
745 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
750 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
752 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
754 alg
->mode
= CHAIN_MODE_CBC
;
755 return STATUS_SUCCESS
;
759 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
760 return STATUS_NOT_SUPPORTED
;
763 FIXME( "unsupported 3des algorithm property %s\n", debugstr_w(prop
) );
764 return STATUS_NOT_IMPLEMENTED
;
767 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
769 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
771 alg
->mode
= CHAIN_MODE_ECB
;
772 return STATUS_SUCCESS
;
774 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
776 alg
->mode
= CHAIN_MODE_CBC
;
777 return STATUS_SUCCESS
;
779 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
781 alg
->mode
= CHAIN_MODE_GCM
;
782 return STATUS_SUCCESS
;
784 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CFB
))
786 alg
->mode
= CHAIN_MODE_CFB
;
787 return STATUS_SUCCESS
;
791 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
792 return STATUS_NOT_IMPLEMENTED
;
795 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
796 return STATUS_NOT_IMPLEMENTED
;
799 FIXME( "unsupported algorithm %u\n", alg
->id
);
800 return STATUS_NOT_IMPLEMENTED
;
804 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
806 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
808 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
810 key
->u
.s
.mode
= CHAIN_MODE_ECB
;
811 return STATUS_SUCCESS
;
813 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
815 key
->u
.s
.mode
= CHAIN_MODE_CBC
;
816 return STATUS_SUCCESS
;
818 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
820 key
->u
.s
.mode
= CHAIN_MODE_GCM
;
821 return STATUS_SUCCESS
;
823 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CFB
))
825 key
->u
.s
.mode
= CHAIN_MODE_CFB
;
826 return STATUS_SUCCESS
;
830 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
831 return STATUS_NOT_IMPLEMENTED
;
834 else if (!wcscmp( prop
, BCRYPT_KEY_LENGTH
))
836 if (size
< sizeof(DWORD
)) return STATUS_INVALID_PARAMETER
;
837 key
->u
.a
.bitlen
= *(DWORD
*)value
;
838 return STATUS_SUCCESS
;
841 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
842 return STATUS_NOT_IMPLEMENTED
;
845 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
849 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
850 if (status
== STATUS_NOT_IMPLEMENTED
)
851 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
855 static NTSTATUS
get_key_property( const struct key
*key
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
860 return get_3des_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
863 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
)) return STATUS_NOT_SUPPORTED
;
864 return get_aes_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
867 FIXME( "unsupported algorithm %u\n", key
->alg_id
);
868 return STATUS_NOT_IMPLEMENTED
;
872 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
,
875 struct object
*object
= get_object( handle
, 0 );
877 TRACE( "%p, %s, %p, %lu, %p, %#lx\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
879 if (!object
) return STATUS_INVALID_HANDLE
;
880 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
882 switch (object
->magic
)
886 const struct algorithm
*alg
= (const struct algorithm
*)object
;
887 return get_alg_property( alg
, prop
, buffer
, count
, res
);
891 const struct key
*key
= (const struct key
*)object
;
892 return get_key_property( key
, prop
, buffer
, count
, res
);
896 const struct hash
*hash
= (const struct hash
*)object
;
897 return get_hash_property( hash
, prop
, buffer
, count
, res
);
900 WARN( "unknown magic %#lx\n", object
->magic
);
901 return STATUS_INVALID_HANDLE
;
905 static NTSTATUS
hash_prepare( struct hash
*hash
)
907 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
911 /* initialize hash */
912 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) return status
;
913 if (!(hash
->flags
& HASH_FLAG_HMAC
)) return STATUS_SUCCESS
;
915 /* initialize hmac */
916 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) return status
;
917 block_bytes
= builtin_algorithms
[hash
->alg_id
].block_bits
/ 8;
918 if (hash
->secret_len
> block_bytes
)
920 struct hash_impl temp
;
921 if ((status
= hash_init( &temp
, hash
->alg_id
))) return status
;
922 if ((status
= hash_update( &temp
, hash
->alg_id
, hash
->secret
, hash
->secret_len
))) return status
;
923 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
924 builtin_algorithms
[hash
->alg_id
].hash_length
))) return status
;
926 else memcpy( buffer
, hash
->secret
, hash
->secret_len
);
928 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
929 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) return status
;
930 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
931 return hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
934 static NTSTATUS
hash_create( const struct algorithm
*alg
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
,
935 struct hash
**ret_hash
)
940 if (!(hash
= calloc( 1, sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
941 hash
->hdr
.magic
= MAGIC_HASH
;
942 hash
->alg_id
= alg
->id
;
943 if (alg
->flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
) hash
->flags
= HASH_FLAG_HMAC
;
944 if ((alg
->flags
& BCRYPT_HASH_REUSABLE_FLAG
) || (flags
& BCRYPT_HASH_REUSABLE_FLAG
))
945 hash
->flags
|= HASH_FLAG_REUSABLE
;
947 if (secret_len
&& !(hash
->secret
= malloc( secret_len
)))
950 return STATUS_NO_MEMORY
;
952 memcpy( hash
->secret
, secret
, secret_len
);
953 hash
->secret_len
= secret_len
;
955 if ((status
= hash_prepare( hash
)))
957 free( hash
->secret
);
963 return STATUS_SUCCESS
;
966 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE handle
, BCRYPT_HASH_HANDLE
*ret_handle
, UCHAR
*object
,
967 ULONG object_len
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
)
969 struct algorithm
*alg
= get_alg_object( handle
);
973 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, ret_handle
, object
, object_len
, secret
, secret_len
, flags
);
974 if (flags
& ~BCRYPT_HASH_REUSABLE_FLAG
)
976 FIXME( "unimplemented flags %#lx\n", flags
);
977 return STATUS_NOT_IMPLEMENTED
;
979 if (object
) FIXME( "ignoring object buffer\n" );
981 if (!alg
) return STATUS_INVALID_HANDLE
;
982 if (!ret_handle
) return STATUS_INVALID_PARAMETER
;
984 if ((status
= hash_create( alg
, secret
, secret_len
, flags
, &hash
))) return status
;
986 return STATUS_SUCCESS
;
989 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
990 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
992 struct hash
*hash_orig
= get_hash_object( handle
);
993 struct hash
*hash_copy
;
995 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, handle_copy
, object
, objectlen
, flags
);
997 if (!hash_orig
) return STATUS_INVALID_HANDLE
;
998 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
999 if (object
) FIXME( "ignoring object buffer\n" );
1001 if (!(hash_copy
= malloc( sizeof(*hash_copy
) ))) return STATUS_NO_MEMORY
;
1003 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
1004 if (hash_orig
->secret
&& !(hash_copy
->secret
= malloc( hash_orig
->secret_len
)))
1007 return STATUS_NO_MEMORY
;
1009 memcpy( hash_copy
->secret
, hash_orig
->secret
, hash_orig
->secret_len
);
1011 *handle_copy
= hash_copy
;
1012 return STATUS_SUCCESS
;
1015 static void hash_destroy( struct hash
*hash
)
1018 free( hash
->secret
);
1019 destroy_object( &hash
->hdr
);
1022 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
1024 struct hash
*hash
= get_hash_object( handle
);
1026 TRACE( "%p\n", handle
);
1028 if (!hash
) return STATUS_INVALID_PARAMETER
;
1029 hash_destroy( hash
);
1030 return STATUS_SUCCESS
;
1033 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
1035 struct hash
*hash
= get_hash_object( handle
);
1037 TRACE( "%p, %p, %lu, %#lx\n", handle
, input
, size
, flags
);
1039 if (!hash
) return STATUS_INVALID_HANDLE
;
1040 if (!input
) return STATUS_SUCCESS
;
1042 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
1045 static NTSTATUS
hash_finalize( struct hash
*hash
, UCHAR
*output
, ULONG size
)
1047 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
1051 if (!(hash
->flags
& HASH_FLAG_HMAC
))
1053 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
))) return status
;
1054 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
1055 return STATUS_SUCCESS
;
1058 hash_length
= builtin_algorithms
[hash
->alg_id
].hash_length
;
1059 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
1060 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
1061 if ((status
= hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
))) return status
;
1063 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
1064 return STATUS_SUCCESS
;
1067 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
1069 struct hash
*hash
= get_hash_object( handle
);
1071 TRACE( "%p, %p, %lu, %#lx\n", handle
, output
, size
, flags
);
1073 if (!hash
) return STATUS_INVALID_HANDLE
;
1074 if (!output
) return STATUS_INVALID_PARAMETER
;
1076 return hash_finalize( hash
, output
, size
);
1079 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE handle
, UCHAR
*secret
, ULONG secret_len
,
1080 UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
1082 struct algorithm
*alg
= get_alg_object( handle
);
1086 TRACE( "%p, %p, %lu, %p, %lu, %p, %lu\n", handle
, secret
, secret_len
, input
, input_len
, output
, output_len
);
1088 if (!alg
) return STATUS_INVALID_HANDLE
;
1090 if ((status
= hash_create( alg
, secret
, secret_len
, 0, &hash
))) return status
;
1091 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, input
, input_len
)))
1093 hash_destroy( hash
);
1096 status
= hash_finalize( hash
, output
, output_len
);
1097 hash_destroy( hash
);
1101 static NTSTATUS
key_asymmetric_create( enum alg_id alg_id
, ULONG bitlen
, struct key
**ret_key
)
1107 ERR( "no encryption support\n" );
1108 return STATUS_NOT_IMPLEMENTED
;
1111 if (!(key
= calloc( 1, sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1112 key
->hdr
.magic
= MAGIC_KEY
;
1113 key
->alg_id
= alg_id
;
1114 key
->u
.a
.bitlen
= bitlen
;
1117 return STATUS_SUCCESS
;
1120 static BOOL
key_is_symmetric( struct key
*key
)
1122 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_CIPHER_INTERFACE
;
1125 static BOOL
is_equal_vector( const UCHAR
*vector
, ULONG len
, const UCHAR
*vector2
, ULONG len2
)
1127 if (!vector
&& !vector2
) return TRUE
;
1128 if (len
!= len2
) return FALSE
;
1129 return !memcmp( vector
, vector2
, len
);
1132 static NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
, BOOL force_reset
)
1134 BOOL needs_reset
= force_reset
|| !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
);
1136 free( key
->u
.s
.vector
);
1137 key
->u
.s
.vector
= NULL
;
1138 key
->u
.s
.vector_len
= 0;
1141 if (!(key
->u
.s
.vector
= malloc( vector_len
))) return STATUS_NO_MEMORY
;
1142 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
1143 key
->u
.s
.vector_len
= vector_len
;
1145 if (needs_reset
) UNIX_CALL( key_symmetric_vector_reset
, key
);
1146 return STATUS_SUCCESS
;
1149 static struct key
*create_symmetric_key( enum alg_id alg
, enum chain_mode mode
, ULONG block_size
, UCHAR
*secret
,
1154 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
1155 InitializeCriticalSection( &ret
->u
.s
.cs
);
1156 ret
->hdr
.magic
= MAGIC_KEY
;
1158 ret
->u
.s
.mode
= mode
;
1159 ret
->u
.s
.block_size
= block_size
;
1161 if (!(ret
->u
.s
.secret
= malloc( secret_len
)))
1163 DeleteCriticalSection( &ret
->u
.s
.cs
);
1167 memcpy( ret
->u
.s
.secret
, secret
, secret_len
);
1168 ret
->u
.s
.secret_len
= secret_len
;
1173 static ULONG
get_block_size( struct algorithm
*alg
)
1175 ULONG ret
= 0, size
= sizeof(ret
);
1176 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
1180 static NTSTATUS
generate_symmetric_key( struct algorithm
*alg
, BCRYPT_KEY_HANDLE
*ret_handle
, UCHAR
*secret
,
1183 BCRYPT_KEY_LENGTHS_STRUCT key_lengths
;
1184 ULONG block_size
, size
;
1188 if (!(block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1189 if (!get_alg_property( alg
, BCRYPT_KEY_LENGTHS
, (UCHAR
*)&key_lengths
, sizeof(key_lengths
), &size
))
1191 if (secret_len
> (size
= key_lengths
.dwMaxLength
/ 8))
1193 WARN( "secret_len %lu exceeds key max length %lu, setting to maximum\n", secret_len
, size
);
1196 else if (secret_len
< (size
= key_lengths
.dwMinLength
/ 8))
1198 WARN( "secret_len %lu is less than minimum key length %lu\n", secret_len
, size
);
1199 return STATUS_INVALID_PARAMETER
;
1201 else if (key_lengths
.dwIncrement
&& (secret_len
* 8 - key_lengths
.dwMinLength
) % key_lengths
.dwIncrement
)
1203 WARN( "secret_len %lu is not a valid key length\n", secret_len
);
1204 return STATUS_INVALID_PARAMETER
;
1208 if (!(key
= create_symmetric_key( alg
->id
, alg
->mode
, block_size
, secret
, secret_len
))) status
= STATUS_NO_MEMORY
;
1212 status
= STATUS_SUCCESS
;
1218 static NTSTATUS
key_import( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
1219 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
1223 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1225 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
1227 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
)) return STATUS_BUFFER_TOO_SMALL
;
1228 if (header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
) return STATUS_INVALID_PARAMETER
;
1229 if (header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
1231 FIXME( "unknown key data blob version %lu\n", header
->dwVersion
);
1232 return STATUS_INVALID_PARAMETER
;
1234 len
= header
->cbKeyData
;
1235 if (len
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
) return STATUS_INVALID_PARAMETER
;
1237 return generate_symmetric_key( alg
, key
, (UCHAR
*)&header
[1], len
);
1239 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1241 if (input_len
< sizeof(len
)) return STATUS_BUFFER_TOO_SMALL
;
1242 len
= *(ULONG
*)input
;
1243 if (len
+ sizeof(len
) > input_len
) return STATUS_INVALID_PARAMETER
;
1245 return generate_symmetric_key( alg
, key
, input
+ sizeof(len
), len
);
1248 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1249 return STATUS_NOT_IMPLEMENTED
;
1252 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1254 struct key_asymmetric_export_params params
;
1256 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1258 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
1259 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
1262 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1265 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
1266 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
1267 header
->cbKeyData
= key
->u
.s
.secret_len
;
1268 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1270 return STATUS_SUCCESS
;
1272 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1274 ULONG len
, req_size
= sizeof(len
) + key
->u
.s
.secret_len
;
1277 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1280 *(ULONG
*)output
= key
->u
.s
.secret_len
;
1281 memcpy( output
+ sizeof(len
), key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1283 return STATUS_SUCCESS
;
1285 else if (!wcscmp( type
, BCRYPT_DSA_PRIVATE_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
) ||
1286 !wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1290 params
.buf
= output
;
1291 params
.len
= output_len
;
1292 params
.ret_len
= size
;
1293 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1295 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1298 params
.flags
= (wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
)) ? KEY_EXPORT_FLAG_RSA_FULL
: 0;
1299 params
.buf
= output
;
1300 params
.len
= output_len
;
1301 params
.ret_len
= size
;
1302 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1304 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
) ||
1305 !wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
) || !wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1308 params
.flags
= KEY_EXPORT_FLAG_PUBLIC
;
1309 params
.buf
= output
;
1310 params
.len
= output_len
;
1311 params
.ret_len
= size
;
1312 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1315 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1316 return STATUS_NOT_IMPLEMENTED
;
1319 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1320 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1322 struct key_symmetric_set_auth_data_params auth_params
;
1323 struct key_symmetric_encrypt_params encrypt_params
;
1324 struct key_symmetric_get_tag_params tag_params
;
1325 ULONG bytes_left
= input_len
;
1329 if (key
->u
.s
.mode
== CHAIN_MODE_GCM
)
1331 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1333 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1334 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1335 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1336 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1337 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1338 FIXME( "call chaining not implemented\n" );
1340 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
, TRUE
)))
1343 *ret_len
= input_len
;
1344 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1345 if (input
&& !output
) return STATUS_SUCCESS
;
1346 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1348 auth_params
.key
= key
;
1349 auth_params
.auth_data
= auth_info
->pbAuthData
;
1350 auth_params
.len
= auth_info
->cbAuthData
;
1351 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1353 encrypt_params
.key
= key
;
1354 encrypt_params
.input
= input
;
1355 encrypt_params
.input_len
= input_len
;
1356 encrypt_params
.output
= output
;
1357 encrypt_params
.output_len
= output_len
;
1358 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
))) return status
;
1360 tag_params
.key
= key
;
1361 tag_params
.tag
= auth_info
->pbTag
;
1362 tag_params
.len
= auth_info
->cbTag
;
1363 return UNIX_CALL( key_symmetric_get_tag
, &tag_params
);
1366 *ret_len
= input_len
;
1368 if (flags
& BCRYPT_BLOCK_PADDING
)
1369 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1370 else if (input_len
& (key
->u
.s
.block_size
- 1))
1371 return STATUS_INVALID_BUFFER_SIZE
;
1373 if (!output
) return STATUS_SUCCESS
;
1374 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1375 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1376 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
, flags
& BCRYPT_BLOCK_PADDING
))) return status
;
1378 encrypt_params
.key
= key
;
1379 encrypt_params
.input
= input
;
1380 encrypt_params
.input_len
= key
->u
.s
.block_size
;
1381 encrypt_params
.output
= output
;
1382 encrypt_params
.output_len
= key
->u
.s
.block_size
;
1383 while (bytes_left
>= key
->u
.s
.block_size
)
1385 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
)))
1387 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0, TRUE
)))
1389 bytes_left
-= key
->u
.s
.block_size
;
1390 encrypt_params
.input
+= key
->u
.s
.block_size
;
1391 encrypt_params
.output
+= key
->u
.s
.block_size
;
1394 if (flags
& BCRYPT_BLOCK_PADDING
)
1396 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1397 memcpy( buf
, encrypt_params
.input
, bytes_left
);
1398 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1399 encrypt_params
.input
= buf
;
1400 status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
);
1407 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1408 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1410 struct key_symmetric_set_auth_data_params auth_params
;
1411 struct key_symmetric_decrypt_params decrypt_params
;
1412 struct key_symmetric_get_tag_params tag_params
;
1413 ULONG bytes_left
= input_len
;
1416 if (key
->u
.s
.mode
== CHAIN_MODE_GCM
)
1418 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1421 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1422 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1423 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1424 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1426 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
, TRUE
)))
1429 *ret_len
= input_len
;
1430 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1431 if (!output
) return STATUS_SUCCESS
;
1432 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1434 auth_params
.key
= key
;
1435 auth_params
.auth_data
= auth_info
->pbAuthData
;
1436 auth_params
.len
= auth_info
->cbAuthData
;
1437 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1439 decrypt_params
.key
= key
;
1440 decrypt_params
.input
= input
;
1441 decrypt_params
.input_len
= input_len
;
1442 decrypt_params
.output
= output
;
1443 decrypt_params
.output_len
= output_len
;
1444 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1446 tag_params
.key
= key
;
1447 tag_params
.tag
= tag
;
1448 tag_params
.len
= sizeof(tag
);
1449 if ((status
= UNIX_CALL( key_symmetric_get_tag
, &tag_params
))) return status
;
1450 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1452 return STATUS_SUCCESS
;
1455 *ret_len
= input_len
;
1457 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1458 if (!output
) return STATUS_SUCCESS
;
1459 if (flags
& BCRYPT_BLOCK_PADDING
)
1461 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1462 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1463 bytes_left
-= key
->u
.s
.block_size
;
1465 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1467 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1468 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
, flags
& BCRYPT_BLOCK_PADDING
))) return status
;
1470 decrypt_params
.key
= key
;
1471 decrypt_params
.input
= input
;
1472 decrypt_params
.input_len
= key
->u
.s
.block_size
;
1473 decrypt_params
.output
= output
;
1474 decrypt_params
.output_len
= key
->u
.s
.block_size
;
1475 while (bytes_left
>= key
->u
.s
.block_size
)
1477 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1478 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0, TRUE
)))
1480 bytes_left
-= key
->u
.s
.block_size
;
1481 decrypt_params
.input
+= key
->u
.s
.block_size
;
1482 decrypt_params
.output
+= key
->u
.s
.block_size
;
1485 if (flags
& BCRYPT_BLOCK_PADDING
)
1487 UCHAR
*buf
, *dst
= decrypt_params
.output
;
1488 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1489 decrypt_params
.output
= buf
;
1490 status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
);
1491 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1493 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1494 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1495 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1497 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1504 static void key_destroy( struct key
*key
)
1506 if (key_is_symmetric( key
))
1508 UNIX_CALL( key_symmetric_destroy
, key
);
1509 free( key
->u
.s
.vector
);
1510 free( key
->u
.s
.secret
);
1511 DeleteCriticalSection( &key
->u
.s
.cs
);
1514 UNIX_CALL( key_asymmetric_destroy
, key
);
1516 destroy_object( &key
->hdr
);
1519 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1522 struct key_asymmetric_import_params params
;
1527 if (!wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
))
1529 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1530 DWORD key_size
, magic
;
1532 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1536 case ALG_ID_ECDH_P256
:
1538 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
1541 case ALG_ID_ECDH_P384
:
1543 magic
= BCRYPT_ECDH_PUBLIC_P384_MAGIC
;
1546 case ALG_ID_ECDSA_P256
:
1548 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
1551 case ALG_ID_ECDSA_P384
:
1553 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
1557 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1558 return STATUS_NOT_SUPPORTED
;
1561 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1562 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2)
1563 return STATUS_INVALID_PARAMETER
;
1565 if ((status
= key_asymmetric_create( alg
->id
, key_size
* 8, &key
))) return status
;
1567 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1569 params
.len
= input_len
;
1570 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1577 return STATUS_SUCCESS
;
1579 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1581 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1582 DWORD key_size
, magic
;
1584 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1588 case ALG_ID_ECDH_P256
:
1590 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
1593 case ALG_ID_ECDH_P384
:
1595 magic
= BCRYPT_ECDH_PRIVATE_P384_MAGIC
;
1598 case ALG_ID_ECDSA_P256
:
1600 magic
= BCRYPT_ECDSA_PRIVATE_P256_MAGIC
;
1604 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1605 return STATUS_NOT_SUPPORTED
;
1608 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1609 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 3)
1610 return STATUS_INVALID_PARAMETER
;
1612 if ((status
= key_asymmetric_create( alg
->id
, key_size
* 8, &key
))) return status
;
1616 params
.len
= input_len
;
1617 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1624 return STATUS_SUCCESS
;
1626 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1628 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1630 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1631 if ((alg
->id
!= ALG_ID_RSA
&& alg
->id
!= ALG_ID_RSA_SIGN
) || rsa_blob
->Magic
!= BCRYPT_RSAPUBLIC_MAGIC
)
1632 return STATUS_NOT_SUPPORTED
;
1634 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1635 if (size
!= input_len
) return NTE_BAD_DATA
;
1637 if ((status
= key_asymmetric_create( alg
->id
, rsa_blob
->BitLength
, &key
))) return status
;
1639 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1641 params
.len
= input_len
;
1642 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1649 return STATUS_SUCCESS
;
1651 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1653 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1655 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1656 if (alg
->id
!= ALG_ID_RSA
|| (rsa_blob
->Magic
!= BCRYPT_RSAPRIVATE_MAGIC
&&
1657 rsa_blob
->Magic
!= BCRYPT_RSAFULLPRIVATE_MAGIC
)) return STATUS_NOT_SUPPORTED
;
1659 if ((status
= key_asymmetric_create( alg
->id
, rsa_blob
->BitLength
, &key
))) return status
;
1663 params
.len
= input_len
;
1664 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1671 return STATUS_SUCCESS
;
1673 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
))
1675 BCRYPT_DSA_KEY_BLOB
*dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)input
;
1677 if (input_len
< sizeof(*dsa_blob
)) return STATUS_INVALID_PARAMETER
;
1678 if ((alg
->id
!= ALG_ID_DSA
) || dsa_blob
->dwMagic
!= BCRYPT_DSA_PUBLIC_MAGIC
)
1679 return STATUS_NOT_SUPPORTED
;
1681 if ((status
= key_asymmetric_create( alg
->id
, dsa_blob
->cbKey
* 8, &key
))) return status
;
1683 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1685 params
.len
= input_len
;
1686 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1693 return STATUS_SUCCESS
;
1695 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1697 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1700 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1702 if (hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1704 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1705 return STATUS_NOT_SUPPORTED
;
1707 if (alg
->id
!= ALG_ID_DSA
)
1709 FIXME( "algorithm %u does not support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1710 return STATUS_NOT_SUPPORTED
;
1713 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1714 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1715 if (pubkey
->magic
!= MAGIC_DSS2
) return STATUS_NOT_SUPPORTED
;
1717 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 2 + 40 + sizeof(DSSSEED
))
1718 return STATUS_INVALID_PARAMETER
;
1720 if ((status
= key_asymmetric_create( alg
->id
, pubkey
->bitlen
, &key
))) return status
;
1721 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1725 params
.len
= input_len
;
1726 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1733 return STATUS_SUCCESS
;
1735 else if (!wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
)) /* not supported on native */
1737 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1740 if (alg
->id
!= ALG_ID_DSA
) return STATUS_NOT_SUPPORTED
;
1741 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1743 if (hdr
->bType
!= PUBLICKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1745 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1746 return STATUS_NOT_SUPPORTED
;
1749 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1750 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1751 if (pubkey
->magic
!= MAGIC_DSS1
) return STATUS_NOT_SUPPORTED
;
1753 size
= sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 3 + 20 + sizeof(DSSSEED
);
1754 if (input_len
< size
) return STATUS_INVALID_PARAMETER
;
1756 if ((status
= key_asymmetric_create( alg
->id
, pubkey
->bitlen
, &key
))) return status
;
1757 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1759 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1761 params
.len
= input_len
;
1762 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1769 return STATUS_SUCCESS
;
1772 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1773 return STATUS_NOT_SUPPORTED
;
1776 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE
*ret_handle
,
1777 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1780 struct algorithm
*alg
= get_alg_object( handle
);
1782 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, ret_handle
, object
, object_len
, secret
, secret_len
, flags
);
1783 if (object
) FIXME( "ignoring object buffer\n" );
1786 ERR( "no encryption support\n" );
1787 return STATUS_NOT_IMPLEMENTED
;
1790 if (!alg
) return STATUS_INVALID_HANDLE
;
1791 return generate_symmetric_key( alg
, ret_handle
, secret
, secret_len
);
1794 NTSTATUS WINAPI
BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE
*ret_handle
, ULONG key_len
,
1797 struct algorithm
*alg
= get_alg_object( handle
);
1801 TRACE( "%p, %p, %lu, %#lx\n", handle
, ret_handle
, key_len
, flags
);
1803 if (!alg
) return STATUS_INVALID_HANDLE
;
1804 if (!ret_handle
) return STATUS_INVALID_PARAMETER
;
1806 if ((status
= key_asymmetric_create( alg
->id
, key_len
, &key
))) return status
;
1808 return STATUS_SUCCESS
;
1811 NTSTATUS WINAPI
BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle
, ULONG flags
)
1813 struct key
*key
= get_key_object( handle
);
1815 TRACE( "%p, %#lx\n", key
, flags
);
1817 if (!key
) return STATUS_INVALID_HANDLE
;
1818 return UNIX_CALL( key_asymmetric_generate
, key
);
1821 NTSTATUS WINAPI
BCryptImportKey( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1822 BCRYPT_KEY_HANDLE
*ret_handle
, UCHAR
*object
, ULONG object_len
, UCHAR
*input
,
1823 ULONG input_len
, ULONG flags
)
1825 struct algorithm
*alg
= get_alg_object( handle
);
1827 TRACE( "%p, %p, %s, %p, %p, %lu, %p, %lu, %#lx\n", handle
, decrypt_key
, debugstr_w(type
), ret_handle
, object
,
1828 object_len
, input
, input_len
, flags
);
1830 if (!alg
) return STATUS_INVALID_HANDLE
;
1831 if (!ret_handle
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1834 FIXME( "decryption of key not yet supported\n" );
1835 return STATUS_NOT_IMPLEMENTED
;
1838 return key_import( alg
, type
, ret_handle
, object
, object_len
, input
, input_len
);
1841 NTSTATUS WINAPI
BCryptExportKey( BCRYPT_KEY_HANDLE export_key_handle
, BCRYPT_KEY_HANDLE encrypt_key_handle
,
1842 const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1844 struct key
*key
= get_key_object( export_key_handle
);
1846 TRACE( "%p, %p, %s, %p, %lu, %p, %#lx\n", export_key_handle
, encrypt_key_handle
, debugstr_w(type
), output
,
1847 output_len
, size
, flags
);
1849 if (!key
) return STATUS_INVALID_HANDLE
;
1850 if (!type
|| !size
) return STATUS_INVALID_PARAMETER
;
1851 if (encrypt_key_handle
)
1853 FIXME( "encryption of key not yet supported\n" );
1854 return STATUS_NOT_IMPLEMENTED
;
1857 return key_export( key
, type
, output
, output_len
, size
);
1860 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
1865 memset( key_copy
, 0, sizeof(*key_copy
) );
1866 key_copy
->hdr
= key_orig
->hdr
;
1867 key_copy
->alg_id
= key_orig
->alg_id
;
1869 if (key_is_symmetric( key_orig
))
1871 if (!(buffer
= malloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
1872 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
1874 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
1875 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
1876 key_copy
->u
.s
.secret
= buffer
;
1877 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
1878 InitializeCriticalSection( &key_copy
->u
.s
.cs
);
1882 struct key_asymmetric_duplicate_params params
;
1884 key_copy
->u
.a
.bitlen
= key_orig
->u
.a
.bitlen
;
1885 key_copy
->u
.a
.flags
= key_orig
->u
.a
.flags
;
1886 key_copy
->u
.a
.dss_seed
= key_orig
->u
.a
.dss_seed
;
1888 params
.key_orig
= key_orig
;
1889 params
.key_copy
= key_copy
;
1890 if ((status
= UNIX_CALL( key_asymmetric_duplicate
, ¶ms
))) return status
;
1893 return STATUS_SUCCESS
;
1896 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
1897 UCHAR
*object
, ULONG object_len
, ULONG flags
)
1899 struct key
*key_orig
= get_key_object( handle
);
1900 struct key
*key_copy
;
1903 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, handle_copy
, object
, object_len
, flags
);
1904 if (object
) FIXME( "ignoring object buffer\n" );
1906 if (!key_orig
) return STATUS_INVALID_HANDLE
;
1907 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1908 if (!(key_copy
= malloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
1910 if ((status
= key_duplicate( key_orig
, key_copy
)))
1912 key_destroy( key_copy
);
1916 *handle_copy
= key_copy
;
1917 return STATUS_SUCCESS
;
1920 static const WCHAR
*resolve_blob_type( const WCHAR
*type
, UCHAR
*input
, ULONG input_len
)
1922 BCRYPT_KEY_BLOB
*blob
= (BCRYPT_KEY_BLOB
*)input
;
1924 if (!type
) return NULL
;
1925 if (wcscmp( type
, BCRYPT_PUBLIC_KEY_BLOB
)) return type
;
1926 if (input_len
< sizeof(*blob
)) return NULL
;
1928 switch (blob
->Magic
)
1930 case BCRYPT_ECDH_PUBLIC_P256_MAGIC
:
1931 case BCRYPT_ECDH_PUBLIC_P384_MAGIC
:
1932 case BCRYPT_ECDSA_PUBLIC_P256_MAGIC
:
1933 case BCRYPT_ECDSA_PUBLIC_P384_MAGIC
:
1934 return BCRYPT_ECCPUBLIC_BLOB
;
1936 case BCRYPT_RSAPUBLIC_MAGIC
:
1937 return BCRYPT_RSAPUBLIC_BLOB
;
1939 case BCRYPT_DSA_PUBLIC_MAGIC
:
1940 return BCRYPT_DSA_PUBLIC_BLOB
;
1943 FIXME( "unsupported key magic %#lx\n", blob
->Magic
);
1948 NTSTATUS WINAPI
BCryptImportKeyPair( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE decrypt_key_handle
, const WCHAR
*type
,
1949 BCRYPT_KEY_HANDLE
*ret_handle
, UCHAR
*input
, ULONG input_len
, ULONG flags
)
1951 struct algorithm
*alg
= get_alg_object( handle
);
1953 TRACE( "%p, %p, %s, %p, %p, %lu, %#lx\n", handle
, decrypt_key_handle
, debugstr_w(type
), ret_handle
, input
,
1956 if (!alg
) return STATUS_INVALID_HANDLE
;
1957 if (!ret_handle
|| !input
|| !(type
= resolve_blob_type( type
, input
, input_len
)))
1958 return STATUS_INVALID_PARAMETER
;
1959 if (decrypt_key_handle
)
1961 FIXME( "decryption of key not yet supported\n" );
1962 return STATUS_NOT_IMPLEMENTED
;
1965 return key_import_pair( alg
, type
, ret_handle
, input
, input_len
);
1968 NTSTATUS WINAPI
BCryptSignHash( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*input
, ULONG input_len
,
1969 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1971 struct key_asymmetric_sign_params params
;
1972 struct key
*key
= get_key_object( handle
);
1974 TRACE( "%p, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, padding
, input
, input_len
, output
, output_len
,
1977 if (!key
) return STATUS_INVALID_HANDLE
;
1978 if (key_is_symmetric( key
))
1980 FIXME( "signing with symmetric keys not yet supported\n" );
1981 return STATUS_NOT_IMPLEMENTED
;
1985 params
.padding
= padding
;
1986 params
.input
= input
;
1987 params
.input_len
= input_len
;
1988 params
.output
= output
;
1989 params
.output_len
= output_len
;
1990 params
.ret_len
= ret_len
;
1991 params
.flags
= flags
;
1992 return UNIX_CALL( key_asymmetric_sign
, ¶ms
);
1995 NTSTATUS WINAPI
BCryptVerifySignature( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*hash
, ULONG hash_len
,
1996 UCHAR
*signature
, ULONG signature_len
, ULONG flags
)
1998 struct key_asymmetric_verify_params params
;
1999 struct key
*key
= get_key_object( handle
);
2001 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
2003 if (!key
) return STATUS_INVALID_HANDLE
;
2004 if (!hash
|| !hash_len
|| !signature
|| !signature_len
) return STATUS_INVALID_PARAMETER
;
2005 if (key_is_symmetric( key
)) return STATUS_NOT_SUPPORTED
;
2008 params
.padding
= padding
;
2010 params
.hash_len
= hash_len
;
2011 params
.signature
= signature
;
2012 params
.signature_len
= signature_len
;
2013 params
.flags
= flags
;
2014 return UNIX_CALL( key_asymmetric_verify
, ¶ms
);
2017 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
2019 struct key
*key
= get_key_object( handle
);
2021 TRACE( "%p\n", handle
);
2023 if (!key
) return STATUS_INVALID_HANDLE
;
2025 return STATUS_SUCCESS
;
2028 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
2029 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
2031 struct key
*key
= get_key_object( handle
);
2032 struct key_asymmetric_encrypt_params asymmetric_params
;
2035 TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
2036 output_len
, ret_len
, flags
);
2038 if (!key
) return STATUS_INVALID_HANDLE
;
2040 if (key_is_symmetric( key
))
2042 if (flags
& ~BCRYPT_BLOCK_PADDING
)
2044 FIXME( "flags %#lx not implemented\n", flags
);
2045 return STATUS_NOT_IMPLEMENTED
;
2047 EnterCriticalSection( &key
->u
.s
.cs
);
2048 ret
= key_symmetric_encrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
2049 LeaveCriticalSection( &key
->u
.s
.cs
);
2053 if (flags
& BCRYPT_PAD_NONE
|| flags
& BCRYPT_PAD_OAEP
)
2055 FIXME( "flags %#lx not implemented\n", flags
);
2056 return STATUS_NOT_IMPLEMENTED
;
2058 asymmetric_params
.input
= input
;
2059 asymmetric_params
.input_len
= input_len
;
2060 asymmetric_params
.key
= key
;
2061 asymmetric_params
.output
= output
;
2062 asymmetric_params
.output_len
= output_len
;
2063 asymmetric_params
.ret_len
= ret_len
;
2064 ret
= UNIX_CALL(key_asymmetric_encrypt
, &asymmetric_params
);
2070 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
2071 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
2073 struct key
*key
= get_key_object( handle
);
2074 struct key_asymmetric_decrypt_params params
;
2077 TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
2078 output_len
, ret_len
, flags
);
2080 if (!key
) return STATUS_INVALID_HANDLE
;
2082 if (key_is_symmetric( key
))
2084 if (flags
& ~BCRYPT_BLOCK_PADDING
)
2086 FIXME( "flags %#lx not supported\n", flags
);
2087 return STATUS_NOT_IMPLEMENTED
;
2090 EnterCriticalSection( &key
->u
.s
.cs
);
2091 ret
= key_symmetric_decrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
2092 LeaveCriticalSection( &key
->u
.s
.cs
);
2096 if (flags
& BCRYPT_PAD_NONE
|| flags
& BCRYPT_PAD_OAEP
)
2098 FIXME( "flags %#lx not implemented\n", flags
);
2099 return STATUS_NOT_IMPLEMENTED
;
2102 params
.input
= input
;
2103 params
.input_len
= input_len
;
2104 params
.output
= output
;
2105 params
.output_len
= output_len
;
2106 params
.ret_len
= ret_len
;
2107 ret
= UNIX_CALL(key_asymmetric_decrypt
, ¶ms
);
2113 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
2115 struct object
*object
= get_object( handle
, 0 );
2117 TRACE( "%p, %s, %p, %lu, %#lx\n", handle
, debugstr_w(prop
), value
, size
, flags
);
2119 if (!handle
) return STATUS_INVALID_HANDLE
;
2120 if (is_alg_pseudo_handle( handle
)) return STATUS_ACCESS_DENIED
;
2122 switch (object
->magic
)
2126 struct algorithm
*alg
= (struct algorithm
*)object
;
2127 return set_alg_property( alg
, prop
, value
, size
, flags
);
2131 struct key
*key
= (struct key
*)object
;
2132 return set_key_property( key
, prop
, value
, size
, flags
);
2135 WARN( "unknown magic %#lx\n", object
->magic
);
2136 return STATUS_INVALID_HANDLE
;
2140 #define HMAC_PAD_LEN 64
2141 NTSTATUS WINAPI
BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle
, BCRYPT_ALG_HANDLE halg
, UCHAR
*key
, ULONG keylen
, ULONG flags
)
2143 struct hash
*hash
= get_hash_object( handle
);
2144 UCHAR buf
[MAX_HASH_OUTPUT_BYTES
* 2];
2148 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, halg
, key
, keylen
, flags
);
2150 if (!hash
) return STATUS_INVALID_HANDLE
;
2151 if (!key
|| !keylen
) return STATUS_INVALID_PARAMETER
;
2152 if (keylen
> builtin_algorithms
[hash
->alg_id
].hash_length
* 2) return STATUS_INVALID_PARAMETER
;
2155 FIXME( "algorithm handle not supported\n" );
2156 return STATUS_NOT_IMPLEMENTED
;
2159 len
= builtin_algorithms
[hash
->alg_id
].hash_length
;
2160 if ((status
= hash_finalize( hash
, buf
, len
))) return status
;
2164 UCHAR pad1
[HMAC_PAD_LEN
], pad2
[HMAC_PAD_LEN
];
2167 for (i
= 0; i
< sizeof(pad1
); i
++)
2169 pad1
[i
] = 0x36 ^ (i
< len
? buf
[i
] : 0);
2170 pad2
[i
] = 0x5c ^ (i
< len
? buf
[i
] : 0);
2173 if ((status
= hash_prepare( hash
)) ||
2174 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad1
, sizeof(pad1
) )) ||
2175 (status
= hash_finalize( hash
, buf
, len
))) return status
;
2177 if ((status
= hash_prepare( hash
)) ||
2178 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad2
, sizeof(pad2
) )) ||
2179 (status
= hash_finalize( hash
, buf
+ len
, len
))) return status
;
2182 memcpy( key
, buf
, keylen
);
2183 return STATUS_SUCCESS
;
2186 static NTSTATUS
pbkdf2( struct hash
*hash
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2187 ULONGLONG iterations
, ULONG i
, UCHAR
*dst
, ULONG hash_len
)
2189 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
2190 UCHAR bytes
[4], *buf
;
2193 if (!(buf
= malloc( hash_len
))) return STATUS_NO_MEMORY
;
2195 for (j
= 0; j
< iterations
; j
++)
2199 /* use salt || INT(i) */
2200 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, salt
, salt_len
)))
2205 bytes
[0] = (i
>> 24) & 0xff;
2206 bytes
[1] = (i
>> 16) & 0xff;
2207 bytes
[2] = (i
>> 8) & 0xff;
2208 bytes
[3] = i
& 0xff;
2209 status
= hash_update( &hash
->inner
, hash
->alg_id
, bytes
, 4 );
2211 else status
= hash_update( &hash
->inner
, hash
->alg_id
, buf
, hash_len
); /* use U_j */
2219 if ((status
= hash_finalize( hash
, buf
, hash_len
)))
2225 if (j
== 0) memcpy( dst
, buf
, hash_len
);
2226 else for (k
= 0; k
< hash_len
; k
++) dst
[k
] ^= buf
[k
];
2233 static NTSTATUS
derive_key_pbkdf2( struct algorithm
*alg
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2234 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
)
2236 ULONG hash_len
, block_count
, bytes_left
, i
;
2241 hash_len
= builtin_algorithms
[alg
->id
].hash_length
;
2242 if (dk_len
<= 0 || dk_len
> ((((ULONGLONG
)1) << 32) - 1) * hash_len
) return STATUS_INVALID_PARAMETER
;
2244 block_count
= 1 + ((dk_len
- 1) / hash_len
); /* ceil(dk_len / hash_len) */
2245 bytes_left
= dk_len
- (block_count
- 1) * hash_len
;
2247 if ((status
= hash_create( alg
, pwd
, pwd_len
, BCRYPT_HASH_REUSABLE_FLAG
, &hash
))) return status
;
2250 for (i
= 1; i
< block_count
; i
++)
2252 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, i
, dk
+ ((i
- 1) * hash_len
), hash_len
)))
2254 hash_destroy( hash
);
2259 /* final partial block */
2260 if (!(partial
= malloc( hash_len
)))
2262 hash_destroy( hash
);
2263 return STATUS_NO_MEMORY
;
2266 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, block_count
, partial
, hash_len
)))
2268 hash_destroy( hash
);
2272 memcpy( dk
+ ((block_count
- 1) * hash_len
), partial
, bytes_left
);
2274 hash_destroy( hash
);
2276 return STATUS_SUCCESS
;
2279 NTSTATUS WINAPI
BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2280 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
, ULONG flags
)
2282 struct algorithm
*alg
= get_alg_object( handle
);
2284 TRACE( "%p, %p, %lu, %p, %lu, %s, %p, %lu, %#lx\n", handle
, pwd
, pwd_len
, salt
, salt_len
,
2285 wine_dbgstr_longlong(iterations
), dk
, dk_len
, flags
);
2287 if (!alg
) return STATUS_INVALID_HANDLE
;
2288 return derive_key_pbkdf2( alg
, pwd
, pwd_len
, salt
, salt_len
, iterations
, dk
, dk_len
);
2291 NTSTATUS WINAPI
BCryptSecretAgreement( BCRYPT_KEY_HANDLE privkey_handle
, BCRYPT_KEY_HANDLE pubkey_handle
,
2292 BCRYPT_SECRET_HANDLE
*ret_handle
, ULONG flags
)
2294 struct key
*privkey
= get_key_object( privkey_handle
);
2295 struct key
*pubkey
= get_key_object( pubkey_handle
);
2296 struct secret
*secret
;
2298 FIXME( "%p, %p, %p, %#lx\n", privkey_handle
, pubkey_handle
, ret_handle
, flags
);
2300 if (!privkey
|| !pubkey
) return STATUS_INVALID_HANDLE
;
2301 if (!ret_handle
) return STATUS_INVALID_PARAMETER
;
2303 if (!(secret
= calloc( 1, sizeof(*secret
) ))) return STATUS_NO_MEMORY
;
2304 secret
->hdr
.magic
= MAGIC_SECRET
;
2306 *ret_handle
= secret
;
2307 return STATUS_SUCCESS
;
2310 NTSTATUS WINAPI
BCryptDestroySecret( BCRYPT_SECRET_HANDLE handle
)
2312 struct secret
*secret
= get_secret_object( handle
);
2314 FIXME( "%p\n", handle
);
2316 if (!secret
) return STATUS_INVALID_HANDLE
;
2317 destroy_object( &secret
->hdr
);
2318 return STATUS_SUCCESS
;
2321 NTSTATUS WINAPI
BCryptDeriveKey( BCRYPT_SECRET_HANDLE handle
, const WCHAR
*kdf
, BCryptBufferDesc
*parameter
,
2322 UCHAR
*derived
, ULONG derived_size
, ULONG
*result
, ULONG flags
)
2324 struct secret
*secret
= get_secret_object( handle
);
2326 FIXME( "%p, %s, %p, %p, %lu, %p, %#lx\n", secret
, debugstr_w(kdf
), parameter
, derived
, derived_size
, result
, flags
);
2328 if (!secret
) return STATUS_INVALID_HANDLE
;
2329 if (!kdf
) return STATUS_INVALID_PARAMETER
;
2331 return STATUS_INTERNAL_ERROR
;
2334 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
2338 case DLL_PROCESS_ATTACH
:
2339 DisableThreadLibraryCalls( hinst
);
2340 if (!NtQueryVirtualMemory( GetCurrentProcess(), hinst
, MemoryWineUnixFuncs
,
2341 &bcrypt_handle
, sizeof(bcrypt_handle
), NULL
))
2343 if (UNIX_CALL( process_attach
, NULL
)) bcrypt_handle
= 0;
2346 case DLL_PROCESS_DETACH
:
2347 if (reserved
) break;
2348 if (bcrypt_handle
) UNIX_CALL( process_detach
, NULL
);