bcrypt: Add support for BCRYPT_DSA_ALGORITHM.
[wine.git] / dlls / bcrypt / bcrypt_main.c
blob5492c1947e325a6a203483982902993877d2cc6a
1 /*
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
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
25 #include <AvailabilityMacros.h>
26 #include <CommonCrypto/CommonCryptor.h>
27 #endif
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "ntsecapi.h"
34 #include "bcrypt.h"
36 #include "bcrypt_internal.h"
38 #include "wine/debug.h"
39 #include "wine/heap.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
44 static HINSTANCE instance;
46 NTSTATUS WINAPI BCryptAddContextFunction(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, ULONG pos)
48 FIXME("%08x, %s, %08x, %s, %u: stub\n", table, debugstr_w(context), iface, debugstr_w(function), pos);
49 return STATUS_SUCCESS;
52 NTSTATUS WINAPI BCryptAddContextFunctionProvider(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, LPCWSTR provider, ULONG pos)
54 FIXME("%08x, %s, %08x, %s, %s, %u: stub\n", table, debugstr_w(context), iface, debugstr_w(function), debugstr_w(provider), pos);
55 return STATUS_SUCCESS;
58 NTSTATUS WINAPI BCryptRemoveContextFunction(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function)
60 FIXME("%08x, %s, %08x, %s: stub\n", table, debugstr_w(context), iface, debugstr_w(function));
61 return STATUS_NOT_IMPLEMENTED;
64 NTSTATUS WINAPI BCryptRemoveContextFunctionProvider(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, LPCWSTR provider)
66 FIXME("%08x, %s, %08x, %s, %s: stub\n", table, debugstr_w(context), iface, debugstr_w(function), debugstr_w(provider));
67 return STATUS_NOT_IMPLEMENTED;
70 NTSTATUS WINAPI BCryptEnumContextFunctions( ULONG table, const WCHAR *ctx, ULONG iface, ULONG *buflen,
71 CRYPT_CONTEXT_FUNCTIONS **buffer )
73 FIXME( "%u, %s, %u, %p, %p\n", table, debugstr_w(ctx), iface, buflen, buffer );
74 return STATUS_NOT_IMPLEMENTED;
77 void WINAPI BCryptFreeBuffer( void *buffer )
79 FIXME( "%p\n", buffer );
82 NTSTATUS WINAPI BCryptRegisterProvider(LPCWSTR provider, ULONG flags, PCRYPT_PROVIDER_REG reg)
84 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider), flags, reg);
85 return STATUS_SUCCESS;
88 NTSTATUS WINAPI BCryptUnregisterProvider(LPCWSTR provider)
90 FIXME("%s: stub\n", debugstr_w(provider));
91 return STATUS_NOT_IMPLEMENTED;
94 #define MAX_HASH_OUTPUT_BYTES 64
95 #define MAX_HASH_BLOCK_BITS 1024
97 /* ordered by class, keep in sync with enum alg_id */
98 static const struct
100 const WCHAR *name;
101 ULONG class;
102 ULONG object_length;
103 ULONG hash_length;
104 ULONG block_bits;
106 builtin_algorithms[] =
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;
128 switch (class)
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;
136 default: break;
138 return FALSE;
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, count = 0;
152 TRACE( "%08x, %p, %p, %08x\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 = heap_alloc( count * sizeof(*list) ))) return STATUS_NO_MEMORY;
163 for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
165 if (!match_operation_type( type, builtin_algorithms[i].class )) continue;
166 list[i].pszName = (WCHAR *)builtin_algorithms[i].name;
167 list[i].dwClass = builtin_algorithms[i].class;
168 list[i].dwFlags = 0;
171 *ret_count = count;
172 *ret_list = list;
173 return STATUS_SUCCESS;
176 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
178 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
179 struct algorithm *algorithm = handle;
181 TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags);
183 if (!algorithm)
185 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
186 * is set. In this case the preferred system RNG is used.
188 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
189 return STATUS_INVALID_HANDLE;
191 else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
192 return STATUS_INVALID_HANDLE;
194 if (!buffer)
195 return STATUS_INVALID_PARAMETER;
197 if (flags & ~supported_flags)
198 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
200 if (algorithm)
201 FIXME("ignoring selected algorithm\n");
203 /* When zero bytes are requested the function returns success too. */
204 if (!count)
205 return STATUS_SUCCESS;
207 if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
209 if (RtlGenRandom(buffer, count))
210 return STATUS_SUCCESS;
213 FIXME("called with unsupported parameters, returning error\n");
214 return STATUS_NOT_IMPLEMENTED;
217 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
219 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG | BCRYPT_HASH_REUSABLE_FLAG;
220 struct algorithm *alg;
221 enum alg_id alg_id;
222 ULONG i;
224 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
226 if (!handle || !id) return STATUS_INVALID_PARAMETER;
227 if (flags & ~supported_flags)
229 FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
230 return STATUS_NOT_IMPLEMENTED;
233 for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
235 if (!strcmpW( id, builtin_algorithms[i].name))
237 alg_id = i;
238 break;
241 if (i == ARRAY_SIZE( builtin_algorithms ))
243 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
244 return STATUS_NOT_IMPLEMENTED;
247 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
249 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
250 return STATUS_NOT_IMPLEMENTED;
253 if (!(alg = heap_alloc( sizeof(*alg) ))) return STATUS_NO_MEMORY;
254 alg->hdr.magic = MAGIC_ALG;
255 alg->id = alg_id;
256 alg->mode = MODE_ID_CBC;
257 alg->flags = flags;
259 *handle = alg;
260 return STATUS_SUCCESS;
263 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
265 struct algorithm *alg = handle;
267 TRACE( "%p, %08x\n", handle, flags );
269 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
270 alg->hdr.magic = 0;
271 heap_free( alg );
272 return STATUS_SUCCESS;
275 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
277 FIXME("%p - semi-stub\n", enabled);
279 if (!enabled)
280 return STATUS_INVALID_PARAMETER;
282 *enabled = FALSE;
283 return STATUS_SUCCESS;
286 struct hash_impl
288 union
290 MD2_CTX md2;
291 MD4_CTX md4;
292 MD5_CTX md5;
293 SHA_CTX sha1;
294 SHA256_CTX sha256;
295 SHA512_CTX sha512;
296 } u;
299 static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id )
301 switch (alg_id)
303 case ALG_ID_MD2:
304 md2_init( &hash->u.md2 );
305 break;
307 case ALG_ID_MD4:
308 MD4Init( &hash->u.md4 );
309 break;
311 case ALG_ID_MD5:
312 MD5Init( &hash->u.md5 );
313 break;
315 case ALG_ID_SHA1:
316 A_SHAInit( &hash->u.sha1 );
317 break;
319 case ALG_ID_SHA256:
320 sha256_init( &hash->u.sha256 );
321 break;
323 case ALG_ID_SHA384:
324 sha384_init( &hash->u.sha512 );
325 break;
327 case ALG_ID_SHA512:
328 sha512_init( &hash->u.sha512 );
329 break;
331 default:
332 ERR( "unhandled id %u\n", alg_id );
333 return STATUS_NOT_IMPLEMENTED;
335 return STATUS_SUCCESS;
338 static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id,
339 UCHAR *input, ULONG size )
341 switch (alg_id)
343 case ALG_ID_MD2:
344 md2_update( &hash->u.md2, input, size );
345 break;
347 case ALG_ID_MD4:
348 MD4Update( &hash->u.md4, input, size );
349 break;
351 case ALG_ID_MD5:
352 MD5Update( &hash->u.md5, input, size );
353 break;
355 case ALG_ID_SHA1:
356 A_SHAUpdate( &hash->u.sha1, input, size );
357 break;
359 case ALG_ID_SHA256:
360 sha256_update( &hash->u.sha256, input, size );
361 break;
363 case ALG_ID_SHA384:
364 sha384_update( &hash->u.sha512, input, size );
365 break;
367 case ALG_ID_SHA512:
368 sha512_update( &hash->u.sha512, input, size );
369 break;
371 default:
372 ERR( "unhandled id %u\n", alg_id );
373 return STATUS_NOT_IMPLEMENTED;
375 return STATUS_SUCCESS;
378 static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id,
379 UCHAR *output, ULONG size )
381 switch (alg_id)
383 case ALG_ID_MD2:
384 md2_finalize( &hash->u.md2, output );
385 break;
387 case ALG_ID_MD4:
388 MD4Final( &hash->u.md4 );
389 memcpy( output, hash->u.md4.digest, 16 );
390 break;
392 case ALG_ID_MD5:
393 MD5Final( &hash->u.md5 );
394 memcpy( output, hash->u.md5.digest, 16 );
395 break;
397 case ALG_ID_SHA1:
398 A_SHAFinal( &hash->u.sha1, (ULONG *)output );
399 break;
401 case ALG_ID_SHA256:
402 sha256_finalize( &hash->u.sha256, output );
403 break;
405 case ALG_ID_SHA384:
406 sha384_finalize( &hash->u.sha512, output );
407 break;
409 case ALG_ID_SHA512:
410 sha512_finalize( &hash->u.sha512, output );
411 break;
413 default:
414 ERR( "unhandled id %u\n", alg_id );
415 return STATUS_NOT_IMPLEMENTED;
417 return STATUS_SUCCESS;
420 #define HASH_FLAG_HMAC 0x01
421 #define HASH_FLAG_REUSABLE 0x02
422 struct hash
424 struct object hdr;
425 enum alg_id alg_id;
426 ULONG flags;
427 UCHAR *secret;
428 ULONG secret_len;
429 struct hash_impl outer;
430 struct hash_impl inner;
433 #define BLOCK_LENGTH_AES 16
435 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
437 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
439 if (!builtin_algorithms[id].object_length)
440 return STATUS_NOT_SUPPORTED;
441 *ret_size = sizeof(ULONG);
442 if (size < sizeof(ULONG))
443 return STATUS_BUFFER_TOO_SMALL;
444 if (buf)
445 *(ULONG *)buf = builtin_algorithms[id].object_length;
446 return STATUS_SUCCESS;
449 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
451 if (!builtin_algorithms[id].hash_length)
452 return STATUS_NOT_SUPPORTED;
453 *ret_size = sizeof(ULONG);
454 if (size < sizeof(ULONG))
455 return STATUS_BUFFER_TOO_SMALL;
456 if(buf)
457 *(ULONG*)buf = builtin_algorithms[id].hash_length;
458 return STATUS_SUCCESS;
461 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
463 *ret_size = (strlenW(builtin_algorithms[id].name) + 1) * sizeof(WCHAR);
464 if (size < *ret_size)
465 return STATUS_BUFFER_TOO_SMALL;
466 if(buf)
467 memcpy(buf, builtin_algorithms[id].name, *ret_size);
468 return STATUS_SUCCESS;
471 return STATUS_NOT_IMPLEMENTED;
474 static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
476 if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
478 *ret_size = sizeof(ULONG);
479 if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
480 if (buf) *(ULONG *)buf = BLOCK_LENGTH_AES;
481 return STATUS_SUCCESS;
483 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
485 const WCHAR *str;
486 switch (mode)
488 case MODE_ID_ECB: str = BCRYPT_CHAIN_MODE_ECB; break;
489 case MODE_ID_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
490 case MODE_ID_GCM: str = BCRYPT_CHAIN_MODE_GCM; break;
491 default: return STATUS_NOT_IMPLEMENTED;
494 *ret_size = 64;
495 if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
496 memcpy( buf, str, (strlenW(str) + 1) * sizeof(WCHAR) );
497 return STATUS_SUCCESS;
499 if (!strcmpW( prop, BCRYPT_KEY_LENGTHS ))
501 BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
502 *ret_size = sizeof(*key_lengths);
503 if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
504 if (key_lengths)
506 key_lengths->dwMinLength = 128;
507 key_lengths->dwMaxLength = 256;
508 key_lengths->dwIncrement = 64;
510 return STATUS_SUCCESS;
512 if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH ))
514 BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
515 if (mode != MODE_ID_GCM) return STATUS_NOT_SUPPORTED;
516 *ret_size = sizeof(*tag_length);
517 if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
518 if (tag_length)
520 tag_length->dwMinLength = 12;
521 tag_length->dwMaxLength = 16;
522 tag_length->dwIncrement = 1;
524 return STATUS_SUCCESS;
527 FIXME( "unsupported property %s\n", debugstr_w(prop) );
528 return STATUS_NOT_IMPLEMENTED;
531 static NTSTATUS get_rsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
533 if (!strcmpW( prop, BCRYPT_PADDING_SCHEMES ))
535 *ret_size = sizeof(ULONG);
536 if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
537 if (buf) *(ULONG *)buf = BCRYPT_SUPPORTED_PAD_PKCS1_SIG;
538 return STATUS_SUCCESS;
541 FIXME( "unsupported property %s\n", debugstr_w(prop) );
542 return STATUS_NOT_IMPLEMENTED;
545 static NTSTATUS get_dsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
547 if (!strcmpW( prop, BCRYPT_PADDING_SCHEMES )) return STATUS_NOT_SUPPORTED;
548 FIXME( "unsupported property %s\n", debugstr_w(prop) );
549 return STATUS_NOT_IMPLEMENTED;
552 NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
554 NTSTATUS status;
556 status = generic_alg_property( alg->id, prop, buf, size, ret_size );
557 if (status != STATUS_NOT_IMPLEMENTED)
558 return status;
560 switch (alg->id)
562 case ALG_ID_AES:
563 return get_aes_property( alg->mode, prop, buf, size, ret_size );
565 case ALG_ID_RSA:
566 return get_rsa_property( alg->mode, prop, buf, size, ret_size );
568 case ALG_ID_DSA:
569 return get_dsa_property( alg->mode, prop, buf, size, ret_size );
571 default:
572 break;
575 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop), alg->id );
576 return STATUS_NOT_IMPLEMENTED;
579 static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
581 switch (alg->id)
583 case ALG_ID_AES:
584 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
586 if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_ECB ))
588 alg->mode = MODE_ID_ECB;
589 return STATUS_SUCCESS;
591 else if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
593 alg->mode = MODE_ID_CBC;
594 return STATUS_SUCCESS;
596 else if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM ))
598 alg->mode = MODE_ID_GCM;
599 return STATUS_SUCCESS;
601 else
603 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
604 return STATUS_NOT_IMPLEMENTED;
607 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) );
608 return STATUS_NOT_IMPLEMENTED;
610 default:
611 FIXME( "unsupported algorithm %u\n", alg->id );
612 return STATUS_NOT_IMPLEMENTED;
616 static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
618 NTSTATUS status;
620 status = generic_alg_property( hash->alg_id, prop, buf, size, ret_size );
621 if (status == STATUS_NOT_IMPLEMENTED)
622 FIXME( "unsupported property %s\n", debugstr_w(prop) );
623 return status;
626 static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
628 switch (key->alg_id)
630 case ALG_ID_AES:
631 if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
632 return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
634 default:
635 FIXME( "unsupported algorithm %u\n", key->alg_id );
636 return STATUS_NOT_IMPLEMENTED;
640 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
642 struct object *object = handle;
644 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
646 if (!object) return STATUS_INVALID_HANDLE;
647 if (!prop || !res) return STATUS_INVALID_PARAMETER;
649 switch (object->magic)
651 case MAGIC_ALG:
653 const struct algorithm *alg = (const struct algorithm *)object;
654 return get_alg_property( alg, prop, buffer, count, res );
656 case MAGIC_KEY:
658 const struct key *key = (const struct key *)object;
659 return get_key_property( key, prop, buffer, count, res );
661 case MAGIC_HASH:
663 const struct hash *hash = (const struct hash *)object;
664 return get_hash_property( hash, prop, buffer, count, res );
666 default:
667 WARN( "unknown magic %08x\n", object->magic );
668 return STATUS_INVALID_HANDLE;
672 static NTSTATUS prepare_hash( struct hash *hash )
674 UCHAR buffer[MAX_HASH_BLOCK_BITS / 8] = {0};
675 int block_bytes, i;
676 NTSTATUS status;
678 /* initialize hash */
679 if ((status = hash_init( &hash->inner, hash->alg_id ))) return status;
680 if (!(hash->flags & HASH_FLAG_HMAC)) return STATUS_SUCCESS;
682 /* initialize hmac */
683 if ((status = hash_init( &hash->outer, hash->alg_id ))) return status;
684 block_bytes = builtin_algorithms[hash->alg_id].block_bits / 8;
685 if (hash->secret_len > block_bytes)
687 struct hash_impl temp;
688 if ((status = hash_init( &temp, hash->alg_id ))) return status;
689 if ((status = hash_update( &temp, hash->alg_id, hash->secret, hash->secret_len ))) return status;
690 if ((status = hash_finish( &temp, hash->alg_id, buffer,
691 builtin_algorithms[hash->alg_id].hash_length ))) return status;
693 else memcpy( buffer, hash->secret, hash->secret_len );
695 for (i = 0; i < block_bytes; i++) buffer[i] ^= 0x5c;
696 if ((status = hash_update( &hash->outer, hash->alg_id, buffer, block_bytes ))) return status;
697 for (i = 0; i < block_bytes; i++) buffer[i] ^= (0x5c ^ 0x36);
698 return hash_update( &hash->inner, hash->alg_id, buffer, block_bytes );
701 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
702 UCHAR *secret, ULONG secretlen, ULONG flags )
704 struct algorithm *alg = algorithm;
705 struct hash *hash;
706 NTSTATUS status;
708 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
709 secret, secretlen, flags );
710 if (flags & ~BCRYPT_HASH_REUSABLE_FLAG)
712 FIXME( "unimplemented flags %08x\n", flags );
713 return STATUS_NOT_IMPLEMENTED;
716 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
717 if (object) FIXME( "ignoring object buffer\n" );
719 if (!(hash = heap_alloc_zero( sizeof(*hash) ))) return STATUS_NO_MEMORY;
720 hash->hdr.magic = MAGIC_HASH;
721 hash->alg_id = alg->id;
722 if (alg->flags & BCRYPT_ALG_HANDLE_HMAC_FLAG) hash->flags = HASH_FLAG_HMAC;
723 if ((alg->flags & BCRYPT_HASH_REUSABLE_FLAG) || (flags & BCRYPT_HASH_REUSABLE_FLAG))
724 hash->flags |= HASH_FLAG_REUSABLE;
726 if (secretlen && !(hash->secret = heap_alloc( secretlen )))
728 heap_free( hash );
729 return STATUS_NO_MEMORY;
731 memcpy( hash->secret, secret, secretlen );
732 hash->secret_len = secretlen;
734 if ((status = prepare_hash( hash )) != STATUS_SUCCESS)
736 heap_free( hash->secret );
737 heap_free( hash );
738 return status;
741 *handle = hash;
742 return STATUS_SUCCESS;
745 NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy,
746 UCHAR *object, ULONG objectlen, ULONG flags )
748 struct hash *hash_orig = handle;
749 struct hash *hash_copy;
751 TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, objectlen, flags );
753 if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
754 if (!handle_copy) return STATUS_INVALID_PARAMETER;
755 if (object) FIXME( "ignoring object buffer\n" );
757 if (!(hash_copy = heap_alloc( sizeof(*hash_copy) )))
758 return STATUS_NO_MEMORY;
760 memcpy( hash_copy, hash_orig, sizeof(*hash_orig) );
761 if (hash_orig->secret && !(hash_copy->secret = heap_alloc( hash_orig->secret_len )))
763 heap_free( hash_copy );
764 return STATUS_NO_MEMORY;
766 memcpy( hash_copy->secret, hash_orig->secret, hash_orig->secret_len );
768 *handle_copy = hash_copy;
769 return STATUS_SUCCESS;
772 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
774 struct hash *hash = handle;
776 TRACE( "%p\n", handle );
778 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_PARAMETER;
779 hash->hdr.magic = 0;
780 heap_free( hash->secret );
781 heap_free( hash );
782 return STATUS_SUCCESS;
785 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
787 struct hash *hash = handle;
789 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
791 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
792 if (!input) return STATUS_SUCCESS;
794 return hash_update( &hash->inner, hash->alg_id, input, size );
797 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
799 UCHAR buffer[MAX_HASH_OUTPUT_BYTES];
800 struct hash *hash = handle;
801 NTSTATUS status;
802 int hash_length;
804 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
806 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
807 if (!output) return STATUS_INVALID_PARAMETER;
809 if (!(hash->flags & HASH_FLAG_HMAC))
811 if ((status = hash_finish( &hash->inner, hash->alg_id, output, size ))) return status;
812 if (hash->flags & HASH_FLAG_REUSABLE) return prepare_hash( hash );
813 return STATUS_SUCCESS;
816 hash_length = builtin_algorithms[hash->alg_id].hash_length;
817 if ((status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_length ))) return status;
818 if ((status = hash_update( &hash->outer, hash->alg_id, buffer, hash_length ))) return status;
819 if ((status = hash_finish( &hash->outer, hash->alg_id, output, size ))) return status;
820 if (hash->flags & HASH_FLAG_REUSABLE) return prepare_hash( hash );
821 return STATUS_SUCCESS;
824 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
825 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
827 NTSTATUS status;
828 BCRYPT_HASH_HANDLE handle;
830 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
831 input, inputlen, output, outputlen );
833 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
834 if (status != STATUS_SUCCESS)
836 return status;
839 status = BCryptHashData( handle, input, inputlen, 0 );
840 if (status != STATUS_SUCCESS)
842 BCryptDestroyHash( handle );
843 return status;
846 status = BCryptFinishHash( handle, output, outputlen, 0 );
847 if (status != STATUS_SUCCESS)
849 BCryptDestroyHash( handle );
850 return status;
853 return BCryptDestroyHash( handle );
856 #if defined(HAVE_GNUTLS_CIPHER_INIT) || defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
857 BOOL key_is_symmetric( struct key *key )
859 return builtin_algorithms[key->alg_id].class == BCRYPT_CIPHER_INTERFACE;
862 BOOL is_zero_vector( const UCHAR *vector, ULONG len )
864 ULONG i;
865 if (!vector) return FALSE;
866 for (i = 0; i < len; i++) if (vector[i]) return FALSE;
867 return TRUE;
870 BOOL is_equal_vector( const UCHAR *vector, ULONG len, const UCHAR *vector2, ULONG len2 )
872 if (!vector && !vector2) return TRUE;
873 if (len != len2) return FALSE;
874 return !memcmp( vector, vector2, len );
877 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
878 ULONG object_len, UCHAR *input, ULONG input_len )
880 ULONG len;
882 if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
884 BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)input;
886 if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) return STATUS_BUFFER_TOO_SMALL;
887 if (header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) return STATUS_INVALID_PARAMETER;
888 if (header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1)
890 FIXME( "unknown key data blob version %u\n", header->dwVersion );
891 return STATUS_INVALID_PARAMETER;
893 len = header->cbKeyData;
894 if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER;
896 return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, (UCHAR *)&header[1], len, 0 );
898 else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
900 if (input_len < sizeof(len)) return STATUS_BUFFER_TOO_SMALL;
901 len = *(ULONG *)input;
902 if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER;
904 return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, input + sizeof(len), len, 0 );
907 FIXME( "unsupported key type %s\n", debugstr_w(type) );
908 return STATUS_NOT_IMPLEMENTED;
911 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
913 if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
915 BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)output;
916 ULONG req_size = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key->u.s.secret_len;
918 *size = req_size;
919 if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
921 header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
922 header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
923 header->cbKeyData = key->u.s.secret_len;
924 memcpy( &header[1], key->u.s.secret, key->u.s.secret_len );
925 return STATUS_SUCCESS;
927 else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
929 ULONG len, req_size = sizeof(len) + key->u.s.secret_len;
931 *size = req_size;
932 if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
934 *(ULONG *)output = key->u.s.secret_len;
935 memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len );
936 return STATUS_SUCCESS;
938 else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ) || !strcmpW( type, BCRYPT_DSA_PUBLIC_BLOB ) ||
939 !strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
941 *size = key->u.a.pubkey_len;
942 if (output_len < key->u.a.pubkey_len) return STATUS_SUCCESS;
944 memcpy( output, key->u.a.pubkey, key->u.a.pubkey_len );
945 return STATUS_SUCCESS;
947 else if (!strcmpW( type, BCRYPT_ECCPRIVATE_BLOB ))
949 return key_export_ecc( key, output, output_len, size );
952 FIXME( "unsupported key type %s\n", debugstr_w(type) );
953 return STATUS_NOT_IMPLEMENTED;
956 static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
958 UCHAR *buffer;
960 memset( key_copy, 0, sizeof(*key_copy) );
961 key_copy->hdr = key_orig->hdr;
962 key_copy->alg_id = key_orig->alg_id;
964 if (key_is_symmetric( key_orig ))
966 if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY;
967 memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len );
969 key_copy->u.s.mode = key_orig->u.s.mode;
970 key_copy->u.s.block_size = key_orig->u.s.block_size;
971 key_copy->u.s.secret = buffer;
972 key_copy->u.s.secret_len = key_orig->u.s.secret_len;
974 else
976 if (!(buffer = heap_alloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY;
977 memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len );
979 key_copy->u.a.pubkey = buffer;
980 key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len;
983 return STATUS_SUCCESS;
986 static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
987 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
989 ULONG bytes_left = input_len;
990 UCHAR *buf, *src, *dst;
991 NTSTATUS status;
993 if (key->u.s.mode == MODE_ID_GCM)
995 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
997 if (!auth_info) return STATUS_INVALID_PARAMETER;
998 if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
999 if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
1000 if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
1001 if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
1002 FIXME( "call chaining not implemented\n" );
1004 if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
1005 return status;
1007 *ret_len = input_len;
1008 if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
1009 if (input && !output) return STATUS_SUCCESS;
1010 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1012 if ((status = key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData )))
1013 return status;
1014 if ((status = key_symmetric_encrypt( key, input, input_len, output, output_len ))) return status;
1016 return key_symmetric_get_tag( key, auth_info->pbTag, auth_info->cbTag );
1019 *ret_len = input_len;
1021 if (flags & BCRYPT_BLOCK_PADDING)
1022 *ret_len = (input_len + key->u.s.block_size) & ~(key->u.s.block_size - 1);
1023 else if (input_len & (key->u.s.block_size - 1))
1024 return STATUS_INVALID_BUFFER_SIZE;
1026 if (!output) return STATUS_SUCCESS;
1027 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1028 if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
1029 if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
1031 src = input;
1032 dst = output;
1033 while (bytes_left >= key->u.s.block_size)
1035 if ((status = key_symmetric_encrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
1036 return status;
1037 if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
1038 bytes_left -= key->u.s.block_size;
1039 src += key->u.s.block_size;
1040 dst += key->u.s.block_size;
1043 if (flags & BCRYPT_BLOCK_PADDING)
1045 if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
1046 memcpy( buf, src, bytes_left );
1047 memset( buf + bytes_left, key->u.s.block_size - bytes_left, key->u.s.block_size - bytes_left );
1048 status = key_symmetric_encrypt( key, buf, key->u.s.block_size, dst, key->u.s.block_size );
1049 heap_free( buf );
1052 return status;
1055 static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1056 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1058 ULONG bytes_left = input_len;
1059 UCHAR *buf, *src, *dst;
1060 NTSTATUS status;
1062 if (key->u.s.mode == MODE_ID_GCM)
1064 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
1065 UCHAR tag[16];
1067 if (!auth_info) return STATUS_INVALID_PARAMETER;
1068 if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
1069 if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
1070 if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
1072 if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
1073 return status;
1075 *ret_len = input_len;
1076 if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
1077 if (!output) return STATUS_SUCCESS;
1078 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1080 if ((status = key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData )))
1081 return status;
1082 if ((status = key_symmetric_decrypt( key, input, input_len, output, output_len ))) return status;
1084 if ((status = key_symmetric_get_tag( key, tag, sizeof(tag) ))) return status;
1085 if (memcmp( tag, auth_info->pbTag, auth_info->cbTag )) return STATUS_AUTH_TAG_MISMATCH;
1087 return STATUS_SUCCESS;
1090 *ret_len = input_len;
1092 if (input_len & (key->u.s.block_size - 1)) return STATUS_INVALID_BUFFER_SIZE;
1093 if (!output) return STATUS_SUCCESS;
1094 if (flags & BCRYPT_BLOCK_PADDING)
1096 if (output_len + key->u.s.block_size < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1097 if (input_len < key->u.s.block_size) return STATUS_BUFFER_TOO_SMALL;
1098 bytes_left -= key->u.s.block_size;
1100 else if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1102 if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
1103 if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
1105 src = input;
1106 dst = output;
1107 while (bytes_left >= key->u.s.block_size)
1109 if ((status = key_symmetric_decrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
1110 return status;
1111 if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
1112 bytes_left -= key->u.s.block_size;
1113 src += key->u.s.block_size;
1114 dst += key->u.s.block_size;
1117 if (flags & BCRYPT_BLOCK_PADDING)
1119 if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
1120 status = key_symmetric_decrypt( key, src, key->u.s.block_size, buf, key->u.s.block_size );
1121 if (!status && buf[ key->u.s.block_size - 1 ] <= key->u.s.block_size)
1123 *ret_len -= buf[ key->u.s.block_size - 1 ];
1124 if (output_len < *ret_len) status = STATUS_BUFFER_TOO_SMALL;
1125 else memcpy( dst, buf, key->u.s.block_size - buf[ key->u.s.block_size - 1 ] );
1127 else status = STATUS_UNSUCCESSFUL; /* FIXME: invalid padding */
1128 heap_free( buf );
1131 return status;
1134 static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
1135 ULONG input_len )
1137 struct key *key;
1138 NTSTATUS status;
1140 if (!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
1142 BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
1143 DWORD key_size, magic, size;
1145 if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
1147 switch (alg->id)
1149 case ALG_ID_ECDH_P256:
1150 key_size = 32;
1151 magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
1152 break;
1154 case ALG_ID_ECDSA_P256:
1155 key_size = 32;
1156 magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
1157 break;
1159 case ALG_ID_ECDSA_P384:
1160 key_size = 48;
1161 magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
1162 break;
1164 default:
1165 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
1166 return STATUS_NOT_SUPPORTED;
1169 if (ecc_blob->dwMagic != magic) return STATUS_NOT_SUPPORTED;
1170 if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2)
1171 return STATUS_INVALID_PARAMETER;
1173 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1174 key->hdr.magic = MAGIC_KEY;
1176 size = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
1177 if ((status = key_asymmetric_init( key, alg, key_size * 8, (BYTE *)ecc_blob, size )))
1179 heap_free( key );
1180 return status;
1183 *ret_key = key;
1184 return STATUS_SUCCESS;
1186 else if (!strcmpW( type, BCRYPT_ECCPRIVATE_BLOB ))
1188 BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
1189 DWORD key_size, magic;
1191 if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
1193 switch (alg->id)
1195 case ALG_ID_ECDH_P256:
1196 key_size = 32;
1197 magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
1198 break;
1200 default:
1201 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
1202 return STATUS_NOT_SUPPORTED;
1205 if (ecc_blob->dwMagic != magic) return STATUS_NOT_SUPPORTED;
1206 if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3)
1207 return STATUS_INVALID_PARAMETER;
1209 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1210 key->hdr.magic = MAGIC_KEY;
1212 if ((status = key_asymmetric_init( key, alg, key_size * 8, NULL, 0 )))
1214 heap_free( key );
1215 return status;
1217 if ((status = key_import_ecc( key, input, input_len )))
1219 heap_free( key );
1220 return status;
1223 *ret_key = key;
1224 return STATUS_SUCCESS;
1226 else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ))
1228 BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
1229 ULONG size;
1231 if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER;
1232 if ((alg->id != ALG_ID_RSA && alg->id != ALG_ID_RSA_SIGN) || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC)
1233 return STATUS_NOT_SUPPORTED;
1235 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1236 key->hdr.magic = MAGIC_KEY;
1238 size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
1239 if ((status = key_asymmetric_init( key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size )))
1241 heap_free( key );
1242 return status;
1245 *ret_key = key;
1246 return STATUS_SUCCESS;
1248 else if (!strcmpW( type, BCRYPT_DSA_PUBLIC_BLOB ))
1250 BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input;
1251 ULONG size;
1253 if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER;
1254 if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC)
1255 return STATUS_NOT_SUPPORTED;
1257 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1258 key->hdr.magic = MAGIC_KEY;
1260 size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
1261 if ((status = key_asymmetric_init( key, alg, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size )))
1263 heap_free( key );
1264 return status;
1267 *ret_key = key;
1268 return STATUS_SUCCESS;
1271 FIXME( "unsupported key type %s\n", debugstr_w(type) );
1272 return STATUS_NOT_SUPPORTED;
1274 #else
1275 NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR *secret, ULONG secret_len )
1277 ERR( "support for keys not available at build time\n" );
1278 return STATUS_NOT_IMPLEMENTED;
1281 BOOL key_is_symmetric( struct key *key )
1283 ERR( "support for keys not available at build time\n" );
1284 return FALSE;
1287 NTSTATUS key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
1289 ERR( "support for keys not available at build time\n" );
1290 return STATUS_NOT_IMPLEMENTED;
1293 static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
1295 ERR( "support for keys not available at build time\n" );
1296 return STATUS_NOT_IMPLEMENTED;
1299 NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, ULONG bitlen, const UCHAR *pubkey,
1300 ULONG pubkey_len )
1302 ERR( "support for keys not available at build time\n" );
1303 return STATUS_NOT_IMPLEMENTED;
1306 NTSTATUS key_asymmetric_generate( struct key *key )
1308 ERR( "support for keys not available at build time\n" );
1309 return STATUS_NOT_IMPLEMENTED;
1312 NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
1313 ULONG output_len, ULONG *ret_len, ULONG flags )
1315 ERR( "support for keys not available at build time\n" );
1316 return STATUS_NOT_IMPLEMENTED;
1319 NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
1320 ULONG signature_len, DWORD flags )
1322 ERR( "support for keys not available at build time\n" );
1323 return STATUS_NOT_IMPLEMENTED;
1326 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
1327 ULONG object_len, UCHAR *input, ULONG input_len )
1329 ERR( "support for keys not available at build time\n" );
1330 return STATUS_NOT_IMPLEMENTED;
1333 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
1335 ERR( "support for keys not available at build time\n" );
1336 return STATUS_NOT_IMPLEMENTED;
1339 NTSTATUS key_destroy( struct key *key )
1341 ERR( "support for keys not available at build time\n" );
1342 return STATUS_NOT_IMPLEMENTED;
1345 static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1346 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1348 ERR( "support for keys not available at build time\n" );
1349 return STATUS_NOT_IMPLEMENTED;
1352 static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1353 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1355 ERR( "support for keys not available at build time\n" );
1356 return STATUS_NOT_IMPLEMENTED;
1359 static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
1360 ULONG input_len )
1362 ERR( "support for keys not available at build time\n" );
1363 return STATUS_NOT_IMPLEMENTED;
1366 NTSTATUS key_export_ecc( struct key *key, UCHAR *output, ULONG len, ULONG *ret_len )
1368 ERR( "support for keys not available at build time\n" );
1369 return STATUS_NOT_IMPLEMENTED;
1372 NTSTATUS key_import_ecc( struct key *key, UCHAR *input, ULONG len )
1374 ERR( "support for keys not available at build time\n" );
1375 return STATUS_NOT_IMPLEMENTED;
1377 #endif
1379 NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle,
1380 UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len,
1381 ULONG flags )
1383 struct algorithm *alg = algorithm;
1384 struct key *key;
1385 NTSTATUS status;
1387 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm, handle, object, object_len, secret, secret_len, flags );
1389 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1390 if (object) FIXME( "ignoring object buffer\n" );
1392 if (!(key = heap_alloc( sizeof(*key) ))) return STATUS_NO_MEMORY;
1393 key->hdr.magic = MAGIC_KEY;
1395 if ((status = key_symmetric_init( key, alg, secret, secret_len )))
1397 heap_free( key );
1398 return status;
1401 *handle = key;
1402 return STATUS_SUCCESS;
1405 NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, ULONG key_len,
1406 ULONG flags )
1408 struct algorithm *alg = algorithm;
1409 struct key *key;
1410 NTSTATUS status;
1412 TRACE( "%p, %p, %u, %08x\n", algorithm, handle, key_len, flags );
1414 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1415 if (!handle) return STATUS_INVALID_PARAMETER;
1417 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1418 key->hdr.magic = MAGIC_KEY;
1420 if ((status = key_asymmetric_init( key, alg, key_len, NULL, 0 )))
1422 heap_free( key );
1423 return status;
1426 *handle = key;
1427 return STATUS_SUCCESS;
1430 NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags )
1432 struct key *key = handle;
1434 TRACE( "%p, %08x\n", key, flags );
1435 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1437 return key_asymmetric_generate( key );
1440 NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type,
1441 BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input,
1442 ULONG input_len, ULONG flags )
1444 struct algorithm *alg = algorithm;
1446 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm, decrypt_key, debugstr_w(type), key, object,
1447 object_len, input, input_len, flags);
1449 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1450 if (!key || !type || !input) return STATUS_INVALID_PARAMETER;
1452 if (decrypt_key)
1454 FIXME( "decryption of key not yet supported\n" );
1455 return STATUS_NOT_IMPLEMENTED;
1458 return key_import( algorithm, type, key, object, object_len, input, input_len );
1461 NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type,
1462 PUCHAR output, ULONG output_len, ULONG *size, ULONG flags )
1464 struct key *key = export_key;
1466 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key, encrypt_key, debugstr_w(type), output, output_len, size, flags);
1468 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1469 if (!type || !size) return STATUS_INVALID_PARAMETER;
1471 if (encrypt_key)
1473 FIXME( "encryption of key not yet supported\n" );
1474 return STATUS_NOT_IMPLEMENTED;
1477 return key_export( key, type, output, output_len, size );
1480 NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE *handle_copy,
1481 UCHAR *object, ULONG object_len, ULONG flags )
1483 struct key *key_orig = handle;
1484 struct key *key_copy;
1485 NTSTATUS status;
1487 TRACE( "%p, %p, %p, %u, %08x\n", handle, handle_copy, object, object_len, flags );
1488 if (object) FIXME( "ignoring object buffer\n" );
1490 if (!key_orig || key_orig->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1491 if (!handle_copy) return STATUS_INVALID_PARAMETER;
1492 if (!(key_copy = heap_alloc( sizeof(*key_copy) ))) return STATUS_NO_MEMORY;
1494 if ((status = key_duplicate( key_orig, key_copy )))
1496 heap_free( key_copy );
1497 return status;
1500 *handle_copy = key_copy;
1501 return STATUS_SUCCESS;
1504 NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
1505 BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len, ULONG flags )
1507 struct algorithm *alg = algorithm;
1509 TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm, decrypt_key, debugstr_w(type), ret_key, input,
1510 input_len, flags );
1512 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1513 if (!ret_key || !type || !input) return STATUS_INVALID_PARAMETER;
1514 if (decrypt_key)
1516 FIXME( "decryption of key not yet supported\n" );
1517 return STATUS_NOT_IMPLEMENTED;
1520 return key_import_pair( alg, type, ret_key, input, input_len );
1523 NTSTATUS WINAPI BCryptSignHash( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *input, ULONG input_len,
1524 UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1526 struct key *key = handle;
1528 TRACE( "%p, %p, %p, %u, %p, %u, %p, %08x\n", handle, padding, input, input_len, output, output_len,
1529 ret_len, flags );
1531 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1532 if (key_is_symmetric( key ))
1534 FIXME( "signing with symmetric keys not yet supported\n" );
1535 return STATUS_NOT_IMPLEMENTED;
1538 return key_asymmetric_sign( key, padding, input, input_len, output, output_len, ret_len, flags );
1541 NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len,
1542 UCHAR *signature, ULONG signature_len, ULONG flags )
1544 struct key *key = handle;
1546 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle, padding, hash, hash_len, signature, signature_len, flags );
1548 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1549 if (!hash || !hash_len || !signature || !signature_len) return STATUS_INVALID_PARAMETER;
1550 if (key_is_symmetric( key )) return STATUS_NOT_SUPPORTED;
1552 return key_asymmetric_verify( key, padding, hash, hash_len, signature, signature_len, flags );
1555 NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle )
1557 struct key *key = handle;
1559 TRACE( "%p\n", handle );
1561 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1562 key->hdr.magic = 0;
1563 return key_destroy( key );
1566 NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1567 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1569 struct key *key = handle;
1571 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output,
1572 output_len, ret_len, flags );
1574 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1575 if (!key_is_symmetric( key ))
1577 FIXME( "encryption with asymmetric keys not yet supported\n" );
1578 return STATUS_NOT_IMPLEMENTED;
1580 if (flags & ~BCRYPT_BLOCK_PADDING)
1582 FIXME( "flags %08x not implemented\n", flags );
1583 return STATUS_NOT_IMPLEMENTED;
1586 return key_encrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
1589 NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1590 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1592 struct key *key = handle;
1594 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output,
1595 output_len, ret_len, flags );
1597 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1598 if (!key_is_symmetric( key ))
1600 FIXME( "decryption with asymmetric keys not yet supported\n" );
1601 return STATUS_NOT_IMPLEMENTED;
1603 if (flags & ~BCRYPT_BLOCK_PADDING)
1605 FIXME( "flags %08x not supported\n", flags );
1606 return STATUS_NOT_IMPLEMENTED;
1609 return key_decrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
1612 NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
1614 struct object *object = handle;
1616 TRACE( "%p, %s, %p, %u, %08x\n", handle, debugstr_w(prop), value, size, flags );
1618 if (!object) return STATUS_INVALID_HANDLE;
1620 switch (object->magic)
1622 case MAGIC_ALG:
1624 struct algorithm *alg = (struct algorithm *)object;
1625 return set_alg_property( alg, prop, value, size, flags );
1627 case MAGIC_KEY:
1629 struct key *key = (struct key *)object;
1630 return key_set_property( key, prop, value, size, flags );
1632 default:
1633 WARN( "unknown magic %08x\n", object->magic );
1634 return STATUS_INVALID_HANDLE;
1638 #define HMAC_PAD_LEN 64
1639 NTSTATUS WINAPI BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle, BCRYPT_ALG_HANDLE halg, UCHAR *key, ULONG keylen, ULONG flags )
1641 struct hash *hash = handle;
1642 UCHAR buf[MAX_HASH_OUTPUT_BYTES * 2];
1643 NTSTATUS status;
1644 ULONG len;
1646 TRACE( "%p, %p, %p, %u, %08x\n", handle, halg, key, keylen, flags );
1648 if (!key || !keylen) return STATUS_INVALID_PARAMETER;
1649 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
1650 if (keylen > builtin_algorithms[hash->alg_id].hash_length * 2) return STATUS_INVALID_PARAMETER;
1652 if (halg)
1654 FIXME( "algorithm handle not supported\n" );
1655 return STATUS_NOT_IMPLEMENTED;
1658 len = builtin_algorithms[hash->alg_id].hash_length;
1659 if ((status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
1661 if (len < keylen)
1663 UCHAR pad1[HMAC_PAD_LEN], pad2[HMAC_PAD_LEN];
1664 ULONG i;
1666 for (i = 0; i < sizeof(pad1); i++)
1668 pad1[i] = 0x36 ^ (i < len ? buf[i] : 0);
1669 pad2[i] = 0x5c ^ (i < len ? buf[i] : 0);
1672 if ((status = prepare_hash( hash )) ||
1673 (status = BCryptHashData( handle, pad1, sizeof(pad1), 0 )) ||
1674 (status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
1676 if ((status = prepare_hash( hash )) ||
1677 (status = BCryptHashData( handle, pad2, sizeof(pad2), 0 )) ||
1678 (status = BCryptFinishHash( handle, buf + len, len, 0 ))) return status;
1681 memcpy( key, buf, keylen );
1682 return STATUS_SUCCESS;
1685 static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
1686 ULONGLONG iterations, ULONG i, UCHAR *dst, ULONG hash_len )
1688 NTSTATUS status = STATUS_INVALID_PARAMETER;
1689 UCHAR bytes[4], *buf;
1690 ULONG j, k;
1692 if (!(buf = heap_alloc( hash_len ))) return STATUS_NO_MEMORY;
1694 for (j = 0; j < iterations; j++)
1696 if (j == 0)
1698 /* use salt || INT(i) */
1699 status = BCryptHashData( handle, salt, salt_len, 0 );
1700 if (status != STATUS_SUCCESS)
1702 heap_free( buf );
1703 return status;
1705 bytes[0] = (i >> 24) & 0xff;
1706 bytes[1] = (i >> 16) & 0xff;
1707 bytes[2] = (i >> 8) & 0xff;
1708 bytes[3] = i & 0xff;
1709 status = BCryptHashData( handle, bytes, 4, 0 );
1711 else status = BCryptHashData( handle, buf, hash_len, 0 ); /* use U_j */
1712 if (status != STATUS_SUCCESS)
1714 heap_free( buf );
1715 return status;
1718 status = BCryptFinishHash( handle, buf, hash_len, 0 );
1719 if (status != STATUS_SUCCESS)
1721 heap_free( buf );
1722 return status;
1725 if (j == 0) memcpy( dst, buf, hash_len );
1726 else for (k = 0; k < hash_len; k++) dst[k] ^= buf[k];
1729 heap_free( buf );
1730 return status;
1733 NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
1734 ULONGLONG iterations, UCHAR *dk, ULONG dk_len, ULONG flags )
1736 struct algorithm *alg = handle;
1737 ULONG hash_len, block_count, bytes_left, i;
1738 BCRYPT_HASH_HANDLE hash;
1739 UCHAR *partial;
1740 NTSTATUS status;
1742 TRACE( "%p, %p, %u, %p, %u, %s, %p, %u, %08x\n", handle, pwd, pwd_len, salt, salt_len,
1743 wine_dbgstr_longlong(iterations), dk, dk_len, flags );
1745 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1747 hash_len = builtin_algorithms[alg->id].hash_length;
1748 if (dk_len <= 0 || dk_len > ((((ULONGLONG)1) << 32) - 1) * hash_len) return STATUS_INVALID_PARAMETER;
1750 block_count = 1 + ((dk_len - 1) / hash_len); /* ceil(dk_len / hash_len) */
1751 bytes_left = dk_len - (block_count - 1) * hash_len;
1753 status = BCryptCreateHash( handle, &hash, NULL, 0, pwd, pwd_len, BCRYPT_HASH_REUSABLE_FLAG );
1754 if (status != STATUS_SUCCESS)
1755 return status;
1757 /* full blocks */
1758 for (i = 1; i < block_count; i++)
1760 status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, i, dk + ((i - 1) * hash_len), hash_len );
1761 if (status != STATUS_SUCCESS)
1763 BCryptDestroyHash( hash );
1764 return status;
1768 /* final partial block */
1769 if (!(partial = heap_alloc( hash_len )))
1771 BCryptDestroyHash( hash );
1772 return STATUS_NO_MEMORY;
1775 status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, block_count, partial, hash_len );
1776 if (status != STATUS_SUCCESS)
1778 BCryptDestroyHash( hash );
1779 heap_free( partial );
1780 return status;
1782 memcpy( dk + ((block_count - 1) * hash_len), partial, bytes_left );
1784 BCryptDestroyHash( hash );
1785 heap_free( partial );
1786 return STATUS_SUCCESS;
1789 NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE key, BCRYPT_SECRET_HANDLE *secret, ULONG flags)
1791 FIXME( "%p, %p, %p, %08x\n", handle, key, secret, flags );
1793 if(secret)
1794 *secret = (BCRYPT_SECRET_HANDLE *)0xDEADFEED;
1796 return STATUS_SUCCESS;
1799 NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE secret)
1801 FIXME( "%p\n", secret );
1802 return STATUS_SUCCESS;
1805 NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE secret, LPCWSTR kdf, BCryptBufferDesc *parameter,
1806 PUCHAR derived, ULONG derived_size, ULONG *result, ULONG flags)
1808 FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(kdf), parameter, derived, derived_size, result, flags );
1809 return STATUS_INTERNAL_ERROR;
1812 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1814 switch (reason)
1816 case DLL_PROCESS_ATTACH:
1817 instance = hinst;
1818 DisableThreadLibraryCalls( hinst );
1819 #ifdef HAVE_GNUTLS_CIPHER_INIT
1820 gnutls_initialize();
1821 #endif
1822 break;
1824 case DLL_PROCESS_DETACH:
1825 if (reserved) break;
1826 #ifdef HAVE_GNUTLS_CIPHER_INIT
1827 gnutls_uninitialize();
1828 #endif
1829 break;
1831 return TRUE;