api-ms-win-core-comm-l1-1-0: Add dll.
[wine.git] / dlls / bcrypt / bcrypt_main.c
blob2b9ae0b766f1974a9e7406bb2db6c38c868d60be
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/library.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 BCryptRegisterProvider(LPCWSTR provider, ULONG flags, PCRYPT_PROVIDER_REG reg)
73 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider), flags, reg);
74 return STATUS_SUCCESS;
77 NTSTATUS WINAPI BCryptUnregisterProvider(LPCWSTR provider)
79 FIXME("%s: stub\n", debugstr_w(provider));
80 return STATUS_NOT_IMPLEMENTED;
83 NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
84 BCRYPT_ALGORITHM_IDENTIFIER **ppAlgList, ULONG dwFlags)
86 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations, pAlgCount, ppAlgList, dwFlags);
88 *ppAlgList=NULL;
89 *pAlgCount=0;
91 return STATUS_NOT_IMPLEMENTED;
94 #define MAX_HASH_OUTPUT_BYTES 64
95 #define MAX_HASH_BLOCK_BITS 1024
97 static const struct
99 ULONG object_length;
100 ULONG hash_length;
101 ULONG block_bits;
102 const WCHAR *alg_name;
103 BOOL symmetric;
105 alg_props[] =
107 /* ALG_ID_AES */ { 654, 0, 0, BCRYPT_AES_ALGORITHM, TRUE },
108 /* ALG_ID_MD2 */ { 270, 16, 128, BCRYPT_MD2_ALGORITHM, FALSE },
109 /* ALG_ID_MD4 */ { 270, 16, 512, BCRYPT_MD4_ALGORITHM, FALSE },
110 /* ALG_ID_MD5 */ { 274, 16, 512, BCRYPT_MD5_ALGORITHM, FALSE },
111 /* ALG_ID_RNG */ { 0, 0, 0, BCRYPT_RNG_ALGORITHM, FALSE },
112 /* ALG_ID_RSA */ { 0, 0, 0, BCRYPT_RSA_ALGORITHM, FALSE },
113 /* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM, FALSE },
114 /* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM, FALSE },
115 /* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM, FALSE },
116 /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM, FALSE },
117 /* ALG_ID_ECDSA_P256 */ { 0, 0, 0, BCRYPT_ECDSA_P256_ALGORITHM, FALSE },
118 /* ALG_ID_ECDSA_P384 */ { 0, 0, 0, BCRYPT_ECDSA_P384_ALGORITHM, FALSE },
121 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
123 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
124 struct algorithm *algorithm = handle;
126 TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags);
128 if (!algorithm)
130 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
131 * is set. In this case the preferred system RNG is used.
133 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
134 return STATUS_INVALID_HANDLE;
136 else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
137 return STATUS_INVALID_HANDLE;
139 if (!buffer)
140 return STATUS_INVALID_PARAMETER;
142 if (flags & ~supported_flags)
143 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
145 if (algorithm)
146 FIXME("ignoring selected algorithm\n");
148 /* When zero bytes are requested the function returns success too. */
149 if (!count)
150 return STATUS_SUCCESS;
152 if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
154 if (RtlGenRandom(buffer, count))
155 return STATUS_SUCCESS;
158 FIXME("called with unsupported parameters, returning error\n");
159 return STATUS_NOT_IMPLEMENTED;
162 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
164 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
165 struct algorithm *alg;
166 enum alg_id alg_id;
168 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
170 if (!handle || !id) return STATUS_INVALID_PARAMETER;
171 if (flags & ~supported_flags)
173 FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
174 return STATUS_NOT_IMPLEMENTED;
177 if (!strcmpW( id, BCRYPT_AES_ALGORITHM )) alg_id = ALG_ID_AES;
178 else if (!strcmpW( id, BCRYPT_MD2_ALGORITHM )) alg_id = ALG_ID_MD2;
179 else if (!strcmpW( id, BCRYPT_MD4_ALGORITHM )) alg_id = ALG_ID_MD4;
180 else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
181 else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG;
182 else if (!strcmpW( id, BCRYPT_RSA_ALGORITHM )) alg_id = ALG_ID_RSA;
183 else if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
184 else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
185 else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
186 else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
187 else if (!strcmpW( id, BCRYPT_ECDSA_P256_ALGORITHM )) alg_id = ALG_ID_ECDSA_P256;
188 else if (!strcmpW( id, BCRYPT_ECDSA_P384_ALGORITHM )) alg_id = ALG_ID_ECDSA_P384;
189 else
191 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
192 return STATUS_NOT_IMPLEMENTED;
194 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
196 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
197 return STATUS_NOT_IMPLEMENTED;
200 if (!(alg = heap_alloc( sizeof(*alg) ))) return STATUS_NO_MEMORY;
201 alg->hdr.magic = MAGIC_ALG;
202 alg->id = alg_id;
203 alg->mode = MODE_ID_CBC;
204 alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG;
206 *handle = alg;
207 return STATUS_SUCCESS;
210 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
212 struct algorithm *alg = handle;
214 TRACE( "%p, %08x\n", handle, flags );
216 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
217 heap_free( alg );
218 return STATUS_SUCCESS;
221 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
223 FIXME("%p - semi-stub\n", enabled);
225 if (!enabled)
226 return STATUS_INVALID_PARAMETER;
228 *enabled = FALSE;
229 return STATUS_SUCCESS;
232 struct hash_impl
234 union
236 MD2_CTX md2;
237 MD4_CTX md4;
238 MD5_CTX md5;
239 SHA_CTX sha1;
240 SHA256_CTX sha256;
241 SHA512_CTX sha512;
242 } u;
245 static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id )
247 switch (alg_id)
249 case ALG_ID_MD2:
250 md2_init( &hash->u.md2 );
251 break;
253 case ALG_ID_MD4:
254 MD4Init( &hash->u.md4 );
255 break;
257 case ALG_ID_MD5:
258 MD5Init( &hash->u.md5 );
259 break;
261 case ALG_ID_SHA1:
262 A_SHAInit( &hash->u.sha1 );
263 break;
265 case ALG_ID_SHA256:
266 sha256_init( &hash->u.sha256 );
267 break;
269 case ALG_ID_SHA384:
270 sha384_init( &hash->u.sha512 );
271 break;
273 case ALG_ID_SHA512:
274 sha512_init( &hash->u.sha512 );
275 break;
277 default:
278 ERR( "unhandled id %u\n", alg_id );
279 return STATUS_NOT_IMPLEMENTED;
281 return STATUS_SUCCESS;
284 static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id,
285 UCHAR *input, ULONG size )
287 switch (alg_id)
289 case ALG_ID_MD2:
290 md2_update( &hash->u.md2, input, size );
291 break;
293 case ALG_ID_MD4:
294 MD4Update( &hash->u.md4, input, size );
295 break;
297 case ALG_ID_MD5:
298 MD5Update( &hash->u.md5, input, size );
299 break;
301 case ALG_ID_SHA1:
302 A_SHAUpdate( &hash->u.sha1, input, size );
303 break;
305 case ALG_ID_SHA256:
306 sha256_update( &hash->u.sha256, input, size );
307 break;
309 case ALG_ID_SHA384:
310 sha384_update( &hash->u.sha512, input, size );
311 break;
313 case ALG_ID_SHA512:
314 sha512_update( &hash->u.sha512, input, size );
315 break;
317 default:
318 ERR( "unhandled id %u\n", alg_id );
319 return STATUS_NOT_IMPLEMENTED;
321 return STATUS_SUCCESS;
324 static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id,
325 UCHAR *output, ULONG size )
327 switch (alg_id)
329 case ALG_ID_MD2:
330 md2_finalize( &hash->u.md2, output );
331 break;
333 case ALG_ID_MD4:
334 MD4Final( &hash->u.md4 );
335 memcpy( output, hash->u.md4.digest, 16 );
336 break;
338 case ALG_ID_MD5:
339 MD5Final( &hash->u.md5 );
340 memcpy( output, hash->u.md5.digest, 16 );
341 break;
343 case ALG_ID_SHA1:
344 A_SHAFinal( &hash->u.sha1, (ULONG *)output );
345 break;
347 case ALG_ID_SHA256:
348 sha256_finalize( &hash->u.sha256, output );
349 break;
351 case ALG_ID_SHA384:
352 sha384_finalize( &hash->u.sha512, output );
353 break;
355 case ALG_ID_SHA512:
356 sha512_finalize( &hash->u.sha512, output );
357 break;
359 default:
360 ERR( "unhandled id %u\n", alg_id );
361 return STATUS_NOT_IMPLEMENTED;
363 return STATUS_SUCCESS;
366 struct hash
368 struct object hdr;
369 enum alg_id alg_id;
370 BOOL hmac;
371 struct hash_impl outer;
372 struct hash_impl inner;
375 #define BLOCK_LENGTH_AES 16
377 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
379 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
381 if (!alg_props[id].object_length)
382 return STATUS_NOT_SUPPORTED;
383 *ret_size = sizeof(ULONG);
384 if (size < sizeof(ULONG))
385 return STATUS_BUFFER_TOO_SMALL;
386 if (buf)
387 *(ULONG *)buf = alg_props[id].object_length;
388 return STATUS_SUCCESS;
391 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
393 if (!alg_props[id].hash_length)
394 return STATUS_NOT_SUPPORTED;
395 *ret_size = sizeof(ULONG);
396 if (size < sizeof(ULONG))
397 return STATUS_BUFFER_TOO_SMALL;
398 if(buf)
399 *(ULONG*)buf = alg_props[id].hash_length;
400 return STATUS_SUCCESS;
403 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
405 *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR);
406 if (size < *ret_size)
407 return STATUS_BUFFER_TOO_SMALL;
408 if(buf)
409 memcpy(buf, alg_props[id].alg_name, *ret_size);
410 return STATUS_SUCCESS;
413 return STATUS_NOT_IMPLEMENTED;
416 NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
418 NTSTATUS status;
420 status = generic_alg_property( alg->id, prop, buf, size, ret_size );
421 if (status != STATUS_NOT_IMPLEMENTED)
422 return status;
424 switch (alg->id)
426 case ALG_ID_AES:
427 if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
429 *ret_size = sizeof(ULONG);
430 if (size < sizeof(ULONG))
431 return STATUS_BUFFER_TOO_SMALL;
432 if (buf)
433 *(ULONG *)buf = BLOCK_LENGTH_AES;
434 return STATUS_SUCCESS;
436 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
438 const WCHAR *mode;
439 switch (alg->mode)
441 case MODE_ID_ECB: mode = BCRYPT_CHAIN_MODE_ECB; break;
442 case MODE_ID_CBC: mode = BCRYPT_CHAIN_MODE_CBC; break;
443 case MODE_ID_GCM: mode = BCRYPT_CHAIN_MODE_GCM; break;
444 default: return STATUS_NOT_IMPLEMENTED;
447 *ret_size = 64;
448 if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
449 memcpy( buf, mode, (strlenW(mode) + 1) * sizeof(WCHAR) );
450 return STATUS_SUCCESS;
452 if (!strcmpW( prop, BCRYPT_KEY_LENGTHS ))
454 BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
455 *ret_size = sizeof(*key_lengths);
456 if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
457 if (key_lengths)
459 key_lengths->dwMinLength = 128;
460 key_lengths->dwMaxLength = 256;
461 key_lengths->dwIncrement = 64;
463 return STATUS_SUCCESS;
465 if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH ))
467 BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
468 if (alg->mode != MODE_ID_GCM) return STATUS_NOT_SUPPORTED;
469 *ret_size = sizeof(*tag_length);
470 if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
471 if (tag_length)
473 tag_length->dwMinLength = 12;
474 tag_length->dwMaxLength = 16;
475 tag_length->dwIncrement = 1;
477 return STATUS_SUCCESS;
479 break;
481 default:
482 break;
485 FIXME( "unsupported property %s\n", debugstr_w(prop) );
486 return STATUS_NOT_IMPLEMENTED;
489 static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
491 switch (alg->id)
493 case ALG_ID_AES:
494 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
496 if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_ECB, size ))
498 alg->mode = MODE_ID_ECB;
499 return STATUS_SUCCESS;
501 else if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC, size ))
503 alg->mode = MODE_ID_CBC;
504 return STATUS_SUCCESS;
506 else if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM, size ))
508 alg->mode = MODE_ID_GCM;
509 return STATUS_SUCCESS;
511 else
513 FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR *)value, size ) );
514 return STATUS_NOT_IMPLEMENTED;
517 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) );
518 return STATUS_NOT_IMPLEMENTED;
520 default:
521 FIXME( "unsupported algorithm %u\n", alg->id );
522 return STATUS_NOT_IMPLEMENTED;
526 static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
528 NTSTATUS status;
530 status = generic_alg_property( hash->alg_id, prop, buf, size, ret_size );
531 if (status == STATUS_NOT_IMPLEMENTED)
532 FIXME( "unsupported property %s\n", debugstr_w(prop) );
533 return status;
536 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
538 struct object *object = handle;
540 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
542 if (!object) return STATUS_INVALID_HANDLE;
543 if (!prop || !res) return STATUS_INVALID_PARAMETER;
545 switch (object->magic)
547 case MAGIC_ALG:
549 const struct algorithm *alg = (const struct algorithm *)object;
550 return get_alg_property( alg, prop, buffer, count, res );
552 case MAGIC_HASH:
554 const struct hash *hash = (const struct hash *)object;
555 return get_hash_property( hash, prop, buffer, count, res );
557 default:
558 WARN( "unknown magic %08x\n", object->magic );
559 return STATUS_INVALID_HANDLE;
563 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
564 UCHAR *secret, ULONG secretlen, ULONG flags )
566 struct algorithm *alg = algorithm;
567 UCHAR buffer[MAX_HASH_BLOCK_BITS / 8] = {0};
568 struct hash *hash;
569 int block_bytes;
570 NTSTATUS status;
571 int i;
573 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
574 secret, secretlen, flags );
575 if (flags)
577 FIXME( "unimplemented flags %08x\n", flags );
578 return STATUS_NOT_IMPLEMENTED;
581 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
582 if (object) FIXME( "ignoring object buffer\n" );
584 if (!(hash = heap_alloc( sizeof(*hash) ))) return STATUS_NO_MEMORY;
585 hash->hdr.magic = MAGIC_HASH;
586 hash->alg_id = alg->id;
587 hash->hmac = alg->hmac;
589 /* initialize hash */
590 if ((status = hash_init( &hash->inner, hash->alg_id ))) goto end;
591 if (!hash->hmac) goto end;
593 /* initialize hmac */
594 if ((status = hash_init( &hash->outer, hash->alg_id ))) goto end;
595 block_bytes = alg_props[hash->alg_id].block_bits / 8;
596 if (secretlen > block_bytes)
598 struct hash_impl temp;
599 if ((status = hash_init( &temp, hash->alg_id ))) goto end;
600 if ((status = hash_update( &temp, hash->alg_id, secret, secretlen ))) goto end;
601 if ((status = hash_finish( &temp, hash->alg_id, buffer,
602 alg_props[hash->alg_id].hash_length ))) goto end;
604 else
606 memcpy( buffer, secret, secretlen );
608 for (i = 0; i < block_bytes; i++) buffer[i] ^= 0x5c;
609 if ((status = hash_update( &hash->outer, hash->alg_id, buffer, block_bytes ))) goto end;
610 for (i = 0; i < block_bytes; i++) buffer[i] ^= (0x5c ^ 0x36);
611 status = hash_update( &hash->inner, hash->alg_id, buffer, block_bytes );
613 end:
614 if (status != STATUS_SUCCESS)
616 heap_free( hash );
617 return status;
620 *handle = hash;
621 return STATUS_SUCCESS;
624 NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy,
625 UCHAR *object, ULONG objectlen, ULONG flags )
627 struct hash *hash_orig = handle;
628 struct hash *hash_copy;
630 TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, objectlen, flags );
632 if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
633 if (!handle_copy) return STATUS_INVALID_PARAMETER;
634 if (object) FIXME( "ignoring object buffer\n" );
636 if (!(hash_copy = heap_alloc( sizeof(*hash_copy) )))
637 return STATUS_NO_MEMORY;
639 memcpy( hash_copy, hash_orig, sizeof(*hash_orig) );
641 *handle_copy = hash_copy;
642 return STATUS_SUCCESS;
645 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
647 struct hash *hash = handle;
649 TRACE( "%p\n", handle );
651 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
652 heap_free( hash );
653 return STATUS_SUCCESS;
656 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
658 struct hash *hash = handle;
660 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
662 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
663 if (!input) return STATUS_SUCCESS;
665 return hash_update( &hash->inner, hash->alg_id, input, size );
668 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
670 UCHAR buffer[MAX_HASH_OUTPUT_BYTES];
671 struct hash *hash = handle;
672 NTSTATUS status;
673 int hash_length;
675 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
677 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
678 if (!output) return STATUS_INVALID_PARAMETER;
680 if (!hash->hmac)
681 return hash_finish( &hash->inner, hash->alg_id, output, size );
683 hash_length = alg_props[hash->alg_id].hash_length;
684 if ((status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_length ))) return status;
685 if ((status = hash_update( &hash->outer, hash->alg_id, buffer, hash_length ))) return status;
686 return hash_finish( &hash->outer, hash->alg_id, output, size );
689 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
690 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
692 NTSTATUS status;
693 BCRYPT_HASH_HANDLE handle;
695 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
696 input, inputlen, output, outputlen );
698 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
699 if (status != STATUS_SUCCESS)
701 return status;
704 status = BCryptHashData( handle, input, inputlen, 0 );
705 if (status != STATUS_SUCCESS)
707 BCryptDestroyHash( handle );
708 return status;
711 status = BCryptFinishHash( handle, output, outputlen, 0 );
712 if (status != STATUS_SUCCESS)
714 BCryptDestroyHash( handle );
715 return status;
718 return BCryptDestroyHash( handle );
721 #if defined(HAVE_GNUTLS_CIPHER_INIT) || defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
722 BOOL key_is_symmetric( struct key *key )
724 return alg_props[key->alg_id].symmetric;
727 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
728 ULONG object_len, UCHAR *input, ULONG input_len )
730 ULONG len;
732 if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
734 BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)input;
736 if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) return STATUS_BUFFER_TOO_SMALL;
737 if (header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) return STATUS_INVALID_PARAMETER;
738 if (header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1)
740 FIXME( "unknown key data blob version %u\n", header->dwVersion );
741 return STATUS_INVALID_PARAMETER;
743 len = header->cbKeyData;
744 if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER;
746 return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, (UCHAR *)&header[1], len, 0 );
748 else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
750 if (input_len < sizeof(len)) return STATUS_BUFFER_TOO_SMALL;
751 len = *(ULONG *)input;
752 if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER;
754 return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, input + sizeof(len), len, 0 );
757 FIXME( "unsupported key type %s\n", debugstr_w(type) );
758 return STATUS_NOT_IMPLEMENTED;
761 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
763 if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
765 BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)output;
766 ULONG req_size = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key->u.s.secret_len;
768 *size = req_size;
769 if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
771 header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
772 header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
773 header->cbKeyData = key->u.s.secret_len;
774 memcpy( &header[1], key->u.s.secret, key->u.s.secret_len );
775 return STATUS_SUCCESS;
777 else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
779 ULONG len, req_size = sizeof(len) + key->u.s.secret_len;
781 *size = req_size;
782 if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
784 *(ULONG *)output = key->u.s.secret_len;
785 memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len );
786 return STATUS_SUCCESS;
789 FIXME( "unsupported key type %s\n", debugstr_w(type) );
790 return STATUS_NOT_IMPLEMENTED;
793 static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
795 UCHAR *buffer;
797 memset( key_copy, 0, sizeof(*key_copy) );
798 key_copy->hdr = key_orig->hdr;
799 key_copy->alg_id = key_orig->alg_id;
801 if (key_is_symmetric( key_orig ))
803 if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY;
804 memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len );
806 key_copy->u.s.mode = key_orig->u.s.mode;
807 key_copy->u.s.block_size = key_orig->u.s.block_size;
808 key_copy->u.s.secret = buffer;
809 key_copy->u.s.secret_len = key_orig->u.s.secret_len;
811 else
813 if (!(buffer = heap_alloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY;
814 memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len );
816 key_copy->u.a.pubkey = buffer;
817 key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len;
820 return STATUS_SUCCESS;
823 static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
824 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
826 ULONG bytes_left = input_len;
827 UCHAR *buf, *src, *dst;
828 NTSTATUS status;
830 if (key->u.s.mode == MODE_ID_GCM)
832 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
834 if (!auth_info) return STATUS_INVALID_PARAMETER;
835 if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
836 if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
837 if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
838 if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
839 FIXME( "call chaining not implemented\n" );
841 if ((status = key_symmetric_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
842 return status;
844 *ret_len = input_len;
845 if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
846 if (input && !output) return STATUS_SUCCESS;
847 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
849 if ((status = key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData )))
850 return status;
851 if ((status = key_symmetric_encrypt( key, input, input_len, output, output_len ))) return status;
853 return key_symmetric_get_tag( key, auth_info->pbTag, auth_info->cbTag );
856 if ((status = key_symmetric_set_params( key, iv, iv_len ))) return status;
857 *ret_len = input_len;
859 if (flags & BCRYPT_BLOCK_PADDING)
860 *ret_len = (input_len + key->u.s.block_size) & ~(key->u.s.block_size - 1);
861 else if (input_len & (key->u.s.block_size - 1))
862 return STATUS_INVALID_BUFFER_SIZE;
864 if (!output) return STATUS_SUCCESS;
865 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
866 if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
868 src = input;
869 dst = output;
870 while (bytes_left >= key->u.s.block_size)
872 if ((status = key_symmetric_encrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
873 return status;
874 if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_params( key, NULL, 0 ))) return status;
875 bytes_left -= key->u.s.block_size;
876 src += key->u.s.block_size;
877 dst += key->u.s.block_size;
880 if (flags & BCRYPT_BLOCK_PADDING)
882 if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
883 memcpy( buf, src, bytes_left );
884 memset( buf + bytes_left, key->u.s.block_size - bytes_left, key->u.s.block_size - bytes_left );
885 status = key_symmetric_encrypt( key, buf, key->u.s.block_size, dst, key->u.s.block_size );
886 heap_free( buf );
889 return status;
892 static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
893 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
895 ULONG bytes_left = input_len;
896 UCHAR *buf, *src, *dst;
897 NTSTATUS status;
899 if (key->u.s.mode == MODE_ID_GCM)
901 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
902 UCHAR tag[16];
904 if (!auth_info) return STATUS_INVALID_PARAMETER;
905 if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
906 if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
907 if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
909 if ((status = key_symmetric_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
910 return status;
912 *ret_len = input_len;
913 if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
914 if (!output) return STATUS_SUCCESS;
915 if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
917 if ((status = key_symmetric_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData )))
918 return status;
919 if ((status = key_symmetric_decrypt( key, input, input_len, output, output_len ))) return status;
921 if ((status = key_symmetric_get_tag( key, tag, sizeof(tag) ))) return status;
922 if (memcmp( tag, auth_info->pbTag, auth_info->cbTag )) return STATUS_AUTH_TAG_MISMATCH;
924 return STATUS_SUCCESS;
927 if ((status = key_symmetric_set_params( key, iv, iv_len ))) return status;
929 *ret_len = input_len;
931 if (input_len & (key->u.s.block_size - 1)) return STATUS_INVALID_BUFFER_SIZE;
932 if (!output) return STATUS_SUCCESS;
933 if (flags & BCRYPT_BLOCK_PADDING)
935 if (output_len + key->u.s.block_size < *ret_len) return STATUS_BUFFER_TOO_SMALL;
936 if (input_len < key->u.s.block_size) return STATUS_BUFFER_TOO_SMALL;
937 bytes_left -= key->u.s.block_size;
939 else if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
941 if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
943 src = input;
944 dst = output;
945 while (bytes_left >= key->u.s.block_size)
947 if ((status = key_symmetric_decrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
948 return status;
949 if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_params( key, NULL, 0 ))) return status;
950 bytes_left -= key->u.s.block_size;
951 src += key->u.s.block_size;
952 dst += key->u.s.block_size;
955 if (flags & BCRYPT_BLOCK_PADDING)
957 if (!(buf = heap_alloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
958 status = key_symmetric_decrypt( key, src, key->u.s.block_size, buf, key->u.s.block_size );
959 if (!status && buf[ key->u.s.block_size - 1 ] <= key->u.s.block_size)
961 *ret_len -= buf[ key->u.s.block_size - 1 ];
962 if (output_len < *ret_len) status = STATUS_BUFFER_TOO_SMALL;
963 else memcpy( dst, buf, key->u.s.block_size - buf[ key->u.s.block_size - 1 ] );
965 else status = STATUS_UNSUCCESSFUL; /* FIXME: invalid padding */
966 heap_free( buf );
969 return status;
972 static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
973 ULONG input_len )
975 struct key *key;
976 NTSTATUS status;
978 if (!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
980 BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
981 DWORD key_size, magic;
983 if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
985 switch (alg->id)
987 case ALG_ID_ECDSA_P256:
988 key_size = 32;
989 magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
990 break;
992 case ALG_ID_ECDSA_P384:
993 key_size = 48;
994 magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
995 break;
997 default:
998 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
999 return STATUS_NOT_SUPPORTED;
1002 if (ecc_blob->dwMagic != magic) return STATUS_NOT_SUPPORTED;
1003 if (ecc_blob->cbKey != key_size) return STATUS_INVALID_PARAMETER;
1005 if (!(key = heap_alloc( sizeof(*key) ))) return STATUS_NO_MEMORY;
1006 key->hdr.magic = MAGIC_KEY;
1007 if ((status = key_asymmetric_init( key, alg, (BYTE *)ecc_blob, sizeof(*ecc_blob) + ecc_blob->cbKey * 2 )))
1009 heap_free( key );
1010 return status;
1013 *ret_key = key;
1014 return STATUS_SUCCESS;
1016 else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ))
1018 BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
1019 ULONG size;
1021 if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER;
1022 if (alg->id != ALG_ID_RSA || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC) return STATUS_NOT_SUPPORTED;
1024 if (!(key = heap_alloc( sizeof(*key) ))) return STATUS_NO_MEMORY;
1025 key->hdr.magic = MAGIC_KEY;
1027 size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
1028 if ((status = key_asymmetric_init( key, alg, (BYTE *)rsa_blob, size )))
1030 heap_free( key );
1031 return status;
1034 *ret_key = key;
1035 return STATUS_SUCCESS;
1038 FIXME( "unsupported key type %s\n", debugstr_w(type) );
1039 return STATUS_NOT_SUPPORTED;
1041 #else
1042 NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR *secret, ULONG secret_len )
1044 ERR( "support for keys not available at build time\n" );
1045 return STATUS_NOT_IMPLEMENTED;
1048 BOOL key_is_symmetric( struct key *key )
1050 ERR( "support for keys not available at build time\n" );
1051 return FALSE;
1054 NTSTATUS key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
1056 ERR( "support for keys not available at build time\n" );
1057 return STATUS_NOT_IMPLEMENTED;
1060 static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
1062 ERR( "support for keys not available at build time\n" );
1063 return STATUS_NOT_IMPLEMENTED;
1066 NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
1067 ULONG signature_len, DWORD flags )
1069 ERR( "support for keys not available at build time\n" );
1070 return STATUS_NOT_IMPLEMENTED;
1073 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
1074 ULONG object_len, UCHAR *input, ULONG input_len )
1076 ERR( "support for keys not available at build time\n" );
1077 return STATUS_NOT_IMPLEMENTED;
1080 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
1082 ERR( "support for keys not available at build time\n" );
1083 return STATUS_NOT_IMPLEMENTED;
1086 NTSTATUS key_destroy( struct key *key )
1088 ERR( "support for keys not available at build time\n" );
1089 return STATUS_NOT_IMPLEMENTED;
1092 static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1093 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1095 ERR( "support for keys not available at build time\n" );
1096 return STATUS_NOT_IMPLEMENTED;
1099 static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1100 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1102 ERR( "support for keys not available at build time\n" );
1103 return STATUS_NOT_IMPLEMENTED;
1106 static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
1107 ULONG input_len )
1109 ERR( "support for keys not available at build time\n" );
1110 return STATUS_NOT_IMPLEMENTED;
1112 #endif
1114 NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle,
1115 UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len,
1116 ULONG flags )
1118 struct algorithm *alg = algorithm;
1119 struct key *key;
1120 NTSTATUS status;
1122 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm, handle, object, object_len, secret, secret_len, flags );
1124 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1125 if (object) FIXME( "ignoring object buffer\n" );
1127 if (!(key = heap_alloc( sizeof(*key) ))) return STATUS_NO_MEMORY;
1128 key->hdr.magic = MAGIC_KEY;
1130 if ((status = key_symmetric_init( key, alg, secret, secret_len )))
1132 heap_free( key );
1133 return status;
1136 *handle = key;
1137 return STATUS_SUCCESS;
1140 NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type,
1141 BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input,
1142 ULONG input_len, ULONG flags )
1144 struct algorithm *alg = algorithm;
1146 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm, decrypt_key, debugstr_w(type), key, object,
1147 object_len, input, input_len, flags);
1149 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1150 if (!key || !type || !input) return STATUS_INVALID_PARAMETER;
1152 if (decrypt_key)
1154 FIXME( "decryption of key not yet supported\n" );
1155 return STATUS_NOT_IMPLEMENTED;
1158 return key_import( algorithm, type, key, object, object_len, input, input_len );
1161 NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type,
1162 PUCHAR output, ULONG output_len, ULONG *size, ULONG flags )
1164 struct key *key = export_key;
1166 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key, encrypt_key, debugstr_w(type), output, output_len, size, flags);
1168 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1169 if (!output || !type || !size) return STATUS_INVALID_PARAMETER;
1171 if (encrypt_key)
1173 FIXME( "encryption of key not yet supported\n" );
1174 return STATUS_NOT_IMPLEMENTED;
1177 return key_export( key, type, output, output_len, size );
1180 NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE *handle_copy,
1181 UCHAR *object, ULONG object_len, ULONG flags )
1183 struct key *key_orig = handle;
1184 struct key *key_copy;
1185 NTSTATUS status;
1187 TRACE( "%p, %p, %p, %u, %08x\n", handle, handle_copy, object, object_len, flags );
1188 if (object) FIXME( "ignoring object buffer\n" );
1190 if (!key_orig || key_orig->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1191 if (!handle_copy) return STATUS_INVALID_PARAMETER;
1192 if (!(key_copy = heap_alloc( sizeof(*key_copy) ))) return STATUS_NO_MEMORY;
1194 if ((status = key_duplicate( key_orig, key_copy )))
1196 heap_free( key_copy );
1197 return status;
1200 *handle_copy = key_copy;
1201 return STATUS_SUCCESS;
1204 NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
1205 BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len, ULONG flags )
1207 struct algorithm *alg = algorithm;
1209 TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm, decrypt_key, debugstr_w(type), ret_key, input,
1210 input_len, flags );
1212 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1213 if (!ret_key || !type || !input) return STATUS_INVALID_PARAMETER;
1214 if (decrypt_key)
1216 FIXME( "decryption of key not yet supported\n" );
1217 return STATUS_NOT_IMPLEMENTED;
1220 return key_import_pair( alg, type, ret_key, input, input_len );
1223 NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len,
1224 UCHAR *signature, ULONG signature_len, ULONG flags )
1226 struct key *key = handle;
1228 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", handle, padding, hash, hash_len, signature, signature_len, flags );
1230 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1231 if (!hash || !hash_len || !signature || !signature_len) return STATUS_INVALID_PARAMETER;
1232 if (key_is_symmetric( key )) return STATUS_NOT_SUPPORTED;
1234 return key_asymmetric_verify( key, padding, hash, hash_len, signature, signature_len, flags );
1237 NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle )
1239 struct key *key = handle;
1241 TRACE( "%p\n", handle );
1243 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1244 return key_destroy( key );
1247 NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1248 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1250 struct key *key = handle;
1252 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output,
1253 output_len, ret_len, flags );
1255 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1256 if (!key_is_symmetric( key ))
1258 FIXME( "encryption with asymmetric keys not yet supported\n" );
1259 return STATUS_NOT_IMPLEMENTED;
1261 if (flags & ~BCRYPT_BLOCK_PADDING)
1263 FIXME( "flags %08x not implemented\n", flags );
1264 return STATUS_NOT_IMPLEMENTED;
1267 return key_encrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
1270 NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1271 ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1273 struct key *key = handle;
1275 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, padding, iv, iv_len, output,
1276 output_len, ret_len, flags );
1278 if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
1279 if (!key_is_symmetric( key ))
1281 FIXME( "decryption with asymmetric keys not yet supported\n" );
1282 return STATUS_NOT_IMPLEMENTED;
1284 if (flags & ~BCRYPT_BLOCK_PADDING)
1286 FIXME( "flags %08x not supported\n", flags );
1287 return STATUS_NOT_IMPLEMENTED;
1290 return key_decrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
1293 NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
1295 struct object *object = handle;
1297 TRACE( "%p, %s, %p, %u, %08x\n", handle, debugstr_w(prop), value, size, flags );
1299 if (!object) return STATUS_INVALID_HANDLE;
1301 switch (object->magic)
1303 case MAGIC_ALG:
1305 struct algorithm *alg = (struct algorithm *)object;
1306 return set_alg_property( alg, prop, value, size, flags );
1308 case MAGIC_KEY:
1310 struct key *key = (struct key *)object;
1311 return key_set_property( key, prop, value, size, flags );
1313 default:
1314 WARN( "unknown magic %08x\n", object->magic );
1315 return STATUS_INVALID_HANDLE;
1319 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1321 switch (reason)
1323 case DLL_PROCESS_ATTACH:
1324 instance = hinst;
1325 DisableThreadLibraryCalls( hinst );
1326 #ifdef HAVE_GNUTLS_CIPHER_INIT
1327 gnutls_initialize();
1328 #endif
1329 break;
1331 case DLL_PROCESS_DETACH:
1332 if (reserved) break;
1333 #ifdef HAVE_GNUTLS_CIPHER_INIT
1334 gnutls_uninitialize();
1335 #endif
1336 break;
1338 return TRUE;