bcrypt: Add initial support for asymmetric keys in BCryptDecrypt().
[wine.git] / dlls / bcrypt / gnutls.c
blobc065ac31fba3b05cf296d990c8534446d670a794
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
3 * Copyright 2018 Hans Leidekker for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
26 #include "wine/port.h"
28 #ifdef HAVE_GNUTLS_CIPHER_INIT
30 #include <stdarg.h>
31 #include <gnutls/gnutls.h>
32 #include <gnutls/crypto.h>
33 #include <gnutls/abstract.h>
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winternl.h"
40 #include "ntsecapi.h"
41 #include "wincrypt.h"
42 #include "bcrypt.h"
44 #include "bcrypt_internal.h"
46 #include "wine/debug.h"
47 #include "wine/unicode.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
50 WINE_DECLARE_DEBUG_CHANNEL(winediag);
52 #if GNUTLS_VERSION_MAJOR < 3
53 #define GNUTLS_CIPHER_AES_192_CBC 92
54 #define GNUTLS_CIPHER_AES_128_GCM 93
55 #define GNUTLS_CIPHER_AES_256_GCM 94
56 #define GNUTLS_PK_ECC 4
58 #define GNUTLS_CURVE_TO_BITS(curve) (unsigned int)(((unsigned int)1<<31)|((unsigned int)(curve)))
60 typedef enum
62 GNUTLS_ECC_CURVE_INVALID,
63 GNUTLS_ECC_CURVE_SECP224R1,
64 GNUTLS_ECC_CURVE_SECP256R1,
65 GNUTLS_ECC_CURVE_SECP384R1,
66 GNUTLS_ECC_CURVE_SECP521R1,
67 } gnutls_ecc_curve_t;
68 #endif
70 union key_data
72 gnutls_cipher_hd_t cipher;
73 gnutls_privkey_t privkey;
75 C_ASSERT( sizeof(union key_data) <= sizeof(((struct key *)0)->private) );
77 static union key_data *key_data( struct key *key )
79 return (union key_data *)key->private;
82 /* Not present in gnutls version < 3.0 */
83 static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t, void *, size_t);
84 static int (*pgnutls_cipher_add_auth)(gnutls_cipher_hd_t, const void *, size_t);
85 static gnutls_sign_algorithm_t (*pgnutls_pk_to_sign)(gnutls_pk_algorithm_t, gnutls_digest_algorithm_t);
86 static int (*pgnutls_pubkey_import_ecc_raw)(gnutls_pubkey_t, gnutls_ecc_curve_t,
87 const gnutls_datum_t *, const gnutls_datum_t *);
88 static int (*pgnutls_privkey_import_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_t, const gnutls_datum_t *,
89 const gnutls_datum_t *, const gnutls_datum_t *);
90 static int (*pgnutls_pubkey_verify_hash2)(gnutls_pubkey_t, gnutls_sign_algorithm_t, unsigned int,
91 const gnutls_datum_t *, const gnutls_datum_t *);
93 /* Not present in gnutls version < 2.11.0 */
94 static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *);
96 /* Not present in gnutls version < 2.12.0 */
97 static int (*pgnutls_pubkey_import_dsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *,
98 const gnutls_datum_t *, const gnutls_datum_t *);
100 /* Not present in gnutls version < 3.3.0 */
101 static int (*pgnutls_privkey_export_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_t *,
102 gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *);
103 static int (*pgnutls_privkey_export_rsa_raw)(gnutls_privkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
104 gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
105 gnutls_datum_t *);
106 static int (*pgnutls_privkey_export_dsa_raw)(gnutls_privkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
107 gnutls_datum_t *, gnutls_datum_t *);
108 static int (*pgnutls_privkey_generate)(gnutls_privkey_t, gnutls_pk_algorithm_t, unsigned int, unsigned int);
109 static int (*pgnutls_privkey_import_rsa_raw)(gnutls_privkey_t, const gnutls_datum_t *, const gnutls_datum_t *,
110 const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *,
111 const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *);
112 static int (*pgnutls_privkey_decrypt_data)(gnutls_privkey_t, unsigned int flags, const gnutls_datum_t *, gnutls_datum_t *);
114 /* Not present in gnutls version < 3.6.0 */
115 static int (*pgnutls_decode_rs_value)(const gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *);
117 static void *libgnutls_handle;
118 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
119 MAKE_FUNCPTR(gnutls_cipher_decrypt2);
120 MAKE_FUNCPTR(gnutls_cipher_deinit);
121 MAKE_FUNCPTR(gnutls_cipher_encrypt2);
122 MAKE_FUNCPTR(gnutls_cipher_init);
123 MAKE_FUNCPTR(gnutls_global_deinit);
124 MAKE_FUNCPTR(gnutls_global_init);
125 MAKE_FUNCPTR(gnutls_global_set_log_function);
126 MAKE_FUNCPTR(gnutls_global_set_log_level);
127 MAKE_FUNCPTR(gnutls_perror);
128 MAKE_FUNCPTR(gnutls_privkey_decrypt_data);
129 MAKE_FUNCPTR(gnutls_privkey_deinit);
130 MAKE_FUNCPTR(gnutls_privkey_import_dsa_raw);
131 MAKE_FUNCPTR(gnutls_privkey_init);
132 MAKE_FUNCPTR(gnutls_privkey_sign_hash);
133 MAKE_FUNCPTR(gnutls_pubkey_deinit);
134 MAKE_FUNCPTR(gnutls_pubkey_init);
135 #undef MAKE_FUNCPTR
137 static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle, void *tag, size_t tag_size)
139 return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
142 static int compat_gnutls_cipher_add_auth(gnutls_cipher_hd_t handle, const void *ptext, size_t ptext_size)
144 return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
147 static int compat_gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key, gnutls_ecc_curve_t curve,
148 const gnutls_datum_t *x, const gnutls_datum_t *y)
150 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
153 static int compat_gnutls_privkey_export_rsa_raw(gnutls_privkey_t key, gnutls_datum_t *m, gnutls_datum_t *e,
154 gnutls_datum_t *d, gnutls_datum_t *p, gnutls_datum_t *q,
155 gnutls_datum_t *u, gnutls_datum_t *e1, gnutls_datum_t *e2)
157 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
160 static int compat_gnutls_privkey_export_ecc_raw(gnutls_privkey_t key, gnutls_ecc_curve_t *curve,
161 gnutls_datum_t *x, gnutls_datum_t *y, gnutls_datum_t *k)
163 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
166 static int compat_gnutls_privkey_import_ecc_raw(gnutls_privkey_t key, gnutls_ecc_curve_t curve,
167 const gnutls_datum_t *x, const gnutls_datum_t *y,
168 const gnutls_datum_t *k)
170 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
173 static int compat_gnutls_privkey_export_dsa_raw(gnutls_privkey_t key, gnutls_datum_t *p, gnutls_datum_t *q,
174 gnutls_datum_t *g, gnutls_datum_t *y, gnutls_datum_t *x)
176 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
179 static gnutls_sign_algorithm_t compat_gnutls_pk_to_sign(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash)
181 return GNUTLS_SIGN_UNKNOWN;
184 static int compat_gnutls_pubkey_verify_hash2(gnutls_pubkey_t key, gnutls_sign_algorithm_t algo,
185 unsigned int flags, const gnutls_datum_t *hash,
186 const gnutls_datum_t *signature)
188 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
191 static int compat_gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key, const gnutls_datum_t *m, const gnutls_datum_t *e)
193 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
196 static int compat_gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key, const gnutls_datum_t *p, const gnutls_datum_t *q,
197 const gnutls_datum_t *g, const gnutls_datum_t *y)
199 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
202 static int compat_gnutls_privkey_generate(gnutls_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits,
203 unsigned int flags)
205 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
208 static int compat_gnutls_decode_rs_value(const gnutls_datum_t * sig_value, gnutls_datum_t * r, gnutls_datum_t * s)
210 return GNUTLS_E_INTERNAL_ERROR;
213 static int compat_gnutls_privkey_import_rsa_raw(gnutls_privkey_t key, const gnutls_datum_t *m, const gnutls_datum_t *e,
214 const gnutls_datum_t *d, const gnutls_datum_t *p, const gnutls_datum_t *q,
215 const gnutls_datum_t *u, const gnutls_datum_t *e1, const gnutls_datum_t *e2)
217 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
220 static int compat_gnutls_privkey_decrypt_data(gnutls_privkey_t key, unsigned int flags, const gnutls_datum_t *cipher_text,
221 gnutls_datum_t *plain_text)
223 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
226 static void gnutls_log( int level, const char *msg )
228 TRACE( "<%d> %s", level, msg );
231 static BOOL gnutls_initialize(void)
233 const char *env_str;
234 int ret;
236 if ((env_str = getenv("GNUTLS_SYSTEM_PRIORITY_FILE")))
238 WARN("GNUTLS_SYSTEM_PRIORITY_FILE is %s.\n", debugstr_a(env_str));
240 else
242 WARN("Setting GNUTLS_SYSTEM_PRIORITY_FILE to \"/dev/null\".\n");
243 setenv("GNUTLS_SYSTEM_PRIORITY_FILE", "/dev/null", 0);
246 if (!(libgnutls_handle = dlopen( SONAME_LIBGNUTLS, RTLD_NOW )))
248 ERR_(winediag)( "failed to load libgnutls, no support for encryption\n" );
249 return FALSE;
252 #define LOAD_FUNCPTR(f) \
253 if (!(p##f = dlsym( libgnutls_handle, #f ))) \
255 ERR( "failed to load %s\n", #f ); \
256 goto fail; \
259 LOAD_FUNCPTR(gnutls_cipher_decrypt2)
260 LOAD_FUNCPTR(gnutls_cipher_deinit)
261 LOAD_FUNCPTR(gnutls_cipher_encrypt2)
262 LOAD_FUNCPTR(gnutls_cipher_init)
263 LOAD_FUNCPTR(gnutls_global_deinit)
264 LOAD_FUNCPTR(gnutls_global_init)
265 LOAD_FUNCPTR(gnutls_global_set_log_function)
266 LOAD_FUNCPTR(gnutls_global_set_log_level)
267 LOAD_FUNCPTR(gnutls_perror)
268 LOAD_FUNCPTR(gnutls_privkey_deinit);
269 LOAD_FUNCPTR(gnutls_privkey_import_dsa_raw);
270 LOAD_FUNCPTR(gnutls_privkey_init);
271 LOAD_FUNCPTR(gnutls_privkey_sign_hash);
272 LOAD_FUNCPTR(gnutls_pubkey_deinit);
273 LOAD_FUNCPTR(gnutls_pubkey_init);
274 #undef LOAD_FUNCPTR
276 if (!(pgnutls_cipher_tag = dlsym( libgnutls_handle, "gnutls_cipher_tag" )))
278 WARN("gnutls_cipher_tag not found\n");
279 pgnutls_cipher_tag = compat_gnutls_cipher_tag;
281 if (!(pgnutls_cipher_add_auth = dlsym( libgnutls_handle, "gnutls_cipher_add_auth" )))
283 WARN("gnutls_cipher_add_auth not found\n");
284 pgnutls_cipher_add_auth = compat_gnutls_cipher_add_auth;
287 if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
289 pgnutls_perror( ret );
290 goto fail;
292 if (!(pgnutls_pubkey_import_ecc_raw = dlsym( libgnutls_handle, "gnutls_pubkey_import_ecc_raw" )))
294 WARN("gnutls_pubkey_import_ecc_raw not found\n");
295 pgnutls_pubkey_import_ecc_raw = compat_gnutls_pubkey_import_ecc_raw;
297 if (!(pgnutls_privkey_export_rsa_raw = dlsym( libgnutls_handle, "gnutls_privkey_export_rsa_raw" )))
299 WARN("gnutls_privkey_export_rsa_raw not found\n");
300 pgnutls_privkey_export_rsa_raw = compat_gnutls_privkey_export_rsa_raw;
302 if (!(pgnutls_privkey_export_ecc_raw = dlsym( libgnutls_handle, "gnutls_privkey_export_ecc_raw" )))
304 WARN("gnutls_privkey_export_ecc_raw not found\n");
305 pgnutls_privkey_export_ecc_raw = compat_gnutls_privkey_export_ecc_raw;
307 if (!(pgnutls_privkey_import_ecc_raw = dlsym( libgnutls_handle, "gnutls_privkey_import_ecc_raw" )))
309 WARN("gnutls_privkey_import_ecc_raw not found\n");
310 pgnutls_privkey_import_ecc_raw = compat_gnutls_privkey_import_ecc_raw;
312 if (!(pgnutls_privkey_export_dsa_raw = dlsym( libgnutls_handle, "gnutls_privkey_export_dsa_raw" )))
314 WARN("gnutls_privkey_export_dsa_raw not found\n");
315 pgnutls_privkey_export_dsa_raw = compat_gnutls_privkey_export_dsa_raw;
317 if (!(pgnutls_pk_to_sign = dlsym( libgnutls_handle, "gnutls_pk_to_sign" )))
319 WARN("gnutls_pk_to_sign not found\n");
320 pgnutls_pk_to_sign = compat_gnutls_pk_to_sign;
322 if (!(pgnutls_pubkey_verify_hash2 = dlsym( libgnutls_handle, "gnutls_pubkey_verify_hash2" )))
324 WARN("gnutls_pubkey_verify_hash2 not found\n");
325 pgnutls_pubkey_verify_hash2 = compat_gnutls_pubkey_verify_hash2;
327 if (!(pgnutls_pubkey_import_rsa_raw = dlsym( libgnutls_handle, "gnutls_pubkey_import_rsa_raw" )))
329 WARN("gnutls_pubkey_import_rsa_raw not found\n");
330 pgnutls_pubkey_import_rsa_raw = compat_gnutls_pubkey_import_rsa_raw;
332 if (!(pgnutls_pubkey_import_dsa_raw = dlsym( libgnutls_handle, "gnutls_pubkey_import_dsa_raw" )))
334 WARN("gnutls_pubkey_import_dsa_raw not found\n");
335 pgnutls_pubkey_import_dsa_raw = compat_gnutls_pubkey_import_dsa_raw;
337 if (!(pgnutls_privkey_generate = dlsym( libgnutls_handle, "gnutls_privkey_generate" )))
339 WARN("gnutls_privkey_generate not found\n");
340 pgnutls_privkey_generate = compat_gnutls_privkey_generate;
342 if (!(pgnutls_decode_rs_value = dlsym( libgnutls_handle, "gnutls_decode_rs_value" )))
344 WARN("gnutls_decode_rs_value not found\n");
345 pgnutls_decode_rs_value = compat_gnutls_decode_rs_value;
347 if (!(pgnutls_privkey_import_rsa_raw = dlsym( libgnutls_handle, "gnutls_privkey_import_rsa_raw" )))
349 WARN("gnutls_privkey_import_rsa_raw not found\n");
350 pgnutls_privkey_import_rsa_raw = compat_gnutls_privkey_import_rsa_raw;
352 if (!(pgnutls_privkey_decrypt_data = dlsym( libgnutls_handle, "gnutls_privkey_decrypt_data" )))
354 WARN("gnutls_privkey_decrypt_data not found\n");
355 pgnutls_privkey_decrypt_data = compat_gnutls_privkey_decrypt_data;
358 if (TRACE_ON( bcrypt ))
360 pgnutls_global_set_log_level( 4 );
361 pgnutls_global_set_log_function( gnutls_log );
364 return TRUE;
366 fail:
367 dlclose( libgnutls_handle );
368 libgnutls_handle = NULL;
369 return FALSE;
372 static void gnutls_uninitialize(void)
374 pgnutls_global_deinit();
375 dlclose( libgnutls_handle );
376 libgnutls_handle = NULL;
379 struct buffer
381 BYTE *buffer;
382 DWORD length;
383 DWORD pos;
384 BOOL error;
387 static void buffer_init( struct buffer *buffer )
389 buffer->buffer = NULL;
390 buffer->length = 0;
391 buffer->pos = 0;
392 buffer->error = FALSE;
395 static void buffer_free( struct buffer *buffer )
397 free( buffer->buffer );
400 static void buffer_append( struct buffer *buffer, BYTE *data, DWORD len )
402 if (!len) return;
404 if (buffer->pos + len > buffer->length)
406 DWORD new_length = max( max( buffer->pos + len, buffer->length * 2 ), 64 );
407 BYTE *new_buffer;
409 if (!(new_buffer = realloc( buffer->buffer, new_length )))
411 ERR( "out of memory\n" );
412 buffer->error = TRUE;
413 return;
416 buffer->buffer = new_buffer;
417 buffer->length = new_length;
420 memcpy( &buffer->buffer[buffer->pos], data, len );
421 buffer->pos += len;
424 static void buffer_append_byte( struct buffer *buffer, BYTE value )
426 buffer_append( buffer, &value, sizeof(value) );
429 static void buffer_append_asn1_length( struct buffer *buffer, DWORD length )
431 DWORD num_bytes;
433 if (length < 128)
435 buffer_append_byte( buffer, length );
436 return;
439 if (length <= 0xff) num_bytes = 1;
440 else if (length <= 0xffff) num_bytes = 2;
441 else if (length <= 0xffffff) num_bytes = 3;
442 else num_bytes = 4;
444 buffer_append_byte( buffer, 0x80 | num_bytes );
445 while (num_bytes--) buffer_append_byte( buffer, length >> (num_bytes * 8) );
448 static void buffer_append_asn1_integer( struct buffer *buffer, BYTE *data, DWORD len )
450 DWORD leading_zero = (*data & 0x80) != 0;
452 buffer_append_byte( buffer, 0x02 ); /* tag */
453 buffer_append_asn1_length( buffer, len + leading_zero );
454 if (leading_zero) buffer_append_byte( buffer, 0 );
455 buffer_append( buffer, data, len );
458 static void buffer_append_asn1_sequence( struct buffer *buffer, struct buffer *content )
460 if (content->error)
462 buffer->error = TRUE;
463 return;
466 buffer_append_byte( buffer, 0x30 ); /* tag */
467 buffer_append_asn1_length( buffer, content->pos );
468 buffer_append( buffer, content->buffer, content->pos );
471 static void buffer_append_asn1_r_s( struct buffer *buffer, BYTE *r, DWORD r_len, BYTE *s, DWORD s_len )
473 struct buffer value;
475 buffer_init( &value );
476 buffer_append_asn1_integer( &value, r, r_len );
477 buffer_append_asn1_integer( &value, s, s_len );
478 buffer_append_asn1_sequence( buffer, &value );
479 buffer_free( &value );
482 static NTSTATUS CDECL key_set_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
484 if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
486 if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_ECB ))
488 key->u.s.mode = MODE_ID_ECB;
489 return STATUS_SUCCESS;
491 else if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
493 key->u.s.mode = MODE_ID_CBC;
494 return STATUS_SUCCESS;
496 else if (!strcmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM ))
498 key->u.s.mode = MODE_ID_GCM;
499 return STATUS_SUCCESS;
501 else
503 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
504 return STATUS_NOT_IMPLEMENTED;
508 FIXME( "unsupported key property %s\n", debugstr_w(prop) );
509 return STATUS_NOT_IMPLEMENTED;
512 static NTSTATUS CDECL key_symmetric_init( struct key *key )
514 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
516 switch (key->alg_id)
518 case ALG_ID_3DES:
519 case ALG_ID_AES:
520 return STATUS_SUCCESS;
522 default:
523 FIXME( "algorithm %u not supported\n", key->alg_id );
524 return STATUS_NOT_SUPPORTED;
528 static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
530 switch (key->alg_id)
532 case ALG_ID_3DES:
533 WARN( "handle block size\n" );
534 switch (key->u.s.mode)
536 case MODE_ID_CBC:
537 return GNUTLS_CIPHER_3DES_CBC;
538 default:
539 break;
541 FIXME( "3DES mode %u with key length %u not supported\n", key->u.s.mode, key->u.s.secret_len );
542 return GNUTLS_CIPHER_UNKNOWN;
544 case ALG_ID_AES:
545 WARN( "handle block size\n" );
546 switch (key->u.s.mode)
548 case MODE_ID_GCM:
549 if (key->u.s.secret_len == 16) return GNUTLS_CIPHER_AES_128_GCM;
550 if (key->u.s.secret_len == 32) return GNUTLS_CIPHER_AES_256_GCM;
551 break;
552 case MODE_ID_ECB: /* can be emulated with CBC + empty IV */
553 case MODE_ID_CBC:
554 if (key->u.s.secret_len == 16) return GNUTLS_CIPHER_AES_128_CBC;
555 if (key->u.s.secret_len == 24) return GNUTLS_CIPHER_AES_192_CBC;
556 if (key->u.s.secret_len == 32) return GNUTLS_CIPHER_AES_256_CBC;
557 break;
558 default:
559 break;
561 FIXME( "AES mode %u with key length %u not supported\n", key->u.s.mode, key->u.s.secret_len );
562 return GNUTLS_CIPHER_UNKNOWN;
564 default:
565 FIXME( "algorithm %u not supported\n", key->alg_id );
566 return GNUTLS_CIPHER_UNKNOWN;
570 static void CDECL key_symmetric_vector_reset( struct key *key )
572 if (!key_data(key)->cipher) return;
573 TRACE( "invalidating cipher handle\n" );
574 pgnutls_cipher_deinit( key_data(key)->cipher );
575 key_data(key)->cipher = NULL;
578 static NTSTATUS init_cipher_handle( struct key *key )
580 gnutls_cipher_algorithm_t cipher;
581 gnutls_datum_t secret, vector;
582 int ret;
584 if (key_data(key)->cipher) return STATUS_SUCCESS;
585 if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN) return STATUS_NOT_SUPPORTED;
587 secret.data = key->u.s.secret;
588 secret.size = key->u.s.secret_len;
590 vector.data = key->u.s.vector;
591 vector.size = key->u.s.vector_len;
593 if ((ret = pgnutls_cipher_init( &key_data(key)->cipher, cipher, &secret, key->u.s.vector ? &vector : NULL )))
595 pgnutls_perror( ret );
596 return STATUS_INTERNAL_ERROR;
599 return STATUS_SUCCESS;
602 static NTSTATUS CDECL key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len )
604 NTSTATUS status;
605 int ret;
607 if (!auth_data) return STATUS_SUCCESS;
608 if ((status = init_cipher_handle( key ))) return status;
610 if ((ret = pgnutls_cipher_add_auth( key_data(key)->cipher, auth_data, len )))
612 pgnutls_perror( ret );
613 return STATUS_INTERNAL_ERROR;
615 return STATUS_SUCCESS;
618 static NTSTATUS CDECL key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
620 NTSTATUS status;
621 int ret;
623 if ((status = init_cipher_handle( key ))) return status;
625 if ((ret = pgnutls_cipher_encrypt2( key_data(key)->cipher, input, input_len, output, output_len )))
627 pgnutls_perror( ret );
628 return STATUS_INTERNAL_ERROR;
630 return STATUS_SUCCESS;
633 static NTSTATUS CDECL key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
635 NTSTATUS status;
636 int ret;
638 if ((status = init_cipher_handle( key ))) return status;
640 if ((ret = pgnutls_cipher_decrypt2( key_data(key)->cipher, input, input_len, output, output_len )))
642 pgnutls_perror( ret );
643 return STATUS_INTERNAL_ERROR;
645 return STATUS_SUCCESS;
648 static NTSTATUS CDECL key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
650 NTSTATUS status;
651 int ret;
653 if ((status = init_cipher_handle( key ))) return status;
655 if ((ret = pgnutls_cipher_tag( key_data(key)->cipher, tag, len )))
657 pgnutls_perror( ret );
658 return STATUS_INTERNAL_ERROR;
660 return STATUS_SUCCESS;
663 static void CDECL key_symmetric_destroy( struct key *key )
665 if (key_data(key)->cipher) pgnutls_cipher_deinit( key_data(key)->cipher );
668 static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len )
670 BCRYPT_RSAKEY_BLOB *rsa_blob;
671 gnutls_datum_t m, e;
672 UCHAR *dst, *src;
673 int ret;
675 if ((ret = pgnutls_privkey_export_rsa_raw( gnutls_key, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL )))
677 pgnutls_perror( ret );
678 return STATUS_INTERNAL_ERROR;
681 if (!(rsa_blob = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*rsa_blob) + e.size + m.size )))
683 pgnutls_perror( ret );
684 free( e.data ); free( m.data );
685 return STATUS_NO_MEMORY;
688 dst = (UCHAR *)(rsa_blob + 1);
689 if (e.size == bitlen / 8 + 1 && !e.data[0])
691 src = e.data + 1;
692 e.size--;
694 else src = e.data;
695 memcpy( dst, src, e.size );
697 dst += e.size;
698 if (m.size == bitlen / 8 + 1 && !m.data[0])
700 src = m.data + 1;
701 m.size--;
703 else src = m.data;
704 memcpy( dst, src, m.size );
706 rsa_blob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
707 rsa_blob->BitLength = bitlen;
708 rsa_blob->cbPublicExp = e.size;
709 rsa_blob->cbModulus = m.size;
710 rsa_blob->cbPrime1 = 0;
711 rsa_blob->cbPrime2 = 0;
713 *pubkey = (UCHAR *)rsa_blob;
714 *pubkey_len = sizeof(*rsa_blob) + e.size + m.size;
716 free( e.data ); free( m.data );
717 return STATUS_SUCCESS;
720 static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, enum alg_id alg_id, UCHAR **pubkey,
721 ULONG *pubkey_len )
723 BCRYPT_ECCKEY_BLOB *ecc_blob;
724 gnutls_ecc_curve_t curve;
725 gnutls_datum_t x, y;
726 DWORD magic, size;
727 UCHAR *src, *dst;
728 int ret;
730 switch (alg_id)
732 case ALG_ID_ECDH_P256:
733 magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
734 size = 32;
735 break;
736 case ALG_ID_ECDSA_P256:
737 magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
738 size = 32;
739 break;
740 default:
741 FIXME( "algorithm %u not supported\n", alg_id );
742 return STATUS_NOT_IMPLEMENTED;
745 if ((ret = pgnutls_privkey_export_ecc_raw( gnutls_key, &curve, &x, &y, NULL )))
747 pgnutls_perror( ret );
748 return STATUS_INTERNAL_ERROR;
751 if (curve != GNUTLS_ECC_CURVE_SECP256R1)
753 FIXME( "curve %u not supported\n", curve );
754 free( x.data ); free( y.data );
755 return STATUS_NOT_IMPLEMENTED;
758 if (!(ecc_blob = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ecc_blob) + x.size + y.size )))
760 pgnutls_perror( ret );
761 free( x.data ); free( y.data );
762 return STATUS_NO_MEMORY;
765 ecc_blob->dwMagic = magic;
766 ecc_blob->cbKey = size;
768 dst = (UCHAR *)(ecc_blob + 1);
769 if (x.size == size + 1) src = x.data + 1;
770 else src = x.data;
771 memcpy( dst, src, size );
773 dst += size;
774 if (y.size == size + 1) src = y.data + 1;
775 else src = y.data;
776 memcpy( dst, src, size );
778 *pubkey = (UCHAR *)ecc_blob;
779 *pubkey_len = sizeof(*ecc_blob) + ecc_blob->cbKey * 2;
781 free( x.data ); free( y.data );
782 return STATUS_SUCCESS;
785 static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len )
787 BCRYPT_DSA_KEY_BLOB *dsa_blob;
788 gnutls_datum_t p, q, g, y;
789 UCHAR *dst, *src;
790 int ret;
792 if ((ret = pgnutls_privkey_export_dsa_raw( gnutls_key, &p, &q, &g, &y, NULL )))
794 pgnutls_perror( ret );
795 return STATUS_INTERNAL_ERROR;
798 if (bitlen > 1024)
800 FIXME( "bitlen > 1024 not supported\n" );
801 return STATUS_NOT_IMPLEMENTED;
804 if (!(dsa_blob = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*dsa_blob) + p.size + g.size + y.size )))
806 pgnutls_perror( ret );
807 free( p.data ); free( q.data ); free( g.data ); free( y.data );
808 return STATUS_NO_MEMORY;
811 dst = (UCHAR *)(dsa_blob + 1);
812 if (p.size == bitlen / 8 + 1 && !p.data[0])
814 src = p.data + 1;
815 p.size--;
817 else src = p.data;
818 memcpy( dst, src, p.size );
820 dst += p.size;
821 if (g.size == bitlen / 8 + 1 && !g.data[0])
823 src = g.data + 1;
824 g.size--;
826 else src = g.data;
827 memcpy( dst, src, g.size );
829 dst += g.size;
830 if (y.size == bitlen / 8 + 1 && !y.data[0])
832 src = y.data + 1;
833 y.size--;
835 else src = y.data;
836 memcpy( dst, src, y.size );
838 dst = dsa_blob->q;
839 if (q.size == sizeof(dsa_blob->q) + 1 && !q.data[0])
841 src = q.data + 1;
842 q.size--;
844 else src = q.data;
845 memcpy( dst, src, sizeof(dsa_blob->q) );
847 dsa_blob->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
848 dsa_blob->cbKey = bitlen / 8;
849 memset( dsa_blob->Count, 0, sizeof(dsa_blob->Count) ); /* FIXME */
850 memset( dsa_blob->Seed, 0, sizeof(dsa_blob->Seed) ); /* FIXME */
852 *pubkey = (UCHAR *)dsa_blob;
853 *pubkey_len = sizeof(*dsa_blob) + p.size + g.size + y.size;
855 free( p.data ); free( q.data ); free( g.data ); free( y.data );
856 return STATUS_SUCCESS;
859 static NTSTATUS export_gnutls_pubkey_dsa_capi( gnutls_privkey_t gnutls_key, const DSSSEED *seed, ULONG bitlen,
860 UCHAR **pubkey, ULONG *pubkey_len )
862 BLOBHEADER *hdr;
863 DSSPUBKEY *dsskey;
864 gnutls_datum_t p, q, g, y;
865 UCHAR *dst, *src;
866 int i, ret, size = sizeof(*hdr) + sizeof(*dsskey) + sizeof(*seed);
868 if (bitlen > 1024)
870 FIXME( "bitlen > 1024 not supported\n" );
871 return STATUS_NOT_IMPLEMENTED;
874 if ((ret = pgnutls_privkey_export_dsa_raw( gnutls_key, &p, &q, &g, &y, NULL )))
876 pgnutls_perror( ret );
877 return STATUS_INTERNAL_ERROR;
880 if (!(hdr = RtlAllocateHeap( GetProcessHeap(), 0, size + p.size + q.size + g.size + y.size )))
882 pgnutls_perror( ret );
883 free( p.data ); free( q.data ); free( g.data ); free( y.data );
884 return STATUS_NO_MEMORY;
887 hdr->bType = PUBLICKEYBLOB;
888 hdr->bVersion = 2;
889 hdr->reserved = 0;
890 hdr->aiKeyAlg = CALG_DSS_SIGN;
892 dsskey = (DSSPUBKEY *)(hdr + 1);
893 dsskey->magic = MAGIC_DSS1;
894 dsskey->bitlen = bitlen;
896 dst = (UCHAR *)(dsskey + 1);
897 if (p.size % 2)
899 src = p.data + 1;
900 p.size--;
902 else src = p.data;
903 for (i = 0; i < p.size; i++) dst[i] = src[p.size - i - 1];
905 dst += p.size;
906 if (q.size % 2)
908 src = q.data + 1;
909 q.size--;
911 else src = q.data;
912 for (i = 0; i < q.size; i++) dst[i] = src[q.size - i - 1];
914 dst += q.size;
915 if (g.size % 2)
917 src = g.data + 1;
918 g.size--;
920 else src = g.data;
921 for (i = 0; i < g.size; i++) dst[i] = src[g.size - i - 1];
923 dst += g.size;
924 if (y.size % 2)
926 src = y.data + 1;
927 y.size--;
929 else src = y.data;
930 for (i = 0; i < y.size; i++) dst[i] = src[y.size - i - 1];
932 dst += y.size;
933 memcpy( dst, seed, sizeof(*seed) );
935 *pubkey = (UCHAR *)hdr;
936 *pubkey_len = size + p.size + q.size + g.size + y.size;
938 free( p.data ); free( q.data ); free( g.data ); free( y.data );
939 return STATUS_SUCCESS;
942 static NTSTATUS CDECL key_asymmetric_generate( struct key *key )
944 gnutls_pk_algorithm_t pk_alg;
945 gnutls_privkey_t handle;
946 unsigned int bitlen;
947 NTSTATUS status;
948 int ret;
950 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
952 switch (key->alg_id)
954 case ALG_ID_RSA:
955 case ALG_ID_RSA_SIGN:
956 pk_alg = GNUTLS_PK_RSA;
957 bitlen = key->u.a.bitlen;
958 break;
960 case ALG_ID_DSA:
961 pk_alg = GNUTLS_PK_DSA;
962 bitlen = key->u.a.bitlen;
963 break;
965 case ALG_ID_ECDH_P256:
966 case ALG_ID_ECDSA_P256:
967 pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */
968 bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 );
969 break;
971 default:
972 FIXME( "algorithm %u not supported\n", key->alg_id );
973 return STATUS_NOT_SUPPORTED;
976 if ((ret = pgnutls_privkey_init( &handle )))
978 pgnutls_perror( ret );
979 return STATUS_INTERNAL_ERROR;
982 if ((ret = pgnutls_privkey_generate( handle, pk_alg, bitlen, 0 )))
984 pgnutls_perror( ret );
985 pgnutls_privkey_deinit( handle );
986 return STATUS_INTERNAL_ERROR;
989 switch (pk_alg)
991 case GNUTLS_PK_RSA:
992 status = export_gnutls_pubkey_rsa( handle, key->u.a.bitlen, &key->u.a.pubkey, &key->u.a.pubkey_len );
993 break;
995 case GNUTLS_PK_ECC:
996 status = export_gnutls_pubkey_ecc( handle, key->alg_id, &key->u.a.pubkey, &key->u.a.pubkey_len );
997 break;
999 case GNUTLS_PK_DSA:
1000 status = export_gnutls_pubkey_dsa( handle, key->u.a.bitlen, &key->u.a.pubkey, &key->u.a.pubkey_len );
1001 break;
1003 default:
1004 ERR( "unhandled algorithm %u\n", pk_alg );
1005 return STATUS_INTERNAL_ERROR;
1008 if (status)
1010 pgnutls_privkey_deinit( handle );
1011 return status;
1014 key_data(key)->privkey = handle;
1015 return STATUS_SUCCESS;
1018 static NTSTATUS CDECL key_export_ecc( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
1020 BCRYPT_ECCKEY_BLOB *ecc_blob;
1021 gnutls_ecc_curve_t curve;
1022 gnutls_datum_t x, y, d;
1023 DWORD magic, size;
1024 UCHAR *src, *dst;
1025 int ret;
1027 switch (key->alg_id)
1029 case ALG_ID_ECDH_P256:
1030 magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
1031 size = 32;
1032 break;
1033 case ALG_ID_ECDSA_P256:
1034 magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC;
1035 size = 32;
1036 break;
1038 default:
1039 FIXME( "algorithm %u does not yet support exporting ecc blob\n", key->alg_id );
1040 return STATUS_NOT_IMPLEMENTED;
1043 if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key)->privkey, &curve, &x, &y, &d )))
1045 pgnutls_perror( ret );
1046 return STATUS_INTERNAL_ERROR;
1049 if (curve != GNUTLS_ECC_CURVE_SECP256R1)
1051 FIXME( "curve %u not supported\n", curve );
1052 free( x.data ); free( y.data ); free( d.data );
1053 return STATUS_NOT_IMPLEMENTED;
1056 *ret_len = sizeof(*ecc_blob) + size * 3;
1057 if (len >= *ret_len && buf)
1059 ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf;
1060 ecc_blob->dwMagic = magic;
1061 ecc_blob->cbKey = size;
1063 dst = (UCHAR *)(ecc_blob + 1);
1064 if (x.size == size + 1) src = x.data + 1;
1065 else src = x.data;
1066 memcpy( dst, src, size );
1068 dst += size;
1069 if (y.size == size + 1) src = y.data + 1;
1070 else src = y.data;
1071 memcpy( dst, src, size );
1073 dst += size;
1074 if (d.size == size + 1) src = d.data + 1;
1075 else src = d.data;
1076 memcpy( dst, src, size );
1079 free( x.data ); free( y.data ); free( d.data );
1080 return STATUS_SUCCESS;
1083 static NTSTATUS CDECL key_import_ecc( struct key *key, UCHAR *buf, ULONG len )
1085 BCRYPT_ECCKEY_BLOB *ecc_blob;
1086 gnutls_ecc_curve_t curve;
1087 gnutls_privkey_t handle;
1088 gnutls_datum_t x, y, k;
1089 NTSTATUS status;
1090 int ret;
1092 switch (key->alg_id)
1094 case ALG_ID_ECDH_P256:
1095 case ALG_ID_ECDSA_P256:
1096 curve = GNUTLS_ECC_CURVE_SECP256R1;
1097 break;
1099 default:
1100 FIXME( "algorithm %u not yet supported\n", key->alg_id );
1101 return STATUS_NOT_IMPLEMENTED;
1104 if ((ret = pgnutls_privkey_init( &handle )))
1106 pgnutls_perror( ret );
1107 return STATUS_INTERNAL_ERROR;
1110 ecc_blob = (BCRYPT_ECCKEY_BLOB *)buf;
1111 x.data = (unsigned char *)(ecc_blob + 1);
1112 x.size = ecc_blob->cbKey;
1113 y.data = x.data + ecc_blob->cbKey;
1114 y.size = ecc_blob->cbKey;
1115 k.data = y.data + ecc_blob->cbKey;
1116 k.size = ecc_blob->cbKey;
1118 if ((ret = pgnutls_privkey_import_ecc_raw( handle, curve, &x, &y, &k )))
1120 pgnutls_perror( ret );
1121 pgnutls_privkey_deinit( handle );
1122 return STATUS_INTERNAL_ERROR;
1125 if ((status = export_gnutls_pubkey_ecc( handle, key->alg_id, &key->u.a.pubkey, &key->u.a.pubkey_len )))
1127 pgnutls_privkey_deinit( handle );
1128 return status;
1131 key_data(key)->privkey = handle;
1132 return STATUS_SUCCESS;
1135 static NTSTATUS CDECL key_import_rsa( struct key *key, UCHAR *buf, ULONG len )
1137 BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)buf;
1138 gnutls_datum_t m, e, p, q;
1139 gnutls_privkey_t handle;
1140 int ret;
1142 if ((ret = pgnutls_privkey_init( &handle )))
1144 pgnutls_perror( ret );
1145 return STATUS_INTERNAL_ERROR;
1148 e.data = (unsigned char *)(rsa_blob + 1);
1149 e.size = rsa_blob->cbPublicExp;
1150 m.data = e.data + e.size;
1151 m.size = rsa_blob->cbModulus;
1152 p.data = m.data + m.size;
1153 p.size = rsa_blob->cbPrime1;
1154 q.data = p.data + p.size;
1155 q.size = rsa_blob->cbPrime2;
1157 if ((ret = pgnutls_privkey_import_rsa_raw( handle, &m, &e, NULL, &p, &q, NULL, NULL, NULL )))
1159 pgnutls_perror( ret );
1160 pgnutls_privkey_deinit( handle );
1161 return STATUS_INTERNAL_ERROR;
1164 key_data(key)->privkey = handle;
1165 return STATUS_SUCCESS;
1168 static NTSTATUS CDECL key_export_dsa_capi( struct key *key, UCHAR *buf, ULONG len, ULONG *ret_len )
1170 BLOBHEADER *hdr;
1171 DSSPUBKEY *pubkey;
1172 gnutls_datum_t p, q, g, y, x;
1173 UCHAR *src, *dst;
1174 int i, ret, size;
1176 if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key)->privkey, &p, &q, &g, &y, &x )))
1178 pgnutls_perror( ret );
1179 return STATUS_INTERNAL_ERROR;
1182 if ((q.size != 20 && q.size != 21) || (x.size != 20 && x.size != 21))
1184 ERR( "can't export key in this format\n" );
1185 free( p.data ); free( q.data ); free( g.data ); free( y.data ); free( x.data );
1186 return STATUS_NOT_SUPPORTED;
1189 size = key->u.a.bitlen / 8;
1190 *ret_len = sizeof(*hdr) + sizeof(*pubkey) + size * 2 + 40 + sizeof(key->u.a.dss_seed);
1191 if (len >= *ret_len && buf)
1193 hdr = (BLOBHEADER *)buf;
1194 hdr->bType = PRIVATEKEYBLOB;
1195 hdr->bVersion = 2;
1196 hdr->reserved = 0;
1197 hdr->aiKeyAlg = CALG_DSS_SIGN;
1199 pubkey = (DSSPUBKEY *)(hdr + 1);
1200 pubkey->magic = MAGIC_DSS2;
1201 pubkey->bitlen = key->u.a.bitlen;
1203 dst = (UCHAR *)(pubkey + 1);
1204 if (p.size % 2) src = p.data + 1;
1205 else src = p.data;
1206 for (i = 0; i < size; i++) dst[i] = src[size - i - 1];
1208 dst += size;
1209 if (q.size % 2) src = q.data + 1;
1210 else src = q.data;
1211 for (i = 0; i < 20; i++) dst[i] = src[20 - i - 1];
1213 dst += 20;
1214 if (g.size % 2) src = g.data + 1;
1215 else src = g.data;
1216 for (i = 0; i < size; i++) dst[i] = src[size - i - 1];
1218 dst += size;
1219 if (x.size % 2) src = x.data + 1;
1220 else src = x.data;
1221 for (i = 0; i < 20; i++) dst[i] = src[20 - i - 1];
1223 dst += 20;
1224 memcpy( dst, &key->u.a.dss_seed, sizeof(key->u.a.dss_seed) );
1227 free( p.data ); free( q.data ); free( g.data ); free( y.data ); free( x.data );
1228 return STATUS_SUCCESS;
1231 static NTSTATUS CDECL key_import_dsa_capi( struct key *key, UCHAR *buf, ULONG len )
1233 BLOBHEADER *hdr = (BLOBHEADER *)buf;
1234 DSSPUBKEY *pubkey;
1235 gnutls_privkey_t handle;
1236 gnutls_datum_t p, q, g, y, x;
1237 unsigned char dummy[128];
1238 unsigned char *data, p_data[128], q_data[20], g_data[128], x_data[20];
1239 int i, ret, size;
1240 NTSTATUS status;
1242 if ((ret = pgnutls_privkey_init( &handle )))
1244 pgnutls_perror( ret );
1245 return STATUS_INTERNAL_ERROR;
1248 hdr = (BLOBHEADER *)buf;
1249 pubkey = (DSSPUBKEY *)(hdr + 1);
1250 if ((size = pubkey->bitlen / 8) > sizeof(p_data))
1252 FIXME( "size %u not supported\n", size );
1253 pgnutls_privkey_deinit( handle );
1254 return STATUS_NOT_SUPPORTED;
1256 data = (unsigned char *)(pubkey + 1);
1258 p.data = p_data;
1259 p.size = size;
1260 for (i = 0; i < p.size; i++) p.data[i] = data[p.size - i - 1];
1261 data += p.size;
1263 q.data = q_data;
1264 q.size = sizeof(q_data);
1265 for (i = 0; i < q.size; i++) q.data[i] = data[q.size - i - 1];
1266 data += q.size;
1268 g.data = g_data;
1269 g.size = size;
1270 for (i = 0; i < g.size; i++) g.data[i] = data[g.size - i - 1];
1271 data += g.size;
1273 x.data = x_data;
1274 x.size = sizeof(x_data);
1275 for (i = 0; i < x.size; i++) x.data[i] = data[x.size - i - 1];
1276 data += x.size;
1278 WARN( "using dummy public key\n" );
1279 memset( dummy, 1, sizeof(dummy) );
1280 y.data = dummy;
1281 y.size = min( p.size, sizeof(dummy) );
1283 if ((ret = pgnutls_privkey_import_dsa_raw( handle, &p, &q, &g, &y, &x )))
1285 pgnutls_perror( ret );
1286 pgnutls_privkey_deinit( handle );
1287 return STATUS_INTERNAL_ERROR;
1290 if ((status = export_gnutls_pubkey_dsa_capi( handle, &key->u.a.dss_seed, key->u.a.bitlen, &key->u.a.pubkey,
1291 &key->u.a.pubkey_len )))
1293 pgnutls_privkey_deinit( handle );
1294 return status;
1297 memcpy( &key->u.a.dss_seed, data, sizeof(key->u.a.dss_seed) );
1299 key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
1300 key_data(key)->privkey = handle;
1302 return STATUS_SUCCESS;
1305 static NTSTATUS CDECL key_asymmetric_init( struct key *key )
1307 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
1309 switch (key->alg_id)
1311 case ALG_ID_ECDH_P256:
1312 case ALG_ID_ECDSA_P256:
1313 case ALG_ID_ECDSA_P384:
1314 case ALG_ID_RSA:
1315 case ALG_ID_RSA_SIGN:
1316 case ALG_ID_DSA:
1317 return STATUS_SUCCESS;
1319 default:
1320 FIXME( "algorithm %u not supported\n", key->alg_id );
1321 return STATUS_NOT_SUPPORTED;
1325 static NTSTATUS import_gnutls_pubkey_ecc( struct key *key, gnutls_pubkey_t *gnutls_key )
1327 BCRYPT_ECCKEY_BLOB *ecc_blob;
1328 gnutls_ecc_curve_t curve;
1329 gnutls_datum_t x, y;
1330 int ret;
1332 switch (key->alg_id)
1334 case ALG_ID_ECDSA_P256: curve = GNUTLS_ECC_CURVE_SECP256R1; break;
1335 case ALG_ID_ECDSA_P384: curve = GNUTLS_ECC_CURVE_SECP384R1; break;
1337 default:
1338 FIXME( "algorithm %u not yet supported\n", key->alg_id );
1339 return STATUS_NOT_IMPLEMENTED;
1342 if ((ret = pgnutls_pubkey_init( gnutls_key )))
1344 pgnutls_perror( ret );
1345 return STATUS_INTERNAL_ERROR;
1348 ecc_blob = (BCRYPT_ECCKEY_BLOB *)key->u.a.pubkey;
1349 x.data = key->u.a.pubkey + sizeof(*ecc_blob);
1350 x.size = ecc_blob->cbKey;
1351 y.data = key->u.a.pubkey + sizeof(*ecc_blob) + ecc_blob->cbKey;
1352 y.size = ecc_blob->cbKey;
1354 if ((ret = pgnutls_pubkey_import_ecc_raw( *gnutls_key, curve, &x, &y )))
1356 pgnutls_perror( ret );
1357 pgnutls_pubkey_deinit( *gnutls_key );
1358 return STATUS_INTERNAL_ERROR;
1361 return STATUS_SUCCESS;
1364 static NTSTATUS import_gnutls_pubkey_rsa( struct key *key, gnutls_pubkey_t *gnutls_key )
1366 BCRYPT_RSAKEY_BLOB *rsa_blob;
1367 gnutls_datum_t m, e;
1368 int ret;
1370 if ((ret = pgnutls_pubkey_init( gnutls_key )))
1372 pgnutls_perror( ret );
1373 return STATUS_INTERNAL_ERROR;
1376 rsa_blob = (BCRYPT_RSAKEY_BLOB *)key->u.a.pubkey;
1377 e.data = key->u.a.pubkey + sizeof(*rsa_blob);
1378 e.size = rsa_blob->cbPublicExp;
1379 m.data = key->u.a.pubkey + sizeof(*rsa_blob) + rsa_blob->cbPublicExp;
1380 m.size = rsa_blob->cbModulus;
1382 if ((ret = pgnutls_pubkey_import_rsa_raw( *gnutls_key, &m, &e )))
1384 pgnutls_perror( ret );
1385 pgnutls_pubkey_deinit( *gnutls_key );
1386 return STATUS_INTERNAL_ERROR;
1389 return STATUS_SUCCESS;
1392 static NTSTATUS import_gnutls_pubkey_dsa( struct key *key, gnutls_pubkey_t *gnutls_key )
1394 BCRYPT_DSA_KEY_BLOB *dsa_blob;
1395 gnutls_datum_t p, q, g, y;
1396 int ret;
1398 if ((ret = pgnutls_pubkey_init( gnutls_key )))
1400 pgnutls_perror( ret );
1401 return STATUS_INTERNAL_ERROR;
1404 dsa_blob = (BCRYPT_DSA_KEY_BLOB *)key->u.a.pubkey;
1405 p.data = key->u.a.pubkey + sizeof(*dsa_blob);
1406 p.size = dsa_blob->cbKey;
1407 q.data = dsa_blob->q;
1408 q.size = sizeof(dsa_blob->q);
1409 g.data = key->u.a.pubkey + sizeof(*dsa_blob) + dsa_blob->cbKey;
1410 g.size = dsa_blob->cbKey;
1411 y.data = key->u.a.pubkey + sizeof(*dsa_blob) + dsa_blob->cbKey * 2;
1412 y.size = dsa_blob->cbKey;
1414 if ((ret = pgnutls_pubkey_import_dsa_raw( *gnutls_key, &p, &q, &g, &y )))
1416 pgnutls_perror( ret );
1417 pgnutls_pubkey_deinit( *gnutls_key );
1418 return STATUS_INTERNAL_ERROR;
1421 return STATUS_SUCCESS;
1424 static NTSTATUS import_gnutls_pubkey_dsa_capi( struct key *key, gnutls_pubkey_t *gnutls_key )
1426 BLOBHEADER *hdr;
1427 DSSPUBKEY *pubkey;
1428 gnutls_datum_t p, q, g, y;
1429 unsigned char *data, p_data[128], q_data[20], g_data[128], y_data[128];
1430 int i, ret, size;
1432 if ((ret = pgnutls_pubkey_init( gnutls_key )))
1434 pgnutls_perror( ret );
1435 return STATUS_INTERNAL_ERROR;
1438 hdr = (BLOBHEADER *)key->u.a.pubkey;
1439 pubkey = (DSSPUBKEY *)(hdr + 1);
1440 size = pubkey->bitlen / 8;
1441 data = (unsigned char *)(pubkey + 1);
1443 p.data = p_data;
1444 p.size = size;
1445 for (i = 0; i < p.size; i++) p.data[i] = data[p.size - i - 1];
1446 data += p.size;
1448 q.data = q_data;
1449 q.size = sizeof(q_data);
1450 for (i = 0; i < q.size; i++) q.data[i] = data[q.size - i - 1];
1451 data += q.size;
1453 g.data = g_data;
1454 g.size = size;
1455 for (i = 0; i < g.size; i++) g.data[i] = data[g.size - i - 1];
1456 data += g.size;
1458 y.data = y_data;
1459 y.size = sizeof(y_data);
1460 for (i = 0; i < y.size; i++) y.data[i] = data[y.size - i - 1];
1462 if ((ret = pgnutls_pubkey_import_dsa_raw( *gnutls_key, &p, &q, &g, &y )))
1464 pgnutls_perror( ret );
1465 pgnutls_pubkey_deinit( *gnutls_key );
1466 return STATUS_INTERNAL_ERROR;
1469 return STATUS_SUCCESS;
1472 static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_key )
1474 switch (key->alg_id)
1476 case ALG_ID_ECDSA_P256:
1477 case ALG_ID_ECDSA_P384:
1478 return import_gnutls_pubkey_ecc( key, gnutls_key );
1480 case ALG_ID_RSA:
1481 case ALG_ID_RSA_SIGN:
1482 return import_gnutls_pubkey_rsa( key, gnutls_key );
1484 case ALG_ID_DSA:
1485 if (key->u.a.flags & KEY_FLAG_LEGACY_DSA_V2)
1486 return import_gnutls_pubkey_dsa_capi( key, gnutls_key );
1487 else
1488 return import_gnutls_pubkey_dsa( key, gnutls_key );
1490 default:
1491 FIXME("algorithm %u not yet supported\n", key->alg_id );
1492 return STATUS_NOT_IMPLEMENTED;
1496 static NTSTATUS prepare_gnutls_signature_dsa( struct key *key, UCHAR *signature, ULONG signature_len,
1497 gnutls_datum_t *gnutls_signature )
1499 struct buffer buffer;
1500 DWORD r_len = signature_len / 2;
1501 DWORD s_len = r_len;
1502 BYTE *r = signature;
1503 BYTE *s = signature + r_len;
1505 buffer_init( &buffer );
1506 buffer_append_asn1_r_s( &buffer, r, r_len, s, s_len );
1507 if (buffer.error)
1509 buffer_free( &buffer );
1510 return STATUS_NO_MEMORY;
1513 gnutls_signature->data = buffer.buffer;
1514 gnutls_signature->size = buffer.pos;
1515 return STATUS_SUCCESS;
1518 static NTSTATUS prepare_gnutls_signature_rsa( struct key *key, UCHAR *signature, ULONG signature_len,
1519 gnutls_datum_t *gnutls_signature )
1521 gnutls_signature->data = signature;
1522 gnutls_signature->size = signature_len;
1523 return STATUS_SUCCESS;
1526 static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULONG signature_len,
1527 gnutls_datum_t *gnutls_signature )
1529 switch (key->alg_id)
1531 case ALG_ID_ECDSA_P256:
1532 case ALG_ID_ECDSA_P384:
1533 case ALG_ID_DSA:
1534 return prepare_gnutls_signature_dsa( key, signature, signature_len, gnutls_signature );
1536 case ALG_ID_RSA:
1537 case ALG_ID_RSA_SIGN:
1538 return prepare_gnutls_signature_rsa( key, signature, signature_len, gnutls_signature );
1540 default:
1541 FIXME( "algorithm %u not yet supported\n", key->alg_id );
1542 return STATUS_NOT_IMPLEMENTED;
1546 static gnutls_digest_algorithm_t get_digest_from_id( const WCHAR *alg_id )
1548 if (!strcmpW( alg_id, BCRYPT_SHA1_ALGORITHM )) return GNUTLS_DIG_SHA1;
1549 if (!strcmpW( alg_id, BCRYPT_SHA256_ALGORITHM )) return GNUTLS_DIG_SHA256;
1550 if (!strcmpW( alg_id, BCRYPT_SHA384_ALGORITHM )) return GNUTLS_DIG_SHA384;
1551 if (!strcmpW( alg_id, BCRYPT_SHA512_ALGORITHM )) return GNUTLS_DIG_SHA512;
1552 if (!strcmpW( alg_id, BCRYPT_MD2_ALGORITHM )) return GNUTLS_DIG_MD2;
1553 if (!strcmpW( alg_id, BCRYPT_MD5_ALGORITHM )) return GNUTLS_DIG_MD5;
1554 return -1;
1557 static NTSTATUS CDECL key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len,
1558 UCHAR *signature, ULONG signature_len, DWORD flags )
1560 gnutls_digest_algorithm_t hash_alg;
1561 gnutls_sign_algorithm_t sign_alg;
1562 gnutls_datum_t gnutls_hash, gnutls_signature;
1563 gnutls_pk_algorithm_t pk_alg;
1564 gnutls_pubkey_t gnutls_key;
1565 NTSTATUS status;
1566 int ret;
1568 switch (key->alg_id)
1570 case ALG_ID_ECDSA_P256:
1571 case ALG_ID_ECDSA_P384:
1573 if (flags) FIXME( "flags %08x not supported\n", flags );
1575 /* only the hash size must match, not the actual hash function */
1576 switch (hash_len)
1578 case 20: hash_alg = GNUTLS_DIG_SHA1; break;
1579 case 32: hash_alg = GNUTLS_DIG_SHA256; break;
1580 case 48: hash_alg = GNUTLS_DIG_SHA384; break;
1582 default:
1583 FIXME( "hash size %u not yet supported\n", hash_len );
1584 return STATUS_INVALID_SIGNATURE;
1586 pk_alg = GNUTLS_PK_ECC;
1587 break;
1589 case ALG_ID_RSA:
1590 case ALG_ID_RSA_SIGN:
1592 BCRYPT_PKCS1_PADDING_INFO *info = (BCRYPT_PKCS1_PADDING_INFO *)padding;
1594 if (!(flags & BCRYPT_PAD_PKCS1) || !info) return STATUS_INVALID_PARAMETER;
1595 if (!info->pszAlgId) return STATUS_INVALID_SIGNATURE;
1597 if ((hash_alg = get_digest_from_id(info->pszAlgId)) == -1)
1599 FIXME( "hash algorithm %s not supported\n", debugstr_w(info->pszAlgId) );
1600 return STATUS_NOT_SUPPORTED;
1602 pk_alg = GNUTLS_PK_RSA;
1603 break;
1605 case ALG_ID_DSA:
1607 if (flags) FIXME( "flags %08x not supported\n", flags );
1608 if (hash_len != 20)
1610 FIXME( "hash size %u not supported\n", hash_len );
1611 return STATUS_INVALID_PARAMETER;
1613 hash_alg = GNUTLS_DIG_SHA1;
1614 pk_alg = GNUTLS_PK_DSA;
1615 break;
1617 default:
1618 FIXME( "algorithm %u not yet supported\n", key->alg_id );
1619 return STATUS_NOT_IMPLEMENTED;
1622 if ((sign_alg = pgnutls_pk_to_sign( pk_alg, hash_alg )) == GNUTLS_SIGN_UNKNOWN)
1624 FIXME("GnuTLS does not support algorithm %u with hash len %u\n", key->alg_id, hash_len );
1625 return STATUS_NOT_IMPLEMENTED;
1628 if ((status = import_gnutls_pubkey( key, &gnutls_key ))) return status;
1629 if ((status = prepare_gnutls_signature( key, signature, signature_len, &gnutls_signature )))
1631 pgnutls_pubkey_deinit( gnutls_key );
1632 return status;
1635 gnutls_hash.data = hash;
1636 gnutls_hash.size = hash_len;
1637 ret = pgnutls_pubkey_verify_hash2( gnutls_key, sign_alg, 0, &gnutls_hash, &gnutls_signature );
1639 if (gnutls_signature.data != signature) free( gnutls_signature.data );
1640 pgnutls_pubkey_deinit( gnutls_key );
1641 return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS;
1644 static unsigned int get_signature_length( enum alg_id id )
1646 switch (id)
1648 case ALG_ID_ECDSA_P256: return 64;
1649 case ALG_ID_ECDSA_P384: return 96;
1650 case ALG_ID_DSA: return 40;
1651 default:
1652 FIXME( "unhandled algorithm %u\n", id );
1653 return 0;
1657 static NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signature,
1658 UCHAR *output, ULONG output_len, ULONG *ret_len )
1660 switch (type)
1662 case ALG_ID_RSA:
1663 case ALG_ID_RSA_SIGN:
1665 *ret_len = signature.size;
1666 if (output_len < signature.size) return STATUS_BUFFER_TOO_SMALL;
1667 if (output) memcpy( output, signature.data, signature.size );
1668 return STATUS_SUCCESS;
1670 case ALG_ID_ECDSA_P256:
1671 case ALG_ID_ECDSA_P384:
1672 case ALG_ID_DSA:
1674 int err;
1675 unsigned int pad_size_r, pad_size_s, sig_len = get_signature_length( type );
1676 gnutls_datum_t r, s; /* format as r||s */
1677 unsigned char *r_data, *s_data;
1679 if ((err = pgnutls_decode_rs_value( &signature, &r, &s )))
1681 pgnutls_perror( err );
1682 return STATUS_INTERNAL_ERROR;
1685 *ret_len = sig_len;
1686 if (output_len < sig_len) return STATUS_BUFFER_TOO_SMALL;
1688 if (r.size % 2) /* remove prepended zero byte */
1690 r.size--;
1691 r_data = r.data + 1;
1693 else r_data = r.data;
1695 if (s.size % 2)
1697 s.size--;
1698 s_data = s.data + 1;
1700 else s_data = s.data;
1702 if (r.size + s.size > sig_len)
1704 ERR( "we didn't get a correct signature\n" );
1705 return STATUS_INTERNAL_ERROR;
1708 if (output)
1710 pad_size_r = (sig_len / 2) - r.size;
1711 pad_size_s = (sig_len / 2) - s.size;
1712 memset( output, 0, sig_len );
1714 memcpy( output + pad_size_r, r_data, r.size );
1715 memcpy( output + (sig_len / 2) + pad_size_s, s_data, s.size );
1718 free( r.data ); free( s.data );
1719 return STATUS_SUCCESS;
1721 default:
1722 return STATUS_INTERNAL_ERROR;
1726 static NTSTATUS CDECL key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
1727 ULONG output_len, ULONG *ret_len, ULONG flags )
1729 BCRYPT_PKCS1_PADDING_INFO *pad = padding;
1730 gnutls_datum_t hash, signature;
1731 gnutls_digest_algorithm_t hash_alg;
1732 NTSTATUS status;
1733 int ret;
1735 if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384)
1737 /* With ECDSA, we find the digest algorithm from the hash length, and verify it */
1738 switch (input_len)
1740 case 20: hash_alg = GNUTLS_DIG_SHA1; break;
1741 case 32: hash_alg = GNUTLS_DIG_SHA256; break;
1742 case 48: hash_alg = GNUTLS_DIG_SHA384; break;
1743 case 64: hash_alg = GNUTLS_DIG_SHA512; break;
1745 default:
1746 FIXME( "hash size %u not yet supported\n", input_len );
1747 return STATUS_INVALID_PARAMETER;
1750 if (flags == BCRYPT_PAD_PKCS1 && pad && pad->pszAlgId && get_digest_from_id( pad->pszAlgId ) != hash_alg)
1752 WARN( "incorrect hashing algorithm %s, expected %u\n", debugstr_w(pad->pszAlgId), hash_alg );
1753 return STATUS_INVALID_PARAMETER;
1756 else if (key->alg_id == ALG_ID_DSA)
1758 if (flags) FIXME( "flags %08x not supported\n", flags );
1759 if (input_len != 20)
1761 FIXME( "hash size %u not supported\n", input_len );
1762 return STATUS_INVALID_PARAMETER;
1764 hash_alg = GNUTLS_DIG_SHA1;
1766 else if (flags == BCRYPT_PAD_PKCS1)
1768 if (!pad || !pad->pszAlgId)
1770 WARN( "padding info not found\n" );
1771 return STATUS_INVALID_PARAMETER;
1774 if ((hash_alg = get_digest_from_id( pad->pszAlgId )) == -1)
1776 FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
1777 return STATUS_NOT_SUPPORTED;
1780 else if (!flags)
1782 WARN( "invalid flags %08x\n", flags );
1783 return STATUS_INVALID_PARAMETER;
1785 else
1787 FIXME( "flags %08x not implemented\n", flags );
1788 return STATUS_NOT_IMPLEMENTED;
1791 if (!input)
1793 *ret_len = key->u.a.bitlen / 8;
1794 return STATUS_SUCCESS;
1796 if (!key_data(key)->privkey) return STATUS_INVALID_PARAMETER;
1798 hash.data = input;
1799 hash.size = input_len;
1801 signature.data = NULL;
1802 signature.size = 0;
1804 if ((ret = pgnutls_privkey_sign_hash( key_data(key)->privkey, hash_alg, 0, &hash, &signature )))
1806 pgnutls_perror( ret );
1807 return STATUS_INTERNAL_ERROR;
1810 status = format_gnutls_signature( key->alg_id, signature, output, output_len, ret_len );
1812 free( signature.data );
1813 return status;
1816 static void CDECL key_asymmetric_destroy( struct key *key )
1818 if (key_data(key)->privkey) pgnutls_privkey_deinit( key_data(key)->privkey );
1821 static NTSTATUS CDECL key_asymmetric_duplicate( struct key *key_orig, struct key *key_copy )
1823 int ret;
1825 if (!key_data(key_orig)->privkey) return STATUS_SUCCESS;
1827 if ((ret = pgnutls_privkey_init( &key_data(key_copy)->privkey )))
1829 pgnutls_perror( ret );
1830 return STATUS_INTERNAL_ERROR;
1833 switch (key_orig->alg_id)
1835 case ALG_ID_RSA:
1836 case ALG_ID_RSA_SIGN:
1838 gnutls_datum_t m, e, d, p, q, u, e1, e2;
1839 if ((ret = pgnutls_privkey_export_rsa_raw( key_data(key_orig)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 )))
1841 pgnutls_perror( ret );
1842 return STATUS_INTERNAL_ERROR;
1844 ret = pgnutls_privkey_import_rsa_raw( key_data(key_copy)->privkey, &m, &e, &d, &p, &q, &u, &e1, &e2 );
1845 free( m.data ); free( e.data ); free( d.data ); free( p.data ); free( q.data ); free( u.data );
1846 free( e1.data ); free( e2.data );
1847 if (ret)
1849 pgnutls_perror( ret );
1850 return STATUS_INTERNAL_ERROR;
1852 break;
1854 case ALG_ID_DSA:
1856 gnutls_datum_t p, q, g, y, x;
1857 if ((ret = pgnutls_privkey_export_dsa_raw( key_data(key_orig)->privkey, &p, &q, &g, &y, &x )))
1859 pgnutls_perror( ret );
1860 return STATUS_INTERNAL_ERROR;
1862 ret = pgnutls_privkey_import_dsa_raw( key_data(key_copy)->privkey, &p, &q, &g, &y, &x );
1863 free( p.data ); free( q.data ); free( g.data ); free( y.data ); free( x.data );
1864 if (ret)
1866 pgnutls_perror( ret );
1867 return STATUS_INTERNAL_ERROR;
1869 break;
1871 case ALG_ID_ECDH_P256:
1872 case ALG_ID_ECDSA_P256:
1873 case ALG_ID_ECDSA_P384:
1875 gnutls_ecc_curve_t curve;
1876 gnutls_datum_t x, y, k;
1877 if ((ret = pgnutls_privkey_export_ecc_raw( key_data(key_orig)->privkey, &curve, &x, &y, &k )))
1879 pgnutls_perror( ret );
1880 return STATUS_INTERNAL_ERROR;
1882 ret = pgnutls_privkey_import_ecc_raw( key_data(key_copy)->privkey, curve, &x, &y, &k );
1883 free( x.data ); free( y.data ); free( k.data );
1884 if (ret)
1886 pgnutls_perror( ret );
1887 return STATUS_INTERNAL_ERROR;
1889 break;
1891 default:
1892 ERR( "unhandled algorithm %u\n", key_orig->alg_id );
1893 return STATUS_INTERNAL_ERROR;
1896 return STATUS_SUCCESS;
1899 static NTSTATUS CDECL key_asymmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len,
1900 UCHAR *output, ULONG *output_len )
1902 gnutls_datum_t e, d = { 0 };
1903 NTSTATUS status = STATUS_SUCCESS;
1904 int ret;
1906 e.data = (unsigned char *)input;
1907 e.size = input_len;
1909 if ((ret = pgnutls_privkey_decrypt_data( key_data(key)->privkey, 0, &e, &d )))
1911 pgnutls_perror( ret );
1912 return STATUS_INTERNAL_ERROR;
1915 if (*output_len >= d.size)
1917 *output_len = d.size;
1918 memcpy( output, d.data, *output_len );
1920 else
1921 status = STATUS_BUFFER_TOO_SMALL;
1923 free( d.data );
1925 return status;
1928 static const struct key_funcs key_funcs =
1930 key_set_property,
1931 key_symmetric_init,
1932 key_symmetric_vector_reset,
1933 key_symmetric_set_auth_data,
1934 key_symmetric_encrypt,
1935 key_symmetric_decrypt,
1936 key_symmetric_get_tag,
1937 key_symmetric_destroy,
1938 key_asymmetric_init,
1939 key_asymmetric_generate,
1940 key_asymmetric_decrypt,
1941 key_asymmetric_duplicate,
1942 key_asymmetric_sign,
1943 key_asymmetric_verify,
1944 key_asymmetric_destroy,
1945 key_export_dsa_capi,
1946 key_export_ecc,
1947 key_import_dsa_capi,
1948 key_import_ecc,
1949 key_import_rsa
1952 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
1954 switch (reason)
1956 case DLL_PROCESS_ATTACH:
1957 if (!gnutls_initialize()) return STATUS_DLL_NOT_FOUND;
1958 *(const struct key_funcs **)ptr_out = &key_funcs;
1959 break;
1960 case DLL_PROCESS_DETACH:
1961 gnutls_uninitialize();
1962 break;
1964 return STATUS_SUCCESS;
1967 #endif /* HAVE_GNUTLS_CIPHER_INIT */