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>
27 #elif defined(HAVE_GNUTLS_CIPHER_INIT)
28 #include <gnutls/gnutls.h>
29 #include <gnutls/crypto.h>
33 #define WIN32_NO_STATUS
39 #include "bcrypt_internal.h"
41 #include "wine/debug.h"
42 #include "wine/heap.h"
43 #include "wine/library.h"
44 #include "wine/unicode.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
48 static HINSTANCE instance
;
50 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
51 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
53 /* Not present in gnutls version < 3.0 */
54 static int (*pgnutls_cipher_tag
)(gnutls_cipher_hd_t handle
, void * tag
, size_t tag_size
);
55 static int (*pgnutls_cipher_add_auth
)(gnutls_cipher_hd_t handle
, const void *ptext
, size_t ptext_size
);
57 static void *libgnutls_handle
;
58 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
59 MAKE_FUNCPTR(gnutls_cipher_decrypt2
);
60 MAKE_FUNCPTR(gnutls_cipher_deinit
);
61 MAKE_FUNCPTR(gnutls_cipher_encrypt2
);
62 MAKE_FUNCPTR(gnutls_cipher_init
);
63 MAKE_FUNCPTR(gnutls_global_deinit
);
64 MAKE_FUNCPTR(gnutls_global_init
);
65 MAKE_FUNCPTR(gnutls_global_set_log_function
);
66 MAKE_FUNCPTR(gnutls_global_set_log_level
);
67 MAKE_FUNCPTR(gnutls_perror
);
70 #if GNUTLS_VERSION_MAJOR < 3
71 #define GNUTLS_CIPHER_AES_192_CBC 92
72 #define GNUTLS_CIPHER_AES_128_GCM 93
73 #define GNUTLS_CIPHER_AES_256_GCM 94
76 static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle
, void *tag
, size_t tag_size
)
78 return GNUTLS_E_UNKNOWN_CIPHER_TYPE
;
81 static int compat_gnutls_cipher_add_auth(gnutls_cipher_hd_t handle
, const void *ptext
, size_t ptext_size
)
83 return GNUTLS_E_UNKNOWN_CIPHER_TYPE
;
86 static void gnutls_log( int level
, const char *msg
)
88 TRACE( "<%d> %s", level
, msg
);
91 static BOOL
gnutls_initialize(void)
95 if (!(libgnutls_handle
= wine_dlopen( SONAME_LIBGNUTLS
, RTLD_NOW
, NULL
, 0 )))
97 ERR_(winediag
)( "failed to load libgnutls, no support for encryption\n" );
101 #define LOAD_FUNCPTR(f) \
102 if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \
104 ERR( "failed to load %s\n", #f ); \
108 LOAD_FUNCPTR(gnutls_cipher_decrypt2
)
109 LOAD_FUNCPTR(gnutls_cipher_deinit
)
110 LOAD_FUNCPTR(gnutls_cipher_encrypt2
)
111 LOAD_FUNCPTR(gnutls_cipher_init
)
112 LOAD_FUNCPTR(gnutls_global_deinit
)
113 LOAD_FUNCPTR(gnutls_global_init
)
114 LOAD_FUNCPTR(gnutls_global_set_log_function
)
115 LOAD_FUNCPTR(gnutls_global_set_log_level
)
116 LOAD_FUNCPTR(gnutls_perror
)
119 if (!(pgnutls_cipher_tag
= wine_dlsym( libgnutls_handle
, "gnutls_cipher_tag", NULL
, 0 )))
121 WARN("gnutls_cipher_tag not found\n");
122 pgnutls_cipher_tag
= compat_gnutls_cipher_tag
;
124 if (!(pgnutls_cipher_add_auth
= wine_dlsym( libgnutls_handle
, "gnutls_cipher_add_auth", NULL
, 0 )))
126 WARN("gnutls_cipher_add_auth not found\n");
127 pgnutls_cipher_add_auth
= compat_gnutls_cipher_add_auth
;
130 if ((ret
= pgnutls_global_init()) != GNUTLS_E_SUCCESS
)
132 pgnutls_perror( ret
);
136 if (TRACE_ON( bcrypt
))
138 pgnutls_global_set_log_level( 4 );
139 pgnutls_global_set_log_function( gnutls_log
);
145 wine_dlclose( libgnutls_handle
, NULL
, 0 );
146 libgnutls_handle
= NULL
;
150 static void gnutls_uninitialize(void)
152 pgnutls_global_deinit();
153 wine_dlclose( libgnutls_handle
, NULL
, 0 );
154 libgnutls_handle
= NULL
;
156 #endif /* HAVE_GNUTLS_CIPHER_INIT && !HAVE_COMMONCRYPTO_COMMONCRYPTOR_H */
158 NTSTATUS WINAPI
BCryptAddContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, ULONG pos
)
160 FIXME("%08x, %s, %08x, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), pos
);
161 return STATUS_SUCCESS
;
164 NTSTATUS WINAPI
BCryptAddContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
, ULONG pos
)
166 FIXME("%08x, %s, %08x, %s, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
), pos
);
167 return STATUS_SUCCESS
;
170 NTSTATUS WINAPI
BCryptRemoveContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
)
172 FIXME("%08x, %s, %08x, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
));
173 return STATUS_NOT_IMPLEMENTED
;
176 NTSTATUS WINAPI
BCryptRemoveContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
)
178 FIXME("%08x, %s, %08x, %s, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
));
179 return STATUS_NOT_IMPLEMENTED
;
182 NTSTATUS WINAPI
BCryptRegisterProvider(LPCWSTR provider
, ULONG flags
, PCRYPT_PROVIDER_REG reg
)
184 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider
), flags
, reg
);
185 return STATUS_SUCCESS
;
188 NTSTATUS WINAPI
BCryptUnregisterProvider(LPCWSTR provider
)
190 FIXME("%s: stub\n", debugstr_w(provider
));
191 return STATUS_NOT_IMPLEMENTED
;
194 NTSTATUS WINAPI
BCryptEnumAlgorithms(ULONG dwAlgOperations
, ULONG
*pAlgCount
,
195 BCRYPT_ALGORITHM_IDENTIFIER
**ppAlgList
, ULONG dwFlags
)
197 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations
, pAlgCount
, ppAlgList
, dwFlags
);
202 return STATUS_NOT_IMPLEMENTED
;
205 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
206 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
207 #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0')
233 #define MAX_HASH_OUTPUT_BYTES 64
234 #define MAX_HASH_BLOCK_BITS 1024
241 const WCHAR
*alg_name
;
246 /* ALG_ID_AES */ { 654, 0, 0, BCRYPT_AES_ALGORITHM
, TRUE
},
247 /* ALG_ID_MD2 */ { 270, 16, 128, BCRYPT_MD2_ALGORITHM
, FALSE
},
248 /* ALG_ID_MD4 */ { 270, 16, 512, BCRYPT_MD4_ALGORITHM
, FALSE
},
249 /* ALG_ID_MD5 */ { 274, 16, 512, BCRYPT_MD5_ALGORITHM
, FALSE
},
250 /* ALG_ID_RNG */ { 0, 0, 0, BCRYPT_RNG_ALGORITHM
, FALSE
},
251 /* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM
, FALSE
},
252 /* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM
, FALSE
},
253 /* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM
, FALSE
},
254 /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM
, FALSE
}
265 NTSTATUS WINAPI
BCryptGenRandom(BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
267 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
268 struct algorithm
*algorithm
= handle
;
270 TRACE("%p, %p, %u, %08x - semi-stub\n", handle
, buffer
, count
, flags
);
274 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
275 * is set. In this case the preferred system RNG is used.
277 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
278 return STATUS_INVALID_HANDLE
;
280 else if (algorithm
->hdr
.magic
!= MAGIC_ALG
|| algorithm
->id
!= ALG_ID_RNG
)
281 return STATUS_INVALID_HANDLE
;
284 return STATUS_INVALID_PARAMETER
;
286 if (flags
& ~supported_flags
)
287 FIXME("unsupported flags %08x\n", flags
& ~supported_flags
);
290 FIXME("ignoring selected algorithm\n");
292 /* When zero bytes are requested the function returns success too. */
294 return STATUS_SUCCESS
;
296 if (algorithm
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
298 if (RtlGenRandom(buffer
, count
))
299 return STATUS_SUCCESS
;
302 FIXME("called with unsupported parameters, returning error\n");
303 return STATUS_NOT_IMPLEMENTED
;
306 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, LPCWSTR id
, LPCWSTR implementation
, DWORD flags
)
308 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
;
309 struct algorithm
*alg
;
312 TRACE( "%p, %s, %s, %08x\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
314 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
315 if (flags
& ~supported_flags
)
317 FIXME( "unsupported flags %08x\n", flags
& ~supported_flags
);
318 return STATUS_NOT_IMPLEMENTED
;
321 if (!strcmpW( id
, BCRYPT_AES_ALGORITHM
)) alg_id
= ALG_ID_AES
;
322 else if (!strcmpW( id
, BCRYPT_MD2_ALGORITHM
)) alg_id
= ALG_ID_MD2
;
323 else if (!strcmpW( id
, BCRYPT_MD4_ALGORITHM
)) alg_id
= ALG_ID_MD4
;
324 else if (!strcmpW( id
, BCRYPT_MD5_ALGORITHM
)) alg_id
= ALG_ID_MD5
;
325 else if (!strcmpW( id
, BCRYPT_RNG_ALGORITHM
)) alg_id
= ALG_ID_RNG
;
326 else if (!strcmpW( id
, BCRYPT_SHA1_ALGORITHM
)) alg_id
= ALG_ID_SHA1
;
327 else if (!strcmpW( id
, BCRYPT_SHA256_ALGORITHM
)) alg_id
= ALG_ID_SHA256
;
328 else if (!strcmpW( id
, BCRYPT_SHA384_ALGORITHM
)) alg_id
= ALG_ID_SHA384
;
329 else if (!strcmpW( id
, BCRYPT_SHA512_ALGORITHM
)) alg_id
= ALG_ID_SHA512
;
332 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
333 return STATUS_NOT_IMPLEMENTED
;
335 if (implementation
&& strcmpW( implementation
, MS_PRIMITIVE_PROVIDER
))
337 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
338 return STATUS_NOT_IMPLEMENTED
;
341 if (!(alg
= heap_alloc( sizeof(*alg
) ))) return STATUS_NO_MEMORY
;
342 alg
->hdr
.magic
= MAGIC_ALG
;
344 alg
->mode
= MODE_ID_CBC
;
345 alg
->hmac
= flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
;
348 return STATUS_SUCCESS
;
351 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
353 struct algorithm
*alg
= handle
;
355 TRACE( "%p, %08x\n", handle
, flags
);
357 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
359 return STATUS_SUCCESS
;
362 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
364 FIXME("%p - semi-stub\n", enabled
);
367 return STATUS_INVALID_PARAMETER
;
370 return STATUS_SUCCESS
;
386 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
391 md2_init( &hash
->u
.md2
);
395 MD4Init( &hash
->u
.md4
);
399 MD5Init( &hash
->u
.md5
);
403 A_SHAInit( &hash
->u
.sha1
);
407 sha256_init( &hash
->u
.sha256
);
411 sha384_init( &hash
->u
.sha512
);
415 sha512_init( &hash
->u
.sha512
);
419 ERR( "unhandled id %u\n", alg_id
);
420 return STATUS_NOT_IMPLEMENTED
;
422 return STATUS_SUCCESS
;
425 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
,
426 UCHAR
*input
, ULONG size
)
431 md2_update( &hash
->u
.md2
, input
, size
);
435 MD4Update( &hash
->u
.md4
, input
, size
);
439 MD5Update( &hash
->u
.md5
, input
, size
);
443 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
447 sha256_update( &hash
->u
.sha256
, input
, size
);
451 sha384_update( &hash
->u
.sha512
, input
, size
);
455 sha512_update( &hash
->u
.sha512
, input
, size
);
459 ERR( "unhandled id %u\n", alg_id
);
460 return STATUS_NOT_IMPLEMENTED
;
462 return STATUS_SUCCESS
;
465 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
,
466 UCHAR
*output
, ULONG size
)
471 md2_finalize( &hash
->u
.md2
, output
);
475 MD4Final( &hash
->u
.md4
);
476 memcpy( output
, hash
->u
.md4
.digest
, 16 );
480 MD5Final( &hash
->u
.md5
);
481 memcpy( output
, hash
->u
.md5
.digest
, 16 );
485 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
489 sha256_finalize( &hash
->u
.sha256
, output
);
493 sha384_finalize( &hash
->u
.sha512
, output
);
497 sha512_finalize( &hash
->u
.sha512
, output
);
501 ERR( "unhandled id %u\n", alg_id
);
502 return STATUS_NOT_IMPLEMENTED
;
504 return STATUS_SUCCESS
;
512 struct hash_impl outer
;
513 struct hash_impl inner
;
516 #define BLOCK_LENGTH_AES 16
518 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
520 if (!strcmpW( prop
, BCRYPT_OBJECT_LENGTH
))
522 if (!alg_props
[id
].object_length
)
523 return STATUS_NOT_SUPPORTED
;
524 *ret_size
= sizeof(ULONG
);
525 if (size
< sizeof(ULONG
))
526 return STATUS_BUFFER_TOO_SMALL
;
528 *(ULONG
*)buf
= alg_props
[id
].object_length
;
529 return STATUS_SUCCESS
;
532 if (!strcmpW( prop
, BCRYPT_HASH_LENGTH
))
534 if (!alg_props
[id
].hash_length
)
535 return STATUS_NOT_SUPPORTED
;
536 *ret_size
= sizeof(ULONG
);
537 if (size
< sizeof(ULONG
))
538 return STATUS_BUFFER_TOO_SMALL
;
540 *(ULONG
*)buf
= alg_props
[id
].hash_length
;
541 return STATUS_SUCCESS
;
544 if (!strcmpW( prop
, BCRYPT_ALGORITHM_NAME
))
546 *ret_size
= (strlenW(alg_props
[id
].alg_name
)+1)*sizeof(WCHAR
);
547 if (size
< *ret_size
)
548 return STATUS_BUFFER_TOO_SMALL
;
550 memcpy(buf
, alg_props
[id
].alg_name
, *ret_size
);
551 return STATUS_SUCCESS
;
554 return STATUS_NOT_IMPLEMENTED
;
557 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
561 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
562 if (status
!= STATUS_NOT_IMPLEMENTED
)
568 if (!strcmpW( prop
, BCRYPT_BLOCK_LENGTH
))
570 *ret_size
= sizeof(ULONG
);
571 if (size
< sizeof(ULONG
))
572 return STATUS_BUFFER_TOO_SMALL
;
574 *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
575 return STATUS_SUCCESS
;
577 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
582 case MODE_ID_ECB
: mode
= BCRYPT_CHAIN_MODE_ECB
; break;
583 case MODE_ID_CBC
: mode
= BCRYPT_CHAIN_MODE_CBC
; break;
584 case MODE_ID_GCM
: mode
= BCRYPT_CHAIN_MODE_GCM
; break;
585 default: return STATUS_NOT_IMPLEMENTED
;
589 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
590 memcpy( buf
, mode
, (strlenW(mode
) + 1) * sizeof(WCHAR
) );
591 return STATUS_SUCCESS
;
593 if (!strcmpW( prop
, BCRYPT_KEY_LENGTHS
))
595 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
596 *ret_size
= sizeof(*key_lengths
);
597 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
600 key_lengths
->dwMinLength
= 128;
601 key_lengths
->dwMaxLength
= 256;
602 key_lengths
->dwIncrement
= 64;
604 return STATUS_SUCCESS
;
606 if (!strcmpW( prop
, BCRYPT_AUTH_TAG_LENGTH
))
608 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
609 if (alg
->mode
!= MODE_ID_GCM
) return STATUS_NOT_SUPPORTED
;
610 *ret_size
= sizeof(*tag_length
);
611 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
614 tag_length
->dwMinLength
= 12;
615 tag_length
->dwMaxLength
= 16;
616 tag_length
->dwIncrement
= 1;
618 return STATUS_SUCCESS
;
626 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
627 return STATUS_NOT_IMPLEMENTED
;
630 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
635 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
637 if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
, size
))
639 alg
->mode
= MODE_ID_ECB
;
640 return STATUS_SUCCESS
;
642 else if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
, size
))
644 alg
->mode
= MODE_ID_CBC
;
645 return STATUS_SUCCESS
;
647 else if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
, size
))
649 alg
->mode
= MODE_ID_GCM
;
650 return STATUS_SUCCESS
;
654 FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR
*)value
, size
) );
655 return STATUS_NOT_IMPLEMENTED
;
658 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
659 return STATUS_NOT_IMPLEMENTED
;
662 FIXME( "unsupported algorithm %u\n", alg
->id
);
663 return STATUS_NOT_IMPLEMENTED
;
667 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
671 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
672 if (status
== STATUS_NOT_IMPLEMENTED
)
673 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
677 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, LPCWSTR prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
, ULONG flags
)
679 struct object
*object
= handle
;
681 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
683 if (!object
) return STATUS_INVALID_HANDLE
;
684 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
686 switch (object
->magic
)
690 const struct algorithm
*alg
= (const struct algorithm
*)object
;
691 return get_alg_property( alg
, prop
, buffer
, count
, res
);
695 const struct hash
*hash
= (const struct hash
*)object
;
696 return get_hash_property( hash
, prop
, buffer
, count
, res
);
699 WARN( "unknown magic %08x\n", object
->magic
);
700 return STATUS_INVALID_HANDLE
;
704 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_HASH_HANDLE
*handle
, UCHAR
*object
, ULONG objectlen
,
705 UCHAR
*secret
, ULONG secretlen
, ULONG flags
)
707 struct algorithm
*alg
= algorithm
;
708 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
714 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm
, handle
, object
, objectlen
,
715 secret
, secretlen
, flags
);
718 FIXME( "unimplemented flags %08x\n", flags
);
719 return STATUS_NOT_IMPLEMENTED
;
722 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
723 if (object
) FIXME( "ignoring object buffer\n" );
725 if (!(hash
= heap_alloc( sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
726 hash
->hdr
.magic
= MAGIC_HASH
;
727 hash
->alg_id
= alg
->id
;
728 hash
->hmac
= alg
->hmac
;
730 /* initialize hash */
731 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) goto end
;
732 if (!hash
->hmac
) goto end
;
734 /* initialize hmac */
735 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) goto end
;
736 block_bytes
= alg_props
[hash
->alg_id
].block_bits
/ 8;
737 if (secretlen
> block_bytes
)
739 struct hash_impl temp
;
740 if ((status
= hash_init( &temp
, hash
->alg_id
))) goto end
;
741 if ((status
= hash_update( &temp
, hash
->alg_id
, secret
, secretlen
))) goto end
;
742 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
743 alg_props
[hash
->alg_id
].hash_length
))) goto end
;
747 memcpy( buffer
, secret
, secretlen
);
749 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
750 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) goto end
;
751 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
752 status
= hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
755 if (status
!= STATUS_SUCCESS
)
762 return STATUS_SUCCESS
;
765 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
766 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
768 struct hash
*hash_orig
= handle
;
769 struct hash
*hash_copy
;
771 TRACE( "%p, %p, %p, %u, %u\n", handle
, handle_copy
, object
, objectlen
, flags
);
773 if (!hash_orig
|| hash_orig
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
774 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
775 if (object
) FIXME( "ignoring object buffer\n" );
777 if (!(hash_copy
= heap_alloc( sizeof(*hash_copy
) )))
778 return STATUS_NO_MEMORY
;
780 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
782 *handle_copy
= hash_copy
;
783 return STATUS_SUCCESS
;
786 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
788 struct hash
*hash
= handle
;
790 TRACE( "%p\n", handle
);
792 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
794 return STATUS_SUCCESS
;
797 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
799 struct hash
*hash
= handle
;
801 TRACE( "%p, %p, %u, %08x\n", handle
, input
, size
, flags
);
803 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
804 if (!input
) return STATUS_SUCCESS
;
806 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
809 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
811 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
812 struct hash
*hash
= handle
;
816 TRACE( "%p, %p, %u, %08x\n", handle
, output
, size
, flags
);
818 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
819 if (!output
) return STATUS_INVALID_PARAMETER
;
822 return hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
);
824 hash_length
= alg_props
[hash
->alg_id
].hash_length
;
825 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
826 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
827 return hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
);
830 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE algorithm
, UCHAR
*secret
, ULONG secretlen
,
831 UCHAR
*input
, ULONG inputlen
, UCHAR
*output
, ULONG outputlen
)
834 BCRYPT_HASH_HANDLE handle
;
836 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm
, secret
, secretlen
,
837 input
, inputlen
, output
, outputlen
);
839 status
= BCryptCreateHash( algorithm
, &handle
, NULL
, 0, secret
, secretlen
, 0);
840 if (status
!= STATUS_SUCCESS
)
845 status
= BCryptHashData( handle
, input
, inputlen
, 0 );
846 if (status
!= STATUS_SUCCESS
)
848 BCryptDestroyHash( handle
);
852 status
= BCryptFinishHash( handle
, output
, outputlen
, 0 );
853 if (status
!= STATUS_SUCCESS
)
855 BCryptDestroyHash( handle
);
859 return BCryptDestroyHash( handle
);
862 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
867 gnutls_cipher_hd_t handle
;
878 struct key_symmetric s
;
882 #elif defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
887 CCCryptorRef ref_encrypt
;
888 CCCryptorRef ref_decrypt
;
899 struct key_symmetric s
;
914 struct key_symmetric s
;
919 #if defined(HAVE_GNUTLS_CIPHER_INIT) || defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
920 static inline BOOL
key_is_symmetric( struct key
*key
)
922 return alg_props
[key
->alg_id
].symmetric
;
925 static ULONG
get_block_size( struct algorithm
*alg
)
927 ULONG ret
= 0, size
= sizeof(ret
);
928 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
932 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
934 if (!strcmpW( type
, BCRYPT_KEY_DATA_BLOB
))
936 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
937 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
940 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
942 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
943 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
944 header
->cbKeyData
= key
->u
.s
.secret_len
;
945 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
946 return STATUS_SUCCESS
;
949 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
950 return STATUS_NOT_IMPLEMENTED
;
953 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
957 if (!key_is_symmetric( key_orig
)) return STATUS_NOT_IMPLEMENTED
;
959 if (!(buffer
= heap_alloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
960 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
962 memset( key_copy
, 0, sizeof(*key_copy
) );
963 key_copy
->hdr
= key_orig
->hdr
;
964 key_copy
->alg_id
= key_orig
->alg_id
;
965 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
966 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
967 key_copy
->u
.s
.secret
= buffer
;
968 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
970 return STATUS_SUCCESS
;
974 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
975 static NTSTATUS
key_symmetric_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
979 if (!libgnutls_handle
) return STATUS_INTERNAL_ERROR
;
987 FIXME( "algorithm %u not supported\n", alg
->id
);
988 return STATUS_NOT_SUPPORTED
;
991 if (!(key
->u
.s
.block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
992 if (!(buffer
= heap_alloc( secret_len
))) return STATUS_NO_MEMORY
;
993 memcpy( buffer
, secret
, secret_len
);
995 key
->alg_id
= alg
->id
;
996 key
->u
.s
.mode
= alg
->mode
;
997 key
->u
.s
.handle
= 0; /* initialized on first use */
998 key
->u
.s
.secret
= buffer
;
999 key
->u
.s
.secret_len
= secret_len
;
1001 return STATUS_SUCCESS
;
1004 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1006 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
1008 if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
, size
))
1010 key
->u
.s
.mode
= MODE_ID_ECB
;
1011 return STATUS_SUCCESS
;
1013 else if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
, size
))
1015 key
->u
.s
.mode
= MODE_ID_CBC
;
1016 return STATUS_SUCCESS
;
1018 else if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
, size
))
1020 key
->u
.s
.mode
= MODE_ID_GCM
;
1021 return STATUS_SUCCESS
;
1025 FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR
*)value
, size
) );
1026 return STATUS_NOT_IMPLEMENTED
;
1030 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
1031 return STATUS_NOT_IMPLEMENTED
;
1034 static gnutls_cipher_algorithm_t
get_gnutls_cipher( const struct key
*key
)
1036 switch (key
->alg_id
)
1039 WARN( "handle block size\n" );
1040 switch (key
->u
.s
.mode
)
1043 if (key
->u
.s
.secret_len
== 16) return GNUTLS_CIPHER_AES_128_GCM
;
1044 if (key
->u
.s
.secret_len
== 32) return GNUTLS_CIPHER_AES_256_GCM
;
1046 case MODE_ID_ECB
: /* can be emulated with CBC + empty IV */
1048 if (key
->u
.s
.secret_len
== 16) return GNUTLS_CIPHER_AES_128_CBC
;
1049 if (key
->u
.s
.secret_len
== 24) return GNUTLS_CIPHER_AES_192_CBC
;
1050 if (key
->u
.s
.secret_len
== 32) return GNUTLS_CIPHER_AES_256_CBC
;
1055 FIXME( "AES mode %u with key length %u not supported\n", key
->u
.s
.mode
, key
->u
.s
.secret_len
);
1056 return GNUTLS_CIPHER_UNKNOWN
;
1059 FIXME( "algorithm %u not supported\n", key
->alg_id
);
1060 return GNUTLS_CIPHER_UNKNOWN
;
1064 static NTSTATUS
key_symmetric_set_params( struct key
*key
, UCHAR
*iv
, ULONG iv_len
)
1066 gnutls_cipher_algorithm_t cipher
;
1067 gnutls_datum_t secret
, vector
;
1070 if (key
->u
.s
.handle
)
1072 pgnutls_cipher_deinit( key
->u
.s
.handle
);
1073 key
->u
.s
.handle
= NULL
;
1076 if ((cipher
= get_gnutls_cipher( key
)) == GNUTLS_CIPHER_UNKNOWN
)
1077 return STATUS_NOT_SUPPORTED
;
1079 secret
.data
= key
->u
.s
.secret
;
1080 secret
.size
= key
->u
.s
.secret_len
;
1084 vector
.size
= iv_len
;
1087 if ((ret
= pgnutls_cipher_init( &key
->u
.s
.handle
, cipher
, &secret
, iv
? &vector
: NULL
)))
1089 pgnutls_perror( ret
);
1090 return STATUS_INTERNAL_ERROR
;
1093 return STATUS_SUCCESS
;
1096 static NTSTATUS
key_symmetric_set_auth_data( struct key
*key
, UCHAR
*auth_data
, ULONG len
)
1100 if (!auth_data
) return STATUS_SUCCESS
;
1102 if ((ret
= pgnutls_cipher_add_auth( key
->u
.s
.handle
, auth_data
, len
)))
1104 pgnutls_perror( ret
);
1105 return STATUS_INTERNAL_ERROR
;
1108 return STATUS_SUCCESS
;
1111 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1116 if ((ret
= pgnutls_cipher_encrypt2( key
->u
.s
.handle
, input
, input_len
, output
, output_len
)))
1118 pgnutls_perror( ret
);
1119 return STATUS_INTERNAL_ERROR
;
1122 return STATUS_SUCCESS
;
1125 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1130 if ((ret
= pgnutls_cipher_decrypt2( key
->u
.s
.handle
, input
, input_len
, output
, output_len
)))
1132 pgnutls_perror( ret
);
1133 return STATUS_INTERNAL_ERROR
;
1136 return STATUS_SUCCESS
;
1139 static NTSTATUS
key_symmetric_get_tag( struct key
*key
, UCHAR
*tag
, ULONG len
)
1143 if ((ret
= pgnutls_cipher_tag( key
->u
.s
.handle
, tag
, len
)))
1145 pgnutls_perror( ret
);
1146 return STATUS_INTERNAL_ERROR
;
1149 return STATUS_SUCCESS
;
1152 static NTSTATUS
key_destroy( struct key
*key
)
1154 if (key
->u
.s
.handle
) pgnutls_cipher_deinit( key
->u
.s
.handle
);
1155 heap_free( key
->u
.s
.secret
);
1157 return STATUS_SUCCESS
;
1159 #elif defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1160 static NTSTATUS
key_symmetric_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
1173 FIXME( "mode %u not supported\n", alg
->mode
);
1174 return STATUS_NOT_SUPPORTED
;
1179 FIXME( "algorithm %u not supported\n", alg
->id
);
1180 return STATUS_NOT_SUPPORTED
;
1183 if (!(key
->u
.s
.block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1184 if (!(buffer
= heap_alloc( secret_len
))) return STATUS_NO_MEMORY
;
1185 memcpy( buffer
, secret
, secret_len
);
1187 key
->alg_id
= alg
->id
;
1188 key
->u
.s
.mode
= alg
->mode
;
1189 key
->u
.s
.ref_encrypt
= NULL
; /* initialized on first use */
1190 key
->u
.s
.ref_decrypt
= NULL
;
1191 key
->u
.s
.secret
= buffer
;
1192 key
->u
.s
.secret_len
= secret_len
;
1194 return STATUS_SUCCESS
;
1197 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1199 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
1201 if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
, size
))
1203 key
->u
.s
.mode
= MODE_ID_ECB
;
1204 return STATUS_SUCCESS
;
1206 else if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
, size
))
1208 key
->u
.s
.mode
= MODE_ID_CBC
;
1209 return STATUS_SUCCESS
;
1213 FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR
*)value
, size
) );
1214 return STATUS_NOT_IMPLEMENTED
;
1218 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
1219 return STATUS_NOT_IMPLEMENTED
;
1222 static CCMode
get_cryptor_mode( struct key
*key
)
1224 switch (key
->u
.s
.mode
)
1226 case MODE_ID_ECB
: return kCCModeECB
;
1227 case MODE_ID_CBC
: return kCCModeCBC
;
1229 FIXME( "unsupported mode %u\n", key
->u
.s
.mode
);
1234 static NTSTATUS
key_symmetric_set_params( struct key
*key
, UCHAR
*iv
, ULONG iv_len
)
1236 CCCryptorStatus status
;
1239 if (!(mode
= get_cryptor_mode( key
))) return STATUS_NOT_SUPPORTED
;
1241 if (key
->u
.s
.ref_encrypt
)
1243 CCCryptorRelease( key
->u
.s
.ref_encrypt
);
1244 key
->u
.s
.ref_encrypt
= NULL
;
1246 if (key
->u
.s
.ref_decrypt
)
1248 CCCryptorRelease( key
->u
.s
.ref_decrypt
);
1249 key
->u
.s
.ref_decrypt
= NULL
;
1252 if ((status
= CCCryptorCreateWithMode( kCCEncrypt
, mode
, kCCAlgorithmAES128
, ccNoPadding
, iv
, key
->u
.s
.secret
,
1253 key
->u
.s
.secret_len
, NULL
, 0, 0, 0, &key
->u
.s
.ref_encrypt
)) != kCCSuccess
)
1255 WARN( "CCCryptorCreateWithMode failed %d\n", status
);
1256 return STATUS_INTERNAL_ERROR
;
1258 if ((status
= CCCryptorCreateWithMode( kCCDecrypt
, mode
, kCCAlgorithmAES128
, ccNoPadding
, iv
, key
->u
.s
.secret
,
1259 key
->u
.s
.secret_len
, NULL
, 0, 0, 0, &key
->u
.s
.ref_decrypt
)) != kCCSuccess
)
1261 WARN( "CCCryptorCreateWithMode failed %d\n", status
);
1262 CCCryptorRelease( key
->u
.s
.ref_encrypt
);
1263 key
->u
.s
.ref_encrypt
= NULL
;
1264 return STATUS_INTERNAL_ERROR
;
1267 return STATUS_SUCCESS
;
1270 static NTSTATUS
key_symmetric_set_auth_data( struct key
*key
, UCHAR
*auth_data
, ULONG len
)
1272 FIXME( "not implemented on Mac\n" );
1273 return STATUS_NOT_IMPLEMENTED
;
1276 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1279 CCCryptorStatus status
;
1281 if ((status
= CCCryptorUpdate( key
->u
.s
.ref_encrypt
, input
, input_len
, output
, output_len
, NULL
)) != kCCSuccess
)
1283 WARN( "CCCryptorUpdate failed %d\n", status
);
1284 return STATUS_INTERNAL_ERROR
;
1287 return STATUS_SUCCESS
;
1290 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1293 CCCryptorStatus status
;
1295 if ((status
= CCCryptorUpdate( key
->u
.s
.ref_decrypt
, input
, input_len
, output
, output_len
, NULL
)) != kCCSuccess
)
1297 WARN( "CCCryptorUpdate failed %d\n", status
);
1298 return STATUS_INTERNAL_ERROR
;
1301 return STATUS_SUCCESS
;
1304 static NTSTATUS
key_symmetric_get_tag( struct key
*key
, UCHAR
*tag
, ULONG len
)
1306 FIXME( "not implemented on Mac\n" );
1307 return STATUS_NOT_IMPLEMENTED
;
1310 static NTSTATUS
key_destroy( struct key
*key
)
1312 if (key
->u
.s
.ref_encrypt
) CCCryptorRelease( key
->u
.s
.ref_encrypt
);
1313 if (key
->u
.s
.ref_decrypt
) CCCryptorRelease( key
->u
.s
.ref_decrypt
);
1314 heap_free( key
->u
.s
.secret
);
1316 return STATUS_SUCCESS
;
1319 static NTSTATUS
key_symmetric_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
1321 ERR( "support for keys not available at build time\n" );
1322 return STATUS_NOT_IMPLEMENTED
;
1325 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1327 ERR( "support for keys not available at build time\n" );
1328 return STATUS_NOT_IMPLEMENTED
;
1331 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
1333 ERR( "support for keys not available at build time\n" );
1334 return STATUS_NOT_IMPLEMENTED
;
1337 static NTSTATUS
key_symmetric_set_params( struct key
*key
, UCHAR
*iv
, ULONG iv_len
)
1339 ERR( "support for keys not available at build time\n" );
1340 return STATUS_NOT_IMPLEMENTED
;
1343 static NTSTATUS
key_symmetric_set_auth_data( struct key
*key
, UCHAR
*auth_data
, ULONG len
)
1345 ERR( "support for keys not available at build time\n" );
1346 return STATUS_NOT_IMPLEMENTED
;
1349 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1352 ERR( "support for keys not available at build time\n" );
1353 return STATUS_NOT_IMPLEMENTED
;
1356 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1359 ERR( "support for keys not available at build time\n" );
1360 return STATUS_NOT_IMPLEMENTED
;
1363 static NTSTATUS
key_symmetric_get_tag( struct key
*key
, UCHAR
*tag
, ULONG len
)
1365 ERR( "support for keys not available at build time\n" );
1366 return STATUS_NOT_IMPLEMENTED
;
1369 static NTSTATUS
key_destroy( struct key
*key
)
1371 ERR( "support for keys not available at build time\n" );
1372 return STATUS_NOT_IMPLEMENTED
;
1375 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1377 ERR( "support for keys not available at build time\n" );
1378 return STATUS_NOT_IMPLEMENTED
;
1381 static inline BOOL
key_is_symmetric( struct key
*key
)
1383 ERR( "support for keys not available at build time\n" );
1388 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1389 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1392 struct algorithm
*alg
= algorithm
;
1396 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
1398 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1399 if (object
) FIXME( "ignoring object buffer\n" );
1401 if (!(key
= heap_alloc( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1402 key
->hdr
.magic
= MAGIC_KEY
;
1404 if ((status
= key_symmetric_init( key
, alg
, secret
, secret_len
)))
1411 return STATUS_SUCCESS
;
1414 NTSTATUS WINAPI
BCryptImportKey(BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, LPCWSTR type
,
1415 BCRYPT_KEY_HANDLE
*key
, PUCHAR object
, ULONG object_len
, PUCHAR input
,
1416 ULONG input_len
, ULONG flags
)
1418 struct algorithm
*alg
= algorithm
;
1420 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm
, decrypt_key
, debugstr_w(type
), key
, object
,
1421 object_len
, input
, input_len
, flags
);
1423 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1424 if (!key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1428 FIXME("Decrypting of key not yet supported\n");
1429 return STATUS_NO_MEMORY
;
1432 if (!strcmpW(type
, BCRYPT_KEY_DATA_BLOB
))
1434 BCRYPT_KEY_DATA_BLOB_HEADER
*key_header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
1436 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
))
1437 return STATUS_BUFFER_TOO_SMALL
;
1439 if (key_header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
)
1440 return STATUS_INVALID_PARAMETER
;
1442 if (key_header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
1444 FIXME("Unknown key data blob version: %d\n", key_header
->dwVersion
);
1445 return STATUS_INVALID_PARAMETER
;
1448 if (key_header
->cbKeyData
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
)
1449 return STATUS_INVALID_PARAMETER
;
1451 return BCryptGenerateSymmetricKey(algorithm
, key
, object
, object_len
, (UCHAR
*)&key_header
[1], key_header
->cbKeyData
, 0);
1454 FIXME("Unsupported key type: %s\n", debugstr_w(type
));
1455 return STATUS_INVALID_PARAMETER
;
1458 NTSTATUS WINAPI
BCryptExportKey(BCRYPT_KEY_HANDLE export_key
, BCRYPT_KEY_HANDLE encrypt_key
, LPCWSTR type
,
1459 PUCHAR output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1461 struct key
*key
= export_key
;
1463 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key
, encrypt_key
, debugstr_w(type
), output
, output_len
, size
, flags
);
1465 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1466 if (!output
|| !output_len
|| !size
) return STATUS_INVALID_PARAMETER
;
1470 FIXME("Encryption of key not yet supported\n");
1471 return STATUS_NO_MEMORY
;
1474 return key_export( key
, type
, output
, output_len
, size
);
1477 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
1478 UCHAR
*object
, ULONG object_len
, ULONG flags
)
1480 struct key
*key_orig
= handle
;
1481 struct key
*key_copy
;
1484 TRACE( "%p, %p, %p, %u, %08x\n", handle
, handle_copy
, object
, object_len
, flags
);
1485 if (object
) FIXME( "ignoring object buffer\n" );
1487 if (!key_orig
|| key_orig
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1488 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1489 if (!(key_copy
= heap_alloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
1491 if ((status
= key_duplicate( key_orig
, key_copy
)))
1493 heap_free( key_copy
);
1497 *handle_copy
= key_copy
;
1498 return STATUS_SUCCESS
;
1501 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
1503 struct key
*key
= handle
;
1505 TRACE( "%p\n", handle
);
1507 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1508 return key_destroy( key
);
1511 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
,
1512 void *padding
, UCHAR
*iv
, ULONG iv_len
, UCHAR
*output
,
1513 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1515 struct key
*key
= handle
;
1516 ULONG bytes_left
= input_len
;
1517 UCHAR
*buf
, *src
, *dst
;
1520 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
,
1521 padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1523 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1524 if (!key_is_symmetric( key
))
1526 FIXME( "encryption with asymmetric keys not yet supported\n" );
1527 return STATUS_NOT_IMPLEMENTED
;
1529 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1531 FIXME( "flags %08x not implemented\n", flags
);
1532 return STATUS_NOT_IMPLEMENTED
;
1535 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1537 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1539 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1540 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1541 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1542 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1543 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1544 FIXME( "call chaining not implemented\n" );
1546 if ((status
= key_symmetric_set_params( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1549 *ret_len
= input_len
;
1550 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1551 if (input
&& !output
) return STATUS_SUCCESS
;
1552 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1554 if ((status
= key_symmetric_set_auth_data( key
, auth_info
->pbAuthData
, auth_info
->cbAuthData
)))
1556 if ((status
= key_symmetric_encrypt( key
, input
, input_len
, output
, output_len
))) return status
;
1558 return key_symmetric_get_tag( key
, auth_info
->pbTag
, auth_info
->cbTag
);
1561 if ((status
= key_symmetric_set_params( key
, iv
, iv_len
))) return status
;
1562 *ret_len
= input_len
;
1564 if (flags
& BCRYPT_BLOCK_PADDING
)
1565 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1566 else if (input_len
& (key
->u
.s
.block_size
- 1))
1567 return STATUS_INVALID_BUFFER_SIZE
;
1569 if (!output
) return STATUS_SUCCESS
;
1570 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1571 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1575 while (bytes_left
>= key
->u
.s
.block_size
)
1577 if ((status
= key_symmetric_encrypt( key
, src
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
)))
1579 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_params( key
, NULL
, 0 ))) return status
;
1580 bytes_left
-= key
->u
.s
.block_size
;
1581 src
+= key
->u
.s
.block_size
;
1582 dst
+= key
->u
.s
.block_size
;
1585 if (flags
& BCRYPT_BLOCK_PADDING
)
1587 if (!(buf
= heap_alloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1588 memcpy( buf
, src
, bytes_left
);
1589 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1590 status
= key_symmetric_encrypt( key
, buf
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
);
1597 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
,
1598 void *padding
, UCHAR
*iv
, ULONG iv_len
, UCHAR
*output
,
1599 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1601 struct key
*key
= handle
;
1602 ULONG bytes_left
= input_len
;
1603 UCHAR
*buf
, *src
, *dst
;
1606 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
,
1607 padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1609 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1610 if (!key_is_symmetric( key
))
1612 FIXME( "decryption with asymmetric keys not yet supported\n" );
1613 return STATUS_NOT_IMPLEMENTED
;
1615 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1617 FIXME( "flags %08x not supported\n", flags
);
1618 return STATUS_NOT_IMPLEMENTED
;
1621 if (key
->u
.s
.mode
== MODE_ID_GCM
)
1623 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1626 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1627 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1628 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1629 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1631 if ((status
= key_symmetric_set_params( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1634 *ret_len
= input_len
;
1635 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1636 if (!output
) return STATUS_SUCCESS
;
1637 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1639 if ((status
= key_symmetric_set_auth_data( key
, auth_info
->pbAuthData
, auth_info
->cbAuthData
)))
1641 if ((status
= key_symmetric_decrypt( key
, input
, input_len
, output
, output_len
))) return status
;
1643 if ((status
= key_symmetric_get_tag( key
, tag
, sizeof(tag
) ))) return status
;
1644 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1646 return STATUS_SUCCESS
;
1649 if ((status
= key_symmetric_set_params( key
, iv
, iv_len
))) return status
;
1651 *ret_len
= input_len
;
1653 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1654 if (!output
) return STATUS_SUCCESS
;
1655 if (flags
& BCRYPT_BLOCK_PADDING
)
1657 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1658 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1659 bytes_left
-= key
->u
.s
.block_size
;
1661 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1663 if (key
->u
.s
.mode
== MODE_ID_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1667 while (bytes_left
>= key
->u
.s
.block_size
)
1669 if ((status
= key_symmetric_decrypt( key
, src
, key
->u
.s
.block_size
, dst
, key
->u
.s
.block_size
)))
1671 if (key
->u
.s
.mode
== MODE_ID_ECB
&& (status
= key_symmetric_set_params( key
, NULL
, 0 ))) return status
;
1672 bytes_left
-= key
->u
.s
.block_size
;
1673 src
+= key
->u
.s
.block_size
;
1674 dst
+= key
->u
.s
.block_size
;
1677 if (flags
& BCRYPT_BLOCK_PADDING
)
1679 if (!(buf
= heap_alloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1680 status
= key_symmetric_decrypt( key
, src
, key
->u
.s
.block_size
, buf
, key
->u
.s
.block_size
);
1681 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1683 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1684 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1685 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1687 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1694 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
1696 struct object
*object
= handle
;
1698 TRACE( "%p, %s, %p, %u, %08x\n", handle
, debugstr_w(prop
), value
, size
, flags
);
1700 if (!object
) return STATUS_INVALID_HANDLE
;
1702 switch (object
->magic
)
1706 struct algorithm
*alg
= (struct algorithm
*)object
;
1707 return set_alg_property( alg
, prop
, value
, size
, flags
);
1711 struct key
*key
= (struct key
*)object
;
1712 return set_key_property( key
, prop
, value
, size
, flags
);
1715 WARN( "unknown magic %08x\n", object
->magic
);
1716 return STATUS_INVALID_HANDLE
;
1720 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
1724 case DLL_PROCESS_ATTACH
:
1726 DisableThreadLibraryCalls( hinst
);
1727 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
1728 gnutls_initialize();
1732 case DLL_PROCESS_DETACH
:
1733 if (reserved
) break;
1734 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
1735 gnutls_uninitialize();