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
21 #include "wine/port.h"
24 #ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
25 #include <AvailabilityMacros.h>
26 #include <CommonCrypto/CommonCryptor.h>
30 #define WIN32_NO_STATUS
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
);
91 return STATUS_NOT_IMPLEMENTED
;
94 #define MAX_HASH_OUTPUT_BYTES 64
95 #define MAX_HASH_BLOCK_BITS 1024
102 const WCHAR
*alg_name
;
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
);
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
;
140 return STATUS_INVALID_PARAMETER
;
142 if (flags
& ~supported_flags
)
143 FIXME("unsupported flags %08x\n", flags
& ~supported_flags
);
146 FIXME("ignoring selected algorithm\n");
148 /* When zero bytes are requested the function returns success too. */
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
;
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
;
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
;
203 alg
->mode
= MODE_ID_CBC
;
204 alg
->hmac
= flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
;
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
;
218 return STATUS_SUCCESS
;
221 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
223 FIXME("%p - semi-stub\n", enabled
);
226 return STATUS_INVALID_PARAMETER
;
229 return STATUS_SUCCESS
;
245 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
250 md2_init( &hash
->u
.md2
);
254 MD4Init( &hash
->u
.md4
);
258 MD5Init( &hash
->u
.md5
);
262 A_SHAInit( &hash
->u
.sha1
);
266 sha256_init( &hash
->u
.sha256
);
270 sha384_init( &hash
->u
.sha512
);
274 sha512_init( &hash
->u
.sha512
);
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
)
290 md2_update( &hash
->u
.md2
, input
, size
);
294 MD4Update( &hash
->u
.md4
, input
, size
);
298 MD5Update( &hash
->u
.md5
, input
, size
);
302 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
306 sha256_update( &hash
->u
.sha256
, input
, size
);
310 sha384_update( &hash
->u
.sha512
, input
, size
);
314 sha512_update( &hash
->u
.sha512
, input
, size
);
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
)
330 md2_finalize( &hash
->u
.md2
, output
);
334 MD4Final( &hash
->u
.md4
);
335 memcpy( output
, hash
->u
.md4
.digest
, 16 );
339 MD5Final( &hash
->u
.md5
);
340 memcpy( output
, hash
->u
.md5
.digest
, 16 );
344 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
348 sha256_finalize( &hash
->u
.sha256
, output
);
352 sha384_finalize( &hash
->u
.sha512
, output
);
356 sha512_finalize( &hash
->u
.sha512
, output
);
360 ERR( "unhandled id %u\n", alg_id
);
361 return STATUS_NOT_IMPLEMENTED
;
363 return STATUS_SUCCESS
;
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
;
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
;
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
;
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
)
420 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
421 if (status
!= STATUS_NOT_IMPLEMENTED
)
427 if (!strcmpW( prop
, BCRYPT_BLOCK_LENGTH
))
429 *ret_size
= sizeof(ULONG
);
430 if (size
< sizeof(ULONG
))
431 return STATUS_BUFFER_TOO_SMALL
;
433 *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
434 return STATUS_SUCCESS
;
436 if (!strcmpW( prop
, BCRYPT_CHAINING_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
;
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
;
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
;
473 tag_length
->dwMinLength
= 12;
474 tag_length
->dwMaxLength
= 16;
475 tag_length
->dwIncrement
= 1;
477 return STATUS_SUCCESS
;
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
)
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
;
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
;
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
)
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
) );
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
)
549 const struct algorithm
*alg
= (const struct algorithm
*)object
;
550 return get_alg_property( alg
, prop
, buffer
, count
, res
);
554 const struct hash
*hash
= (const struct hash
*)object
;
555 return get_hash_property( hash
, prop
, buffer
, count
, res
);
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};
573 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm
, handle
, object
, objectlen
,
574 secret
, secretlen
, 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
;
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
);
614 if (status
!= STATUS_SUCCESS
)
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
;
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
;
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
;
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
)
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
)
704 status
= BCryptHashData( handle
, input
, inputlen
, 0 );
705 if (status
!= STATUS_SUCCESS
)
707 BCryptDestroyHash( handle
);
711 status
= BCryptFinishHash( handle
, output
, outputlen
, 0 );
712 if (status
!= STATUS_SUCCESS
)
714 BCryptDestroyHash( handle
);
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
)
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
;
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
;
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
)
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
;
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
;
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
)))
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
)))
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
;
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
)))
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
);
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
;
899 if (key
->u
.s
.mode
== MODE_ID_GCM
)
901 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
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
)))
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
)))
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
;
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
)))
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 */
972 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
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
;
987 case ALG_ID_ECDSA_P256
:
989 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
992 case ALG_ID_ECDSA_P384
:
994 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
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 )))
1014 return STATUS_SUCCESS
;
1016 else if (!strcmpW( type
, BCRYPT_RSAPUBLIC_BLOB
))
1018 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
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
)))
1035 return STATUS_SUCCESS
;
1038 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1039 return STATUS_NOT_SUPPORTED
;
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" );
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
,
1109 ERR( "support for keys not available at build time\n" );
1110 return STATUS_NOT_IMPLEMENTED
;
1114 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1115 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1118 struct algorithm
*alg
= algorithm
;
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
)))
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
;
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
;
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
;
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
);
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
,
1212 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1213 if (!ret_key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
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
)
1305 struct algorithm
*alg
= (struct algorithm
*)object
;
1306 return set_alg_property( alg
, prop
, value
, size
, flags
);
1310 struct key
*key
= (struct key
*)object
;
1311 return key_set_property( key
, prop
, value
, size
, flags
);
1314 WARN( "unknown magic %08x\n", object
->magic
);
1315 return STATUS_INVALID_HANDLE
;
1319 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
1323 case DLL_PROCESS_ATTACH
:
1325 DisableThreadLibraryCalls( hinst
);
1326 #ifdef HAVE_GNUTLS_CIPHER_INIT
1327 gnutls_initialize();
1331 case DLL_PROCESS_DETACH
:
1332 if (reserved
) break;
1333 #ifdef HAVE_GNUTLS_CIPHER_INIT
1334 gnutls_uninitialize();