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
22 #include "wine/port.h"
25 #ifdef HAVE_GNUTLS_CIPHER_INIT
26 #include <gnutls/gnutls.h>
27 #include <gnutls/crypto.h>
28 #include <gnutls/abstract.h>
32 #define WIN32_NO_STATUS
38 #include "bcrypt_internal.h"
40 #include "wine/debug.h"
41 #include "wine/heap.h"
42 #include "wine/unicode.h"
44 #ifdef HAVE_GNUTLS_CIPHER_INIT
45 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
46 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
48 #if GNUTLS_VERSION_MAJOR < 3
49 #define GNUTLS_CIPHER_AES_192_CBC 92
50 #define GNUTLS_CIPHER_AES_128_GCM 93
51 #define GNUTLS_CIPHER_AES_256_GCM 94
52 #define GNUTLS_PK_ECC 4
54 #define GNUTLS_CURVE_TO_BITS(curve) (unsigned int)(((unsigned int)1<<31)|((unsigned int)(curve)))
58 GNUTLS_ECC_CURVE_INVALID
,
59 GNUTLS_ECC_CURVE_SECP224R1
,
60 GNUTLS_ECC_CURVE_SECP256R1
,
61 GNUTLS_ECC_CURVE_SECP384R1
,
62 GNUTLS_ECC_CURVE_SECP521R1
,
66 /* Not present in gnutls version < 3.0 */
67 static int (*pgnutls_cipher_tag
)(gnutls_cipher_hd_t
, void *, size_t);
68 static int (*pgnutls_cipher_add_auth
)(gnutls_cipher_hd_t
, const void *, size_t);
69 static gnutls_sign_algorithm_t (*pgnutls_pk_to_sign
)(gnutls_pk_algorithm_t
, gnutls_digest_algorithm_t
);
70 static int (*pgnutls_pubkey_import_ecc_raw
)(gnutls_pubkey_t
, gnutls_ecc_curve_t
,
71 const gnutls_datum_t
*, const gnutls_datum_t
*);
72 static int (*pgnutls_privkey_import_ecc_raw
)(gnutls_privkey_t
, gnutls_ecc_curve_t
, const gnutls_datum_t
*,
73 const gnutls_datum_t
*, const gnutls_datum_t
*);
74 static int (*pgnutls_pubkey_verify_hash2
)(gnutls_pubkey_t
, gnutls_sign_algorithm_t
, unsigned int,
75 const gnutls_datum_t
*, const gnutls_datum_t
*);
77 /* Not present in gnutls version < 2.11.0 */
78 static int (*pgnutls_pubkey_import_rsa_raw
)(gnutls_pubkey_t
, const gnutls_datum_t
*, const gnutls_datum_t
*);
80 /* Not present in gnutls version < 2.12.0 */
81 static int (*pgnutls_pubkey_import_dsa_raw
)(gnutls_pubkey_t
, const gnutls_datum_t
*, const gnutls_datum_t
*,
82 const gnutls_datum_t
*, const gnutls_datum_t
*);
84 /* Not present in gnutls version < 3.3.0 */
85 static int (*pgnutls_privkey_export_ecc_raw
)(gnutls_privkey_t
, gnutls_ecc_curve_t
*,
86 gnutls_datum_t
*, gnutls_datum_t
*, gnutls_datum_t
*);
87 static int (*pgnutls_privkey_export_rsa_raw
)(gnutls_privkey_t
, gnutls_datum_t
*, gnutls_datum_t
*, gnutls_datum_t
*,
88 gnutls_datum_t
*, gnutls_datum_t
*, gnutls_datum_t
*, gnutls_datum_t
*,
90 static int (*pgnutls_privkey_export_dsa_raw
)(gnutls_privkey_t
, gnutls_datum_t
*, gnutls_datum_t
*, gnutls_datum_t
*,
91 gnutls_datum_t
*, gnutls_datum_t
*);
92 static int (*pgnutls_privkey_generate
)(gnutls_privkey_t
, gnutls_pk_algorithm_t
, unsigned int, unsigned int);
94 /* Not present in gnutls version < 3.6.0 */
95 static int (*pgnutls_decode_rs_value
)(const gnutls_datum_t
*, gnutls_datum_t
*, gnutls_datum_t
*);
97 static void *libgnutls_handle
;
98 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
99 MAKE_FUNCPTR(gnutls_cipher_decrypt2
);
100 MAKE_FUNCPTR(gnutls_cipher_deinit
);
101 MAKE_FUNCPTR(gnutls_cipher_encrypt2
);
102 MAKE_FUNCPTR(gnutls_cipher_init
);
103 MAKE_FUNCPTR(gnutls_global_deinit
);
104 MAKE_FUNCPTR(gnutls_global_init
);
105 MAKE_FUNCPTR(gnutls_global_set_log_function
);
106 MAKE_FUNCPTR(gnutls_global_set_log_level
);
107 MAKE_FUNCPTR(gnutls_perror
);
108 MAKE_FUNCPTR(gnutls_privkey_deinit
);
109 MAKE_FUNCPTR(gnutls_privkey_init
);
110 MAKE_FUNCPTR(gnutls_privkey_sign_hash
);
111 MAKE_FUNCPTR(gnutls_pubkey_deinit
);
112 MAKE_FUNCPTR(gnutls_pubkey_init
);
115 static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle
, void *tag
, size_t tag_size
)
117 return GNUTLS_E_UNKNOWN_CIPHER_TYPE
;
120 static int compat_gnutls_cipher_add_auth(gnutls_cipher_hd_t handle
, const void *ptext
, size_t ptext_size
)
122 return GNUTLS_E_UNKNOWN_CIPHER_TYPE
;
125 static int compat_gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key
, gnutls_ecc_curve_t curve
,
126 const gnutls_datum_t
*x
, const gnutls_datum_t
*y
)
128 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
131 static int compat_gnutls_privkey_export_rsa_raw(gnutls_privkey_t key
, gnutls_datum_t
*m
, gnutls_datum_t
*e
,
132 gnutls_datum_t
*d
, gnutls_datum_t
*p
, gnutls_datum_t
*q
,
133 gnutls_datum_t
*u
, gnutls_datum_t
*e1
, gnutls_datum_t
*e2
)
135 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
138 static int compat_gnutls_privkey_export_ecc_raw(gnutls_privkey_t key
, gnutls_ecc_curve_t
*curve
,
139 gnutls_datum_t
*x
, gnutls_datum_t
*y
, gnutls_datum_t
*k
)
141 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
144 static int compat_gnutls_privkey_import_ecc_raw(gnutls_privkey_t key
, gnutls_ecc_curve_t curve
,
145 const gnutls_datum_t
*x
, const gnutls_datum_t
*y
,
146 const gnutls_datum_t
*k
)
148 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
151 static int compat_gnutls_privkey_export_dsa_raw(gnutls_privkey_t key
, gnutls_datum_t
*p
, gnutls_datum_t
*q
,
152 gnutls_datum_t
*g
, gnutls_datum_t
*y
, gnutls_datum_t
*x
)
154 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
157 static gnutls_sign_algorithm_t
compat_gnutls_pk_to_sign(gnutls_pk_algorithm_t pk
, gnutls_digest_algorithm_t hash
)
159 return GNUTLS_SIGN_UNKNOWN
;
162 static int compat_gnutls_pubkey_verify_hash2(gnutls_pubkey_t key
, gnutls_sign_algorithm_t algo
,
163 unsigned int flags
, const gnutls_datum_t
*hash
,
164 const gnutls_datum_t
*signature
)
166 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
169 static int compat_gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key
, const gnutls_datum_t
*m
, const gnutls_datum_t
*e
)
171 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
174 static int compat_gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key
, const gnutls_datum_t
*p
, const gnutls_datum_t
*q
,
175 const gnutls_datum_t
*g
, const gnutls_datum_t
*y
)
177 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
180 static int compat_gnutls_privkey_generate(gnutls_privkey_t key
, gnutls_pk_algorithm_t algo
, unsigned int bits
,
183 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
186 static int compat_gnutls_decode_rs_value(const gnutls_datum_t
* sig_value
, gnutls_datum_t
* r
, gnutls_datum_t
* s
)
188 return GNUTLS_E_INTERNAL_ERROR
;
191 static void gnutls_log( int level
, const char *msg
)
193 TRACE( "<%d> %s", level
, msg
);
196 BOOL
gnutls_initialize(void)
200 if (!(libgnutls_handle
= dlopen( SONAME_LIBGNUTLS
, RTLD_NOW
)))
202 ERR_(winediag
)( "failed to load libgnutls, no support for encryption\n" );
206 #define LOAD_FUNCPTR(f) \
207 if (!(p##f = dlsym( libgnutls_handle, #f ))) \
209 ERR( "failed to load %s\n", #f ); \
213 LOAD_FUNCPTR(gnutls_cipher_decrypt2
)
214 LOAD_FUNCPTR(gnutls_cipher_deinit
)
215 LOAD_FUNCPTR(gnutls_cipher_encrypt2
)
216 LOAD_FUNCPTR(gnutls_cipher_init
)
217 LOAD_FUNCPTR(gnutls_global_deinit
)
218 LOAD_FUNCPTR(gnutls_global_init
)
219 LOAD_FUNCPTR(gnutls_global_set_log_function
)
220 LOAD_FUNCPTR(gnutls_global_set_log_level
)
221 LOAD_FUNCPTR(gnutls_perror
)
222 LOAD_FUNCPTR(gnutls_privkey_deinit
);
223 LOAD_FUNCPTR(gnutls_privkey_init
);
224 LOAD_FUNCPTR(gnutls_privkey_sign_hash
);
225 LOAD_FUNCPTR(gnutls_pubkey_deinit
);
226 LOAD_FUNCPTR(gnutls_pubkey_init
);
229 if (!(pgnutls_cipher_tag
= dlsym( libgnutls_handle
, "gnutls_cipher_tag" )))
231 WARN("gnutls_cipher_tag not found\n");
232 pgnutls_cipher_tag
= compat_gnutls_cipher_tag
;
234 if (!(pgnutls_cipher_add_auth
= dlsym( libgnutls_handle
, "gnutls_cipher_add_auth" )))
236 WARN("gnutls_cipher_add_auth not found\n");
237 pgnutls_cipher_add_auth
= compat_gnutls_cipher_add_auth
;
240 if ((ret
= pgnutls_global_init()) != GNUTLS_E_SUCCESS
)
242 pgnutls_perror( ret
);
245 if (!(pgnutls_pubkey_import_ecc_raw
= dlsym( libgnutls_handle
, "gnutls_pubkey_import_ecc_raw" )))
247 WARN("gnutls_pubkey_import_ecc_raw not found\n");
248 pgnutls_pubkey_import_ecc_raw
= compat_gnutls_pubkey_import_ecc_raw
;
250 if (!(pgnutls_privkey_export_rsa_raw
= dlsym( libgnutls_handle
, "gnutls_privkey_export_rsa_raw" )))
252 WARN("gnutls_privkey_export_rsa_raw not found\n");
253 pgnutls_privkey_export_rsa_raw
= compat_gnutls_privkey_export_rsa_raw
;
255 if (!(pgnutls_privkey_export_ecc_raw
= dlsym( libgnutls_handle
, "gnutls_privkey_export_ecc_raw" )))
257 WARN("gnutls_privkey_export_ecc_raw not found\n");
258 pgnutls_privkey_export_ecc_raw
= compat_gnutls_privkey_export_ecc_raw
;
260 if (!(pgnutls_privkey_import_ecc_raw
= dlsym( libgnutls_handle
, "gnutls_privkey_import_ecc_raw" )))
262 WARN("gnutls_privkey_import_ecc_raw not found\n");
263 pgnutls_privkey_import_ecc_raw
= compat_gnutls_privkey_import_ecc_raw
;
265 if (!(pgnutls_privkey_export_dsa_raw
= dlsym( libgnutls_handle
, "gnutls_privkey_export_dsa_raw" )))
267 WARN("gnutls_privkey_export_dsa_raw not found\n");
268 pgnutls_privkey_export_dsa_raw
= compat_gnutls_privkey_export_dsa_raw
;
270 if (!(pgnutls_pk_to_sign
= dlsym( libgnutls_handle
, "gnutls_pk_to_sign" )))
272 WARN("gnutls_pk_to_sign not found\n");
273 pgnutls_pk_to_sign
= compat_gnutls_pk_to_sign
;
275 if (!(pgnutls_pubkey_verify_hash2
= dlsym( libgnutls_handle
, "gnutls_pubkey_verify_hash2" )))
277 WARN("gnutls_pubkey_verify_hash2 not found\n");
278 pgnutls_pubkey_verify_hash2
= compat_gnutls_pubkey_verify_hash2
;
280 if (!(pgnutls_pubkey_import_rsa_raw
= dlsym( libgnutls_handle
, "gnutls_pubkey_import_rsa_raw" )))
282 WARN("gnutls_pubkey_import_rsa_raw not found\n");
283 pgnutls_pubkey_import_rsa_raw
= compat_gnutls_pubkey_import_rsa_raw
;
285 if (!(pgnutls_pubkey_import_dsa_raw
= dlsym( libgnutls_handle
, "gnutls_pubkey_import_dsa_raw" )))
287 WARN("gnutls_pubkey_import_dsa_raw not found\n");
288 pgnutls_pubkey_import_dsa_raw
= compat_gnutls_pubkey_import_dsa_raw
;
290 if (!(pgnutls_privkey_generate
= dlsym( libgnutls_handle
, "gnutls_privkey_generate" )))
292 WARN("gnutls_privkey_generate not found\n");
293 pgnutls_privkey_generate
= compat_gnutls_privkey_generate
;
295 if (!(pgnutls_decode_rs_value
= dlsym( libgnutls_handle
, "gnutls_decode_rs_value" )))
297 WARN("gnutls_decode_rs_value not found\n");
298 pgnutls_decode_rs_value
= compat_gnutls_decode_rs_value
;
301 if (TRACE_ON( bcrypt
))
303 pgnutls_global_set_log_level( 4 );
304 pgnutls_global_set_log_function( gnutls_log
);
310 dlclose( libgnutls_handle
);
311 libgnutls_handle
= NULL
;
315 void gnutls_uninitialize(void)
317 pgnutls_global_deinit();
318 dlclose( libgnutls_handle
);
319 libgnutls_handle
= NULL
;
330 static void buffer_init( struct buffer
*buffer
)
332 buffer
->buffer
= NULL
;
335 buffer
->error
= FALSE
;
338 static void buffer_free( struct buffer
*buffer
)
340 heap_free( buffer
->buffer
);
343 static void buffer_append( struct buffer
*buffer
, BYTE
*data
, DWORD len
)
347 if (buffer
->pos
+ len
> buffer
->length
)
349 DWORD new_length
= max( max( buffer
->pos
+ len
, buffer
->length
* 2 ), 64 );
352 if (!(new_buffer
= heap_realloc( buffer
->buffer
, new_length
)))
354 ERR( "out of memory\n" );
355 buffer
->error
= TRUE
;
359 buffer
->buffer
= new_buffer
;
360 buffer
->length
= new_length
;
363 memcpy( &buffer
->buffer
[buffer
->pos
], data
, len
);
367 static void buffer_append_byte( struct buffer
*buffer
, BYTE value
)
369 buffer_append( buffer
, &value
, sizeof(value
) );
372 static void buffer_append_asn1_length( struct buffer
*buffer
, DWORD length
)
378 buffer_append_byte( buffer
, length
);
382 if (length
<= 0xff) num_bytes
= 1;
383 else if (length
<= 0xffff) num_bytes
= 2;
384 else if (length
<= 0xffffff) num_bytes
= 3;
387 buffer_append_byte( buffer
, 0x80 | num_bytes
);
388 while (num_bytes
--) buffer_append_byte( buffer
, length
>> (num_bytes
* 8) );
391 static void buffer_append_asn1_integer( struct buffer
*buffer
, BYTE
*data
, DWORD len
)
393 DWORD leading_zero
= (*data
& 0x80) != 0;
395 buffer_append_byte( buffer
, 0x02 ); /* tag */
396 buffer_append_asn1_length( buffer
, len
+ leading_zero
);
397 if (leading_zero
) buffer_append_byte( buffer
, 0 );
398 buffer_append( buffer
, data
, len
);
401 static void buffer_append_asn1_sequence( struct buffer
*buffer
, struct buffer
*content
)
405 buffer
->error
= TRUE
;
409 buffer_append_byte( buffer
, 0x30 ); /* tag */
410 buffer_append_asn1_length( buffer
, content
->pos
);
411 buffer_append( buffer
, content
->buffer
, content
->pos
);
414 static void buffer_append_asn1_r_s( struct buffer
*buffer
, BYTE
*r
, DWORD r_len
, BYTE
*s
, DWORD s_len
)
418 buffer_init( &value
);
419 buffer_append_asn1_integer( &value
, r
, r_len
);
420 buffer_append_asn1_integer( &value
, s
, s_len
);
421 buffer_append_asn1_sequence( buffer
, &value
);
422 buffer_free( &value
);
425 NTSTATUS
key_set_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
427 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
429 if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
431 key
->u
.s
.mode
= MODE_ID_ECB
;
432 return STATUS_SUCCESS
;
434 else if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
436 key
->u
.s
.mode
= MODE_ID_CBC
;
437 return STATUS_SUCCESS
;
439 else if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
441 key
->u
.s
.mode
= MODE_ID_GCM
;
442 return STATUS_SUCCESS
;
446 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
447 return STATUS_NOT_IMPLEMENTED
;
451 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
452 return STATUS_NOT_IMPLEMENTED
;
455 static ULONG
get_block_size( struct algorithm
*alg
)
457 ULONG ret
= 0, size
= sizeof(ret
);
458 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
462 NTSTATUS
key_symmetric_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
464 if (!libgnutls_handle
) return STATUS_INTERNAL_ERROR
;
472 FIXME( "algorithm %u not supported\n", alg
->id
);
473 return STATUS_NOT_SUPPORTED
;
476 if (!(key
->u
.s
.block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
477 if (!(key
->u
.s
.secret
= heap_alloc( secret_len
))) return STATUS_NO_MEMORY
;
478 memcpy( key
->u
.s
.secret
, secret
, secret_len
);
479 key
->u
.s
.secret_len
= secret_len
;
481 key
->alg_id
= alg
->id
;
482 key
->u
.s
.mode
= alg
->mode
;
483 key
->u
.s
.handle
= 0; /* initialized on first use */
484 key
->u
.s
.vector
= NULL
;
485 key
->u
.s
.vector_len
= 0;
487 return STATUS_SUCCESS
;
490 static gnutls_cipher_algorithm_t
get_gnutls_cipher( const struct key
*key
)
495 WARN( "handle block size\n" );
496 switch (key
->u
.s
.mode
)
499 if (key
->u
.s
.secret_len
== 16) return GNUTLS_CIPHER_AES_128_GCM
;
500 if (key
->u
.s
.secret_len
== 32) return GNUTLS_CIPHER_AES_256_GCM
;
502 case MODE_ID_ECB
: /* can be emulated with CBC + empty IV */
504 if (key
->u
.s
.secret_len
== 16) return GNUTLS_CIPHER_AES_128_CBC
;
505 if (key
->u
.s
.secret_len
== 24) return GNUTLS_CIPHER_AES_192_CBC
;
506 if (key
->u
.s
.secret_len
== 32) return GNUTLS_CIPHER_AES_256_CBC
;
511 FIXME( "AES mode %u with key length %u not supported\n", key
->u
.s
.mode
, key
->u
.s
.secret_len
);
512 return GNUTLS_CIPHER_UNKNOWN
;
515 FIXME( "algorithm %u not supported\n", key
->alg_id
);
516 return GNUTLS_CIPHER_UNKNOWN
;
520 NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
)
522 if (key
->u
.s
.handle
&& (!is_zero_vector( vector
, vector_len
) ||
523 !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
)))
525 TRACE( "invalidating cipher handle\n" );
526 pgnutls_cipher_deinit( key
->u
.s
.handle
);
527 key
->u
.s
.handle
= NULL
;
530 heap_free( key
->u
.s
.vector
);
531 key
->u
.s
.vector
= NULL
;
532 key
->u
.s
.vector_len
= 0;
535 if (!(key
->u
.s
.vector
= heap_alloc( vector_len
))) return STATUS_NO_MEMORY
;
536 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
537 key
->u
.s
.vector_len
= vector_len
;
540 return STATUS_SUCCESS
;
543 static NTSTATUS
init_cipher_handle( struct key
*key
)
545 gnutls_cipher_algorithm_t cipher
;
546 gnutls_datum_t secret
, vector
;
549 if (key
->u
.s
.handle
) return STATUS_SUCCESS
;
550 if ((cipher
= get_gnutls_cipher( key
)) == GNUTLS_CIPHER_UNKNOWN
) return STATUS_NOT_SUPPORTED
;
552 secret
.data
= key
->u
.s
.secret
;
553 secret
.size
= key
->u
.s
.secret_len
;
555 vector
.data
= key
->u
.s
.vector
;
556 vector
.size
= key
->u
.s
.vector_len
;
558 if ((ret
= pgnutls_cipher_init( &key
->u
.s
.handle
, cipher
, &secret
, key
->u
.s
.vector
? &vector
: NULL
)))
560 pgnutls_perror( ret
);
561 return STATUS_INTERNAL_ERROR
;
564 return STATUS_SUCCESS
;
567 NTSTATUS
key_symmetric_set_auth_data( struct key
*key
, UCHAR
*auth_data
, ULONG len
)
572 if (!auth_data
) return STATUS_SUCCESS
;
573 if ((status
= init_cipher_handle( key
))) return status
;
575 if ((ret
= pgnutls_cipher_add_auth( key
->u
.s
.handle
, auth_data
, len
)))
577 pgnutls_perror( ret
);
578 return STATUS_INTERNAL_ERROR
;
580 return STATUS_SUCCESS
;
583 NTSTATUS
key_symmetric_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
588 if ((status
= init_cipher_handle( key
))) return status
;
590 if ((ret
= pgnutls_cipher_encrypt2( key
->u
.s
.handle
, input
, input_len
, output
, output_len
)))
592 pgnutls_perror( ret
);
593 return STATUS_INTERNAL_ERROR
;
595 return STATUS_SUCCESS
;
598 NTSTATUS
key_symmetric_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
603 if ((status
= init_cipher_handle( key
))) return status
;
605 if ((ret
= pgnutls_cipher_decrypt2( key
->u
.s
.handle
, input
, input_len
, output
, output_len
)))
607 pgnutls_perror( ret
);
608 return STATUS_INTERNAL_ERROR
;
610 return STATUS_SUCCESS
;
613 NTSTATUS
key_symmetric_get_tag( struct key
*key
, UCHAR
*tag
, ULONG len
)
618 if ((status
= init_cipher_handle( key
))) return status
;
620 if ((ret
= pgnutls_cipher_tag( key
->u
.s
.handle
, tag
, len
)))
622 pgnutls_perror( ret
);
623 return STATUS_INTERNAL_ERROR
;
625 return STATUS_SUCCESS
;
628 static NTSTATUS
export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key
, ULONG bitlen
, UCHAR
**pubkey
, ULONG
*pubkey_len
)
630 BCRYPT_RSAKEY_BLOB
*rsa_blob
;
635 if ((ret
= pgnutls_privkey_export_rsa_raw( gnutls_key
, &m
, &e
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
)))
637 pgnutls_perror( ret
);
638 return STATUS_INTERNAL_ERROR
;
641 if (!(rsa_blob
= heap_alloc( sizeof(*rsa_blob
) + e
.size
+ m
.size
)))
643 pgnutls_perror( ret
);
644 free( e
.data
); free( m
.data
);
645 return STATUS_NO_MEMORY
;
648 dst
= (UCHAR
*)(rsa_blob
+ 1);
649 if (e
.size
== bitlen
/ 8 + 1 && !e
.data
[0])
655 memcpy( dst
, src
, e
.size
);
658 if (m
.size
== bitlen
/ 8 + 1 && !m
.data
[0])
664 memcpy( dst
, src
, m
.size
);
666 rsa_blob
->Magic
= BCRYPT_RSAPUBLIC_MAGIC
;
667 rsa_blob
->BitLength
= bitlen
;
668 rsa_blob
->cbPublicExp
= e
.size
;
669 rsa_blob
->cbModulus
= m
.size
;
670 rsa_blob
->cbPrime1
= 0;
671 rsa_blob
->cbPrime2
= 0;
673 *pubkey
= (UCHAR
*)rsa_blob
;
674 *pubkey_len
= sizeof(*rsa_blob
) + e
.size
+ m
.size
;
676 free( e
.data
); free( m
.data
);
677 return STATUS_SUCCESS
;
680 static NTSTATUS
export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key
, UCHAR
**pubkey
, ULONG
*pubkey_len
)
682 BCRYPT_ECCKEY_BLOB
*ecc_blob
;
683 gnutls_ecc_curve_t curve
;
689 if ((ret
= pgnutls_privkey_export_ecc_raw( gnutls_key
, &curve
, &x
, &y
, NULL
)))
691 pgnutls_perror( ret
);
692 return STATUS_INTERNAL_ERROR
;
697 case GNUTLS_ECC_CURVE_SECP256R1
:
698 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
703 FIXME( "curve %u not supported\n", curve
);
704 free( x
.data
); free( y
.data
);
705 return STATUS_NOT_IMPLEMENTED
;
708 if (!(ecc_blob
= heap_alloc( sizeof(*ecc_blob
) + x
.size
+ y
.size
)))
710 pgnutls_perror( ret
);
711 free( x
.data
); free( y
.data
);
712 return STATUS_NO_MEMORY
;
715 ecc_blob
->dwMagic
= magic
;
716 ecc_blob
->cbKey
= size
;
718 dst
= (UCHAR
*)(ecc_blob
+ 1);
719 if (x
.size
== size
+ 1) src
= x
.data
+ 1;
721 memcpy( dst
, src
, size
);
724 if (y
.size
== size
+ 1) src
= y
.data
+ 1;
726 memcpy( dst
, src
, size
);
728 *pubkey
= (UCHAR
*)ecc_blob
;
729 *pubkey_len
= sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2;
731 free( x
.data
); free( y
.data
);
732 return STATUS_SUCCESS
;
735 static NTSTATUS
export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key
, ULONG bitlen
, UCHAR
**pubkey
, ULONG
*pubkey_len
)
737 BCRYPT_DSA_KEY_BLOB
*dsa_blob
;
738 gnutls_datum_t p
, q
, g
, y
;
742 if ((ret
= pgnutls_privkey_export_dsa_raw( gnutls_key
, &p
, &q
, &g
, &y
, NULL
)))
744 pgnutls_perror( ret
);
745 return STATUS_INTERNAL_ERROR
;
750 FIXME( "bitlen > 1024 not supported\n" );
751 return STATUS_NOT_IMPLEMENTED
;
754 if (!(dsa_blob
= heap_alloc( sizeof(*dsa_blob
) + p
.size
+ g
.size
+ y
.size
)))
756 pgnutls_perror( ret
);
757 free( p
.data
); free( q
.data
); free( g
.data
); free( y
.data
);
758 return STATUS_NO_MEMORY
;
761 dst
= (UCHAR
*)(dsa_blob
+ 1);
762 if (p
.size
== bitlen
/ 8 + 1 && !p
.data
[0])
768 memcpy( dst
, src
, p
.size
);
771 if (g
.size
== bitlen
/ 8 + 1 && !g
.data
[0])
777 memcpy( dst
, src
, g
.size
);
780 if (y
.size
== bitlen
/ 8 + 1 && !y
.data
[0])
786 memcpy( dst
, src
, y
.size
);
789 if (q
.size
== sizeof(dsa_blob
->q
) + 1 && !q
.data
[0])
795 memcpy( dst
, src
, sizeof(dsa_blob
->q
) );
797 dsa_blob
->dwMagic
= BCRYPT_DSA_PUBLIC_MAGIC
;
798 dsa_blob
->cbKey
= bitlen
/ 8;
799 memset( dsa_blob
->Count
, 0, sizeof(dsa_blob
->Count
) ); /* FIXME */
800 memset( dsa_blob
->Seed
, 0, sizeof(dsa_blob
->Seed
) ); /* FIXME */
802 *pubkey
= (UCHAR
*)dsa_blob
;
803 *pubkey_len
= sizeof(*dsa_blob
) + p
.size
+ g
.size
+ y
.size
;
805 free( p
.data
); free( q
.data
); free( g
.data
); free( y
.data
);
806 return STATUS_SUCCESS
;
809 NTSTATUS
key_asymmetric_generate( struct key
*key
)
811 gnutls_pk_algorithm_t pk_alg
;
812 gnutls_privkey_t handle
;
817 if (!libgnutls_handle
) return STATUS_INTERNAL_ERROR
;
822 case ALG_ID_RSA_SIGN
:
823 pk_alg
= GNUTLS_PK_RSA
;
824 bitlen
= key
->u
.a
.bitlen
;
828 pk_alg
= GNUTLS_PK_DSA
;
829 bitlen
= key
->u
.a
.bitlen
;
832 case ALG_ID_ECDH_P256
:
833 case ALG_ID_ECDSA_P256
:
834 pk_alg
= GNUTLS_PK_ECC
; /* compatible with ECDSA and ECDH */
835 bitlen
= GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1
);
839 FIXME( "algorithm %u not supported\n", key
->alg_id
);
840 return STATUS_NOT_SUPPORTED
;
843 if ((ret
= pgnutls_privkey_init( &handle
)))
845 pgnutls_perror( ret
);
846 return STATUS_INTERNAL_ERROR
;
849 if ((ret
= pgnutls_privkey_generate( handle
, pk_alg
, bitlen
, 0 )))
851 pgnutls_perror( ret
);
852 pgnutls_privkey_deinit( handle
);
853 return STATUS_INTERNAL_ERROR
;
859 status
= export_gnutls_pubkey_rsa( handle
, key
->u
.a
.bitlen
, &key
->u
.a
.pubkey
, &key
->u
.a
.pubkey_len
);
863 status
= export_gnutls_pubkey_ecc( handle
, &key
->u
.a
.pubkey
, &key
->u
.a
.pubkey_len
);
867 status
= export_gnutls_pubkey_dsa( handle
, key
->u
.a
.bitlen
, &key
->u
.a
.pubkey
, &key
->u
.a
.pubkey_len
);
871 ERR( "unhandled algorithm %u\n", pk_alg
);
872 return STATUS_INTERNAL_ERROR
;
877 pgnutls_privkey_deinit( handle
);
881 key
->u
.a
.handle
= handle
;
882 return STATUS_SUCCESS
;
885 NTSTATUS
key_export_ecc( struct key
*key
, UCHAR
*buf
, ULONG len
, ULONG
*ret_len
)
887 BCRYPT_ECCKEY_BLOB
*ecc_blob
;
888 gnutls_ecc_curve_t curve
;
889 gnutls_datum_t x
, y
, d
;
894 if ((ret
= pgnutls_privkey_export_ecc_raw( key
->u
.a
.handle
, &curve
, &x
, &y
, &d
)))
896 pgnutls_perror( ret
);
897 return STATUS_INTERNAL_ERROR
;
902 case GNUTLS_ECC_CURVE_SECP256R1
:
903 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
908 FIXME( "curve %u not supported\n", curve
);
909 free( x
.data
); free( y
.data
); free( d
.data
);
910 return STATUS_NOT_IMPLEMENTED
;
913 *ret_len
= sizeof(*ecc_blob
) + size
* 3;
914 if (len
>= *ret_len
&& buf
)
916 ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)buf
;
917 ecc_blob
->dwMagic
= magic
;
918 ecc_blob
->cbKey
= size
;
920 dst
= (UCHAR
*)(ecc_blob
+ 1);
921 if (x
.size
== size
+ 1) src
= x
.data
+ 1;
923 memcpy( dst
, src
, size
);
926 if (y
.size
== size
+ 1) src
= y
.data
+ 1;
928 memcpy( dst
, src
, size
);
931 if (d
.size
== size
+ 1) src
= d
.data
+ 1;
933 memcpy( dst
, src
, size
);
936 free( x
.data
); free( y
.data
); free( d
.data
);
937 return STATUS_SUCCESS
;
940 NTSTATUS
key_import_ecc( struct key
*key
, UCHAR
*buf
, ULONG len
)
942 BCRYPT_ECCKEY_BLOB
*ecc_blob
;
943 gnutls_ecc_curve_t curve
;
944 gnutls_privkey_t handle
;
945 gnutls_datum_t x
, y
, k
;
951 case ALG_ID_ECDH_P256
:
952 curve
= GNUTLS_ECC_CURVE_SECP256R1
;
956 FIXME( "algorithm %u not yet supported\n", key
->alg_id
);
957 return STATUS_NOT_IMPLEMENTED
;
960 if ((ret
= pgnutls_privkey_init( &handle
)))
962 pgnutls_perror( ret
);
963 return STATUS_INTERNAL_ERROR
;
966 ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)buf
;
967 x
.data
= (unsigned char *)(ecc_blob
+ 1);
968 x
.size
= ecc_blob
->cbKey
;
969 y
.data
= x
.data
+ ecc_blob
->cbKey
;
970 y
.size
= ecc_blob
->cbKey
;
971 k
.data
= y
.data
+ ecc_blob
->cbKey
;
972 k
.size
= ecc_blob
->cbKey
;
974 if ((ret
= pgnutls_privkey_import_ecc_raw( handle
, curve
, &x
, &y
, &k
)))
976 pgnutls_perror( ret
);
977 pgnutls_privkey_deinit( handle
);
978 return STATUS_INTERNAL_ERROR
;
981 if ((status
= export_gnutls_pubkey_ecc( handle
, &key
->u
.a
.pubkey
, &key
->u
.a
.pubkey_len
)))
983 pgnutls_privkey_deinit( handle
);
987 key
->u
.a
.handle
= handle
;
988 return STATUS_SUCCESS
;
991 NTSTATUS
key_asymmetric_init( struct key
*key
, struct algorithm
*alg
, ULONG bitlen
, const UCHAR
*pubkey
,
994 if (!libgnutls_handle
) return STATUS_INTERNAL_ERROR
;
998 case ALG_ID_ECDH_P256
:
999 case ALG_ID_ECDSA_P256
:
1000 case ALG_ID_ECDSA_P384
:
1002 case ALG_ID_RSA_SIGN
:
1007 FIXME( "algorithm %u not supported\n", alg
->id
);
1008 return STATUS_NOT_SUPPORTED
;
1013 if (!(key
->u
.a
.pubkey
= heap_alloc( pubkey_len
))) return STATUS_NO_MEMORY
;
1014 memcpy( key
->u
.a
.pubkey
, pubkey
, pubkey_len
);
1015 key
->u
.a
.pubkey_len
= pubkey_len
;
1017 key
->alg_id
= alg
->id
;
1018 key
->u
.a
.bitlen
= bitlen
;
1020 return STATUS_SUCCESS
;
1023 static NTSTATUS
import_gnutls_pubkey_ecc( struct key
*key
, gnutls_pubkey_t
*gnutls_key
)
1025 BCRYPT_ECCKEY_BLOB
*ecc_blob
;
1026 gnutls_ecc_curve_t curve
;
1027 gnutls_datum_t x
, y
;
1030 switch (key
->alg_id
)
1032 case ALG_ID_ECDSA_P256
: curve
= GNUTLS_ECC_CURVE_SECP256R1
; break;
1033 case ALG_ID_ECDSA_P384
: curve
= GNUTLS_ECC_CURVE_SECP384R1
; break;
1036 FIXME( "algorithm %u not yet supported\n", key
->alg_id
);
1037 return STATUS_NOT_IMPLEMENTED
;
1040 if ((ret
= pgnutls_pubkey_init( gnutls_key
)))
1042 pgnutls_perror( ret
);
1043 return STATUS_INTERNAL_ERROR
;
1046 ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)key
->u
.a
.pubkey
;
1047 x
.data
= key
->u
.a
.pubkey
+ sizeof(*ecc_blob
);
1048 x
.size
= ecc_blob
->cbKey
;
1049 y
.data
= key
->u
.a
.pubkey
+ sizeof(*ecc_blob
) + ecc_blob
->cbKey
;
1050 y
.size
= ecc_blob
->cbKey
;
1052 if ((ret
= pgnutls_pubkey_import_ecc_raw( *gnutls_key
, curve
, &x
, &y
)))
1054 pgnutls_perror( ret
);
1055 pgnutls_pubkey_deinit( *gnutls_key
);
1056 return STATUS_INTERNAL_ERROR
;
1059 return STATUS_SUCCESS
;
1062 static NTSTATUS
import_gnutls_pubkey_rsa( struct key
*key
, gnutls_pubkey_t
*gnutls_key
)
1064 BCRYPT_RSAKEY_BLOB
*rsa_blob
;
1065 gnutls_datum_t m
, e
;
1068 if ((ret
= pgnutls_pubkey_init( gnutls_key
)))
1070 pgnutls_perror( ret
);
1071 return STATUS_INTERNAL_ERROR
;
1074 rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)key
->u
.a
.pubkey
;
1075 e
.data
= key
->u
.a
.pubkey
+ sizeof(*rsa_blob
);
1076 e
.size
= rsa_blob
->cbPublicExp
;
1077 m
.data
= key
->u
.a
.pubkey
+ sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
;
1078 m
.size
= rsa_blob
->cbModulus
;
1080 if ((ret
= pgnutls_pubkey_import_rsa_raw( *gnutls_key
, &m
, &e
)))
1082 pgnutls_perror( ret
);
1083 pgnutls_pubkey_deinit( *gnutls_key
);
1084 return STATUS_INTERNAL_ERROR
;
1087 return STATUS_SUCCESS
;
1090 static NTSTATUS
import_gnutls_pubkey_dsa( struct key
*key
, gnutls_pubkey_t
*gnutls_key
)
1092 BCRYPT_DSA_KEY_BLOB
*dsa_blob
;
1093 gnutls_datum_t p
, q
, g
, y
;
1096 if ((ret
= pgnutls_pubkey_init( gnutls_key
)))
1098 pgnutls_perror( ret
);
1099 return STATUS_INTERNAL_ERROR
;
1102 dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)key
->u
.a
.pubkey
;
1103 p
.data
= key
->u
.a
.pubkey
+ sizeof(*dsa_blob
);
1104 p
.size
= dsa_blob
->cbKey
;
1105 q
.data
= dsa_blob
->q
;
1106 q
.size
= sizeof(dsa_blob
->q
);
1107 g
.data
= key
->u
.a
.pubkey
+ sizeof(*dsa_blob
) + dsa_blob
->cbKey
;
1108 g
.size
= dsa_blob
->cbKey
;
1109 y
.data
= key
->u
.a
.pubkey
+ sizeof(*dsa_blob
) + dsa_blob
->cbKey
* 2;
1110 y
.size
= dsa_blob
->cbKey
;
1112 if ((ret
= pgnutls_pubkey_import_dsa_raw( *gnutls_key
, &p
, &q
, &g
, &y
)))
1114 pgnutls_perror( ret
);
1115 pgnutls_pubkey_deinit( *gnutls_key
);
1116 return STATUS_INTERNAL_ERROR
;
1119 return STATUS_SUCCESS
;
1122 static NTSTATUS
import_gnutls_pubkey( struct key
*key
, gnutls_pubkey_t
*gnutls_key
)
1124 switch (key
->alg_id
)
1126 case ALG_ID_ECDSA_P256
:
1127 case ALG_ID_ECDSA_P384
:
1128 return import_gnutls_pubkey_ecc( key
, gnutls_key
);
1131 case ALG_ID_RSA_SIGN
:
1132 return import_gnutls_pubkey_rsa( key
, gnutls_key
);
1135 return import_gnutls_pubkey_dsa( key
, gnutls_key
);
1138 FIXME("algorithm %u not yet supported\n", key
->alg_id
);
1139 return STATUS_NOT_IMPLEMENTED
;
1143 static NTSTATUS
prepare_gnutls_signature_dsa( struct key
*key
, UCHAR
*signature
, ULONG signature_len
,
1144 gnutls_datum_t
*gnutls_signature
)
1146 struct buffer buffer
;
1147 DWORD r_len
= signature_len
/ 2;
1148 DWORD s_len
= r_len
;
1149 BYTE
*r
= signature
;
1150 BYTE
*s
= signature
+ r_len
;
1152 buffer_init( &buffer
);
1153 buffer_append_asn1_r_s( &buffer
, r
, r_len
, s
, s_len
);
1156 buffer_free( &buffer
);
1157 return STATUS_NO_MEMORY
;
1160 gnutls_signature
->data
= buffer
.buffer
;
1161 gnutls_signature
->size
= buffer
.pos
;
1162 return STATUS_SUCCESS
;
1165 static NTSTATUS
prepare_gnutls_signature_rsa( struct key
*key
, UCHAR
*signature
, ULONG signature_len
,
1166 gnutls_datum_t
*gnutls_signature
)
1168 gnutls_signature
->data
= signature
;
1169 gnutls_signature
->size
= signature_len
;
1170 return STATUS_SUCCESS
;
1173 static NTSTATUS
prepare_gnutls_signature( struct key
*key
, UCHAR
*signature
, ULONG signature_len
,
1174 gnutls_datum_t
*gnutls_signature
)
1176 switch (key
->alg_id
)
1178 case ALG_ID_ECDSA_P256
:
1179 case ALG_ID_ECDSA_P384
:
1181 return prepare_gnutls_signature_dsa( key
, signature
, signature_len
, gnutls_signature
);
1184 case ALG_ID_RSA_SIGN
:
1185 return prepare_gnutls_signature_rsa( key
, signature
, signature_len
, gnutls_signature
);
1188 FIXME( "algorithm %u not yet supported\n", key
->alg_id
);
1189 return STATUS_NOT_IMPLEMENTED
;
1193 static gnutls_digest_algorithm_t
get_digest_from_id( const WCHAR
*alg_id
)
1195 if (!strcmpW( alg_id
, BCRYPT_SHA1_ALGORITHM
)) return GNUTLS_DIG_SHA1
;
1196 if (!strcmpW( alg_id
, BCRYPT_SHA256_ALGORITHM
)) return GNUTLS_DIG_SHA256
;
1197 if (!strcmpW( alg_id
, BCRYPT_SHA384_ALGORITHM
)) return GNUTLS_DIG_SHA384
;
1198 if (!strcmpW( alg_id
, BCRYPT_SHA512_ALGORITHM
)) return GNUTLS_DIG_SHA512
;
1199 if (!strcmpW( alg_id
, BCRYPT_MD2_ALGORITHM
)) return GNUTLS_DIG_MD2
;
1200 if (!strcmpW( alg_id
, BCRYPT_MD5_ALGORITHM
)) return GNUTLS_DIG_MD5
;
1204 NTSTATUS
key_asymmetric_verify( struct key
*key
, void *padding
, UCHAR
*hash
, ULONG hash_len
, UCHAR
*signature
,
1205 ULONG signature_len
, DWORD flags
)
1207 gnutls_digest_algorithm_t hash_alg
;
1208 gnutls_sign_algorithm_t sign_alg
;
1209 gnutls_datum_t gnutls_hash
, gnutls_signature
;
1210 gnutls_pk_algorithm_t pk_alg
;
1211 gnutls_pubkey_t gnutls_key
;
1215 switch (key
->alg_id
)
1217 case ALG_ID_ECDSA_P256
:
1218 case ALG_ID_ECDSA_P384
:
1220 if (flags
) FIXME( "flags %08x not supported\n", flags
);
1222 /* only the hash size must match, not the actual hash function */
1225 case 20: hash_alg
= GNUTLS_DIG_SHA1
; break;
1226 case 32: hash_alg
= GNUTLS_DIG_SHA256
; break;
1227 case 48: hash_alg
= GNUTLS_DIG_SHA384
; break;
1230 FIXME( "hash size %u not yet supported\n", hash_len
);
1231 return STATUS_INVALID_SIGNATURE
;
1233 pk_alg
= GNUTLS_PK_ECC
;
1237 case ALG_ID_RSA_SIGN
:
1239 BCRYPT_PKCS1_PADDING_INFO
*info
= (BCRYPT_PKCS1_PADDING_INFO
*)padding
;
1241 if (!(flags
& BCRYPT_PAD_PKCS1
) || !info
) return STATUS_INVALID_PARAMETER
;
1242 if (!info
->pszAlgId
) return STATUS_INVALID_SIGNATURE
;
1244 if ((hash_alg
= get_digest_from_id(info
->pszAlgId
)) == -1)
1246 FIXME( "hash algorithm %s not supported\n", debugstr_w(info
->pszAlgId
) );
1247 return STATUS_NOT_SUPPORTED
;
1249 pk_alg
= GNUTLS_PK_RSA
;
1254 if (flags
) FIXME( "flags %08x not supported\n", flags
);
1257 FIXME( "hash size %u not supported\n", hash_len
);
1258 return STATUS_INVALID_PARAMETER
;
1260 hash_alg
= GNUTLS_DIG_SHA1
;
1261 pk_alg
= GNUTLS_PK_DSA
;
1265 FIXME( "algorithm %u not yet supported\n", key
->alg_id
);
1266 return STATUS_NOT_IMPLEMENTED
;
1269 if ((sign_alg
= pgnutls_pk_to_sign( pk_alg
, hash_alg
)) == GNUTLS_SIGN_UNKNOWN
)
1271 FIXME("GnuTLS does not support algorithm %u with hash len %u\n", key
->alg_id
, hash_len
);
1272 return STATUS_NOT_IMPLEMENTED
;
1275 if ((status
= import_gnutls_pubkey( key
, &gnutls_key
))) return status
;
1276 if ((status
= prepare_gnutls_signature( key
, signature
, signature_len
, &gnutls_signature
)))
1278 pgnutls_pubkey_deinit( gnutls_key
);
1282 gnutls_hash
.data
= hash
;
1283 gnutls_hash
.size
= hash_len
;
1284 ret
= pgnutls_pubkey_verify_hash2( gnutls_key
, sign_alg
, 0, &gnutls_hash
, &gnutls_signature
);
1286 if (gnutls_signature
.data
!= signature
) heap_free( gnutls_signature
.data
);
1287 pgnutls_pubkey_deinit( gnutls_key
);
1288 return (ret
< 0) ? STATUS_INVALID_SIGNATURE
: STATUS_SUCCESS
;
1291 static unsigned int get_signature_length( enum alg_id id
)
1295 case ALG_ID_ECDSA_P256
: return 64;
1296 case ALG_ID_ECDSA_P384
: return 96;
1297 case ALG_ID_DSA
: return 40;
1299 FIXME( "unhandled algorithm %u\n", id
);
1304 static NTSTATUS
format_gnutls_signature( enum alg_id type
, gnutls_datum_t signature
,
1305 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
)
1310 case ALG_ID_RSA_SIGN
:
1312 if (output_len
< signature
.size
) return STATUS_BUFFER_TOO_SMALL
;
1313 memcpy( output
, signature
.data
, signature
.size
);
1314 *ret_len
= signature
.size
;
1315 return STATUS_SUCCESS
;
1317 case ALG_ID_ECDSA_P256
:
1318 case ALG_ID_ECDSA_P384
:
1322 unsigned int pad_size
, sig_len
= get_signature_length( type
);
1323 gnutls_datum_t r
, s
; /* format as r||s */
1325 if ((err
= pgnutls_decode_rs_value( &signature
, &r
, &s
)))
1327 pgnutls_perror( err
);
1328 return STATUS_INTERNAL_ERROR
;
1331 if (output_len
< sig_len
) return STATUS_BUFFER_TOO_SMALL
;
1333 /* remove prepended zero byte */
1345 if (r
.size
!= s
.size
|| r
.size
+ s
.size
> sig_len
)
1347 ERR( "we didn't get a correct signature\n" );
1348 return STATUS_INTERNAL_ERROR
;
1351 pad_size
= (sig_len
/ 2) - s
.size
;
1352 memset( output
, 0, sig_len
);
1354 memcpy( output
+ pad_size
, r
.data
, r
.size
);
1355 memcpy( output
+ (sig_len
/ 2) + pad_size
, s
.data
, s
.size
);
1358 return STATUS_SUCCESS
;
1361 return STATUS_INTERNAL_ERROR
;
1365 NTSTATUS
key_asymmetric_sign( struct key
*key
, void *padding
, UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
1366 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1368 BCRYPT_PKCS1_PADDING_INFO
*pad
= padding
;
1369 gnutls_datum_t hash
, signature
;
1370 gnutls_digest_algorithm_t hash_alg
;
1374 if (key
->alg_id
== ALG_ID_ECDSA_P256
|| key
->alg_id
== ALG_ID_ECDSA_P384
)
1376 /* With ECDSA, we find the digest algorithm from the hash length, and verify it */
1379 case 20: hash_alg
= GNUTLS_DIG_SHA1
; break;
1380 case 32: hash_alg
= GNUTLS_DIG_SHA256
; break;
1381 case 48: hash_alg
= GNUTLS_DIG_SHA384
; break;
1382 case 64: hash_alg
= GNUTLS_DIG_SHA512
; break;
1385 FIXME( "hash size %u not yet supported\n", input_len
);
1386 return STATUS_INVALID_PARAMETER
;
1389 if (flags
== BCRYPT_PAD_PKCS1
&& pad
&& pad
->pszAlgId
&& get_digest_from_id( pad
->pszAlgId
) != hash_alg
)
1391 WARN( "incorrect hashing algorithm %s, expected %u\n", debugstr_w(pad
->pszAlgId
), hash_alg
);
1392 return STATUS_INVALID_PARAMETER
;
1395 else if (key
->alg_id
== ALG_ID_DSA
)
1397 if (flags
) FIXME( "flags %08x not supported\n", flags
);
1398 if (input_len
!= 20)
1400 FIXME( "hash size %u not supported\n", input_len
);
1401 return STATUS_INVALID_PARAMETER
;
1403 hash_alg
= GNUTLS_DIG_SHA1
;
1405 else if (flags
== BCRYPT_PAD_PKCS1
)
1407 if (!pad
|| !pad
->pszAlgId
)
1409 WARN( "padding info not found\n" );
1410 return STATUS_INVALID_PARAMETER
;
1413 if ((hash_alg
= get_digest_from_id( pad
->pszAlgId
)) == -1)
1415 FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad
->pszAlgId
) );
1416 return STATUS_NOT_SUPPORTED
;
1421 WARN( "invalid flags %08x\n", flags
);
1422 return STATUS_INVALID_PARAMETER
;
1426 FIXME( "flags %08x not implemented\n", flags
);
1427 return STATUS_NOT_IMPLEMENTED
;
1432 *ret_len
= key
->u
.a
.bitlen
/ 8;
1433 return STATUS_SUCCESS
;
1435 if (!key
->u
.a
.handle
) return STATUS_INVALID_PARAMETER
;
1438 hash
.size
= input_len
;
1440 signature
.data
= NULL
;
1443 if ((ret
= pgnutls_privkey_sign_hash( key
->u
.a
.handle
, hash_alg
, 0, &hash
, &signature
)))
1445 pgnutls_perror( ret
);
1446 return STATUS_INTERNAL_ERROR
;
1449 status
= format_gnutls_signature( key
->alg_id
, signature
, output
, output_len
, ret_len
);
1451 free( signature
.data
);
1455 NTSTATUS
key_destroy( struct key
*key
)
1457 if (key_is_symmetric( key
))
1459 if (key
->u
.s
.handle
) pgnutls_cipher_deinit( key
->u
.s
.handle
);
1460 heap_free( key
->u
.s
.vector
);
1461 heap_free( key
->u
.s
.secret
);
1465 if (key
->u
.a
.handle
) pgnutls_privkey_deinit( key
->u
.a
.handle
);
1466 heap_free( key
->u
.a
.pubkey
);
1469 return STATUS_SUCCESS
;