qdvd: Add IDvdGraphBuilder stub.
[wine/zf.git] / dlls / bcrypt / bcrypt_main.c
blobfee40ebe8d7a97b8682de143434200e8bc976750
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 "wincrypt.h"
35 #include "bcrypt.h"
37 #include "bcrypt_internal.h"
39 #include "wine/debug.h"
40 #include "wine/heap.h"
41 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
45 static HINSTANCE instance;
47 NTSTATUS WINAPI BCryptAddContextFunction(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, ULONG pos)
49 FIXME("%08x, %s, %08x, %s, %u: stub\n", table, debugstr_w(context), iface, debugstr_w(function), pos);
50 return STATUS_SUCCESS;
53 NTSTATUS WINAPI BCryptAddContextFunctionProvider(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, LPCWSTR provider, ULONG pos)
55 FIXME("%08x, %s, %08x, %s, %s, %u: stub\n", table, debugstr_w(context), iface, debugstr_w(function), debugstr_w(provider), pos);
56 return STATUS_SUCCESS;
59 NTSTATUS WINAPI BCryptRemoveContextFunction(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function)
61 FIXME("%08x, %s, %08x, %s: stub\n", table, debugstr_w(context), iface, debugstr_w(function));
62 return STATUS_NOT_IMPLEMENTED;
65 NTSTATUS WINAPI BCryptRemoveContextFunctionProvider(ULONG table, LPCWSTR context, ULONG iface, LPCWSTR function, LPCWSTR provider)
67 FIXME("%08x, %s, %08x, %s, %s: stub\n", table, debugstr_w(context), iface, debugstr_w(function), debugstr_w(provider));
68 return STATUS_NOT_IMPLEMENTED;
71 NTSTATUS WINAPI BCryptEnumContextFunctions( ULONG table, const WCHAR *ctx, ULONG iface, ULONG *buflen,
72 CRYPT_CONTEXT_FUNCTIONS **buffer )
74 FIXME( "%u, %s, %u, %p, %p\n", table, debugstr_w(ctx), iface, buflen, buffer );
75 return STATUS_NOT_IMPLEMENTED;
78 void WINAPI BCryptFreeBuffer( void *buffer )
80 FIXME( "%p\n", buffer );
83 NTSTATUS WINAPI BCryptRegisterProvider(LPCWSTR provider, ULONG flags, PCRYPT_PROVIDER_REG reg)
85 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider), flags, reg);
86 return STATUS_SUCCESS;
89 NTSTATUS WINAPI BCryptUnregisterProvider(LPCWSTR provider)
91 FIXME("%s: stub\n", debugstr_w(provider));
92 return STATUS_NOT_IMPLEMENTED;
95 #define MAX_HASH_OUTPUT_BYTES 64
96 #define MAX_HASH_BLOCK_BITS 1024
98 /* ordered by class, keep in sync with enum alg_id */
99 static const struct
101 const WCHAR *name;
102 ULONG class;
103 ULONG object_length;
104 ULONG hash_length;
105 ULONG block_bits;
107 builtin_algorithms[] =
109 { BCRYPT_AES_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 654, 0, 0 },
110 { BCRYPT_SHA256_ALGORITHM, BCRYPT_HASH_INTERFACE, 286, 32, 512 },
111 { BCRYPT_SHA384_ALGORITHM, BCRYPT_HASH_INTERFACE, 382, 48, 1024 },
112 { BCRYPT_SHA512_ALGORITHM, BCRYPT_HASH_INTERFACE, 382, 64, 1024 },
113 { BCRYPT_SHA1_ALGORITHM, BCRYPT_HASH_INTERFACE, 278, 20, 512 },
114 { BCRYPT_MD5_ALGORITHM, BCRYPT_HASH_INTERFACE, 274, 16, 512 },
115 { BCRYPT_MD4_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 512 },
116 { BCRYPT_MD2_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 128 },
117 { BCRYPT_RSA_ALGORITHM, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE, 0, 0, 0 },
118 { BCRYPT_ECDH_P256_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;
129 switch (class)
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;
137 default: break;
139 return FALSE;
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, count = 0;
153 TRACE( "%08x, %p, %p, %08x\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 = heap_alloc( count * sizeof(*list) ))) return STATUS_NO_MEMORY;
164 for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
166 if (!match_operation_type( type, builtin_algorithms[i].class )) continue;
167 list[i].pszName = (WCHAR *)builtin_algorithms[i].name;
168 list[i].dwClass = builtin_algorithms[i].class;
169 list[i].dwFlags = 0;
172 *ret_count = count;
173 *ret_list = list;
174 return STATUS_SUCCESS;
177 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
179 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
180 struct algorithm *algorithm = handle;
182 TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags);
184 if (!algorithm)
186 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
187 * is set. In this case the preferred system RNG is used.
189 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
190 return STATUS_INVALID_HANDLE;
192 else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
193 return STATUS_INVALID_HANDLE;
195 if (!buffer)
196 return STATUS_INVALID_PARAMETER;
198 if (flags & ~supported_flags)
199 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
201 if (algorithm)
202 FIXME("ignoring selected algorithm\n");
204 /* When zero bytes are requested the function returns success too. */
205 if (!count)
206 return STATUS_SUCCESS;
208 if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
210 if (RtlGenRandom(buffer, count))
211 return STATUS_SUCCESS;
214 FIXME("called with unsupported parameters, returning error\n");
215 return STATUS_NOT_IMPLEMENTED;
218 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
220 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG | BCRYPT_HASH_REUSABLE_FLAG;
221 struct algorithm *alg;
222 enum alg_id alg_id;
223 ULONG i;
225 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
227 if (!handle || !id) return STATUS_INVALID_PARAMETER;
228 if (flags & ~supported_flags)
230 FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
231 return STATUS_NOT_IMPLEMENTED;
234 for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
236 if (!strcmpW( id, builtin_algorithms[i].name))
238 alg_id = i;
239 break;
242 if (i == ARRAY_SIZE( builtin_algorithms ))
244 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
245 return STATUS_NOT_IMPLEMENTED;
248 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
250 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
251 return STATUS_NOT_IMPLEMENTED;
254 if (!(alg = heap_alloc( sizeof(*alg) ))) return STATUS_NO_MEMORY;
255 alg->hdr.magic = MAGIC_ALG;
256 alg->id = alg_id;
257 alg->mode = MODE_ID_CBC;
258 alg->flags = flags;
260 *handle = alg;
261 return STATUS_SUCCESS;
264 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
266 struct algorithm *alg = handle;
268 TRACE( "%p, %08x\n", handle, flags );
270 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
271 alg->hdr.magic = 0;
272 heap_free( alg );
273 return STATUS_SUCCESS;
276 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
278 FIXME("%p - semi-stub\n", enabled);
280 if (!enabled)
281 return STATUS_INVALID_PARAMETER;
283 *enabled = FALSE;
284 return STATUS_SUCCESS;
287 struct hash_impl
289 union
291 MD2_CTX md2;
292 MD4_CTX md4;
293 MD5_CTX md5;
294 SHA_CTX sha1;
295 SHA256_CTX sha256;
296 SHA512_CTX sha512;
297 } u;
300 static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id )
302 switch (alg_id)
304 case ALG_ID_MD2:
305 md2_init( &hash->u.md2 );
306 break;
308 case ALG_ID_MD4:
309 MD4Init( &hash->u.md4 );
310 break;
312 case ALG_ID_MD5:
313 MD5Init( &hash->u.md5 );
314 break;
316 case ALG_ID_SHA1:
317 A_SHAInit( &hash->u.sha1 );
318 break;
320 case ALG_ID_SHA256:
321 sha256_init( &hash->u.sha256 );
322 break;
324 case ALG_ID_SHA384:
325 sha384_init( &hash->u.sha512 );
326 break;
328 case ALG_ID_SHA512:
329 sha512_init( &hash->u.sha512 );
330 break;
332 default:
333 ERR( "unhandled id %u\n", alg_id );
334 return STATUS_NOT_IMPLEMENTED;
336 return STATUS_SUCCESS;
339 static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id,
340 UCHAR *input, ULONG size )
342 switch (alg_id)
344 case ALG_ID_MD2:
345 md2_update( &hash->u.md2, input, size );
346 break;
348 case ALG_ID_MD4:
349 MD4Update( &hash->u.md4, input, size );
350 break;
352 case ALG_ID_MD5:
353 MD5Update( &hash->u.md5, input, size );
354 break;
356 case ALG_ID_SHA1:
357 A_SHAUpdate( &hash->u.sha1, input, size );
358 break;
360 case ALG_ID_SHA256:
361 sha256_update( &hash->u.sha256, input, size );
362 break;
364 case ALG_ID_SHA384:
365 sha384_update( &hash->u.sha512, input, size );
366 break;
368 case ALG_ID_SHA512:
369 sha512_update( &hash->u.sha512, input, size );
370 break;
372 default:
373 ERR( "unhandled id %u\n", alg_id );
374 return STATUS_NOT_IMPLEMENTED;
376 return STATUS_SUCCESS;
379 static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id,
380 UCHAR *output, ULONG size )
382 switch (alg_id)
384 case ALG_ID_MD2:
385 md2_finalize( &hash->u.md2, output );
386 break;
388 case ALG_ID_MD4:
389 MD4Final( &hash->u.md4 );
390 memcpy( output, hash->u.md4.digest, 16 );
391 break;
393 case ALG_ID_MD5:
394 MD5Final( &hash->u.md5 );
395 memcpy( output, hash->u.md5.digest, 16 );
396 break;
398 case ALG_ID_SHA1:
399 A_SHAFinal( &hash->u.sha1, (ULONG *)output );
400 break;
402 case ALG_ID_SHA256:
403 sha256_finalize( &hash->u.sha256, output );
404 break;
406 case ALG_ID_SHA384:
407 sha384_finalize( &hash->u.sha512, output );
408 break;
410 case ALG_ID_SHA512:
411 sha512_finalize( &hash->u.sha512, output );
412 break;
414 default:
415 ERR( "unhandled id %u\n", alg_id );
416 return STATUS_NOT_IMPLEMENTED;
418 return STATUS_SUCCESS;
421 #define HASH_FLAG_HMAC 0x01
422 #define HASH_FLAG_REUSABLE 0x02
423 struct hash
425 struct object hdr;
426 enum alg_id alg_id;
427 ULONG flags;
428 UCHAR *secret;
429 ULONG secret_len;
430 struct hash_impl outer;
431 struct hash_impl inner;
434 #define BLOCK_LENGTH_AES 16
436 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
438 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
440 if (!builtin_algorithms[id].object_length)
441 return STATUS_NOT_SUPPORTED;
442 *ret_size = sizeof(ULONG);
443 if (size < sizeof(ULONG))
444 return STATUS_BUFFER_TOO_SMALL;
445 if (buf)
446 *(ULONG *)buf = builtin_algorithms[id].object_length;
447 return STATUS_SUCCESS;
450 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
452 if (!builtin_algorithms[id].hash_length)
453 return STATUS_NOT_SUPPORTED;
454 *ret_size = sizeof(ULONG);
455 if (size < sizeof(ULONG))
456 return STATUS_BUFFER_TOO_SMALL;
457 if(buf)
458 *(ULONG*)buf = builtin_algorithms[id].hash_length;
459 return STATUS_SUCCESS;
462 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
464 *ret_size = (strlenW(builtin_algorithms[id].name) + 1) * sizeof(WCHAR);
465 if (size < *ret_size)
466 return STATUS_BUFFER_TOO_SMALL;
467 if(buf)
468 memcpy(buf, builtin_algorithms[id].name, *ret_size);
469 return STATUS_SUCCESS;
472 return STATUS_NOT_IMPLEMENTED;
475 static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
477 if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
479 *ret_size = sizeof(ULONG);
480 if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
481 if (buf) *(ULONG *)buf = BLOCK_LENGTH_AES;
482 return STATUS_SUCCESS;
484 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
486 const WCHAR *str;
487 switch (mode)
489 case MODE_ID_ECB: str = BCRYPT_CHAIN_MODE_ECB; break;
490 case MODE_ID_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
491 case MODE_ID_GCM: str = BCRYPT_CHAIN_MODE_GCM; break;
492 default: return STATUS_NOT_IMPLEMENTED;
495 *ret_size = 64;
496 if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
497 memcpy( buf, str, (strlenW(str) + 1) * sizeof(WCHAR) );
498 return STATUS_SUCCESS;
500 if (!strcmpW( prop, BCRYPT_KEY_LENGTHS ))
502 BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
503 *ret_size = sizeof(*key_lengths);
504 if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
505 if (key_lengths)
507 key_lengths->dwMinLength = 128;
508 key_lengths->dwMaxLength = 256;
509 key_lengths->dwIncrement = 64;
511 return STATUS_SUCCESS;
513 if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH ))
515 BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
516 if (mode != MODE_ID_GCM) return STATUS_NOT_SUPPORTED;
517 *ret_size = sizeof(*tag_length);
518 if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
519 if (tag_length)
521 tag_length->dwMinLength = 12;
522 tag_length->dwMaxLength = 16;
523 tag_length->dwIncrement = 1;
525 return STATUS_SUCCESS;
528 FIXME( "unsupported property %s\n", debugstr_w(prop) );
529 return STATUS_NOT_IMPLEMENTED;
532 static NTSTATUS get_rsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
534 if (!strcmpW( prop, BCRYPT_PADDING_SCHEMES ))
536 *ret_size = sizeof(ULONG);
537 if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
538 if (buf) *(ULONG *)buf = BCRYPT_SUPPORTED_PAD_PKCS1_SIG;
539 return STATUS_SUCCESS;
542 FIXME( "unsupported property %s\n", debugstr_w(prop) );
543 return STATUS_NOT_IMPLEMENTED;
546 static NTSTATUS get_dsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
548 if (!strcmpW( prop, BCRYPT_PADDING_SCHEMES )) return STATUS_NOT_SUPPORTED;
549 FIXME( "unsupported property %s\n", debugstr_w(prop) );
550 return STATUS_NOT_IMPLEMENTED;
553 NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
555 NTSTATUS status;
557 status = generic_alg_property( alg->id, prop, buf, size, ret_size );
558 if (status != STATUS_NOT_IMPLEMENTED)
559 return status;
561 switch (alg->id)
563 case ALG_ID_AES:
564 return get_aes_property( alg->mode, prop, buf, size, ret_size );
566 case ALG_ID_RSA:
567 return get_rsa_property( alg->mode, prop, buf, size, ret_size );
569 case ALG_ID_DSA:
570 return get_dsa_property( alg->mode, prop, buf, size, ret_size );
572 default:
573 break;
576 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop), alg->id );
577 return STATUS_NOT_IMPLEMENTED;
580 static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
582 switch (alg->id)
584 case ALG_ID_AES:
585 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
587 if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_ECB ))
589 alg->mode = MODE_ID_ECB;
590 return STATUS_SUCCESS;
592 else if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
594 alg->mode = MODE_ID_CBC;
595 return STATUS_SUCCESS;
597 else if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM ))
599 alg->mode = MODE_ID_GCM;
600 return STATUS_SUCCESS;
602 else
604 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
605 return STATUS_NOT_IMPLEMENTED;
608 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) );
609 return STATUS_NOT_IMPLEMENTED;
611 default:
612 FIXME( "unsupported algorithm %u\n", alg->id );
613 return STATUS_NOT_IMPLEMENTED;
617 static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
619 NTSTATUS status;
621 status = generic_alg_property( hash->alg_id, prop, buf, size, ret_size );
622 if (status == STATUS_NOT_IMPLEMENTED)
623 FIXME( "unsupported property %s\n", debugstr_w(prop) );
624 return status;
627 static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
629 switch (key->alg_id)
631 case ALG_ID_AES:
632 if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
633 return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
635 default:
636 FIXME( "unsupported algorithm %u\n", key->alg_id );
637 return STATUS_NOT_IMPLEMENTED;
641 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
643 struct object *object = handle;
645 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
647 if (!object) return STATUS_INVALID_HANDLE;
648 if (!prop || !res) return STATUS_INVALID_PARAMETER;
650 switch (object->magic)
652 case MAGIC_ALG:
654 const struct algorithm *alg = (const struct algorithm *)object;
655 return get_alg_property( alg, prop, buffer, count, res );
657 case MAGIC_KEY:
659 const struct key *key = (const struct key *)object;
660 return get_key_property( key, prop, buffer, count, res );
662 case MAGIC_HASH:
664 const struct hash *hash = (const struct hash *)object;
665 return get_hash_property( hash, prop, buffer, count, res );
667 default:
668 WARN( "unknown magic %08x\n", object->magic );
669 return STATUS_INVALID_HANDLE;
673 static NTSTATUS prepare_hash( struct hash *hash )
675 UCHAR buffer[MAX_HASH_BLOCK_BITS / 8] = {0};
676 int block_bytes, i;
677 NTSTATUS status;
679 /* initialize hash */
680 if ((status = hash_init( &hash->inner, hash->alg_id ))) return status;
681 if (!(hash->flags & HASH_FLAG_HMAC)) return STATUS_SUCCESS;
683 /* initialize hmac */
684 if ((status = hash_init( &hash->outer, hash->alg_id ))) return status;
685 block_bytes = builtin_algorithms[hash->alg_id].block_bits / 8;
686 if (hash->secret_len > block_bytes)
688 struct hash_impl temp;
689 if ((status = hash_init( &temp, hash->alg_id ))) return status;
690 if ((status = hash_update( &temp, hash->alg_id, hash->secret, hash->secret_len ))) return status;
691 if ((status = hash_finish( &temp, hash->alg_id, buffer,
692 builtin_algorithms[hash->alg_id].hash_length ))) return status;
694 else memcpy( buffer, hash->secret, hash->secret_len );
696 for (i = 0; i < block_bytes; i++) buffer[i] ^= 0x5c;
697 if ((status = hash_update( &hash->outer, hash->alg_id, buffer, block_bytes ))) return status;
698 for (i = 0; i < block_bytes; i++) buffer[i] ^= (0x5c ^ 0x36);
699 return hash_update( &hash->inner, hash->alg_id, buffer, block_bytes );
702 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
703 UCHAR *secret, ULONG secretlen, ULONG flags )
705 struct algorithm *alg = algorithm;
706 struct hash *hash;
707 NTSTATUS status;
709 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
710 secret, secretlen, flags );
711 if (flags & ~BCRYPT_HASH_REUSABLE_FLAG)
713 FIXME( "unimplemented flags %08x\n", flags );
714 return STATUS_NOT_IMPLEMENTED;
717 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
718 if (object) FIXME( "ignoring object buffer\n" );
720 if (!(hash = heap_alloc_zero( sizeof(*hash) ))) return STATUS_NO_MEMORY;
721 hash->hdr.magic = MAGIC_HASH;
722 hash->alg_id = alg->id;
723 if (alg->flags & BCRYPT_ALG_HANDLE_HMAC_FLAG) hash->flags = HASH_FLAG_HMAC;
724 if ((alg->flags & BCRYPT_HASH_REUSABLE_FLAG) || (flags & BCRYPT_HASH_REUSABLE_FLAG))
725 hash->flags |= HASH_FLAG_REUSABLE;
727 if (secretlen && !(hash->secret = heap_alloc( secretlen )))
729 heap_free( hash );
730 return STATUS_NO_MEMORY;
732 memcpy( hash->secret, secret, secretlen );
733 hash->secret_len = secretlen;
735 if ((status = prepare_hash( hash )) != STATUS_SUCCESS)
737 heap_free( hash->secret );
738 heap_free( hash );
739 return status;
742 *handle = hash;
743 return STATUS_SUCCESS;
746 NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy,
747 UCHAR *object, ULONG objectlen, ULONG flags )
749 struct hash *hash_orig = handle;
750 struct hash *hash_copy;
752 TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, objectlen, flags );
754 if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
755 if (!handle_copy) return STATUS_INVALID_PARAMETER;
756 if (object) FIXME( "ignoring object buffer\n" );
758 if (!(hash_copy = heap_alloc( sizeof(*hash_copy) )))
759 return STATUS_NO_MEMORY;
761 memcpy( hash_copy, hash_orig, sizeof(*hash_orig) );
762 if (hash_orig->secret && !(hash_copy->secret = heap_alloc( hash_orig->secret_len )))
764 heap_free( hash_copy );
765 return STATUS_NO_MEMORY;
767 memcpy( hash_copy->secret, hash_orig->secret, hash_orig->secret_len );
769 *handle_copy = hash_copy;
770 return STATUS_SUCCESS;
773 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
775 struct hash *hash = handle;
777 TRACE( "%p\n", handle );
779 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_PARAMETER;
780 hash->hdr.magic = 0;
781 heap_free( hash->secret );
782 heap_free( hash );
783 return STATUS_SUCCESS;
786 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
788 struct hash *hash = handle;
790 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
792 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
793 if (!input) return STATUS_SUCCESS;
795 return hash_update( &hash->inner, hash->alg_id, input, size );
798 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
800 UCHAR buffer[MAX_HASH_OUTPUT_BYTES];
801 struct hash *hash = handle;
802 NTSTATUS status;
803 int hash_length;
805 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
807 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
808 if (!output) return STATUS_INVALID_PARAMETER;
810 if (!(hash->flags & HASH_FLAG_HMAC))
812 if ((status = hash_finish( &hash->inner, hash->alg_id, output, size ))) return status;
813 if (hash->flags & HASH_FLAG_REUSABLE) return prepare_hash( hash );
814 return STATUS_SUCCESS;
817 hash_length = builtin_algorithms[hash->alg_id].hash_length;
818 if ((status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_length ))) return status;
819 if ((status = hash_update( &hash->outer, hash->alg_id, buffer, hash_length ))) return status;
820 if ((status = hash_finish( &hash->outer, hash->alg_id, output, size ))) return status;
821 if (hash->flags & HASH_FLAG_REUSABLE) return prepare_hash( hash );
822 return STATUS_SUCCESS;
825 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
826 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
828 NTSTATUS status;
829 BCRYPT_HASH_HANDLE handle;
831 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
832 input, inputlen, output, outputlen );
834 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
835 if (status != STATUS_SUCCESS)
837 return status;
840 status = BCryptHashData( handle, input, inputlen, 0 );
841 if (status != STATUS_SUCCESS)
843 BCryptDestroyHash( handle );
844 return status;
847 status = BCryptFinishHash( handle, output, outputlen, 0 );
848 if (status != STATUS_SUCCESS)
850 BCryptDestroyHash( handle );
851 return status;
854 return BCryptDestroyHash( handle );
857 #if defined(HAVE_GNUTLS_CIPHER_INIT) || defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
858 BOOL key_is_symmetric( struct key *key )
860 return builtin_algorithms[key->alg_id].class == BCRYPT_CIPHER_INTERFACE;
863 BOOL is_zero_vector( const UCHAR *vector, ULONG len )
865 ULONG i;
866 if (!vector) return FALSE;
867 for (i = 0; i < len; i++) if (vector[i]) return FALSE;
868 return TRUE;
871 BOOL is_equal_vector( const UCHAR *vector, ULONG len, const UCHAR *vector2, ULONG len2 )
873 if (!vector && !vector2) return TRUE;
874 if (len != len2) return FALSE;
875 return !memcmp( vector, vector2, len );
878 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
879 ULONG object_len, UCHAR *input, ULONG input_len )
881 ULONG len;
883 if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
885 BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)input;
887 if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) return STATUS_BUFFER_TOO_SMALL;
888 if (header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) return STATUS_INVALID_PARAMETER;
889 if (header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1)
891 FIXME( "unknown key data blob version %u\n", header->dwVersion );
892 return STATUS_INVALID_PARAMETER;
894 len = header->cbKeyData;
895 if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER;
897 return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, (UCHAR *)&header[1], len, 0 );
899 else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
901 if (input_len < sizeof(len)) return STATUS_BUFFER_TOO_SMALL;
902 len = *(ULONG *)input;
903 if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER;
905 return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, input + sizeof(len), len, 0 );
908 FIXME( "unsupported key type %s\n", debugstr_w(type) );
909 return STATUS_NOT_IMPLEMENTED;
912 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
914 if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
916 BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)output;
917 ULONG req_size = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key->u.s.secret_len;
919 *size = req_size;
920 if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
922 header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
923 header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
924 header->cbKeyData = key->u.s.secret_len;
925 memcpy( &header[1], key->u.s.secret, key->u.s.secret_len );
926 return STATUS_SUCCESS;
928 else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
930 ULONG len, req_size = sizeof(len) + key->u.s.secret_len;
932 *size = req_size;
933 if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
935 *(ULONG *)output = key->u.s.secret_len;
936 memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len );
937 return STATUS_SUCCESS;
939 else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ) || !strcmpW( type, BCRYPT_DSA_PUBLIC_BLOB ) ||
940 !strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
942 *size = key->u.a.pubkey_len;
943 if (output_len < key->u.a.pubkey_len) return STATUS_SUCCESS;
945 memcpy( output, key->u.a.pubkey, key->u.a.pubkey_len );
946 return STATUS_SUCCESS;
948 else if (!strcmpW( type, BCRYPT_ECCPRIVATE_BLOB ))
950 return key_export_ecc( key, output, output_len, size );
952 else if (!strcmpW( type, LEGACY_DSA_V2_PRIVATE_BLOB ))
954 return key_export_dsa_capi( key, output, output_len, size );
957 FIXME( "unsupported key type %s\n", debugstr_w(type) );
958 return STATUS_NOT_IMPLEMENTED;
961 static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
963 UCHAR *buffer;
965 memset( key_copy, 0, sizeof(*key_copy) );
966 key_copy->hdr = key_orig->hdr;
967 key_copy->alg_id = key_orig->alg_id;
969 if (key_is_symmetric( key_orig ))
971 if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY;
972 memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len );
974 key_copy->u.s.mode = key_orig->u.s.mode;
975 key_copy->u.s.block_size = key_orig->u.s.block_size;
976 key_copy->u.s.secret = buffer;
977 key_copy->u.s.secret_len = key_orig->u.s.secret_len;
979 else
981 if (!(buffer = heap_alloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY;
982 memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len );
984 key_copy->u.a.pubkey = buffer;
985 key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len;
988 return STATUS_SUCCESS;
991 static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
992 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
994 ULONG bytes_left = input_len;
995 UCHAR *buf, *src, *dst;
996 NTSTATUS status;
998 if (key->u.s.mode == MODE_ID_GCM)
1000 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
1002 if (!auth_info) return STATUS_INVALID_PARAMETER;
1003 if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
1004 if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
1005 if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
1006 if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
1007 FIXME( "call chaining not implemented\n" );
1009 if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
1010 return status;
1012 *ret_len = input_len;
1013 if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
1014 if (input && !output) return STATUS_SUCCESS;
1015 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1017 if ((status = key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData )))
1018 return status;
1019 if ((status = key_symmetric_encrypt( key, input, input_len, output, output_len ))) return status;
1021 return key_symmetric_get_tag( key, auth_info->pbTag, auth_info->cbTag );
1024 *ret_len = input_len;
1026 if (flags & BCRYPT_BLOCK_PADDING)
1027 *ret_len = (input_len + key->u.s.block_size) & ~(key->u.s.block_size - 1);
1028 else if (input_len & (key->u.s.block_size - 1))
1029 return STATUS_INVALID_BUFFER_SIZE;
1031 if (!output) return STATUS_SUCCESS;
1032 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1033 if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
1034 if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
1036 src = input;
1037 dst = output;
1038 while (bytes_left >= key->u.s.block_size)
1040 if ((status = key_symmetric_encrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
1041 return status;
1042 if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
1043 bytes_left -= key->u.s.block_size;
1044 src += key->u.s.block_size;
1045 dst += key->u.s.block_size;
1048 if (flags & BCRYPT_BLOCK_PADDING)
1050 if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
1051 memcpy( buf, src, bytes_left );
1052 memset( buf + bytes_left, key->u.s.block_size - bytes_left, key->u.s.block_size - bytes_left );
1053 status = key_symmetric_encrypt( key, buf, key->u.s.block_size, dst, key->u.s.block_size );
1054 heap_free( buf );
1057 return status;
1060 static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1061 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1063 ULONG bytes_left = input_len;
1064 UCHAR *buf, *src, *dst;
1065 NTSTATUS status;
1067 if (key->u.s.mode == MODE_ID_GCM)
1069 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
1070 UCHAR tag[16];
1072 if (!auth_info) return STATUS_INVALID_PARAMETER;
1073 if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
1074 if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
1075 if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
1077 if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
1078 return status;
1080 *ret_len = input_len;
1081 if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
1082 if (!output) return STATUS_SUCCESS;
1083 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1085 if ((status = key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData )))
1086 return status;
1087 if ((status = key_symmetric_decrypt( key, input, input_len, output, output_len ))) return status;
1089 if ((status = key_symmetric_get_tag( key, tag, sizeof(tag) ))) return status;
1090 if (memcmp( tag, auth_info->pbTag, auth_info->cbTag )) return STATUS_AUTH_TAG_MISMATCH;
1092 return STATUS_SUCCESS;
1095 *ret_len = input_len;
1097 if (input_len & (key->u.s.block_size - 1)) return STATUS_INVALID_BUFFER_SIZE;
1098 if (!output) return STATUS_SUCCESS;
1099 if (flags & BCRYPT_BLOCK_PADDING)
1101 if (output_len + key->u.s.block_size < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1102 if (input_len < key->u.s.block_size) return STATUS_BUFFER_TOO_SMALL;
1103 bytes_left -= key->u.s.block_size;
1105 else if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1107 if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
1108 if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
1110 src = input;
1111 dst = output;
1112 while (bytes_left >= key->u.s.block_size)
1114 if ((status = key_symmetric_decrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
1115 return status;
1116 if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
1117 bytes_left -= key->u.s.block_size;
1118 src += key->u.s.block_size;
1119 dst += key->u.s.block_size;
1122 if (flags & BCRYPT_BLOCK_PADDING)
1124 if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
1125 status = key_symmetric_decrypt( key, src, key->u.s.block_size, buf, key->u.s.block_size );
1126 if (!status && buf[ key->u.s.block_size - 1 ] <= key->u.s.block_size)
1128 *ret_len -= buf[ key->u.s.block_size - 1 ];
1129 if (output_len < *ret_len) status = STATUS_BUFFER_TOO_SMALL;
1130 else memcpy( dst, buf, key->u.s.block_size - buf[ key->u.s.block_size - 1 ] );
1132 else status = STATUS_UNSUCCESSFUL; /* FIXME: invalid padding */
1133 heap_free( buf );
1136 return status;
1139 static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
1140 ULONG input_len )
1142 struct key *key;
1143 NTSTATUS status;
1145 if (!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
1147 BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
1148 DWORD key_size, magic, size;
1150 if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
1152 switch (alg->id)
1154 case ALG_ID_ECDH_P256:
1155 key_size = 32;
1156 magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
1157 break;
1159 case ALG_ID_ECDSA_P256:
1160 key_size = 32;
1161 magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
1162 break;
1164 case ALG_ID_ECDSA_P384:
1165 key_size = 48;
1166 magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
1167 break;
1169 default:
1170 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
1171 return STATUS_NOT_SUPPORTED;
1174 if (ecc_blob->dwMagic != magic) return STATUS_NOT_SUPPORTED;
1175 if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2)
1176 return STATUS_INVALID_PARAMETER;
1178 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1179 key->hdr.magic = MAGIC_KEY;
1181 size = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
1182 if ((status = key_asymmetric_init( key, alg, key_size * 8, (BYTE *)ecc_blob, size )))
1184 heap_free( key );
1185 return status;
1188 *ret_key = key;
1189 return STATUS_SUCCESS;
1191 else if (!strcmpW( type, BCRYPT_ECCPRIVATE_BLOB ))
1193 BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
1194 DWORD key_size, magic;
1196 if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
1198 switch (alg->id)
1200 case ALG_ID_ECDH_P256:
1201 key_size = 32;
1202 magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
1203 break;
1205 default:
1206 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
1207 return STATUS_NOT_SUPPORTED;
1210 if (ecc_blob->dwMagic != magic) return STATUS_NOT_SUPPORTED;
1211 if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3)
1212 return STATUS_INVALID_PARAMETER;
1214 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1215 key->hdr.magic = MAGIC_KEY;
1217 if ((status = key_asymmetric_init( key, alg, key_size * 8, NULL, 0 )))
1219 heap_free( key );
1220 return status;
1222 if ((status = key_import_ecc( key, input, input_len )))
1224 heap_free( key );
1225 return status;
1228 *ret_key = key;
1229 return STATUS_SUCCESS;
1231 else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ))
1233 BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
1234 ULONG size;
1236 if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER;
1237 if ((alg->id != ALG_ID_RSA && alg->id != ALG_ID_RSA_SIGN) || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC)
1238 return STATUS_NOT_SUPPORTED;
1240 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1241 key->hdr.magic = MAGIC_KEY;
1243 size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
1244 if ((status = key_asymmetric_init( key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size )))
1246 heap_free( key );
1247 return status;
1250 *ret_key = key;
1251 return STATUS_SUCCESS;
1253 else if (!strcmpW( type, BCRYPT_DSA_PUBLIC_BLOB ))
1255 BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input;
1256 ULONG size;
1258 if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER;
1259 if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC)
1260 return STATUS_NOT_SUPPORTED;
1262 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1263 key->hdr.magic = MAGIC_KEY;
1265 size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
1266 if ((status = key_asymmetric_init( key, alg, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size )))
1268 heap_free( key );
1269 return status;
1272 *ret_key = key;
1273 return STATUS_SUCCESS;
1275 else if (!strcmpW( type, LEGACY_DSA_V2_PRIVATE_BLOB ))
1277 BLOBHEADER *hdr = (BLOBHEADER *)input;
1278 DSSPUBKEY *pubkey;
1280 if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER;
1282 if (hdr->bType != PRIVATEKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN)
1284 FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg );
1285 return STATUS_NOT_SUPPORTED;
1287 if (alg->id != ALG_ID_DSA)
1289 FIXME( "algorithm %u does not support importing blob of type %s\n", alg->id, debugstr_w(type) );
1290 return STATUS_NOT_SUPPORTED;
1293 if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER;
1294 pubkey = (DSSPUBKEY *)(hdr + 1);
1295 if (pubkey->magic != MAGIC_DSS2) return STATUS_NOT_SUPPORTED;
1297 if (input_len < sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 2 + 40 + sizeof(DSSSEED))
1298 return STATUS_INVALID_PARAMETER;
1300 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1301 key->hdr.magic = MAGIC_KEY;
1303 if ((status = key_asymmetric_init( key, alg, pubkey->bitlen, NULL, 0 )))
1305 heap_free( key );
1306 return status;
1308 if ((status = key_import_dsa_capi( key, input, input_len )))
1310 heap_free( key );
1311 return status;
1314 *ret_key = key;
1315 return STATUS_SUCCESS;
1318 FIXME( "unsupported key type %s\n", debugstr_w(type) );
1319 return STATUS_NOT_SUPPORTED;
1321 #else
1322 NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR *secret, ULONG secret_len )
1324 ERR( "support for keys not available at build time\n" );
1325 return STATUS_NOT_IMPLEMENTED;
1328 BOOL key_is_symmetric( struct key *key )
1330 ERR( "support for keys not available at build time\n" );
1331 return FALSE;
1334 NTSTATUS key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
1336 ERR( "support for keys not available at build time\n" );
1337 return STATUS_NOT_IMPLEMENTED;
1340 static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
1342 ERR( "support for keys not available at build time\n" );
1343 return STATUS_NOT_IMPLEMENTED;
1346 NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, ULONG bitlen, const UCHAR *pubkey,
1347 ULONG pubkey_len )
1349 ERR( "support for keys not available at build time\n" );
1350 return STATUS_NOT_IMPLEMENTED;
1353 NTSTATUS key_asymmetric_generate( struct key *key )
1355 ERR( "support for keys not available at build time\n" );
1356 return STATUS_NOT_IMPLEMENTED;
1359 NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
1360 ULONG output_len, ULONG *ret_len, ULONG flags )
1362 ERR( "support for keys not available at build time\n" );
1363 return STATUS_NOT_IMPLEMENTED;
1366 NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
1367 ULONG signature_len, DWORD flags )
1369 ERR( "support for keys not available at build time\n" );
1370 return STATUS_NOT_IMPLEMENTED;
1373 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
1374 ULONG object_len, UCHAR *input, ULONG input_len )
1376 ERR( "support for keys not available at build time\n" );
1377 return STATUS_NOT_IMPLEMENTED;
1380 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
1382 ERR( "support for keys not available at build time\n" );
1383 return STATUS_NOT_IMPLEMENTED;
1386 NTSTATUS key_destroy( struct key *key )
1388 ERR( "support for keys not available at build time\n" );
1389 return STATUS_NOT_IMPLEMENTED;
1392 static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1393 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1395 ERR( "support for keys not available at build time\n" );
1396 return STATUS_NOT_IMPLEMENTED;
1399 static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1400 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1402 ERR( "support for keys not available at build time\n" );
1403 return STATUS_NOT_IMPLEMENTED;
1406 static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
1407 ULONG input_len )
1409 ERR( "support for keys not available at build time\n" );
1410 return STATUS_NOT_IMPLEMENTED;
1413 NTSTATUS key_export_ecc( struct key *key, UCHAR *output, ULONG len, ULONG *ret_len )
1415 ERR( "support for keys not available at build time\n" );
1416 return STATUS_NOT_IMPLEMENTED;
1419 NTSTATUS key_import_ecc( struct key *key, UCHAR *input, ULONG len )
1421 ERR( "support for keys not available at build time\n" );
1422 return STATUS_NOT_IMPLEMENTED;
1424 #endif
1426 NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle,
1427 UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len,
1428 ULONG flags )
1430 struct algorithm *alg = algorithm;
1431 struct key *key;
1432 NTSTATUS status;
1434 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm, handle, object, object_len, secret, secret_len, flags );
1436 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1437 if (object) FIXME( "ignoring object buffer\n" );
1439 if (!(key = heap_alloc( sizeof(*key) ))) return STATUS_NO_MEMORY;
1440 key->hdr.magic = MAGIC_KEY;
1442 if ((status = key_symmetric_init( key, alg, secret, secret_len )))
1444 heap_free( key );
1445 return status;
1448 *handle = key;
1449 return STATUS_SUCCESS;
1452 NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, ULONG key_len,
1453 ULONG flags )
1455 struct algorithm *alg = algorithm;
1456 struct key *key;
1457 NTSTATUS status;
1459 TRACE( "%p, %p, %u, %08x\n", algorithm, handle, key_len, flags );
1461 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1462 if (!handle) return STATUS_INVALID_PARAMETER;
1464 if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
1465 key->hdr.magic = MAGIC_KEY;
1467 if ((status = key_asymmetric_init( key, alg, key_len, NULL, 0 )))
1469 heap_free( key );
1470 return status;
1473 *handle = key;
1474 return STATUS_SUCCESS;
1477 NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags )
1479 struct key *key = handle;
1481 TRACE( "%p, %08x\n", key, flags );
1482 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1484 return key_asymmetric_generate( key );
1487 NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type,
1488 BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input,
1489 ULONG input_len, ULONG flags )
1491 struct algorithm *alg = algorithm;
1493 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm, decrypt_key, debugstr_w(type), key, object,
1494 object_len, input, input_len, flags);
1496 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1497 if (!key || !type || !input) return STATUS_INVALID_PARAMETER;
1499 if (decrypt_key)
1501 FIXME( "decryption of key not yet supported\n" );
1502 return STATUS_NOT_IMPLEMENTED;
1505 return key_import( algorithm, type, key, object, object_len, input, input_len );
1508 NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type,
1509 PUCHAR output, ULONG output_len, ULONG *size, ULONG flags )
1511 struct key *key = export_key;
1513 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key, encrypt_key, debugstr_w(type), output, output_len, size, flags);
1515 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1516 if (!type || !size) return STATUS_INVALID_PARAMETER;
1518 if (encrypt_key)
1520 FIXME( "encryption of key not yet supported\n" );
1521 return STATUS_NOT_IMPLEMENTED;
1524 return key_export( key, type, output, output_len, size );
1527 NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE *handle_copy,
1528 UCHAR *object, ULONG object_len, ULONG flags )
1530 struct key *key_orig = handle;
1531 struct key *key_copy;
1532 NTSTATUS status;
1534 TRACE( "%p, %p, %p, %u, %08x\n", handle, handle_copy, object, object_len, flags );
1535 if (object) FIXME( "ignoring object buffer\n" );
1537 if (!key_orig || key_orig->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1538 if (!handle_copy) return STATUS_INVALID_PARAMETER;
1539 if (!(key_copy = heap_alloc( sizeof(*key_copy) ))) return STATUS_NO_MEMORY;
1541 if ((status = key_duplicate( key_orig, key_copy )))
1543 heap_free( key_copy );
1544 return status;
1547 *handle_copy = key_copy;
1548 return STATUS_SUCCESS;
1551 NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
1552 BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len, ULONG flags )
1554 struct algorithm *alg = algorithm;
1556 TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm, decrypt_key, debugstr_w(type), ret_key, input,
1557 input_len, flags );
1559 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1560 if (!ret_key || !type || !input) return STATUS_INVALID_PARAMETER;
1561 if (decrypt_key)
1563 FIXME( "decryption of key not yet supported\n" );
1564 return STATUS_NOT_IMPLEMENTED;
1567 return key_import_pair( alg, type, ret_key, input, input_len );
1570 NTSTATUS WINAPI BCryptSignHash( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *input, ULONG input_len,
1571 UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1573 struct key *key = handle;
1575 TRACE( "%p, %p, %p, %u, %p, %u, %p, %08x\n", handle, padding, input, input_len, output, output_len,
1576 ret_len, flags );
1578 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1579 if (key_is_symmetric( key ))
1581 FIXME( "signing with symmetric keys not yet supported\n" );
1582 return STATUS_NOT_IMPLEMENTED;
1585 return key_asymmetric_sign( key, padding, input, input_len, output, output_len, ret_len, flags );
1588 NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len,
1589 UCHAR *signature, ULONG signature_len, ULONG flags )
1591 struct key *key = handle;
1593 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle, padding, hash, hash_len, signature, signature_len, flags );
1595 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1596 if (!hash || !hash_len || !signature || !signature_len) return STATUS_INVALID_PARAMETER;
1597 if (key_is_symmetric( key )) return STATUS_NOT_SUPPORTED;
1599 return key_asymmetric_verify( key, padding, hash, hash_len, signature, signature_len, flags );
1602 NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle )
1604 struct key *key = handle;
1606 TRACE( "%p\n", handle );
1608 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1609 key->hdr.magic = 0;
1610 return key_destroy( key );
1613 NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1614 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1616 struct key *key = handle;
1618 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output,
1619 output_len, ret_len, flags );
1621 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1622 if (!key_is_symmetric( key ))
1624 FIXME( "encryption with asymmetric keys not yet supported\n" );
1625 return STATUS_NOT_IMPLEMENTED;
1627 if (flags & ~BCRYPT_BLOCK_PADDING)
1629 FIXME( "flags %08x not implemented\n", flags );
1630 return STATUS_NOT_IMPLEMENTED;
1633 return key_encrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
1636 NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1637 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1639 struct key *key = handle;
1641 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output,
1642 output_len, ret_len, flags );
1644 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1645 if (!key_is_symmetric( key ))
1647 FIXME( "decryption with asymmetric keys not yet supported\n" );
1648 return STATUS_NOT_IMPLEMENTED;
1650 if (flags & ~BCRYPT_BLOCK_PADDING)
1652 FIXME( "flags %08x not supported\n", flags );
1653 return STATUS_NOT_IMPLEMENTED;
1656 return key_decrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
1659 NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
1661 struct object *object = handle;
1663 TRACE( "%p, %s, %p, %u, %08x\n", handle, debugstr_w(prop), value, size, flags );
1665 if (!object) return STATUS_INVALID_HANDLE;
1667 switch (object->magic)
1669 case MAGIC_ALG:
1671 struct algorithm *alg = (struct algorithm *)object;
1672 return set_alg_property( alg, prop, value, size, flags );
1674 case MAGIC_KEY:
1676 struct key *key = (struct key *)object;
1677 return key_set_property( key, prop, value, size, flags );
1679 default:
1680 WARN( "unknown magic %08x\n", object->magic );
1681 return STATUS_INVALID_HANDLE;
1685 #define HMAC_PAD_LEN 64
1686 NTSTATUS WINAPI BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle, BCRYPT_ALG_HANDLE halg, UCHAR *key, ULONG keylen, ULONG flags )
1688 struct hash *hash = handle;
1689 UCHAR buf[MAX_HASH_OUTPUT_BYTES * 2];
1690 NTSTATUS status;
1691 ULONG len;
1693 TRACE( "%p, %p, %p, %u, %08x\n", handle, halg, key, keylen, flags );
1695 if (!key || !keylen) return STATUS_INVALID_PARAMETER;
1696 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
1697 if (keylen > builtin_algorithms[hash->alg_id].hash_length * 2) return STATUS_INVALID_PARAMETER;
1699 if (halg)
1701 FIXME( "algorithm handle not supported\n" );
1702 return STATUS_NOT_IMPLEMENTED;
1705 len = builtin_algorithms[hash->alg_id].hash_length;
1706 if ((status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
1708 if (len < keylen)
1710 UCHAR pad1[HMAC_PAD_LEN], pad2[HMAC_PAD_LEN];
1711 ULONG i;
1713 for (i = 0; i < sizeof(pad1); i++)
1715 pad1[i] = 0x36 ^ (i < len ? buf[i] : 0);
1716 pad2[i] = 0x5c ^ (i < len ? buf[i] : 0);
1719 if ((status = prepare_hash( hash )) ||
1720 (status = BCryptHashData( handle, pad1, sizeof(pad1), 0 )) ||
1721 (status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
1723 if ((status = prepare_hash( hash )) ||
1724 (status = BCryptHashData( handle, pad2, sizeof(pad2), 0 )) ||
1725 (status = BCryptFinishHash( handle, buf + len, len, 0 ))) return status;
1728 memcpy( key, buf, keylen );
1729 return STATUS_SUCCESS;
1732 static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
1733 ULONGLONG iterations, ULONG i, UCHAR *dst, ULONG hash_len )
1735 NTSTATUS status = STATUS_INVALID_PARAMETER;
1736 UCHAR bytes[4], *buf;
1737 ULONG j, k;
1739 if (!(buf = heap_alloc( hash_len ))) return STATUS_NO_MEMORY;
1741 for (j = 0; j < iterations; j++)
1743 if (j == 0)
1745 /* use salt || INT(i) */
1746 status = BCryptHashData( handle, salt, salt_len, 0 );
1747 if (status != STATUS_SUCCESS)
1749 heap_free( buf );
1750 return status;
1752 bytes[0] = (i >> 24) & 0xff;
1753 bytes[1] = (i >> 16) & 0xff;
1754 bytes[2] = (i >> 8) & 0xff;
1755 bytes[3] = i & 0xff;
1756 status = BCryptHashData( handle, bytes, 4, 0 );
1758 else status = BCryptHashData( handle, buf, hash_len, 0 ); /* use U_j */
1759 if (status != STATUS_SUCCESS)
1761 heap_free( buf );
1762 return status;
1765 status = BCryptFinishHash( handle, buf, hash_len, 0 );
1766 if (status != STATUS_SUCCESS)
1768 heap_free( buf );
1769 return status;
1772 if (j == 0) memcpy( dst, buf, hash_len );
1773 else for (k = 0; k < hash_len; k++) dst[k] ^= buf[k];
1776 heap_free( buf );
1777 return status;
1780 NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
1781 ULONGLONG iterations, UCHAR *dk, ULONG dk_len, ULONG flags )
1783 struct algorithm *alg = handle;
1784 ULONG hash_len, block_count, bytes_left, i;
1785 BCRYPT_HASH_HANDLE hash;
1786 UCHAR *partial;
1787 NTSTATUS status;
1789 TRACE( "%p, %p, %u, %p, %u, %s, %p, %u, %08x\n", handle, pwd, pwd_len, salt, salt_len,
1790 wine_dbgstr_longlong(iterations), dk, dk_len, flags );
1792 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1794 hash_len = builtin_algorithms[alg->id].hash_length;
1795 if (dk_len <= 0 || dk_len > ((((ULONGLONG)1) << 32) - 1) * hash_len) return STATUS_INVALID_PARAMETER;
1797 block_count = 1 + ((dk_len - 1) / hash_len); /* ceil(dk_len / hash_len) */
1798 bytes_left = dk_len - (block_count - 1) * hash_len;
1800 status = BCryptCreateHash( handle, &hash, NULL, 0, pwd, pwd_len, BCRYPT_HASH_REUSABLE_FLAG );
1801 if (status != STATUS_SUCCESS)
1802 return status;
1804 /* full blocks */
1805 for (i = 1; i < block_count; i++)
1807 status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, i, dk + ((i - 1) * hash_len), hash_len );
1808 if (status != STATUS_SUCCESS)
1810 BCryptDestroyHash( hash );
1811 return status;
1815 /* final partial block */
1816 if (!(partial = heap_alloc( hash_len )))
1818 BCryptDestroyHash( hash );
1819 return STATUS_NO_MEMORY;
1822 status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, block_count, partial, hash_len );
1823 if (status != STATUS_SUCCESS)
1825 BCryptDestroyHash( hash );
1826 heap_free( partial );
1827 return status;
1829 memcpy( dk + ((block_count - 1) * hash_len), partial, bytes_left );
1831 BCryptDestroyHash( hash );
1832 heap_free( partial );
1833 return STATUS_SUCCESS;
1836 NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE key, BCRYPT_SECRET_HANDLE *secret, ULONG flags)
1838 FIXME( "%p, %p, %p, %08x\n", handle, key, secret, flags );
1840 if(secret)
1841 *secret = (BCRYPT_SECRET_HANDLE *)0xDEADFEED;
1843 return STATUS_SUCCESS;
1846 NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE secret)
1848 FIXME( "%p\n", secret );
1849 return STATUS_SUCCESS;
1852 NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE secret, LPCWSTR kdf, BCryptBufferDesc *parameter,
1853 PUCHAR derived, ULONG derived_size, ULONG *result, ULONG flags)
1855 FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(kdf), parameter, derived, derived_size, result, flags );
1856 return STATUS_INTERNAL_ERROR;
1859 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1861 switch (reason)
1863 case DLL_PROCESS_ATTACH:
1864 instance = hinst;
1865 DisableThreadLibraryCalls( hinst );
1866 #ifdef HAVE_GNUTLS_CIPHER_INIT
1867 gnutls_initialize();
1868 #endif
1869 break;
1871 case DLL_PROCESS_DETACH:
1872 if (reserved) break;
1873 #ifdef HAVE_GNUTLS_CIPHER_INIT
1874 gnutls_uninitialize();
1875 #endif
1876 break;
1878 return TRUE;