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 static void *libgnutls_handle
;
54 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
55 MAKE_FUNCPTR(gnutls_cipher_decrypt2
);
56 MAKE_FUNCPTR(gnutls_cipher_deinit
);
57 MAKE_FUNCPTR(gnutls_cipher_encrypt2
);
58 MAKE_FUNCPTR(gnutls_cipher_init
);
59 MAKE_FUNCPTR(gnutls_global_deinit
);
60 MAKE_FUNCPTR(gnutls_global_init
);
61 MAKE_FUNCPTR(gnutls_global_set_log_function
);
62 MAKE_FUNCPTR(gnutls_global_set_log_level
);
63 MAKE_FUNCPTR(gnutls_perror
);
66 #if GNUTLS_VERSION_MAJOR < 3
67 #define GNUTLS_CIPHER_AES_192_CBC 92
68 #define GNUTLS_CIPHER_AES_128_GCM 93
69 #define GNUTLS_CIPHER_AES_256_GCM 94
72 static void gnutls_log( int level
, const char *msg
)
74 TRACE( "<%d> %s", level
, msg
);
77 static BOOL
gnutls_initialize(void)
81 if (!(libgnutls_handle
= wine_dlopen( SONAME_LIBGNUTLS
, RTLD_NOW
, NULL
, 0 )))
83 ERR_(winediag
)( "failed to load libgnutls, no support for encryption\n" );
87 #define LOAD_FUNCPTR(f) \
88 if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \
90 ERR( "failed to load %s\n", #f ); \
94 LOAD_FUNCPTR(gnutls_cipher_decrypt2
)
95 LOAD_FUNCPTR(gnutls_cipher_deinit
)
96 LOAD_FUNCPTR(gnutls_cipher_encrypt2
)
97 LOAD_FUNCPTR(gnutls_cipher_init
)
98 LOAD_FUNCPTR(gnutls_global_deinit
)
99 LOAD_FUNCPTR(gnutls_global_init
)
100 LOAD_FUNCPTR(gnutls_global_set_log_function
)
101 LOAD_FUNCPTR(gnutls_global_set_log_level
)
102 LOAD_FUNCPTR(gnutls_perror
)
105 if ((ret
= pgnutls_global_init()) != GNUTLS_E_SUCCESS
)
107 pgnutls_perror( ret
);
111 if (TRACE_ON( bcrypt
))
113 pgnutls_global_set_log_level( 4 );
114 pgnutls_global_set_log_function( gnutls_log
);
120 wine_dlclose( libgnutls_handle
, NULL
, 0 );
121 libgnutls_handle
= NULL
;
125 static void gnutls_uninitialize(void)
127 pgnutls_global_deinit();
128 wine_dlclose( libgnutls_handle
, NULL
, 0 );
129 libgnutls_handle
= NULL
;
131 #endif /* HAVE_GNUTLS_CIPHER_INIT && !HAVE_COMMONCRYPTO_COMMONCRYPTOR_H */
133 NTSTATUS WINAPI
BCryptAddContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, ULONG pos
)
135 FIXME("%08x, %s, %08x, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), pos
);
136 return STATUS_SUCCESS
;
139 NTSTATUS WINAPI
BCryptAddContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
, ULONG pos
)
141 FIXME("%08x, %s, %08x, %s, %s, %u: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
), pos
);
142 return STATUS_SUCCESS
;
145 NTSTATUS WINAPI
BCryptRemoveContextFunction(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
)
147 FIXME("%08x, %s, %08x, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
));
148 return STATUS_NOT_IMPLEMENTED
;
151 NTSTATUS WINAPI
BCryptRemoveContextFunctionProvider(ULONG table
, LPCWSTR context
, ULONG iface
, LPCWSTR function
, LPCWSTR provider
)
153 FIXME("%08x, %s, %08x, %s, %s: stub\n", table
, debugstr_w(context
), iface
, debugstr_w(function
), debugstr_w(provider
));
154 return STATUS_NOT_IMPLEMENTED
;
157 NTSTATUS WINAPI
BCryptRegisterProvider(LPCWSTR provider
, ULONG flags
, PCRYPT_PROVIDER_REG reg
)
159 FIXME("%s, %08x, %p: stub\n", debugstr_w(provider
), flags
, reg
);
160 return STATUS_SUCCESS
;
163 NTSTATUS WINAPI
BCryptUnregisterProvider(LPCWSTR provider
)
165 FIXME("%s: stub\n", debugstr_w(provider
));
166 return STATUS_NOT_IMPLEMENTED
;
169 NTSTATUS WINAPI
BCryptEnumAlgorithms(ULONG dwAlgOperations
, ULONG
*pAlgCount
,
170 BCRYPT_ALGORITHM_IDENTIFIER
**ppAlgList
, ULONG dwFlags
)
172 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations
, pAlgCount
, ppAlgList
, dwFlags
);
177 return STATUS_NOT_IMPLEMENTED
;
180 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
181 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
182 #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0')
207 #define MAX_HASH_OUTPUT_BYTES 64
208 #define MAX_HASH_BLOCK_BITS 1024
210 static const struct {
214 const WCHAR
*alg_name
;
216 /* ALG_ID_AES */ { 654, 0, 0, BCRYPT_AES_ALGORITHM
},
217 /* ALG_ID_MD2 */ { 270, 16, 128, BCRYPT_MD2_ALGORITHM
},
218 /* ALG_ID_MD4 */ { 270, 16, 512, BCRYPT_MD4_ALGORITHM
},
219 /* ALG_ID_MD5 */ { 274, 16, 512, BCRYPT_MD5_ALGORITHM
},
220 /* ALG_ID_RNG */ { 0, 0, 0, BCRYPT_RNG_ALGORITHM
},
221 /* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM
},
222 /* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM
},
223 /* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM
},
224 /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM
}
235 NTSTATUS WINAPI
BCryptGenRandom(BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
237 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
238 struct algorithm
*algorithm
= handle
;
240 TRACE("%p, %p, %u, %08x - semi-stub\n", handle
, buffer
, count
, flags
);
244 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
245 * is set. In this case the preferred system RNG is used.
247 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
248 return STATUS_INVALID_HANDLE
;
250 else if (algorithm
->hdr
.magic
!= MAGIC_ALG
|| algorithm
->id
!= ALG_ID_RNG
)
251 return STATUS_INVALID_HANDLE
;
254 return STATUS_INVALID_PARAMETER
;
256 if (flags
& ~supported_flags
)
257 FIXME("unsupported flags %08x\n", flags
& ~supported_flags
);
260 FIXME("ignoring selected algorithm\n");
262 /* When zero bytes are requested the function returns success too. */
264 return STATUS_SUCCESS
;
266 if (algorithm
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
268 if (RtlGenRandom(buffer
, count
))
269 return STATUS_SUCCESS
;
272 FIXME("called with unsupported parameters, returning error\n");
273 return STATUS_NOT_IMPLEMENTED
;
276 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, LPCWSTR id
, LPCWSTR implementation
, DWORD flags
)
278 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
;
279 struct algorithm
*alg
;
282 TRACE( "%p, %s, %s, %08x\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
284 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
285 if (flags
& ~supported_flags
)
287 FIXME( "unsupported flags %08x\n", flags
& ~supported_flags
);
288 return STATUS_NOT_IMPLEMENTED
;
291 if (!strcmpW( id
, BCRYPT_AES_ALGORITHM
)) alg_id
= ALG_ID_AES
;
292 else if (!strcmpW( id
, BCRYPT_MD2_ALGORITHM
)) alg_id
= ALG_ID_MD2
;
293 else if (!strcmpW( id
, BCRYPT_MD4_ALGORITHM
)) alg_id
= ALG_ID_MD4
;
294 else if (!strcmpW( id
, BCRYPT_MD5_ALGORITHM
)) alg_id
= ALG_ID_MD5
;
295 else if (!strcmpW( id
, BCRYPT_RNG_ALGORITHM
)) alg_id
= ALG_ID_RNG
;
296 else if (!strcmpW( id
, BCRYPT_SHA1_ALGORITHM
)) alg_id
= ALG_ID_SHA1
;
297 else if (!strcmpW( id
, BCRYPT_SHA256_ALGORITHM
)) alg_id
= ALG_ID_SHA256
;
298 else if (!strcmpW( id
, BCRYPT_SHA384_ALGORITHM
)) alg_id
= ALG_ID_SHA384
;
299 else if (!strcmpW( id
, BCRYPT_SHA512_ALGORITHM
)) alg_id
= ALG_ID_SHA512
;
302 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
303 return STATUS_NOT_IMPLEMENTED
;
305 if (implementation
&& strcmpW( implementation
, MS_PRIMITIVE_PROVIDER
))
307 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
308 return STATUS_NOT_IMPLEMENTED
;
311 if (!(alg
= heap_alloc( sizeof(*alg
) ))) return STATUS_NO_MEMORY
;
312 alg
->hdr
.magic
= MAGIC_ALG
;
314 alg
->mode
= MODE_ID_CBC
;
315 alg
->hmac
= flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
;
318 return STATUS_SUCCESS
;
321 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
323 struct algorithm
*alg
= handle
;
325 TRACE( "%p, %08x\n", handle
, flags
);
327 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
329 return STATUS_SUCCESS
;
332 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
334 FIXME("%p - semi-stub\n", enabled
);
337 return STATUS_INVALID_PARAMETER
;
340 return STATUS_SUCCESS
;
356 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
361 md2_init( &hash
->u
.md2
);
365 MD4Init( &hash
->u
.md4
);
369 MD5Init( &hash
->u
.md5
);
373 A_SHAInit( &hash
->u
.sha1
);
377 sha256_init( &hash
->u
.sha256
);
381 sha384_init( &hash
->u
.sha512
);
385 sha512_init( &hash
->u
.sha512
);
389 ERR( "unhandled id %u\n", alg_id
);
390 return STATUS_NOT_IMPLEMENTED
;
392 return STATUS_SUCCESS
;
395 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
,
396 UCHAR
*input
, ULONG size
)
401 md2_update( &hash
->u
.md2
, input
, size
);
405 MD4Update( &hash
->u
.md4
, input
, size
);
409 MD5Update( &hash
->u
.md5
, input
, size
);
413 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
417 sha256_update( &hash
->u
.sha256
, input
, size
);
421 sha384_update( &hash
->u
.sha512
, input
, size
);
425 sha512_update( &hash
->u
.sha512
, input
, size
);
429 ERR( "unhandled id %u\n", alg_id
);
430 return STATUS_NOT_IMPLEMENTED
;
432 return STATUS_SUCCESS
;
435 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
,
436 UCHAR
*output
, ULONG size
)
441 md2_finalize( &hash
->u
.md2
, output
);
445 MD4Final( &hash
->u
.md4
);
446 memcpy( output
, hash
->u
.md4
.digest
, 16 );
450 MD5Final( &hash
->u
.md5
);
451 memcpy( output
, hash
->u
.md5
.digest
, 16 );
455 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
459 sha256_finalize( &hash
->u
.sha256
, output
);
463 sha384_finalize( &hash
->u
.sha512
, output
);
467 sha512_finalize( &hash
->u
.sha512
, output
);
471 ERR( "unhandled id %u\n", alg_id
);
472 return STATUS_NOT_IMPLEMENTED
;
474 return STATUS_SUCCESS
;
482 struct hash_impl outer
;
483 struct hash_impl inner
;
486 #define BLOCK_LENGTH_AES 16
488 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
490 if (!strcmpW( prop
, BCRYPT_OBJECT_LENGTH
))
492 if (!alg_props
[id
].object_length
)
493 return STATUS_NOT_SUPPORTED
;
494 *ret_size
= sizeof(ULONG
);
495 if (size
< sizeof(ULONG
))
496 return STATUS_BUFFER_TOO_SMALL
;
498 *(ULONG
*)buf
= alg_props
[id
].object_length
;
499 return STATUS_SUCCESS
;
502 if (!strcmpW( prop
, BCRYPT_HASH_LENGTH
))
504 if (!alg_props
[id
].hash_length
)
505 return STATUS_NOT_SUPPORTED
;
506 *ret_size
= sizeof(ULONG
);
507 if (size
< sizeof(ULONG
))
508 return STATUS_BUFFER_TOO_SMALL
;
510 *(ULONG
*)buf
= alg_props
[id
].hash_length
;
511 return STATUS_SUCCESS
;
514 if (!strcmpW( prop
, BCRYPT_ALGORITHM_NAME
))
516 *ret_size
= (strlenW(alg_props
[id
].alg_name
)+1)*sizeof(WCHAR
);
517 if (size
< *ret_size
)
518 return STATUS_BUFFER_TOO_SMALL
;
520 memcpy(buf
, alg_props
[id
].alg_name
, *ret_size
);
521 return STATUS_SUCCESS
;
524 return STATUS_NOT_IMPLEMENTED
;
527 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
531 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
532 if (status
!= STATUS_NOT_IMPLEMENTED
)
538 if (!strcmpW( prop
, BCRYPT_BLOCK_LENGTH
))
540 *ret_size
= sizeof(ULONG
);
541 if (size
< sizeof(ULONG
))
542 return STATUS_BUFFER_TOO_SMALL
;
544 *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
545 return STATUS_SUCCESS
;
547 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
552 case MODE_ID_GCM
: mode
= BCRYPT_CHAIN_MODE_GCM
; break;
553 case MODE_ID_CBC
: mode
= BCRYPT_CHAIN_MODE_CBC
; break;
554 default: return STATUS_NOT_IMPLEMENTED
;
558 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
559 memcpy( buf
, mode
, (strlenW(mode
) + 1) * sizeof(WCHAR
) );
560 return STATUS_SUCCESS
;
562 if (!strcmpW( prop
, BCRYPT_KEY_LENGTHS
))
564 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
565 *ret_size
= sizeof(*key_lengths
);
566 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
569 key_lengths
->dwMinLength
= 128;
570 key_lengths
->dwMaxLength
= 256;
571 key_lengths
->dwIncrement
= 64;
573 return STATUS_SUCCESS
;
575 if (!strcmpW( prop
, BCRYPT_AUTH_TAG_LENGTH
))
577 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
578 if (alg
->mode
!= MODE_ID_GCM
) return STATUS_NOT_SUPPORTED
;
579 *ret_size
= sizeof(*tag_length
);
580 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
583 tag_length
->dwMinLength
= 12;
584 tag_length
->dwMaxLength
= 16;
585 tag_length
->dwIncrement
= 1;
587 return STATUS_SUCCESS
;
595 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
596 return STATUS_NOT_IMPLEMENTED
;
599 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
604 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
606 if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
, size
))
608 alg
->mode
= MODE_ID_CBC
;
609 return STATUS_SUCCESS
;
611 else if (!strncmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
, size
))
613 alg
->mode
= MODE_ID_GCM
;
614 return STATUS_SUCCESS
;
618 FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR
*)value
, size
) );
619 return STATUS_NOT_IMPLEMENTED
;
622 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
623 return STATUS_NOT_IMPLEMENTED
;
626 FIXME( "unsupported algorithm %u\n", alg
->id
);
627 return STATUS_NOT_IMPLEMENTED
;
631 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
635 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
636 if (status
== STATUS_NOT_IMPLEMENTED
)
637 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
641 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, LPCWSTR prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
, ULONG flags
)
643 struct object
*object
= handle
;
645 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
647 if (!object
) return STATUS_INVALID_HANDLE
;
648 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
650 switch (object
->magic
)
654 const struct algorithm
*alg
= (const struct algorithm
*)object
;
655 return get_alg_property( alg
, prop
, buffer
, count
, res
);
659 const struct hash
*hash
= (const struct hash
*)object
;
660 return get_hash_property( hash
, prop
, buffer
, count
, res
);
663 WARN( "unknown magic %08x\n", object
->magic
);
664 return STATUS_INVALID_HANDLE
;
668 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
670 struct object
*object
= handle
;
672 TRACE( "%p, %s, %p, %u, %08x\n", handle
, debugstr_w(prop
), value
, size
, flags
);
674 if (!object
) return STATUS_INVALID_HANDLE
;
676 switch (object
->magic
)
680 struct algorithm
*alg
= (struct algorithm
*)object
;
681 return set_alg_property( alg
, prop
, value
, size
, flags
);
685 FIXME( "keys not implemented yet\n" );
686 return STATUS_NOT_IMPLEMENTED
;
689 WARN( "unknown magic %08x\n", object
->magic
);
690 return STATUS_INVALID_HANDLE
;
694 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_HASH_HANDLE
*handle
, UCHAR
*object
, ULONG objectlen
,
695 UCHAR
*secret
, ULONG secretlen
, ULONG flags
)
697 struct algorithm
*alg
= algorithm
;
698 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
704 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm
, handle
, object
, objectlen
,
705 secret
, secretlen
, flags
);
708 FIXME( "unimplemented flags %08x\n", flags
);
709 return STATUS_NOT_IMPLEMENTED
;
712 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
713 if (object
) FIXME( "ignoring object buffer\n" );
715 if (!(hash
= heap_alloc( sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
716 hash
->hdr
.magic
= MAGIC_HASH
;
717 hash
->alg_id
= alg
->id
;
718 hash
->hmac
= alg
->hmac
;
720 /* initialize hash */
721 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) goto end
;
722 if (!hash
->hmac
) goto end
;
724 /* initialize hmac */
725 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) goto end
;
726 block_bytes
= alg_props
[hash
->alg_id
].block_bits
/ 8;
727 if (secretlen
> block_bytes
)
729 struct hash_impl temp
;
730 if ((status
= hash_init( &temp
, hash
->alg_id
))) goto end
;
731 if ((status
= hash_update( &temp
, hash
->alg_id
, secret
, secretlen
))) goto end
;
732 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
,
733 alg_props
[hash
->alg_id
].hash_length
))) goto end
;
737 memcpy( buffer
, secret
, secretlen
);
739 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
740 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) goto end
;
741 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
742 status
= hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
745 if (status
!= STATUS_SUCCESS
)
752 return STATUS_SUCCESS
;
755 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
756 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
758 struct hash
*hash_orig
= handle
;
759 struct hash
*hash_copy
;
761 TRACE( "%p, %p, %p, %u, %u\n", handle
, handle_copy
, object
, objectlen
, flags
);
763 if (!hash_orig
|| hash_orig
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
764 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
765 if (object
) FIXME( "ignoring object buffer\n" );
767 if (!(hash_copy
= heap_alloc( sizeof(*hash_copy
) )))
768 return STATUS_NO_MEMORY
;
770 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
772 *handle_copy
= hash_copy
;
773 return STATUS_SUCCESS
;
776 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
778 struct hash
*hash
= handle
;
780 TRACE( "%p\n", handle
);
782 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
784 return STATUS_SUCCESS
;
787 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
789 struct hash
*hash
= handle
;
791 TRACE( "%p, %p, %u, %08x\n", handle
, input
, size
, flags
);
793 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
794 if (!input
) return STATUS_SUCCESS
;
796 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
799 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
801 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
802 struct hash
*hash
= handle
;
806 TRACE( "%p, %p, %u, %08x\n", handle
, output
, size
, flags
);
808 if (!hash
|| hash
->hdr
.magic
!= MAGIC_HASH
) return STATUS_INVALID_HANDLE
;
809 if (!output
) return STATUS_INVALID_PARAMETER
;
812 return hash_finish( &hash
->inner
, hash
->alg_id
, output
, size
);
814 hash_length
= alg_props
[hash
->alg_id
].hash_length
;
815 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
, hash_length
))) return status
;
816 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
817 return hash_finish( &hash
->outer
, hash
->alg_id
, output
, size
);
820 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE algorithm
, UCHAR
*secret
, ULONG secretlen
,
821 UCHAR
*input
, ULONG inputlen
, UCHAR
*output
, ULONG outputlen
)
824 BCRYPT_HASH_HANDLE handle
;
826 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm
, secret
, secretlen
,
827 input
, inputlen
, output
, outputlen
);
829 status
= BCryptCreateHash( algorithm
, &handle
, NULL
, 0, secret
, secretlen
, 0);
830 if (status
!= STATUS_SUCCESS
)
835 status
= BCryptHashData( handle
, input
, inputlen
, 0 );
836 if (status
!= STATUS_SUCCESS
)
838 BCryptDestroyHash( handle
);
842 status
= BCryptFinishHash( handle
, output
, outputlen
, 0 );
843 if (status
!= STATUS_SUCCESS
)
845 BCryptDestroyHash( handle
);
849 return BCryptDestroyHash( handle
);
852 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
859 gnutls_cipher_hd_t handle
;
863 #elif defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
870 CCCryptorRef ref_encrypt
;
871 CCCryptorRef ref_decrypt
;
884 #if defined(HAVE_GNUTLS_CIPHER_INIT) || defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
885 static ULONG
get_block_size( struct algorithm
*alg
)
887 ULONG ret
= 0, size
= sizeof(ret
);
888 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
891 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
893 if (!strcmpW( type
, BCRYPT_KEY_DATA_BLOB
))
895 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
896 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->secret_len
;
899 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
901 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
902 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
903 header
->cbKeyData
= key
->secret_len
;
904 memcpy( &header
[1], key
->secret
, key
->secret_len
);
905 return STATUS_SUCCESS
;
908 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
909 return STATUS_NOT_IMPLEMENTED
;
913 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
914 static NTSTATUS
key_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
918 if (!libgnutls_handle
) return STATUS_INTERNAL_ERROR
;
926 FIXME( "algorithm %u not supported\n", alg
->id
);
927 return STATUS_NOT_SUPPORTED
;
930 if (!(key
->block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
931 if (!(buffer
= heap_alloc( secret_len
))) return STATUS_NO_MEMORY
;
932 memcpy( buffer
, secret
, secret_len
);
934 key
->alg_id
= alg
->id
;
935 key
->mode
= alg
->mode
;
936 key
->handle
= 0; /* initialized on first use */
937 key
->secret
= buffer
;
938 key
->secret_len
= secret_len
;
940 return STATUS_SUCCESS
;
943 static gnutls_cipher_algorithm_t
get_gnutls_cipher( const struct key
*key
)
948 WARN( "handle block size\n" );
951 case MODE_ID_GCM
: return GNUTLS_CIPHER_AES_128_GCM
;
953 default: return GNUTLS_CIPHER_AES_128_CBC
;
956 FIXME( "algorithm %u not supported\n", key
->alg_id
);
957 return GNUTLS_CIPHER_UNKNOWN
;
961 static NTSTATUS
key_set_params( struct key
*key
, UCHAR
*iv
, ULONG iv_len
)
963 gnutls_cipher_algorithm_t cipher
;
964 gnutls_datum_t secret
, vector
;
969 pgnutls_cipher_deinit( key
->handle
);
973 if ((cipher
= get_gnutls_cipher( key
)) == GNUTLS_CIPHER_UNKNOWN
)
974 return STATUS_NOT_SUPPORTED
;
976 secret
.data
= key
->secret
;
977 secret
.size
= key
->secret_len
;
981 vector
.size
= iv_len
;
984 if ((ret
= pgnutls_cipher_init( &key
->handle
, cipher
, &secret
, iv
? &vector
: NULL
)))
986 pgnutls_perror( ret
);
987 return STATUS_INTERNAL_ERROR
;
990 return STATUS_SUCCESS
;
993 static NTSTATUS
key_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
998 if ((ret
= pgnutls_cipher_encrypt2( key
->handle
, input
, input_len
, output
, output_len
)))
1000 pgnutls_perror( ret
);
1001 return STATUS_INTERNAL_ERROR
;
1004 return STATUS_SUCCESS
;
1007 static NTSTATUS
key_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1012 if ((ret
= pgnutls_cipher_decrypt2( key
->handle
, input
, input_len
, output
, output_len
)))
1014 pgnutls_perror( ret
);
1015 return STATUS_INTERNAL_ERROR
;
1018 return STATUS_SUCCESS
;
1021 static NTSTATUS
key_destroy( struct key
*key
)
1023 if (key
->handle
) pgnutls_cipher_deinit( key
->handle
);
1024 heap_free( key
->secret
);
1026 return STATUS_SUCCESS
;
1028 #elif defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1029 static NTSTATUS
key_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
1041 FIXME( "mode %u not supported\n", alg
->mode
);
1042 return STATUS_NOT_SUPPORTED
;
1047 FIXME( "algorithm %u not supported\n", alg
->id
);
1048 return STATUS_NOT_SUPPORTED
;
1051 if (!(key
->block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1052 if (!(buffer
= heap_alloc( secret_len
))) return STATUS_NO_MEMORY
;
1053 memcpy( buffer
, secret
, secret_len
);
1055 key
->alg_id
= alg
->id
;
1056 key
->mode
= alg
->mode
;
1057 key
->ref_encrypt
= NULL
; /* initialized on first use */
1058 key
->ref_decrypt
= NULL
;
1059 key
->secret
= buffer
;
1060 key
->secret_len
= secret_len
;
1062 return STATUS_SUCCESS
;
1065 static NTSTATUS
key_set_params( struct key
*key
, UCHAR
*iv
, ULONG iv_len
)
1067 CCCryptorStatus status
;
1069 if (key
->ref_encrypt
)
1071 CCCryptorRelease( key
->ref_encrypt
);
1072 key
->ref_encrypt
= NULL
;
1074 if (key
->ref_decrypt
)
1076 CCCryptorRelease( key
->ref_decrypt
);
1077 key
->ref_decrypt
= NULL
;
1080 if ((status
= CCCryptorCreateWithMode( kCCEncrypt
, kCCModeCBC
, kCCAlgorithmAES128
, ccNoPadding
, iv
,
1081 key
->secret
, key
->secret_len
, NULL
, 0, 0, 0, &key
->ref_encrypt
)) != kCCSuccess
)
1083 WARN( "CCCryptorCreateWithMode failed %d\n", status
);
1084 return STATUS_INTERNAL_ERROR
;
1086 if ((status
= CCCryptorCreateWithMode( kCCDecrypt
, kCCModeCBC
, kCCAlgorithmAES128
, ccNoPadding
, iv
,
1087 key
->secret
, key
->secret_len
, NULL
, 0, 0, 0, &key
->ref_decrypt
)) != kCCSuccess
)
1089 WARN( "CCCryptorCreateWithMode failed %d\n", status
);
1090 CCCryptorRelease( key
->ref_encrypt
);
1091 key
->ref_encrypt
= NULL
;
1092 return STATUS_INTERNAL_ERROR
;
1095 return STATUS_SUCCESS
;
1098 static NTSTATUS
key_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1101 CCCryptorStatus status
;
1103 if ((status
= CCCryptorUpdate( key
->ref_encrypt
, input
, input_len
, output
, output_len
, NULL
)) != kCCSuccess
)
1105 WARN( "CCCryptorUpdate failed %d\n", status
);
1106 return STATUS_INTERNAL_ERROR
;
1109 return STATUS_SUCCESS
;
1112 static NTSTATUS
key_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1115 CCCryptorStatus status
;
1117 if ((status
= CCCryptorUpdate( key
->ref_decrypt
, input
, input_len
, output
, output_len
, NULL
)) != kCCSuccess
)
1119 WARN( "CCCryptorUpdate failed %d\n", status
);
1120 return STATUS_INTERNAL_ERROR
;
1123 return STATUS_SUCCESS
;
1126 static NTSTATUS
key_destroy( struct key
*key
)
1128 if (key
->ref_encrypt
) CCCryptorRelease( key
->ref_encrypt
);
1129 if (key
->ref_decrypt
) CCCryptorRelease( key
->ref_decrypt
);
1130 heap_free( key
->secret
);
1132 return STATUS_SUCCESS
;
1135 static NTSTATUS
key_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
1137 ERR( "support for keys not available at build time\n" );
1138 return STATUS_NOT_IMPLEMENTED
;
1141 static NTSTATUS
key_set_params( struct key
*key
, UCHAR
*iv
, ULONG iv_len
)
1143 ERR( "support for keys not available at build time\n" );
1144 return STATUS_NOT_IMPLEMENTED
;
1147 static NTSTATUS
key_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1150 ERR( "support for keys not available at build time\n" );
1151 return STATUS_NOT_IMPLEMENTED
;
1154 static NTSTATUS
key_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1157 ERR( "support for keys not available at build time\n" );
1158 return STATUS_NOT_IMPLEMENTED
;
1161 static NTSTATUS
key_destroy( struct key
*key
)
1163 ERR( "support for keys not available at build time\n" );
1164 return STATUS_NOT_IMPLEMENTED
;
1167 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1169 ERR( "support for keys not available at build time\n" );
1170 return STATUS_NOT_IMPLEMENTED
;
1174 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE
*handle
,
1175 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1178 struct algorithm
*alg
= algorithm
;
1182 TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm
, handle
, object
, object_len
, secret
, secret_len
, flags
);
1184 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1185 if (object
) FIXME( "ignoring object buffer\n" );
1187 if (!(key
= heap_alloc( sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1188 key
->hdr
.magic
= MAGIC_KEY
;
1190 if ((status
= key_init( key
, alg
, secret
, secret_len
)))
1197 return STATUS_SUCCESS
;
1200 NTSTATUS WINAPI
BCryptImportKey(BCRYPT_ALG_HANDLE algorithm
, BCRYPT_KEY_HANDLE decrypt_key
, LPCWSTR type
,
1201 BCRYPT_KEY_HANDLE
*key
, PUCHAR object
, ULONG object_len
, PUCHAR input
,
1202 ULONG input_len
, ULONG flags
)
1204 struct algorithm
*alg
= algorithm
;
1206 TRACE("%p, %p, %s, %p, %p, %u, %p, %u, %u\n", algorithm
, decrypt_key
, debugstr_w(type
), key
, object
,
1207 object_len
, input
, input_len
, flags
);
1209 if (!alg
|| alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
1210 if (!key
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1214 FIXME("Decrypting of key not yet supported\n");
1215 return STATUS_NO_MEMORY
;
1218 if (!strcmpW(type
, BCRYPT_KEY_DATA_BLOB
))
1220 BCRYPT_KEY_DATA_BLOB_HEADER
*key_header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
1222 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
))
1223 return STATUS_BUFFER_TOO_SMALL
;
1225 if (key_header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
)
1226 return STATUS_INVALID_PARAMETER
;
1228 if (key_header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
1230 FIXME("Unknown key data blob version: %d\n", key_header
->dwVersion
);
1231 return STATUS_INVALID_PARAMETER
;
1234 if (key_header
->cbKeyData
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
)
1235 return STATUS_INVALID_PARAMETER
;
1237 return BCryptGenerateSymmetricKey(algorithm
, key
, object
, object_len
, (UCHAR
*)&key_header
[1], key_header
->cbKeyData
, 0);
1240 FIXME("Unsupported key type: %s\n", debugstr_w(type
));
1241 return STATUS_INVALID_PARAMETER
;
1244 NTSTATUS WINAPI
BCryptExportKey(BCRYPT_KEY_HANDLE export_key
, BCRYPT_KEY_HANDLE encrypt_key
, LPCWSTR type
,
1245 PUCHAR output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1247 struct key
*key
= export_key
;
1249 TRACE("%p, %p, %s, %p, %u, %p, %u\n", key
, encrypt_key
, debugstr_w(type
), output
, output_len
, size
, flags
);
1251 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1252 if (!output
|| !output_len
|| !size
) return STATUS_INVALID_PARAMETER
;
1256 FIXME("Encryption of key not yet supported\n");
1257 return STATUS_NO_MEMORY
;
1260 return key_export( key
, type
, output
, output_len
, size
);
1263 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
1265 struct key
*key
= handle
;
1267 TRACE( "%p\n", handle
);
1269 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1270 return key_destroy( key
);
1273 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
,
1274 void *padding
, UCHAR
*iv
, ULONG iv_len
, UCHAR
*output
,
1275 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1277 struct key
*key
= handle
;
1278 ULONG bytes_left
= input_len
;
1279 UCHAR
*buf
, *src
, *dst
;
1282 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
,
1283 padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1285 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1286 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1288 FIXME( "flags %08x not implemented\n", flags
);
1289 return STATUS_NOT_IMPLEMENTED
;
1292 if (key
->mode
== MODE_ID_GCM
)
1294 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1296 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1297 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1298 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1299 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1300 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1301 FIXME( "call chaining not implemented\n" );
1303 if ((status
= key_set_params( key
, auth_info
->pbNonce
, auth_info
->cbNonce
)))
1306 *ret_len
= input_len
;
1307 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1308 if (!output
) return STATUS_SUCCESS
;
1309 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1311 if ((status
= key_encrypt( key
, input
, input_len
, output
, output_len
)))
1314 return STATUS_SUCCESS
;
1317 if ((status
= key_set_params( key
, iv
, iv_len
))) return status
;
1319 *ret_len
= input_len
;
1321 if (flags
& BCRYPT_BLOCK_PADDING
)
1322 *ret_len
= (input_len
+ key
->block_size
) & ~(key
->block_size
- 1);
1323 else if (input_len
& (key
->block_size
- 1))
1324 return STATUS_INVALID_BUFFER_SIZE
;
1326 if (!output
) return STATUS_SUCCESS
;
1327 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1331 while (bytes_left
>= key
->block_size
)
1333 if ((status
= key_encrypt( key
, src
, key
->block_size
, dst
, key
->block_size
))) return status
;
1334 bytes_left
-= key
->block_size
;
1335 src
+= key
->block_size
;
1336 dst
+= key
->block_size
;
1339 if (flags
& BCRYPT_BLOCK_PADDING
)
1341 if (!(buf
= heap_alloc( key
->block_size
))) return STATUS_NO_MEMORY
;
1342 memcpy( buf
, src
, bytes_left
);
1343 memset( buf
+ bytes_left
, key
->block_size
- bytes_left
, key
->block_size
- bytes_left
);
1344 status
= key_encrypt( key
, buf
, key
->block_size
, dst
, key
->block_size
);
1351 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
,
1352 void *padding
, UCHAR
*iv
, ULONG iv_len
, UCHAR
*output
,
1353 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1355 struct key
*key
= handle
;
1356 ULONG bytes_left
= input_len
;
1357 UCHAR
*buf
, *src
, *dst
;
1360 TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle
, input
, input_len
,
1361 padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
1363 if (!key
|| key
->hdr
.magic
!= MAGIC_KEY
) return STATUS_INVALID_HANDLE
;
1366 FIXME( "padding info not implemented\n" );
1367 return STATUS_NOT_IMPLEMENTED
;
1369 if (flags
& ~BCRYPT_BLOCK_PADDING
)
1371 FIXME( "flags %08x not supported\n", flags
);
1372 return STATUS_NOT_IMPLEMENTED
;
1375 if ((status
= key_set_params( key
, iv
, iv_len
))) return status
;
1377 *ret_len
= input_len
;
1379 if (input_len
& (key
->block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1380 if (!output
) return STATUS_SUCCESS
;
1381 if (flags
& BCRYPT_BLOCK_PADDING
)
1383 if (output_len
+ key
->block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1384 if (input_len
< key
->block_size
) return STATUS_BUFFER_TOO_SMALL
;
1385 bytes_left
-= key
->block_size
;
1387 else if (output_len
< *ret_len
)
1388 return STATUS_BUFFER_TOO_SMALL
;
1392 while (bytes_left
>= key
->block_size
)
1394 if ((status
= key_decrypt( key
, src
, key
->block_size
, dst
, key
->block_size
))) return status
;
1395 bytes_left
-= key
->block_size
;
1396 src
+= key
->block_size
;
1397 dst
+= key
->block_size
;
1400 if (flags
& BCRYPT_BLOCK_PADDING
)
1402 if (!(buf
= heap_alloc( key
->block_size
))) return STATUS_NO_MEMORY
;
1403 status
= key_decrypt( key
, src
, key
->block_size
, buf
, key
->block_size
);
1404 if (!status
&& buf
[ key
->block_size
- 1 ] <= key
->block_size
)
1406 *ret_len
-= buf
[ key
->block_size
- 1 ];
1407 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1408 else memcpy( dst
, buf
, key
->block_size
- buf
[ key
->block_size
- 1 ] );
1411 status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1418 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
1422 case DLL_PROCESS_ATTACH
:
1424 DisableThreadLibraryCalls( hinst
);
1425 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
1426 gnutls_initialize();
1430 case DLL_PROCESS_DETACH
:
1431 if (reserved
) break;
1432 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
1433 gnutls_uninitialize();