Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/bcrypt/bcrypt_main.c
8623 views
1
/*
2
* Copyright 2009 Henri Verbeet for CodeWeavers
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*
18
*/
19
20
#include <assert.h>
21
#include <stdarg.h>
22
#include <stdlib.h>
23
24
#include "ntstatus.h"
25
#define WIN32_NO_STATUS
26
#include "windef.h"
27
#include "winbase.h"
28
#include "ntsecapi.h"
29
#include "wincrypt.h"
30
#include "winternl.h"
31
#include "bcrypt.h"
32
#include "tomcrypt.h"
33
34
#include "wine/debug.h"
35
#include "bcrypt_internal.h"
36
37
WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
38
39
#define UNIX_CALL( func, params ) WINE_UNIX_CALL( unix_ ## func, params )
40
41
42
NTSTATUS WINAPI BCryptAddContextFunction( ULONG table, const WCHAR *ctx, ULONG iface, const WCHAR *func, ULONG pos )
43
{
44
FIXME( "%#lx, %s, %#lx, %s, %lu: stub\n", table, debugstr_w(ctx), iface, debugstr_w(func), pos );
45
return STATUS_SUCCESS;
46
}
47
48
NTSTATUS WINAPI BCryptAddContextFunctionProvider( ULONG table, const WCHAR *ctx, ULONG iface, const WCHAR *func,
49
const WCHAR *provider, ULONG pos )
50
{
51
FIXME( "%#lx, %s, %#lx, %s, %s, %lu: stub\n", table, debugstr_w(ctx), iface, debugstr_w(func),
52
debugstr_w(provider), pos );
53
return STATUS_SUCCESS;
54
}
55
56
NTSTATUS WINAPI BCryptRemoveContextFunction( ULONG table, const WCHAR *ctx, ULONG iface, const WCHAR *func )
57
{
58
FIXME( "%#lx, %s, %#lx, %s: stub\n", table, debugstr_w(ctx), iface, debugstr_w(func) );
59
return STATUS_NOT_IMPLEMENTED;
60
}
61
62
NTSTATUS WINAPI BCryptRemoveContextFunctionProvider( ULONG table, const WCHAR *ctx, ULONG iface, const WCHAR *func,
63
const WCHAR *provider )
64
{
65
FIXME( "%#lx, %s, %#lx, %s, %s: stub\n", table, debugstr_w(ctx), iface, debugstr_w(func), debugstr_w(provider) );
66
return STATUS_NOT_IMPLEMENTED;
67
}
68
69
NTSTATUS WINAPI BCryptEnumContextFunctions( ULONG table, const WCHAR *ctx, ULONG iface, ULONG *buflen,
70
CRYPT_CONTEXT_FUNCTIONS **buffer )
71
{
72
FIXME( "%#lx, %s, %#lx, %p, %p\n", table, debugstr_w(ctx), iface, buflen, buffer );
73
return STATUS_NOT_IMPLEMENTED;
74
}
75
76
void WINAPI BCryptFreeBuffer( void *buffer )
77
{
78
free( buffer );
79
}
80
81
NTSTATUS WINAPI BCryptRegisterProvider( const WCHAR *provider, ULONG flags, CRYPT_PROVIDER_REG *reg )
82
{
83
FIXME( "%s, %#lx, %p: stub\n", debugstr_w(provider), flags, reg );
84
return STATUS_SUCCESS;
85
}
86
87
NTSTATUS WINAPI BCryptUnregisterProvider( const WCHAR *provider )
88
{
89
FIXME( "%s: stub\n", debugstr_w(provider) );
90
return STATUS_NOT_IMPLEMENTED;
91
}
92
93
#define MAX_HASH_OUTPUT_BYTES 64
94
#define MAX_HASH_BLOCK_BITS 1024
95
96
/* ordered by class, keep in sync with enum alg_id */
97
static const struct
98
{
99
const WCHAR *name;
100
ULONG class;
101
ULONG object_length;
102
ULONG hash_length;
103
ULONG block_bits;
104
}
105
builtin_algorithms[] =
106
{
107
{ BCRYPT_3DES_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 522, 0, 0 },
108
{ BCRYPT_AES_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 654, 0, 0 },
109
{ BCRYPT_RC4_ALGORITHM, BCRYPT_CIPHER_INTERFACE, 654, 0, 0 },
110
{ BCRYPT_SHA256_ALGORITHM, BCRYPT_HASH_INTERFACE, 286, 32, 512 },
111
{ BCRYPT_SHA384_ALGORITHM, BCRYPT_HASH_INTERFACE, 382, 48, 1024 },
112
{ BCRYPT_SHA512_ALGORITHM, BCRYPT_HASH_INTERFACE, 382, 64, 1024 },
113
{ BCRYPT_SHA1_ALGORITHM, BCRYPT_HASH_INTERFACE, 278, 20, 512 },
114
{ BCRYPT_MD5_ALGORITHM, BCRYPT_HASH_INTERFACE, 274, 16, 512 },
115
{ BCRYPT_MD4_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 512 },
116
{ BCRYPT_MD2_ALGORITHM, BCRYPT_HASH_INTERFACE, 270, 16, 128 },
117
{ BCRYPT_RSA_ALGORITHM, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE, 0, 0, 0 },
118
{ BCRYPT_DH_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 },
119
{ BCRYPT_ECDH_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 },
120
{ BCRYPT_ECDH_P256_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 },
121
{ BCRYPT_ECDH_P384_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 },
122
{ BCRYPT_ECDH_P521_ALGORITHM, BCRYPT_SECRET_AGREEMENT_INTERFACE, 0, 0, 0 },
123
{ BCRYPT_RSA_SIGN_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
124
{ BCRYPT_ECDSA_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
125
{ BCRYPT_ECDSA_P256_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
126
{ BCRYPT_ECDSA_P384_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
127
{ BCRYPT_ECDSA_P521_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
128
{ BCRYPT_DSA_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
129
{ BCRYPT_RNG_ALGORITHM, BCRYPT_RNG_INTERFACE, 0, 0, 0 },
130
{ BCRYPT_PBKDF2_ALGORITHM, BCRYPT_KEY_DERIVATION_INTERFACE, 618, 0, 0 },
131
};
132
133
static inline BOOL is_symmetric_key( const struct key *key )
134
{
135
return builtin_algorithms[key->alg_id].class == BCRYPT_CIPHER_INTERFACE
136
|| builtin_algorithms[key->alg_id].class == BCRYPT_KEY_DERIVATION_INTERFACE;
137
}
138
139
static inline BOOL is_asymmetric_encryption_key( struct key *key )
140
{
141
return builtin_algorithms[key->alg_id].class == BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE;
142
}
143
144
static inline BOOL is_agreement_key( struct key *key )
145
{
146
return builtin_algorithms[key->alg_id].class == BCRYPT_SECRET_AGREEMENT_INTERFACE;
147
}
148
149
static inline BOOL is_signature_key( struct key *key )
150
{
151
return builtin_algorithms[key->alg_id].class == BCRYPT_SIGNATURE_INTERFACE || key->alg_id == ALG_ID_RSA;
152
}
153
154
static BOOL match_operation_type( ULONG type, ULONG class )
155
{
156
if (!type) return TRUE;
157
switch (class)
158
{
159
case BCRYPT_CIPHER_INTERFACE: return type & BCRYPT_CIPHER_OPERATION;
160
case BCRYPT_HASH_INTERFACE: return type & BCRYPT_HASH_OPERATION;
161
case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE: return type & BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION;
162
case BCRYPT_SECRET_AGREEMENT_INTERFACE: return type & BCRYPT_SECRET_AGREEMENT_OPERATION;
163
case BCRYPT_SIGNATURE_INTERFACE: return type & BCRYPT_SIGNATURE_OPERATION;
164
case BCRYPT_RNG_INTERFACE: return type & BCRYPT_RNG_OPERATION;
165
case BCRYPT_KEY_DERIVATION_INTERFACE: return type & BCRYPT_KEY_DERIVATION_OPERATION;
166
default: break;
167
}
168
return FALSE;
169
}
170
171
NTSTATUS WINAPI BCryptEnumAlgorithms( ULONG type, ULONG *ret_count, BCRYPT_ALGORITHM_IDENTIFIER **ret_list, ULONG flags )
172
{
173
static const ULONG supported = BCRYPT_CIPHER_OPERATION |\
174
BCRYPT_HASH_OPERATION |\
175
BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION |\
176
BCRYPT_SECRET_AGREEMENT_OPERATION |\
177
BCRYPT_SIGNATURE_OPERATION |\
178
BCRYPT_RNG_OPERATION |\
179
BCRYPT_KEY_DERIVATION_OPERATION;
180
BCRYPT_ALGORITHM_IDENTIFIER *list;
181
ULONG i, j, count = 0;
182
183
TRACE( "%#lx, %p, %p, %#lx\n", type, ret_count, ret_list, flags );
184
185
if (!ret_count || !ret_list || (type & ~supported)) return STATUS_INVALID_PARAMETER;
186
187
for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
188
{
189
if (match_operation_type( type, builtin_algorithms[i].class )) count++;
190
}
191
192
if (!(list = malloc( count * sizeof(*list) ))) return STATUS_NO_MEMORY;
193
194
for (i = 0, j = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
195
{
196
if (!match_operation_type( type, builtin_algorithms[i].class )) continue;
197
list[j].pszName = (WCHAR *)builtin_algorithms[i].name;
198
list[j].dwClass = builtin_algorithms[i].class;
199
list[j].dwFlags = 0;
200
j++;
201
}
202
203
*ret_count = count;
204
*ret_list = list;
205
return STATUS_SUCCESS;
206
}
207
208
static const struct algorithm pseudo_algorithms[] =
209
{
210
{{ MAGIC_ALG }, ALG_ID_MD2 },
211
{{ MAGIC_ALG }, ALG_ID_MD4 },
212
{{ MAGIC_ALG }, ALG_ID_MD5 },
213
{{ MAGIC_ALG }, ALG_ID_SHA1 },
214
{{ MAGIC_ALG }, ALG_ID_SHA256 },
215
{{ MAGIC_ALG }, ALG_ID_SHA384 },
216
{{ MAGIC_ALG }, ALG_ID_SHA512 },
217
{{ MAGIC_ALG }, ALG_ID_RC4 },
218
{{ MAGIC_ALG }, ALG_ID_RNG },
219
{{ MAGIC_ALG }, ALG_ID_MD5, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
220
{{ MAGIC_ALG }, ALG_ID_SHA1, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
221
{{ MAGIC_ALG }, ALG_ID_SHA256, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
222
{{ MAGIC_ALG }, ALG_ID_SHA384, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
223
{{ MAGIC_ALG }, ALG_ID_SHA512, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
224
{{ MAGIC_ALG }, ALG_ID_RSA },
225
{{ MAGIC_ALG }, ALG_ID_ECDSA },
226
{{ 0 }}, /* AES_CMAC */
227
{{ 0 }}, /* AES_GMAC */
228
{{ MAGIC_ALG }, ALG_ID_MD2, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
229
{{ MAGIC_ALG }, ALG_ID_MD4, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
230
{{ MAGIC_ALG }, ALG_ID_3DES, CHAIN_MODE_CBC },
231
{{ MAGIC_ALG }, ALG_ID_3DES, CHAIN_MODE_ECB },
232
{{ MAGIC_ALG }, ALG_ID_3DES, CHAIN_MODE_CFB },
233
{{ 0 }}, /* 3DES_112_CBC */
234
{{ 0 }}, /* 3DES_112_ECB */
235
{{ 0 }}, /* 3DES_112_CFB */
236
{{ MAGIC_ALG }, ALG_ID_AES, CHAIN_MODE_CBC },
237
{{ MAGIC_ALG }, ALG_ID_AES, CHAIN_MODE_ECB },
238
{{ MAGIC_ALG }, ALG_ID_AES, CHAIN_MODE_CFB },
239
{{ MAGIC_ALG }, ALG_ID_AES, CHAIN_MODE_CCM },
240
{{ MAGIC_ALG }, ALG_ID_AES, CHAIN_MODE_GCM },
241
{{ 0 }}, /* DES_CBC */
242
{{ 0 }}, /* DES_ECB */
243
{{ 0 }}, /* DES_CFB */
244
{{ 0 }}, /* DESX_CBC */
245
{{ 0 }}, /* DESX_ECB */
246
{{ 0 }}, /* DESX_CFB */
247
{{ 0 }}, /* RC2_CBC */
248
{{ 0 }}, /* RC2_ECB */
249
{{ 0 }}, /* RC2_CFB */
250
{{ MAGIC_ALG }, ALG_ID_DH },
251
{{ MAGIC_ALG }, ALG_ID_ECDH },
252
{{ MAGIC_ALG }, ALG_ID_ECDH_P256, 0, 0, ECC_CURVE_P256R1 },
253
{{ MAGIC_ALG }, ALG_ID_ECDH_P384, 0, 0, ECC_CURVE_P384R1 },
254
{{ MAGIC_ALG }, ALG_ID_ECDH_P521, 0, 0, ECC_CURVE_P521R1 },
255
{{ MAGIC_ALG }, ALG_ID_DSA },
256
{{ MAGIC_ALG }, ALG_ID_ECDSA_P256, 0, 0, ECC_CURVE_P256R1 },
257
{{ MAGIC_ALG }, ALG_ID_ECDSA_P384, 0, 0, ECC_CURVE_P384R1 },
258
{{ MAGIC_ALG }, ALG_ID_ECDSA_P521, 0, 0, ECC_CURVE_P521R1 },
259
{{ MAGIC_ALG }, ALG_ID_RSA_SIGN },
260
};
261
262
/* Algorithm pseudo-handles are denoted by having the lowest bit set.
263
* An aligned algorithm pointer will never have this bit set.
264
*/
265
static inline BOOL is_alg_pseudo_handle( BCRYPT_ALG_HANDLE handle )
266
{
267
return (((ULONG_PTR)handle & 1) == 1);
268
}
269
270
static struct object *get_object( BCRYPT_HANDLE handle, ULONG magic )
271
{
272
ULONG idx;
273
274
if (!handle) return NULL;
275
276
if (!is_alg_pseudo_handle( handle ))
277
{
278
struct object *obj = handle;
279
if (magic && obj->magic != magic) return NULL;
280
return obj;
281
}
282
283
idx = (ULONG_PTR)handle >> 4;
284
if (idx >= ARRAY_SIZE(pseudo_algorithms) || !pseudo_algorithms[idx].hdr.magic)
285
{
286
FIXME( "pseudo-handle %p not supported\n", handle );
287
return NULL;
288
}
289
return (struct object *)&pseudo_algorithms[idx];
290
}
291
292
static inline struct algorithm *get_alg_object( BCRYPT_ALG_HANDLE handle )
293
{
294
return (struct algorithm *)get_object( handle, MAGIC_ALG );
295
}
296
297
static inline struct hash *get_hash_object( BCRYPT_HASH_HANDLE handle )
298
{
299
return (struct hash *)get_object( handle, MAGIC_HASH );
300
}
301
302
static inline struct key *get_key_object( BCRYPT_KEY_HANDLE handle )
303
{
304
return (struct key *)get_object( handle, MAGIC_KEY );
305
}
306
307
static inline struct secret *get_secret_object( BCRYPT_SECRET_HANDLE handle )
308
{
309
return (struct secret *)get_object( handle, MAGIC_SECRET );
310
}
311
312
NTSTATUS WINAPI BCryptGenRandom( BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags )
313
{
314
const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
315
struct algorithm *alg = get_alg_object( handle );
316
317
TRACE("%p, %p, %lu, %#lx - semi-stub\n", handle, buffer, count, flags);
318
319
if (!handle)
320
{
321
/* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
322
* is set. In this case the preferred system RNG is used.
323
*/
324
if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
325
return STATUS_INVALID_HANDLE;
326
}
327
else if (is_alg_pseudo_handle( handle ) && handle != BCRYPT_RNG_ALG_HANDLE)
328
{
329
FIXME( "pseudo-handle %p not supported\n", handle );
330
return STATUS_NOT_IMPLEMENTED;
331
}
332
else if (!alg || alg->id != ALG_ID_RNG)
333
return STATUS_INVALID_HANDLE;
334
335
if (!buffer)
336
return STATUS_INVALID_PARAMETER;
337
338
if (flags & ~supported_flags)
339
FIXME("unsupported flags %#lx\n", flags & ~supported_flags);
340
341
if (alg)
342
FIXME("ignoring selected algorithm\n");
343
344
/* When zero bytes are requested the function returns success too. */
345
if (!count)
346
return STATUS_SUCCESS;
347
348
if (alg || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
349
{
350
if (RtlGenRandom(buffer, count)) return STATUS_SUCCESS;
351
}
352
353
FIXME("called with unsupported parameters, returning error\n");
354
return STATUS_NOT_IMPLEMENTED;
355
}
356
357
static struct algorithm *create_algorithm( enum alg_id id, enum chain_mode mode, DWORD flags )
358
{
359
struct algorithm *ret;
360
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
361
ret->hdr.magic = MAGIC_ALG;
362
ret->id = id;
363
ret->mode = mode;
364
ret->flags = flags;
365
return ret;
366
}
367
368
NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, const WCHAR *id, const WCHAR *implementation,
369
DWORD flags )
370
{
371
const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG | BCRYPT_HASH_REUSABLE_FLAG;
372
struct algorithm *alg;
373
enum alg_id alg_id;
374
ULONG i;
375
376
TRACE( "%p, %s, %s, %#lx\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
377
378
if (!handle || !id) return STATUS_INVALID_PARAMETER;
379
if (flags & ~supported_flags)
380
{
381
FIXME( "unsupported flags %#lx\n", flags & ~supported_flags );
382
return STATUS_NOT_IMPLEMENTED;
383
}
384
385
for (i = 0; i < ARRAY_SIZE( builtin_algorithms ); i++)
386
{
387
if (!wcscmp( id, builtin_algorithms[i].name))
388
{
389
alg_id = i;
390
break;
391
}
392
}
393
if (i == ARRAY_SIZE( builtin_algorithms ))
394
{
395
FIXME( "algorithm %s not supported\n", debugstr_w(id) );
396
return STATUS_NOT_IMPLEMENTED;
397
}
398
399
if (implementation && wcscmp( implementation, MS_PRIMITIVE_PROVIDER ))
400
{
401
FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
402
return STATUS_NOT_IMPLEMENTED;
403
}
404
405
if (!(alg = create_algorithm( alg_id, 0, flags ))) return STATUS_NO_MEMORY;
406
*handle = alg;
407
TRACE( "returning handle %p\n", *handle );
408
return STATUS_SUCCESS;
409
}
410
411
static void destroy_object( struct object *obj )
412
{
413
SecureZeroMemory( &obj->magic, sizeof(obj->magic) );
414
free( obj );
415
}
416
417
NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
418
{
419
struct algorithm *alg = handle;
420
421
TRACE( "%p, %#lx\n", handle, flags );
422
423
if (!handle || is_alg_pseudo_handle( handle ) || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
424
destroy_object( &alg->hdr );
425
return STATUS_SUCCESS;
426
}
427
428
NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
429
{
430
FIXME("%p - semi-stub\n", enabled);
431
432
if (!enabled)
433
return STATUS_INVALID_PARAMETER;
434
435
*enabled = FALSE;
436
return STATUS_SUCCESS;
437
}
438
439
static const struct ltc_hash_descriptor *get_hash_descriptor( enum alg_id alg_id )
440
{
441
switch (alg_id)
442
{
443
case ALG_ID_MD2: return &md2_desc;
444
case ALG_ID_MD4: return &md4_desc;
445
case ALG_ID_MD5: return &md5_desc;
446
case ALG_ID_SHA1: return &sha1_desc;
447
case ALG_ID_SHA256: return &sha256_desc;
448
case ALG_ID_SHA384: return &sha384_desc;
449
case ALG_ID_SHA512: return &sha512_desc;
450
default:
451
ERR( "unhandled id %u\n", alg_id );
452
return NULL;
453
}
454
}
455
456
#define HASH_FLAG_HMAC 0x01
457
#define HASH_FLAG_REUSABLE 0x02
458
struct hash
459
{
460
struct object hdr;
461
enum alg_id alg_id;
462
const struct ltc_hash_descriptor *desc;
463
ULONG flags;
464
UCHAR *secret;
465
ULONG secret_len;
466
hash_state outer;
467
hash_state inner;
468
};
469
470
#define BLOCK_LENGTH_RC4 1
471
#define BLOCK_LENGTH_3DES 8
472
#define BLOCK_LENGTH_AES 16
473
474
static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
475
{
476
if (!wcscmp( prop, BCRYPT_OBJECT_LENGTH ))
477
{
478
if (!builtin_algorithms[id].object_length)
479
return STATUS_NOT_SUPPORTED;
480
*ret_size = sizeof(ULONG);
481
if (size < sizeof(ULONG))
482
return STATUS_BUFFER_TOO_SMALL;
483
if (buf)
484
*(ULONG *)buf = builtin_algorithms[id].object_length;
485
return STATUS_SUCCESS;
486
}
487
488
if (!wcscmp( prop, BCRYPT_HASH_LENGTH ))
489
{
490
if (!builtin_algorithms[id].hash_length)
491
return STATUS_NOT_SUPPORTED;
492
*ret_size = sizeof(ULONG);
493
if (size < sizeof(ULONG))
494
return STATUS_BUFFER_TOO_SMALL;
495
if(buf)
496
*(ULONG*)buf = builtin_algorithms[id].hash_length;
497
return STATUS_SUCCESS;
498
}
499
500
if (!wcscmp( prop, BCRYPT_ALGORITHM_NAME ))
501
{
502
*ret_size = (lstrlenW(builtin_algorithms[id].name) + 1) * sizeof(WCHAR);
503
if (size < *ret_size)
504
return STATUS_BUFFER_TOO_SMALL;
505
if(buf)
506
memcpy(buf, builtin_algorithms[id].name, *ret_size);
507
return STATUS_SUCCESS;
508
}
509
510
return STATUS_NOT_IMPLEMENTED;
511
}
512
513
static NTSTATUS get_3des_property( enum chain_mode mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
514
{
515
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH ))
516
{
517
*ret_size = sizeof(ULONG);
518
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
519
if (buf) *(ULONG *)buf = BLOCK_LENGTH_3DES;
520
return STATUS_SUCCESS;
521
}
522
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
523
{
524
const WCHAR *str;
525
switch (mode)
526
{
527
case CHAIN_MODE_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
528
default: return STATUS_NOT_IMPLEMENTED;
529
}
530
531
*ret_size = 64;
532
if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
533
memcpy( buf, str, (lstrlenW(str) + 1) * sizeof(WCHAR) );
534
return STATUS_SUCCESS;
535
}
536
if (!wcscmp( prop, BCRYPT_KEY_LENGTHS ))
537
{
538
BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
539
*ret_size = sizeof(*key_lengths);
540
if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
541
if (key_lengths)
542
{
543
key_lengths->dwMinLength = 192;
544
key_lengths->dwMaxLength = 192;
545
key_lengths->dwIncrement = 0;
546
}
547
return STATUS_SUCCESS;
548
}
549
FIXME( "unsupported property %s\n", debugstr_w(prop) );
550
return STATUS_NOT_IMPLEMENTED;
551
}
552
553
static NTSTATUS get_aes_property( enum chain_mode mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
554
{
555
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH ))
556
{
557
*ret_size = sizeof(ULONG);
558
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
559
if (buf) *(ULONG *)buf = BLOCK_LENGTH_AES;
560
return STATUS_SUCCESS;
561
}
562
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
563
{
564
const WCHAR *str;
565
switch (mode)
566
{
567
case CHAIN_MODE_ECB: str = BCRYPT_CHAIN_MODE_ECB; break;
568
case CHAIN_MODE_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
569
case CHAIN_MODE_GCM: str = BCRYPT_CHAIN_MODE_GCM; break;
570
case CHAIN_MODE_CFB: str = BCRYPT_CHAIN_MODE_CFB; break;
571
default: return STATUS_NOT_IMPLEMENTED;
572
}
573
574
*ret_size = 64;
575
if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
576
memcpy( buf, str, (lstrlenW(str) + 1) * sizeof(WCHAR) );
577
return STATUS_SUCCESS;
578
}
579
if (!wcscmp( prop, BCRYPT_KEY_LENGTHS ))
580
{
581
BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
582
*ret_size = sizeof(*key_lengths);
583
if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
584
if (key_lengths)
585
{
586
key_lengths->dwMinLength = 128;
587
key_lengths->dwMaxLength = 256;
588
key_lengths->dwIncrement = 64;
589
}
590
return STATUS_SUCCESS;
591
}
592
if (!wcscmp( prop, BCRYPT_AUTH_TAG_LENGTH ))
593
{
594
BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
595
if (mode != CHAIN_MODE_GCM) return STATUS_NOT_SUPPORTED;
596
*ret_size = sizeof(*tag_length);
597
if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
598
if (tag_length)
599
{
600
tag_length->dwMinLength = 12;
601
tag_length->dwMaxLength = 16;
602
tag_length->dwIncrement = 1;
603
}
604
return STATUS_SUCCESS;
605
}
606
607
FIXME( "unsupported property %s\n", debugstr_w(prop) );
608
return STATUS_NOT_IMPLEMENTED;
609
}
610
611
static NTSTATUS get_rc4_property( enum chain_mode mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
612
{
613
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH ))
614
{
615
*ret_size = sizeof(ULONG);
616
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
617
if (buf) *(ULONG *)buf = BLOCK_LENGTH_RC4;
618
return STATUS_SUCCESS;
619
}
620
621
FIXME( "unsupported property %s\n", debugstr_w(prop) );
622
return STATUS_NOT_IMPLEMENTED;
623
}
624
625
static NTSTATUS get_rsa_property( enum chain_mode mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
626
{
627
if (!wcscmp( prop, BCRYPT_PADDING_SCHEMES ))
628
{
629
*ret_size = sizeof(ULONG);
630
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
631
if (buf) *(ULONG *)buf = BCRYPT_SUPPORTED_PAD_PKCS1_SIG | BCRYPT_SUPPORTED_PAD_OAEP;
632
return STATUS_SUCCESS;
633
}
634
635
FIXME( "unsupported property %s\n", debugstr_w(prop) );
636
return STATUS_NOT_IMPLEMENTED;
637
}
638
639
static NTSTATUS get_dsa_property( enum chain_mode mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
640
{
641
if (!wcscmp( prop, BCRYPT_PADDING_SCHEMES )) return STATUS_NOT_SUPPORTED;
642
FIXME( "unsupported property %s\n", debugstr_w(prop) );
643
return STATUS_NOT_IMPLEMENTED;
644
}
645
646
static NTSTATUS get_pbkdf2_property( enum chain_mode mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
647
{
648
if (!wcscmp( prop, BCRYPT_BLOCK_LENGTH )) return STATUS_NOT_SUPPORTED;
649
if (!wcscmp( prop, BCRYPT_KEY_LENGTHS ))
650
{
651
BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
652
*ret_size = sizeof(*key_lengths);
653
if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
654
if (key_lengths)
655
{
656
key_lengths->dwMinLength = 0;
657
key_lengths->dwMaxLength = 16384;
658
key_lengths->dwIncrement = 8;
659
}
660
return STATUS_SUCCESS;
661
}
662
FIXME( "unsupported property %s\n", debugstr_w(prop) );
663
return STATUS_NOT_IMPLEMENTED;
664
}
665
666
static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size,
667
ULONG *ret_size )
668
{
669
NTSTATUS status;
670
671
status = generic_alg_property( alg->id, prop, buf, size, ret_size );
672
if (status != STATUS_NOT_IMPLEMENTED)
673
return status;
674
675
switch (alg->id)
676
{
677
case ALG_ID_3DES:
678
return get_3des_property( alg->mode, prop, buf, size, ret_size );
679
680
case ALG_ID_AES:
681
return get_aes_property( alg->mode, prop, buf, size, ret_size );
682
683
case ALG_ID_RC4:
684
return get_rc4_property( alg->mode, prop, buf, size, ret_size );
685
686
case ALG_ID_RSA:
687
return get_rsa_property( alg->mode, prop, buf, size, ret_size );
688
689
case ALG_ID_DSA:
690
return get_dsa_property( alg->mode, prop, buf, size, ret_size );
691
692
case ALG_ID_PBKDF2:
693
return get_pbkdf2_property( alg->mode, prop, buf, size, ret_size );
694
695
default:
696
break;
697
}
698
699
FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop), alg->id );
700
return STATUS_NOT_IMPLEMENTED;
701
}
702
703
static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
704
{
705
switch (alg->id)
706
{
707
case ALG_ID_3DES:
708
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
709
{
710
if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
711
{
712
alg->mode = CHAIN_MODE_CBC;
713
return STATUS_SUCCESS;
714
}
715
else
716
{
717
FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
718
return STATUS_NOT_SUPPORTED;
719
}
720
}
721
FIXME( "unsupported 3des algorithm property %s\n", debugstr_w(prop) );
722
return STATUS_NOT_IMPLEMENTED;
723
724
case ALG_ID_AES:
725
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
726
{
727
if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_ECB ))
728
{
729
alg->mode = CHAIN_MODE_ECB;
730
return STATUS_SUCCESS;
731
}
732
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
733
{
734
alg->mode = CHAIN_MODE_CBC;
735
return STATUS_SUCCESS;
736
}
737
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM ))
738
{
739
alg->mode = CHAIN_MODE_GCM;
740
return STATUS_SUCCESS;
741
}
742
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CFB ))
743
{
744
alg->mode = CHAIN_MODE_CFB;
745
return STATUS_SUCCESS;
746
}
747
else
748
{
749
FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
750
return STATUS_NOT_IMPLEMENTED;
751
}
752
}
753
FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) );
754
return STATUS_NOT_IMPLEMENTED;
755
756
case ALG_ID_RC4:
757
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
758
{
759
if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_NA )) return STATUS_SUCCESS;
760
761
FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
762
return STATUS_NOT_IMPLEMENTED;
763
}
764
FIXME( "unsupported rc4 algorithm property %s\n", debugstr_w(prop) );
765
return STATUS_NOT_IMPLEMENTED;
766
767
case ALG_ID_ECDH:
768
case ALG_ID_ECDSA:
769
if (!wcscmp( prop, BCRYPT_ECC_CURVE_NAME ))
770
{
771
if (!wcscmp( (WCHAR *)value, BCRYPT_ECC_CURVE_SECP256R1 ))
772
{
773
alg->curve_id = ECC_CURVE_P256R1;
774
return STATUS_SUCCESS;
775
}
776
else if (!wcscmp( (WCHAR *)value, BCRYPT_ECC_CURVE_SECP384R1 ))
777
{
778
alg->curve_id = ECC_CURVE_P384R1;
779
return STATUS_SUCCESS;
780
}
781
else if (!wcscmp( (WCHAR *)value, BCRYPT_ECC_CURVE_SECP521R1 ))
782
{
783
alg->curve_id = ECC_CURVE_P521R1;
784
return STATUS_SUCCESS;
785
}
786
FIXME( "unsupported curve %s\n", debugstr_w((WCHAR *)value) );
787
return STATUS_NOT_IMPLEMENTED;
788
}
789
FIXME( "unsupported ECDH/ECDSA algorithm property %s\n", debugstr_w(prop) );
790
return STATUS_NOT_IMPLEMENTED;
791
792
default:
793
FIXME( "unsupported algorithm %u\n", alg->id );
794
return STATUS_NOT_IMPLEMENTED;
795
}
796
}
797
798
static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
799
{
800
if (!wcscmp( prop, BCRYPT_CHAINING_MODE ))
801
{
802
if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_ECB ))
803
{
804
key->u.s.mode = CHAIN_MODE_ECB;
805
return STATUS_SUCCESS;
806
}
807
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC ))
808
{
809
key->u.s.mode = CHAIN_MODE_CBC;
810
return STATUS_SUCCESS;
811
}
812
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM ))
813
{
814
key->u.s.mode = CHAIN_MODE_GCM;
815
return STATUS_SUCCESS;
816
}
817
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CFB ))
818
{
819
key->u.s.mode = CHAIN_MODE_CFB;
820
return STATUS_SUCCESS;
821
}
822
else
823
{
824
FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
825
return STATUS_NOT_IMPLEMENTED;
826
}
827
}
828
else if (!wcscmp( prop, BCRYPT_KEY_LENGTH ))
829
{
830
if (size < sizeof(DWORD)) return STATUS_INVALID_PARAMETER;
831
key->u.a.bitlen = *(DWORD*)value;
832
return STATUS_SUCCESS;
833
}
834
else if (!wcscmp( prop, BCRYPT_DH_PARAMETERS ))
835
{
836
BCRYPT_DH_PARAMETER_HEADER *hdr = (BCRYPT_DH_PARAMETER_HEADER *)value;
837
struct key_asymmetric_import_params params;
838
839
if (key->u.a.flags & KEY_FLAG_FINALIZED) return STATUS_INVALID_HANDLE;
840
if (key->alg_id != ALG_ID_DH || size < sizeof(*hdr) || hdr->cbLength != size ||
841
hdr->dwMagic != BCRYPT_DH_PARAMETERS_MAGIC || hdr->cbKeyLength != len_from_bitlen( key->u.a.bitlen ))
842
return STATUS_INVALID_PARAMETER;
843
844
params.key = key;
845
params.flags = KEY_IMPORT_FLAG_DH_PARAMETERS;
846
params.buf = value;
847
params.len = size;
848
return UNIX_CALL( key_asymmetric_import, &params );
849
}
850
851
FIXME( "unsupported key property %s\n", debugstr_w(prop) );
852
return STATUS_NOT_IMPLEMENTED;
853
}
854
855
static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
856
{
857
NTSTATUS status;
858
859
status = generic_alg_property( hash->alg_id, prop, buf, size, ret_size );
860
if (status == STATUS_NOT_IMPLEMENTED)
861
FIXME( "unsupported property %s\n", debugstr_w(prop) );
862
return status;
863
}
864
865
static NTSTATUS get_dh_property( const struct key *key, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
866
{
867
struct key_asymmetric_export_params params;
868
869
if (wcscmp( prop, BCRYPT_DH_PARAMETERS )) return STATUS_NOT_SUPPORTED;
870
if (!(key->u.a.flags & KEY_FLAG_FINALIZED)) return STATUS_INVALID_HANDLE;
871
872
params.key = (struct key *)key;
873
params.flags = KEY_EXPORT_FLAG_DH_PARAMETERS;
874
params.buf = buf;
875
params.len = size;
876
params.ret_len = ret_size;
877
return UNIX_CALL( key_asymmetric_export, &params );
878
}
879
880
static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
881
{
882
if (!wcscmp( prop, BCRYPT_KEY_STRENGTH ))
883
{
884
*ret_size = sizeof(DWORD);
885
if (size < sizeof(DWORD)) return STATUS_BUFFER_TOO_SMALL;
886
if (buf)
887
{
888
if (is_symmetric_key(key)) *(DWORD *)buf = key->u.s.block_size * 8;
889
else *(DWORD *)buf = key->u.a.bitlen;
890
}
891
return STATUS_SUCCESS;
892
}
893
894
switch (key->alg_id)
895
{
896
case ALG_ID_3DES:
897
return get_3des_property( key->u.s.mode, prop, buf, size, ret_size );
898
899
case ALG_ID_AES:
900
if (!wcscmp( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
901
return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
902
903
case ALG_ID_DH:
904
return get_dh_property( key, prop, buf, size, ret_size );
905
906
default:
907
FIXME( "unsupported algorithm %u\n", key->alg_id );
908
return STATUS_NOT_IMPLEMENTED;
909
}
910
}
911
912
NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *buffer, ULONG count, ULONG *res,
913
ULONG flags )
914
{
915
struct object *object = get_object( handle, 0 );
916
917
TRACE( "%p, %s, %p, %lu, %p, %#lx\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
918
919
if (!object) return STATUS_INVALID_HANDLE;
920
if (!prop || !res) return STATUS_INVALID_PARAMETER;
921
922
switch (object->magic)
923
{
924
case MAGIC_ALG:
925
{
926
const struct algorithm *alg = (const struct algorithm *)object;
927
return get_alg_property( alg, prop, buffer, count, res );
928
}
929
case MAGIC_KEY:
930
{
931
const struct key *key = (const struct key *)object;
932
return get_key_property( key, prop, buffer, count, res );
933
}
934
case MAGIC_HASH:
935
{
936
const struct hash *hash = (const struct hash *)object;
937
return get_hash_property( hash, prop, buffer, count, res );
938
}
939
default:
940
WARN( "unknown magic %#lx\n", object->magic );
941
return STATUS_INVALID_HANDLE;
942
}
943
}
944
945
static void hash_prepare( struct hash *hash )
946
{
947
UCHAR buffer[MAX_HASH_BLOCK_BITS / 8] = {0};
948
int block_bytes, i;
949
950
/* initialize hash */
951
hash->desc->init( &hash->inner );
952
if (!(hash->flags & HASH_FLAG_HMAC)) return;
953
954
/* initialize hmac */
955
hash->desc->init( &hash->outer );
956
block_bytes = hash->desc->blocksize;
957
if (hash->secret_len > block_bytes)
958
{
959
hash_state temp;
960
hash->desc->init( &temp );
961
hash->desc->process( &temp, hash->secret, hash->secret_len );
962
hash->desc->done( &temp, buffer );
963
}
964
else memcpy( buffer, hash->secret, hash->secret_len );
965
966
for (i = 0; i < block_bytes; i++) buffer[i] ^= 0x5c;
967
hash->desc->process( &hash->outer, buffer, block_bytes );
968
for (i = 0; i < block_bytes; i++) buffer[i] ^= (0x5c ^ 0x36);
969
hash->desc->process( &hash->inner, buffer, block_bytes );
970
}
971
972
static NTSTATUS hash_create( const struct algorithm *alg, UCHAR *secret, ULONG secret_len, ULONG flags,
973
struct hash **ret_hash )
974
{
975
struct hash *hash;
976
const struct ltc_hash_descriptor *desc = get_hash_descriptor( alg->id );
977
978
if (!desc) return STATUS_NOT_IMPLEMENTED;
979
if (!(hash = calloc( 1, sizeof(*hash) ))) return STATUS_NO_MEMORY;
980
hash->hdr.magic = MAGIC_HASH;
981
hash->alg_id = alg->id;
982
hash->desc = desc;
983
if (alg->flags & BCRYPT_ALG_HANDLE_HMAC_FLAG) hash->flags = HASH_FLAG_HMAC;
984
if ((alg->flags & BCRYPT_HASH_REUSABLE_FLAG) || (flags & BCRYPT_HASH_REUSABLE_FLAG))
985
hash->flags |= HASH_FLAG_REUSABLE;
986
987
if (secret_len && !(hash->secret = malloc( secret_len )))
988
{
989
free( hash );
990
return STATUS_NO_MEMORY;
991
}
992
memcpy( hash->secret, secret, secret_len );
993
hash->secret_len = secret_len;
994
995
hash_prepare( hash );
996
*ret_hash = hash;
997
return STATUS_SUCCESS;
998
}
999
1000
NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE handle, BCRYPT_HASH_HANDLE *ret_handle, UCHAR *object,
1001
ULONG object_len, UCHAR *secret, ULONG secret_len, ULONG flags )
1002
{
1003
struct algorithm *alg = get_alg_object( handle );
1004
struct hash *hash;
1005
NTSTATUS status;
1006
1007
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle, ret_handle, object, object_len, secret, secret_len, flags );
1008
if (flags & ~BCRYPT_HASH_REUSABLE_FLAG)
1009
{
1010
FIXME( "unimplemented flags %#lx\n", flags );
1011
return STATUS_NOT_IMPLEMENTED;
1012
}
1013
if (object) FIXME( "ignoring object buffer\n" );
1014
1015
if (!alg) return STATUS_INVALID_HANDLE;
1016
if (!ret_handle) return STATUS_INVALID_PARAMETER;
1017
1018
if ((status = hash_create( alg, secret, secret_len, flags, &hash ))) return status;
1019
*ret_handle = hash;
1020
TRACE( "returning handle %p\n", *ret_handle );
1021
return STATUS_SUCCESS;
1022
}
1023
1024
NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HANDLE *handle_copy,
1025
UCHAR *object, ULONG objectlen, ULONG flags )
1026
{
1027
struct hash *hash_orig = get_hash_object( handle );
1028
struct hash *hash_copy;
1029
1030
TRACE( "%p, %p, %p, %lu, %#lx\n", handle, handle_copy, object, objectlen, flags );
1031
1032
if (!hash_orig) return STATUS_INVALID_HANDLE;
1033
if (!handle_copy) return STATUS_INVALID_PARAMETER;
1034
if (object) FIXME( "ignoring object buffer\n" );
1035
1036
if (!(hash_copy = malloc( sizeof(*hash_copy) ))) return STATUS_NO_MEMORY;
1037
1038
memcpy( hash_copy, hash_orig, sizeof(*hash_orig) );
1039
if (hash_orig->secret && !(hash_copy->secret = malloc( hash_orig->secret_len )))
1040
{
1041
free( hash_copy );
1042
return STATUS_NO_MEMORY;
1043
}
1044
memcpy( hash_copy->secret, hash_orig->secret, hash_orig->secret_len );
1045
1046
*handle_copy = hash_copy;
1047
TRACE( "returning handle %p\n", *handle_copy );
1048
return STATUS_SUCCESS;
1049
}
1050
1051
static void hash_destroy( struct hash *hash )
1052
{
1053
if (!hash) return;
1054
free( hash->secret );
1055
destroy_object( &hash->hdr );
1056
}
1057
1058
NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
1059
{
1060
struct hash *hash = get_hash_object( handle );
1061
1062
TRACE( "%p\n", handle );
1063
1064
if (!hash) return STATUS_INVALID_PARAMETER;
1065
hash_destroy( hash );
1066
return STATUS_SUCCESS;
1067
}
1068
1069
NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
1070
{
1071
struct hash *hash = get_hash_object( handle );
1072
1073
TRACE( "%p, %p, %lu, %#lx\n", handle, input, size, flags );
1074
1075
if (!hash) return STATUS_INVALID_HANDLE;
1076
if (!input) return STATUS_SUCCESS;
1077
1078
if (hash->desc->process( &hash->inner, input, size )) return STATUS_INVALID_PARAMETER;
1079
return STATUS_SUCCESS;
1080
}
1081
1082
static void hash_finalize( struct hash *hash, UCHAR *output )
1083
{
1084
UCHAR buffer[MAX_HASH_OUTPUT_BYTES];
1085
1086
if (!(hash->flags & HASH_FLAG_HMAC))
1087
{
1088
hash->desc->done( &hash->inner, output );
1089
if (hash->flags & HASH_FLAG_REUSABLE) hash_prepare( hash );
1090
return;
1091
}
1092
1093
hash->desc->done( &hash->inner, buffer );
1094
hash->desc->process( &hash->outer, buffer, hash->desc->hashsize );
1095
hash->desc->done( &hash->outer, output );
1096
1097
if (hash->flags & HASH_FLAG_REUSABLE) hash_prepare( hash );
1098
}
1099
1100
NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
1101
{
1102
struct hash *hash = get_hash_object( handle );
1103
1104
TRACE( "%p, %p, %lu, %#lx\n", handle, output, size, flags );
1105
1106
if (!hash) return STATUS_INVALID_HANDLE;
1107
if (!output || size != hash->desc->hashsize) return STATUS_INVALID_PARAMETER;
1108
1109
hash_finalize( hash, output );
1110
return STATUS_SUCCESS;
1111
}
1112
1113
static NTSTATUS hash_single( struct algorithm *alg, UCHAR *secret, ULONG secret_len, UCHAR *input, ULONG input_len,
1114
UCHAR *output, ULONG output_len )
1115
{
1116
struct hash *hash;
1117
NTSTATUS status;
1118
1119
if ((status = hash_create( alg, secret, secret_len, 0, &hash ))) return status;
1120
if (input_len && hash->desc->process( &hash->inner, input, input_len ))
1121
{
1122
hash_destroy( hash );
1123
return STATUS_INVALID_PARAMETER;
1124
}
1125
hash_finalize( hash, output );
1126
hash_destroy( hash );
1127
return STATUS_SUCCESS;
1128
}
1129
1130
NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE handle, UCHAR *secret, ULONG secret_len, UCHAR *input, ULONG input_len,
1131
UCHAR *output, ULONG output_len )
1132
{
1133
struct algorithm *alg = get_alg_object( handle );
1134
1135
TRACE( "%p, %p, %lu, %p, %lu, %p, %lu\n", handle, secret, secret_len, input, input_len, output, output_len );
1136
1137
if (!alg) return STATUS_INVALID_HANDLE;
1138
if (!output || output_len != builtin_algorithms[alg->id].hash_length) return STATUS_INVALID_PARAMETER;
1139
1140
return hash_single(alg, secret, secret_len, input, input_len, output, output_len );
1141
}
1142
1143
static ULONG curve_strength( enum ecc_curve_id curve_id )
1144
{
1145
switch (curve_id)
1146
{
1147
case ECC_CURVE_P256R1: return 256;
1148
case ECC_CURVE_P384R1: return 384;
1149
case ECC_CURVE_P521R1: return 521;
1150
default:
1151
FIXME( "unsupported curve %u\n", curve_id );
1152
return 0;
1153
}
1154
}
1155
1156
static NTSTATUS key_asymmetric_create( enum alg_id alg_id, enum ecc_curve_id curve_id, ULONG bitlen, struct key **ret_key )
1157
{
1158
struct key *key;
1159
1160
if (!__wine_unixlib_handle)
1161
{
1162
ERR( "no encryption support\n" );
1163
return STATUS_NOT_IMPLEMENTED;
1164
}
1165
1166
if (alg_id == ALG_ID_DH && bitlen < 512) return STATUS_INVALID_PARAMETER;
1167
1168
if (!(key = calloc( 1, sizeof(*key) ))) return STATUS_NO_MEMORY;
1169
key->hdr.magic = MAGIC_KEY;
1170
key->alg_id = alg_id;
1171
key->u.a.bitlen = curve_id ? curve_strength( curve_id ) : bitlen;
1172
key->u.a.curve_id = curve_id;
1173
1174
*ret_key = key;
1175
return STATUS_SUCCESS;
1176
}
1177
1178
static BOOL is_equal_vector( const UCHAR *vector, ULONG len, const UCHAR *vector2, ULONG len2 )
1179
{
1180
if (!vector && !vector2) return TRUE;
1181
if (len != len2) return FALSE;
1182
return !memcmp( vector, vector2, len );
1183
}
1184
1185
static NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG vector_len, BOOL force_reset )
1186
{
1187
BOOL needs_reset = force_reset || !is_equal_vector( key->u.s.vector, key->u.s.vector_len, vector, vector_len );
1188
if (vector)
1189
{
1190
free( key->u.s.vector );
1191
key->u.s.vector = NULL;
1192
key->u.s.vector_len = 0;
1193
1194
if (!(key->u.s.vector = malloc( vector_len ))) return STATUS_NO_MEMORY;
1195
memcpy( key->u.s.vector, vector, vector_len );
1196
key->u.s.vector_len = vector_len;
1197
}
1198
if (needs_reset) UNIX_CALL( key_symmetric_vector_reset, key );
1199
return STATUS_SUCCESS;
1200
}
1201
1202
static struct key *key_symmetric_create( enum alg_id alg, enum chain_mode mode, ULONG block_size, const UCHAR *secret,
1203
ULONG secret_len )
1204
{
1205
struct key *ret;
1206
1207
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
1208
InitializeCriticalSection( &ret->u.s.cs );
1209
ret->hdr.magic = MAGIC_KEY;
1210
ret->alg_id = alg;
1211
ret->u.s.mode = mode;
1212
ret->u.s.block_size = block_size;
1213
1214
if (!(ret->u.s.secret = malloc( secret_len )))
1215
{
1216
DeleteCriticalSection( &ret->u.s.cs );
1217
free( ret );
1218
return NULL;
1219
}
1220
memcpy( ret->u.s.secret, secret, secret_len );
1221
ret->u.s.secret_len = secret_len;
1222
1223
return ret;
1224
}
1225
1226
static void key_destroy( struct key *key )
1227
{
1228
if (is_symmetric_key( key ))
1229
{
1230
UNIX_CALL( key_symmetric_destroy, key );
1231
free( key->u.s.vector );
1232
free( key->u.s.secret );
1233
DeleteCriticalSection( &key->u.s.cs );
1234
}
1235
else
1236
UNIX_CALL( key_asymmetric_destroy, key );
1237
1238
destroy_object( &key->hdr );
1239
}
1240
1241
static ULONG get_block_size( struct algorithm *alg )
1242
{
1243
ULONG ret = 0, size = sizeof(ret);
1244
get_alg_property( alg, BCRYPT_BLOCK_LENGTH, (UCHAR *)&ret, sizeof(ret), &size );
1245
return ret;
1246
}
1247
1248
static NTSTATUS key_symmetric_generate( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_handle, const UCHAR *secret,
1249
ULONG secret_len )
1250
{
1251
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
1252
ULONG block_size, size;
1253
struct key *key;
1254
NTSTATUS status;
1255
1256
if (alg->id == ALG_ID_PBKDF2 &&
1257
!get_alg_property( alg, BCRYPT_KEY_LENGTHS, (UCHAR *)&key_lengths, sizeof(key_lengths), &size ))
1258
{
1259
if (secret_len > key_lengths.dwMaxLength / 8 || secret_len < key_lengths.dwMinLength / 8)
1260
return STATUS_INVALID_PARAMETER;
1261
block_size = secret_len;
1262
}
1263
else if (!(block_size = get_block_size( alg ))) return STATUS_INVALID_PARAMETER;
1264
else if (!get_alg_property( alg, BCRYPT_KEY_LENGTHS, (UCHAR *)&key_lengths, sizeof(key_lengths), &size ))
1265
{
1266
if (secret_len > (size = key_lengths.dwMaxLength / 8))
1267
{
1268
WARN( "secret_len %lu exceeds key max length %lu, setting to maximum\n", secret_len, size );
1269
secret_len = size;
1270
}
1271
else if (secret_len < (size = key_lengths.dwMinLength / 8))
1272
{
1273
WARN( "secret_len %lu is less than minimum key length %lu\n", secret_len, size );
1274
return STATUS_INVALID_PARAMETER;
1275
}
1276
else if (key_lengths.dwIncrement && (secret_len * 8 - key_lengths.dwMinLength) % key_lengths.dwIncrement)
1277
{
1278
WARN( "secret_len %lu is not a valid key length\n", secret_len );
1279
return STATUS_INVALID_PARAMETER;
1280
}
1281
}
1282
1283
if (!(key = key_symmetric_create( alg->id, alg->mode, block_size, secret, secret_len ))) status = STATUS_NO_MEMORY;
1284
else
1285
{
1286
*ret_handle = key;
1287
status = STATUS_SUCCESS;
1288
}
1289
1290
return status;
1291
}
1292
1293
static NTSTATUS key_symmetric_decrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1294
ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1295
{
1296
struct key_symmetric_set_auth_data_params auth_params;
1297
struct key_symmetric_decrypt_params decrypt_params;
1298
struct key_symmetric_get_tag_params tag_params;
1299
ULONG bytes_left = input_len;
1300
NTSTATUS status;
1301
1302
if (key->u.s.mode == CHAIN_MODE_GCM)
1303
{
1304
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
1305
UCHAR tag[16];
1306
1307
if (!auth_info) return STATUS_INVALID_PARAMETER;
1308
if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
1309
if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
1310
if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
1311
1312
if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce, TRUE )))
1313
return status;
1314
1315
*ret_len = input_len;
1316
if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
1317
if (!output) return STATUS_SUCCESS;
1318
if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1319
1320
auth_params.key = key;
1321
auth_params.auth_data = auth_info->pbAuthData;
1322
auth_params.len = auth_info->cbAuthData;
1323
if ((status = UNIX_CALL( key_symmetric_set_auth_data, &auth_params ))) return status;
1324
1325
decrypt_params.key = key;
1326
decrypt_params.input = input;
1327
decrypt_params.input_len = input_len;
1328
decrypt_params.output = output;
1329
decrypt_params.output_len = output_len;
1330
if ((status = UNIX_CALL( key_symmetric_decrypt, &decrypt_params ))) return status;
1331
1332
tag_params.key = key;
1333
tag_params.tag = tag;
1334
tag_params.len = sizeof(tag);
1335
if ((status = UNIX_CALL( key_symmetric_get_tag, &tag_params ))) return status;
1336
if (memcmp( tag, auth_info->pbTag, auth_info->cbTag )) return STATUS_AUTH_TAG_MISMATCH;
1337
1338
return STATUS_SUCCESS;
1339
}
1340
1341
*ret_len = input_len;
1342
1343
if (input_len & (key->u.s.block_size - 1)) return STATUS_INVALID_BUFFER_SIZE;
1344
if (!output) return STATUS_SUCCESS;
1345
if (flags & BCRYPT_BLOCK_PADDING)
1346
{
1347
if (output_len + key->u.s.block_size < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1348
if (input_len < key->u.s.block_size) return STATUS_BUFFER_TOO_SMALL;
1349
bytes_left -= key->u.s.block_size;
1350
}
1351
else if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1352
1353
if (key->u.s.mode == CHAIN_MODE_ECB && iv) return STATUS_INVALID_PARAMETER;
1354
if ((status = key_symmetric_set_vector( key, iv, iv_len, flags & BCRYPT_BLOCK_PADDING ))) return status;
1355
1356
decrypt_params.key = key;
1357
decrypt_params.input = input;
1358
decrypt_params.input_len = key->u.s.block_size;
1359
decrypt_params.output = output;
1360
decrypt_params.output_len = key->u.s.block_size;
1361
while (bytes_left >= key->u.s.block_size)
1362
{
1363
if ((status = UNIX_CALL( key_symmetric_decrypt, &decrypt_params ))) return status;
1364
if (key->u.s.mode == CHAIN_MODE_ECB && (status = key_symmetric_set_vector( key, NULL, 0, TRUE )))
1365
return status;
1366
bytes_left -= key->u.s.block_size;
1367
decrypt_params.input += key->u.s.block_size;
1368
decrypt_params.output += key->u.s.block_size;
1369
}
1370
1371
if (flags & BCRYPT_BLOCK_PADDING)
1372
{
1373
UCHAR *buf, *dst = decrypt_params.output;
1374
if (!(buf = malloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
1375
decrypt_params.output = buf;
1376
status = UNIX_CALL( key_symmetric_decrypt, &decrypt_params );
1377
if (!status && buf[ key->u.s.block_size - 1 ] <= key->u.s.block_size)
1378
{
1379
*ret_len -= buf[ key->u.s.block_size - 1 ];
1380
if (output_len < *ret_len) status = STATUS_BUFFER_TOO_SMALL;
1381
else memcpy( dst, buf, key->u.s.block_size - buf[ key->u.s.block_size - 1 ] );
1382
}
1383
else status = STATUS_UNSUCCESSFUL; /* FIXME: invalid padding */
1384
free( buf );
1385
}
1386
1387
if (!status)
1388
{
1389
if (key->u.s.vector && input_len >= key->u.s.vector_len)
1390
{
1391
memcpy( key->u.s.vector, input + input_len - key->u.s.vector_len, key->u.s.vector_len );
1392
if (iv) memcpy( iv, key->u.s.vector, min( iv_len, key->u.s.vector_len ));
1393
}
1394
else if (key->u.s.vector)
1395
FIXME( "Unexpected vector len %lu, *ret_len %lu.\n", key->u.s.vector_len, *ret_len );
1396
}
1397
1398
return status;
1399
}
1400
1401
/* AES Key Wrap Algorithm (RFC3394) */
1402
static NTSTATUS aes_unwrap( const UCHAR *secret, ULONG secret_len, const UCHAR *cipher, ULONG cipher_len, UCHAR *plain )
1403
{
1404
UCHAR a[8], *r, b[16];
1405
ULONG len, t, i, n = cipher_len / 8;
1406
int j;
1407
struct key *key;
1408
1409
memcpy( a, cipher, 8 );
1410
r = plain;
1411
memcpy( r, cipher + 8, 8 * n );
1412
1413
if (!(key = key_symmetric_create( ALG_ID_AES, CHAIN_MODE_ECB, 16, secret, secret_len ))) return STATUS_NO_MEMORY;
1414
1415
for (j = 5; j >= 0; j--)
1416
{
1417
r = plain + (n - 1) * 8;
1418
for (i = n; i >= 1; i--)
1419
{
1420
memcpy( b, a, 8 );
1421
t = n * j + i;
1422
b[7] ^= t;
1423
b[6] ^= t >> 8;
1424
b[5] ^= t >> 16;
1425
b[4] ^= t >> 24;
1426
1427
memcpy( b + 8, r, 8 );
1428
key_symmetric_decrypt( key, b, 16, NULL, NULL, 0, b, 16, &len, 0 );
1429
memcpy( a, b, 8 );
1430
memcpy( r, b + 8, 8 );
1431
r -= 8;
1432
}
1433
}
1434
1435
key_destroy( key );
1436
1437
for (i = 0; i < 8; i++) if (a[i] != 0xa6) return STATUS_UNSUCCESSFUL;
1438
return STATUS_SUCCESS;
1439
}
1440
1441
static NTSTATUS key_import( struct algorithm *alg, struct key *decrypt_key, const WCHAR *type, BCRYPT_KEY_HANDLE *key,
1442
UCHAR *object, ULONG object_len, UCHAR *input, ULONG input_len )
1443
{
1444
ULONG len;
1445
NTSTATUS status;
1446
1447
if (decrypt_key && wcscmp( type, BCRYPT_AES_WRAP_KEY_BLOB ))
1448
{
1449
FIXME( "decryption of key not supported\n" );
1450
return STATUS_NOT_IMPLEMENTED;
1451
}
1452
1453
if (!wcscmp( type, BCRYPT_KEY_DATA_BLOB ))
1454
{
1455
BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)input;
1456
1457
if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) return STATUS_BUFFER_TOO_SMALL;
1458
if (header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) return STATUS_INVALID_PARAMETER;
1459
if (header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1)
1460
{
1461
FIXME( "unknown key data blob version %lu\n", header->dwVersion );
1462
return STATUS_INVALID_PARAMETER;
1463
}
1464
len = header->cbKeyData;
1465
if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER;
1466
1467
return key_symmetric_generate( alg, key, (UCHAR *)&header[1], len );
1468
}
1469
else if (!wcscmp( type, BCRYPT_OPAQUE_KEY_BLOB ))
1470
{
1471
if (input_len < sizeof(len)) return STATUS_BUFFER_TOO_SMALL;
1472
len = *(ULONG *)input;
1473
if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER;
1474
1475
return key_symmetric_generate( alg, key, input + sizeof(len), len );
1476
}
1477
else if (!wcscmp( type, BCRYPT_AES_WRAP_KEY_BLOB ))
1478
{
1479
UCHAR output[32];
1480
1481
if (!decrypt_key || input_len < 8) return STATUS_INVALID_PARAMETER;
1482
1483
len = input_len - 8;
1484
if (len < BLOCK_LENGTH_AES || len & (BLOCK_LENGTH_AES - 1)) return STATUS_INVALID_PARAMETER;
1485
1486
if ((status = aes_unwrap( decrypt_key->u.s.secret, decrypt_key->u.s.secret_len, input, len, output )))
1487
return status;
1488
1489
return key_symmetric_generate( alg, key, output, len );
1490
}
1491
1492
FIXME( "unsupported key type %s\n", debugstr_w(type) );
1493
return STATUS_NOT_IMPLEMENTED;
1494
}
1495
1496
static NTSTATUS key_symmetric_encrypt( struct key *key, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
1497
ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
1498
{
1499
struct key_symmetric_set_auth_data_params auth_params;
1500
struct key_symmetric_encrypt_params encrypt_params;
1501
struct key_symmetric_get_tag_params tag_params;
1502
ULONG bytes_left = input_len;
1503
UCHAR *buf;
1504
NTSTATUS status;
1505
1506
if (key->u.s.mode == CHAIN_MODE_GCM)
1507
{
1508
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
1509
1510
if (!auth_info) return STATUS_INVALID_PARAMETER;
1511
if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
1512
if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
1513
if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
1514
if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
1515
FIXME( "call chaining not implemented\n" );
1516
1517
if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce, TRUE )))
1518
return status;
1519
1520
*ret_len = input_len;
1521
if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
1522
if (input && !output) return STATUS_SUCCESS;
1523
if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1524
1525
auth_params.key = key;
1526
auth_params.auth_data = auth_info->pbAuthData;
1527
auth_params.len = auth_info->cbAuthData;
1528
if ((status = UNIX_CALL( key_symmetric_set_auth_data, &auth_params ))) return status;
1529
1530
encrypt_params.key = key;
1531
encrypt_params.input = input;
1532
encrypt_params.input_len = input_len;
1533
encrypt_params.output = output;
1534
encrypt_params.output_len = output_len;
1535
if ((status = UNIX_CALL( key_symmetric_encrypt, &encrypt_params ))) return status;
1536
1537
tag_params.key = key;
1538
tag_params.tag = auth_info->pbTag;
1539
tag_params.len = auth_info->cbTag;
1540
return UNIX_CALL( key_symmetric_get_tag, &tag_params );
1541
}
1542
1543
*ret_len = input_len;
1544
1545
if (flags & BCRYPT_BLOCK_PADDING)
1546
*ret_len = (input_len + key->u.s.block_size) & ~(key->u.s.block_size - 1);
1547
else if (input_len & (key->u.s.block_size - 1))
1548
return STATUS_INVALID_BUFFER_SIZE;
1549
1550
if (!output) return STATUS_SUCCESS;
1551
if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
1552
if (key->u.s.mode == CHAIN_MODE_ECB && iv) return STATUS_INVALID_PARAMETER;
1553
if ((status = key_symmetric_set_vector( key, iv, iv_len, flags & BCRYPT_BLOCK_PADDING ))) return status;
1554
1555
encrypt_params.key = key;
1556
encrypt_params.input = input;
1557
encrypt_params.input_len = key->u.s.block_size;
1558
encrypt_params.output = output;
1559
encrypt_params.output_len = key->u.s.block_size;
1560
while (bytes_left >= key->u.s.block_size)
1561
{
1562
if ((status = UNIX_CALL( key_symmetric_encrypt, &encrypt_params )))
1563
return status;
1564
if (key->u.s.mode == CHAIN_MODE_ECB && (status = key_symmetric_set_vector( key, NULL, 0, TRUE )))
1565
return status;
1566
bytes_left -= key->u.s.block_size;
1567
encrypt_params.input += key->u.s.block_size;
1568
encrypt_params.output += key->u.s.block_size;
1569
}
1570
1571
if (flags & BCRYPT_BLOCK_PADDING)
1572
{
1573
if (!(buf = malloc( key->u.s.block_size ))) return STATUS_NO_MEMORY;
1574
memcpy( buf, encrypt_params.input, bytes_left );
1575
memset( buf + bytes_left, key->u.s.block_size - bytes_left, key->u.s.block_size - bytes_left );
1576
encrypt_params.input = buf;
1577
status = UNIX_CALL( key_symmetric_encrypt, &encrypt_params );
1578
free( buf );
1579
}
1580
1581
if (!status)
1582
{
1583
if (key->u.s.vector && *ret_len >= key->u.s.vector_len)
1584
{
1585
memcpy( key->u.s.vector, output + *ret_len - key->u.s.vector_len, key->u.s.vector_len );
1586
if (iv) memcpy( iv, key->u.s.vector, min( iv_len, key->u.s.vector_len ));
1587
}
1588
else if (key->u.s.vector)
1589
FIXME( "Unexpected vector len %lu, *ret_len %lu.\n", key->u.s.vector_len, *ret_len );
1590
}
1591
1592
return status;
1593
}
1594
1595
/* AES Key Wrap Algorithm (RFC3394) */
1596
static NTSTATUS aes_wrap( const UCHAR *secret, ULONG secret_len, const UCHAR *plain, ULONG plain_len, UCHAR *cipher )
1597
{
1598
UCHAR *a, *r, b[16];
1599
ULONG len, t, i, j, n = plain_len / 8;
1600
struct key *key;
1601
1602
a = cipher;
1603
r = cipher + 8;
1604
1605
memset( a, 0xa6, 8 );
1606
memcpy( r, plain, 8 * n );
1607
1608
if (!(key = key_symmetric_create( ALG_ID_AES, CHAIN_MODE_ECB, 16, secret, secret_len ))) return STATUS_NO_MEMORY;
1609
1610
for (j = 0; j <= 5; j++)
1611
{
1612
r = cipher + 8;
1613
for (i = 1; i <= n; i++)
1614
{
1615
memcpy( b, a, 8 );
1616
memcpy( b + 8, r, 8 );
1617
key_symmetric_encrypt( key, b, 16, NULL, NULL, 0, b, 16, &len, 0 );
1618
memcpy( a, b, 8 );
1619
t = n * j + i;
1620
a[7] ^= t;
1621
a[6] ^= t >> 8;
1622
a[5] ^= t >> 16;
1623
a[4] ^= t >> 24;
1624
memcpy( r, b + 8, 8 );
1625
r += 8;
1626
}
1627
}
1628
1629
key_destroy( key );
1630
return STATUS_SUCCESS;
1631
}
1632
1633
static NTSTATUS key_export( struct key *key, struct key *encrypt_key, const WCHAR *type, UCHAR *output,
1634
ULONG output_len, ULONG *size )
1635
{
1636
struct key_asymmetric_export_params params;
1637
NTSTATUS status;
1638
1639
if (encrypt_key && wcscmp( type, BCRYPT_AES_WRAP_KEY_BLOB ))
1640
{
1641
FIXME( "encryption of key not supported\n" );
1642
return STATUS_NOT_IMPLEMENTED;
1643
}
1644
1645
if (!wcscmp( type, BCRYPT_KEY_DATA_BLOB ))
1646
{
1647
BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)output;
1648
ULONG req_size = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key->u.s.secret_len;
1649
1650
*size = req_size;
1651
if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
1652
if (output)
1653
{
1654
header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
1655
header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
1656
header->cbKeyData = key->u.s.secret_len;
1657
memcpy( &header[1], key->u.s.secret, key->u.s.secret_len );
1658
}
1659
return STATUS_SUCCESS;
1660
}
1661
else if (!wcscmp( type, BCRYPT_OPAQUE_KEY_BLOB ))
1662
{
1663
ULONG len, req_size = sizeof(len) + key->u.s.secret_len;
1664
1665
*size = req_size;
1666
if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
1667
if (output)
1668
{
1669
*(ULONG *)output = key->u.s.secret_len;
1670
memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len );
1671
}
1672
return STATUS_SUCCESS;
1673
}
1674
else if (!wcscmp( type, BCRYPT_DSA_PRIVATE_BLOB ) || !wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB ) ||
1675
!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_DH_PRIVATE_BLOB ))
1676
{
1677
params.key = key;
1678
params.flags = 0;
1679
params.buf = output;
1680
params.len = output_len;
1681
params.ret_len = size;
1682
return UNIX_CALL( key_asymmetric_export, &params );
1683
}
1684
else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB ))
1685
{
1686
params.key = key;
1687
params.flags = (wcscmp( type, BCRYPT_RSAPRIVATE_BLOB )) ? KEY_EXPORT_FLAG_RSA_FULL : 0;
1688
params.buf = output;
1689
params.len = output_len;
1690
params.ret_len = size;
1691
return UNIX_CALL( key_asymmetric_export, &params );
1692
}
1693
else if (!wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ) || !wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB ) ||
1694
!wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ) || !wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ) ||
1695
!wcscmp( type, BCRYPT_DH_PUBLIC_BLOB ))
1696
{
1697
params.key = key;
1698
params.flags = KEY_EXPORT_FLAG_PUBLIC;
1699
params.buf = output;
1700
params.len = output_len;
1701
params.ret_len = size;
1702
return UNIX_CALL( key_asymmetric_export, &params );
1703
}
1704
else if (!wcscmp( type, BCRYPT_AES_WRAP_KEY_BLOB ))
1705
{
1706
ULONG req_size = key->u.s.secret_len + 8;
1707
1708
if (!encrypt_key) return STATUS_INVALID_PARAMETER;
1709
1710
*size = req_size;
1711
if (output)
1712
{
1713
if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
1714
if ((status = aes_wrap( encrypt_key->u.s.secret, encrypt_key->u.s.secret_len, key->u.s.secret, key->u.s.secret_len, output )))
1715
return status;
1716
}
1717
return STATUS_SUCCESS;
1718
}
1719
1720
FIXME( "unsupported key type %s\n", debugstr_w(type) );
1721
return STATUS_NOT_IMPLEMENTED;
1722
}
1723
1724
static NTSTATUS convert_legacy_rsaprivate_blob( struct algorithm *alg, BCRYPT_RSAKEY_BLOB **rsa_data,
1725
ULONG *rsa_len, UCHAR *input, ULONG input_len )
1726
{
1727
struct {
1728
PUBLICKEYSTRUC header;
1729
RSAPUBKEY rsapubkey;
1730
} *blob = (void *)input;
1731
ULONG len, pos;
1732
UCHAR *conv;
1733
int i;
1734
1735
if (alg->id != ALG_ID_RSA) return STATUS_NOT_SUPPORTED;
1736
if (input_len < sizeof(*blob)) return NTE_BAD_DATA;
1737
if (blob->header.bType != PRIVATEKEYBLOB || blob->header.bVersion != CUR_BLOB_VERSION ||
1738
blob->header.aiKeyAlg != CALG_RSA_KEYX ||
1739
blob->rsapubkey.magic != BCRYPT_RSAPRIVATE_MAGIC ||
1740
input_len != sizeof(*blob) + blob->rsapubkey.bitlen / 16 * 9) return NTE_BAD_DATA;
1741
if (blob->rsapubkey.bitlen & 0xf) return STATUS_INVALID_PARAMETER;
1742
1743
len = sizeof(**rsa_data) + sizeof(blob->rsapubkey.pubexp) + blob->rsapubkey.bitlen / 4;
1744
if (!(conv = malloc( len ))) return STATUS_NO_MEMORY;
1745
1746
*rsa_data = (BCRYPT_RSAKEY_BLOB *)conv;
1747
(*rsa_data)->Magic = blob->rsapubkey.magic;
1748
(*rsa_data)->BitLength = blob->rsapubkey.bitlen;
1749
(*rsa_data)->cbPublicExp = sizeof(blob->rsapubkey.pubexp);
1750
(*rsa_data)->cbModulus = blob->rsapubkey.bitlen / 8;
1751
(*rsa_data)->cbPrime1 = blob->rsapubkey.bitlen / 16;
1752
(*rsa_data)->cbPrime2 = blob->rsapubkey.bitlen / 16;
1753
len = sizeof(**rsa_data);
1754
1755
for(i = 0; i < (*rsa_data)->cbPublicExp; i++)
1756
conv[len++] = ((UCHAR *)&blob->rsapubkey.pubexp)[(*rsa_data)->cbPublicExp - i - 1];
1757
pos = sizeof(*blob);
1758
for(i = 0; i < (*rsa_data)->cbModulus; i++)
1759
conv[len++] = input[pos + (*rsa_data)->cbModulus - i - 1];
1760
pos += (*rsa_data)->cbModulus;
1761
for(i = 0; i < (*rsa_data)->cbPrime1; i++)
1762
conv[len++] = input[pos + (*rsa_data)->cbPrime1 - i - 1];
1763
pos += (*rsa_data)->cbPrime1;
1764
for(i = 0; i < (*rsa_data)->cbPrime2; i++)
1765
conv[len++] = input[pos + (*rsa_data)->cbPrime2 - i - 1];
1766
1767
*rsa_len = len;
1768
return STATUS_SUCCESS;
1769
}
1770
1771
static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
1772
ULONG input_len )
1773
{
1774
struct key_asymmetric_import_params params;
1775
struct key *key;
1776
NTSTATUS status;
1777
ULONG size;
1778
1779
if (!wcscmp( type, BCRYPT_ECCPUBLIC_BLOB ))
1780
{
1781
BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
1782
DWORD bitlen, magic;
1783
enum ecc_curve_id curve;
1784
1785
if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
1786
1787
switch (alg->id)
1788
{
1789
case ALG_ID_ECDH_P256:
1790
bitlen = 256;
1791
curve = ECC_CURVE_P256R1;
1792
magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
1793
break;
1794
1795
case ALG_ID_ECDH_P384:
1796
bitlen = 384;
1797
curve = ECC_CURVE_P384R1;
1798
magic = BCRYPT_ECDH_PUBLIC_P384_MAGIC;
1799
break;
1800
1801
case ALG_ID_ECDH_P521:
1802
bitlen = 521;
1803
curve = ECC_CURVE_P521R1;
1804
magic = BCRYPT_ECDH_PUBLIC_P521_MAGIC;
1805
break;
1806
1807
case ALG_ID_ECDSA_P256:
1808
bitlen = 256;
1809
curve = ECC_CURVE_P256R1;
1810
magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
1811
break;
1812
1813
case ALG_ID_ECDSA_P384:
1814
bitlen = 384;
1815
curve = ECC_CURVE_P384R1;
1816
magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
1817
break;
1818
1819
case ALG_ID_ECDSA_P521:
1820
bitlen = 521;
1821
curve = ECC_CURVE_P521R1;
1822
magic = BCRYPT_ECDSA_PUBLIC_P521_MAGIC;
1823
break;
1824
1825
default:
1826
FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
1827
return STATUS_NOT_SUPPORTED;
1828
}
1829
1830
if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER;
1831
if (ecc_blob->cbKey != len_from_bitlen( bitlen ) || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2)
1832
return STATUS_INVALID_PARAMETER;
1833
1834
if ((status = key_asymmetric_create( alg->id, curve, bitlen, &key ))) return status;
1835
params.key = key;
1836
params.flags = KEY_IMPORT_FLAG_PUBLIC;
1837
params.buf = input;
1838
params.len = input_len;
1839
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
1840
{
1841
key_destroy( key );
1842
return status;
1843
}
1844
}
1845
else if (!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB ))
1846
{
1847
BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
1848
DWORD bitlen, magic;
1849
enum ecc_curve_id curve;
1850
1851
if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER;
1852
1853
switch (alg->id)
1854
{
1855
case ALG_ID_ECDH_P256:
1856
bitlen = 256;
1857
curve = ECC_CURVE_P256R1;
1858
magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
1859
break;
1860
1861
case ALG_ID_ECDH_P384:
1862
bitlen = 384;
1863
curve = ECC_CURVE_P384R1;
1864
magic = BCRYPT_ECDH_PRIVATE_P384_MAGIC;
1865
break;
1866
1867
case ALG_ID_ECDH_P521:
1868
bitlen = 521;
1869
curve = ECC_CURVE_P521R1;
1870
magic = BCRYPT_ECDH_PRIVATE_P521_MAGIC;
1871
break;
1872
1873
case ALG_ID_ECDSA_P256:
1874
bitlen = 256;
1875
curve = ECC_CURVE_P256R1;
1876
magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC;
1877
break;
1878
1879
case ALG_ID_ECDSA_P384:
1880
bitlen = 384;
1881
curve = ECC_CURVE_P384R1;
1882
magic = BCRYPT_ECDSA_PRIVATE_P384_MAGIC;
1883
break;
1884
1885
case ALG_ID_ECDSA_P521:
1886
bitlen = 521;
1887
curve = ECC_CURVE_P521R1;
1888
magic = BCRYPT_ECDSA_PRIVATE_P521_MAGIC;
1889
break;
1890
1891
default:
1892
FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) );
1893
return STATUS_NOT_SUPPORTED;
1894
}
1895
1896
if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER;
1897
if (ecc_blob->cbKey != len_from_bitlen( bitlen ) || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3)
1898
return STATUS_INVALID_PARAMETER;
1899
1900
if ((status = key_asymmetric_create( alg->id, curve, bitlen, &key ))) return status;
1901
params.key = key;
1902
params.flags = 0;
1903
params.buf = input;
1904
params.len = input_len;
1905
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
1906
{
1907
key_destroy( key );
1908
return status;
1909
}
1910
}
1911
else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB ))
1912
{
1913
BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
1914
1915
if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER;
1916
if ((alg->id != ALG_ID_RSA && alg->id != ALG_ID_RSA_SIGN) || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC)
1917
return STATUS_NOT_SUPPORTED;
1918
1919
size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
1920
if (size != input_len) return NTE_BAD_DATA;
1921
1922
if ((status = key_asymmetric_create( alg->id, 0, rsa_blob->BitLength, &key ))) return status;
1923
params.key = key;
1924
params.flags = KEY_IMPORT_FLAG_PUBLIC;
1925
params.buf = input;
1926
params.len = input_len;
1927
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
1928
{
1929
key_destroy( key );
1930
return status;
1931
}
1932
}
1933
else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB ))
1934
{
1935
BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input;
1936
1937
if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER;
1938
if (alg->id != ALG_ID_RSA || (rsa_blob->Magic != BCRYPT_RSAPRIVATE_MAGIC &&
1939
rsa_blob->Magic != BCRYPT_RSAFULLPRIVATE_MAGIC)) return STATUS_NOT_SUPPORTED;
1940
1941
if ((status = key_asymmetric_create( alg->id, 0, rsa_blob->BitLength, &key ))) return status;
1942
params.key = key;
1943
params.flags = 0;
1944
params.buf = input;
1945
params.len = input_len;
1946
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
1947
{
1948
key_destroy( key );
1949
return status;
1950
}
1951
}
1952
else if (!wcscmp( type, LEGACY_RSAPRIVATE_BLOB ))
1953
{
1954
BCRYPT_RSAKEY_BLOB *rsa_blob;
1955
1956
status = convert_legacy_rsaprivate_blob( alg, &rsa_blob, &input_len, input, input_len );
1957
if (status != STATUS_SUCCESS)
1958
return status;
1959
1960
status = key_import_pair( alg, BCRYPT_RSAPRIVATE_BLOB, ret_key, (UCHAR *)rsa_blob, input_len );
1961
SecureZeroMemory( rsa_blob, input_len );
1962
free( rsa_blob );
1963
return status;
1964
}
1965
else if (!wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB ))
1966
{
1967
BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input;
1968
1969
if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER;
1970
if (alg->id != ALG_ID_DSA || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC)
1971
return STATUS_NOT_SUPPORTED;
1972
1973
if ((status = key_asymmetric_create( alg->id, 0, dsa_blob->cbKey * 8, &key ))) return status;
1974
params.key = key;
1975
params.flags = KEY_IMPORT_FLAG_PUBLIC;
1976
params.buf = input;
1977
params.len = input_len;
1978
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
1979
{
1980
key_destroy( key );
1981
return status;
1982
}
1983
}
1984
else if (!wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB ))
1985
{
1986
BLOBHEADER *hdr = (BLOBHEADER *)input;
1987
DSSPUBKEY *pubkey;
1988
1989
if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER;
1990
1991
if (hdr->bType != PRIVATEKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN)
1992
{
1993
FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg );
1994
return STATUS_NOT_SUPPORTED;
1995
}
1996
if (alg->id != ALG_ID_DSA)
1997
{
1998
FIXME( "algorithm %u does not support importing blob of type %s\n", alg->id, debugstr_w(type) );
1999
return STATUS_NOT_SUPPORTED;
2000
}
2001
2002
if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER;
2003
pubkey = (DSSPUBKEY *)(hdr + 1);
2004
if (pubkey->magic != MAGIC_DSS2) return STATUS_NOT_SUPPORTED;
2005
2006
if (input_len < sizeof(*hdr) + sizeof(*pubkey) + len_from_bitlen( pubkey->bitlen ) * 2 + 40 + sizeof(DSSSEED))
2007
return STATUS_INVALID_PARAMETER;
2008
2009
if ((status = key_asymmetric_create( alg->id, 0, pubkey->bitlen, &key ))) return status;
2010
key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
2011
params.key = key;
2012
params.flags = 0;
2013
params.buf = input;
2014
params.len = input_len;
2015
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
2016
{
2017
key_destroy( key );
2018
return status;
2019
}
2020
}
2021
else if (!wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB )) /* not supported on native */
2022
{
2023
BLOBHEADER *hdr = (BLOBHEADER *)input;
2024
DSSPUBKEY *pubkey;
2025
2026
if (alg->id != ALG_ID_DSA) return STATUS_NOT_SUPPORTED;
2027
if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER;
2028
2029
if (hdr->bType != PUBLICKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN)
2030
{
2031
FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg );
2032
return STATUS_NOT_SUPPORTED;
2033
}
2034
2035
if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER;
2036
pubkey = (DSSPUBKEY *)(hdr + 1);
2037
if (pubkey->magic != MAGIC_DSS1) return STATUS_NOT_SUPPORTED;
2038
2039
size = sizeof(*hdr) + sizeof(*pubkey) + len_from_bitlen( pubkey->bitlen ) * 3 + 20 + sizeof(DSSSEED);
2040
if (input_len < size) return STATUS_INVALID_PARAMETER;
2041
2042
if ((status = key_asymmetric_create( alg->id, 0, pubkey->bitlen, &key ))) return status;
2043
key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
2044
params.key = key;
2045
params.flags = KEY_IMPORT_FLAG_PUBLIC;
2046
params.buf = input;
2047
params.len = input_len;
2048
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
2049
{
2050
key_destroy( key );
2051
return status;
2052
}
2053
}
2054
else if (!wcscmp( type, BCRYPT_DH_PRIVATE_BLOB ))
2055
{
2056
BCRYPT_DH_KEY_BLOB *dh_blob = (BCRYPT_DH_KEY_BLOB *)input;
2057
2058
if (input_len != sizeof(*dh_blob) + dh_blob->cbKey * 4) return STATUS_INVALID_PARAMETER;
2059
if (alg->id != ALG_ID_DH || dh_blob->dwMagic != BCRYPT_DH_PRIVATE_MAGIC)
2060
return STATUS_NOT_SUPPORTED;
2061
2062
if ((status = key_asymmetric_create( alg->id, 0, dh_blob->cbKey * 8, &key ))) return status;
2063
params.key = key;
2064
params.flags = 0;
2065
params.buf = input;
2066
params.len = input_len;
2067
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
2068
{
2069
key_destroy( key );
2070
return status;
2071
}
2072
}
2073
else if (!wcscmp( type, BCRYPT_DH_PUBLIC_BLOB ))
2074
{
2075
BCRYPT_DH_KEY_BLOB *dh_blob = (BCRYPT_DH_KEY_BLOB *)input;
2076
2077
if (input_len != sizeof(*dh_blob) + dh_blob->cbKey * 3) return STATUS_INVALID_PARAMETER;
2078
if (alg->id != ALG_ID_DH || dh_blob->dwMagic != BCRYPT_DH_PUBLIC_MAGIC)
2079
return STATUS_NOT_SUPPORTED;
2080
2081
if ((status = key_asymmetric_create( alg->id, 0, dh_blob->cbKey * 8, &key ))) return status;
2082
params.key = key;
2083
params.flags = KEY_IMPORT_FLAG_PUBLIC;
2084
params.buf = input;
2085
params.len = input_len;
2086
if ((status = UNIX_CALL( key_asymmetric_import, &params )))
2087
{
2088
key_destroy( key );
2089
return status;
2090
}
2091
}
2092
else
2093
{
2094
FIXME( "unsupported key type %s\n", debugstr_w(type) );
2095
return STATUS_NOT_SUPPORTED;
2096
}
2097
2098
if (!status)
2099
{
2100
key->u.a.flags |= KEY_FLAG_FINALIZED;
2101
*ret_key = key;
2102
}
2103
return status;
2104
}
2105
2106
NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE *ret_handle,
2107
UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len,
2108
ULONG flags )
2109
{
2110
struct algorithm *alg = get_alg_object( handle );
2111
NTSTATUS status;
2112
2113
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle, ret_handle, object, object_len, secret, secret_len, flags );
2114
if (object) FIXME( "ignoring object buffer\n" );
2115
if (!__wine_unixlib_handle)
2116
{
2117
ERR( "no encryption support\n" );
2118
return STATUS_NOT_IMPLEMENTED;
2119
}
2120
2121
if (!alg) return STATUS_INVALID_HANDLE;
2122
if ((status = key_symmetric_generate( alg, ret_handle, secret, secret_len ))) return status;
2123
TRACE( "returning handle %p\n", *ret_handle );
2124
return STATUS_SUCCESS;
2125
}
2126
2127
NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE *ret_handle, ULONG key_len,
2128
ULONG flags )
2129
{
2130
struct algorithm *alg = get_alg_object( handle );
2131
struct key *key;
2132
NTSTATUS status;
2133
2134
TRACE( "%p, %p, %lu, %#lx\n", handle, ret_handle, key_len, flags );
2135
2136
if (!alg) return STATUS_INVALID_HANDLE;
2137
if (!ret_handle) return STATUS_INVALID_PARAMETER;
2138
2139
if ((status = key_asymmetric_create( alg->id, alg->curve_id, key_len, &key ))) return status;
2140
*ret_handle = key;
2141
TRACE( "returning handle %p\n", *ret_handle );
2142
return STATUS_SUCCESS;
2143
}
2144
2145
NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags )
2146
{
2147
struct key *key = get_key_object( handle );
2148
NTSTATUS ret;
2149
2150
TRACE( "%p, %#lx\n", key, flags );
2151
2152
if (!key || key->u.a.flags & KEY_FLAG_FINALIZED) return STATUS_INVALID_HANDLE;
2153
2154
if (!(ret = UNIX_CALL( key_asymmetric_generate, key ))) key->u.a.flags |= KEY_FLAG_FINALIZED;
2155
return ret;
2156
}
2157
2158
NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE decrypt_key_handle, const WCHAR *type,
2159
BCRYPT_KEY_HANDLE *ret_handle, UCHAR *object, ULONG object_len, UCHAR *input,
2160
ULONG input_len, ULONG flags )
2161
{
2162
struct algorithm *alg = get_alg_object( handle );
2163
struct key *decrypt_key = NULL;
2164
NTSTATUS status;
2165
2166
TRACE( "%p, %p, %s, %p, %p, %lu, %p, %lu, %#lx\n", handle, decrypt_key_handle, debugstr_w(type), ret_handle,
2167
object, object_len, input, input_len, flags );
2168
2169
if (!alg) return STATUS_INVALID_HANDLE;
2170
if (!ret_handle || !type || !input) return STATUS_INVALID_PARAMETER;
2171
if (decrypt_key_handle && !(decrypt_key = get_key_object( decrypt_key_handle ))) return STATUS_INVALID_HANDLE;
2172
2173
if ((status = key_import( alg, decrypt_key, type, ret_handle, object, object_len, input, input_len ))) return status;
2174
TRACE( "returning handle %p\n", *ret_handle );
2175
return STATUS_SUCCESS;
2176
}
2177
2178
NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key_handle, BCRYPT_KEY_HANDLE encrypt_key_handle,
2179
const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size, ULONG flags )
2180
{
2181
struct key *key = get_key_object( export_key_handle );
2182
struct key *encrypt_key = NULL;
2183
2184
TRACE( "%p, %p, %s, %p, %lu, %p, %#lx\n", export_key_handle, encrypt_key_handle, debugstr_w(type), output,
2185
output_len, size, flags );
2186
2187
if (!key) return STATUS_INVALID_HANDLE;
2188
if (!type || !size) return STATUS_INVALID_PARAMETER;
2189
if (encrypt_key_handle && !(encrypt_key = get_key_object( encrypt_key_handle ))) return STATUS_INVALID_HANDLE;
2190
2191
return key_export( key, encrypt_key, type, output, output_len, size );
2192
}
2193
2194
static NTSTATUS key_duplicate( struct key *key_orig, struct key **ret_key )
2195
{
2196
struct key_asymmetric_duplicate_params params;
2197
struct key *key_copy;
2198
NTSTATUS status;
2199
UCHAR *buffer;
2200
2201
if (!(key_copy = calloc( 1, sizeof(*key_copy) ))) return STATUS_NO_MEMORY;
2202
key_copy->hdr = key_orig->hdr;
2203
key_copy->alg_id = key_orig->alg_id;
2204
2205
if (is_symmetric_key( key_orig ))
2206
{
2207
if (!(buffer = malloc( key_orig->u.s.secret_len )))
2208
{
2209
free( key_copy );
2210
return STATUS_NO_MEMORY;
2211
}
2212
memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len );
2213
2214
key_copy->u.s.mode = key_orig->u.s.mode;
2215
key_copy->u.s.block_size = key_orig->u.s.block_size;
2216
key_copy->u.s.secret = buffer;
2217
key_copy->u.s.secret_len = key_orig->u.s.secret_len;
2218
InitializeCriticalSection( &key_copy->u.s.cs );
2219
*ret_key = key_copy;
2220
return STATUS_SUCCESS;
2221
}
2222
2223
key_copy->u.a.bitlen = key_orig->u.a.bitlen;
2224
key_copy->u.a.flags = key_orig->u.a.flags;
2225
key_copy->u.a.dss_seed = key_orig->u.a.dss_seed;
2226
2227
params.key_orig = key_orig;
2228
params.key_copy = key_copy;
2229
if (!(status = UNIX_CALL( key_asymmetric_duplicate, &params ))) *ret_key = key_copy;
2230
else free( key_copy );
2231
return status;
2232
}
2233
2234
NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE *handle_copy, UCHAR *object,
2235
ULONG object_len, ULONG flags )
2236
{
2237
struct key *key_orig = get_key_object( handle );
2238
struct key *key_copy;
2239
NTSTATUS status;
2240
2241
TRACE( "%p, %p, %p, %lu, %#lx\n", handle, handle_copy, object, object_len, flags );
2242
if (object) FIXME( "ignoring object buffer\n" );
2243
2244
if (!key_orig) return STATUS_INVALID_HANDLE;
2245
if (!handle_copy) return STATUS_INVALID_PARAMETER;
2246
2247
if ((status = key_duplicate( key_orig, &key_copy ))) return status;
2248
2249
*handle_copy = key_copy;
2250
TRACE( "returning handle %p\n", *handle_copy );
2251
return STATUS_SUCCESS;
2252
}
2253
2254
static const WCHAR *resolve_blob_type( const WCHAR *type, UCHAR *input, ULONG input_len )
2255
{
2256
BCRYPT_KEY_BLOB *blob = (BCRYPT_KEY_BLOB *)input;
2257
2258
if (!type) return NULL;
2259
if (wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB )) return type;
2260
if (input_len < sizeof(*blob)) return NULL;
2261
2262
switch (blob->Magic)
2263
{
2264
case BCRYPT_ECDH_PUBLIC_P256_MAGIC:
2265
case BCRYPT_ECDH_PUBLIC_P384_MAGIC:
2266
case BCRYPT_ECDH_PUBLIC_P521_MAGIC:
2267
case BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
2268
case BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
2269
case BCRYPT_ECDSA_PUBLIC_P521_MAGIC:
2270
return BCRYPT_ECCPUBLIC_BLOB;
2271
2272
case BCRYPT_RSAPUBLIC_MAGIC:
2273
return BCRYPT_RSAPUBLIC_BLOB;
2274
2275
case BCRYPT_DSA_PUBLIC_MAGIC:
2276
return BCRYPT_DSA_PUBLIC_BLOB;
2277
2278
default:
2279
FIXME( "unsupported key magic %#lx\n", blob->Magic );
2280
return NULL;
2281
}
2282
}
2283
2284
NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE decrypt_key_handle, const WCHAR *type,
2285
BCRYPT_KEY_HANDLE *ret_handle, UCHAR *input, ULONG input_len, ULONG flags )
2286
{
2287
struct algorithm *alg = get_alg_object( handle );
2288
NTSTATUS status;
2289
2290
TRACE( "%p, %p, %s, %p, %p, %lu, %#lx\n", handle, decrypt_key_handle, debugstr_w(type), ret_handle, input,
2291
input_len, flags );
2292
2293
if (!alg) return STATUS_INVALID_HANDLE;
2294
if (!ret_handle || !input || !(type = resolve_blob_type( type, input, input_len )))
2295
return STATUS_INVALID_PARAMETER;
2296
if (decrypt_key_handle)
2297
{
2298
FIXME( "decryption of key not yet supported\n" );
2299
return STATUS_NOT_IMPLEMENTED;
2300
}
2301
2302
if ((status = key_import_pair( alg, type, ret_handle, input, input_len ))) return status;
2303
TRACE( "returning handle %p\n", *ret_handle );
2304
return STATUS_SUCCESS;
2305
}
2306
2307
NTSTATUS WINAPI BCryptSignHash( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *input, ULONG input_len,
2308
UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
2309
{
2310
struct key_asymmetric_sign_params params;
2311
struct key *key = get_key_object( handle );
2312
2313
TRACE( "%p, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle, padding, input, input_len, output, output_len,
2314
ret_len, flags );
2315
2316
if (!key) return STATUS_INVALID_HANDLE;
2317
if (!is_signature_key( key )) return STATUS_NOT_SUPPORTED;
2318
2319
params.key = key;
2320
params.padding = padding;
2321
params.input = input;
2322
params.input_len = input_len;
2323
params.output = output;
2324
params.output_len = output_len;
2325
params.ret_len = ret_len;
2326
params.flags = flags;
2327
return UNIX_CALL( key_asymmetric_sign, &params );
2328
}
2329
2330
NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len,
2331
UCHAR *signature, ULONG signature_len, ULONG flags )
2332
{
2333
struct key_asymmetric_verify_params params;
2334
struct key *key = get_key_object( handle );
2335
2336
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle, padding, hash, hash_len, signature, signature_len, flags );
2337
2338
if (!key) return STATUS_INVALID_HANDLE;
2339
if (!is_signature_key( key )) return STATUS_NOT_SUPPORTED;
2340
if (!hash || !hash_len || !signature || !signature_len) return STATUS_INVALID_PARAMETER;
2341
2342
params.key = key;
2343
params.padding = padding;
2344
params.hash = hash;
2345
params.hash_len = hash_len;
2346
params.signature = signature;
2347
params.signature_len = signature_len;
2348
params.flags = flags;
2349
return UNIX_CALL( key_asymmetric_verify, &params );
2350
}
2351
2352
NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle )
2353
{
2354
struct key *key = get_key_object( handle );
2355
2356
TRACE( "%p\n", handle );
2357
2358
if (!key) return STATUS_INVALID_HANDLE;
2359
key_destroy( key );
2360
return STATUS_SUCCESS;
2361
}
2362
2363
NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
2364
ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
2365
{
2366
struct key *key = get_key_object( handle );
2367
struct key_asymmetric_encrypt_params asymmetric_params;
2368
NTSTATUS ret;
2369
2370
TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle, input, input_len, padding, iv, iv_len, output,
2371
output_len, ret_len, flags );
2372
2373
if (!key) return STATUS_INVALID_HANDLE;
2374
2375
if (is_symmetric_key( key ))
2376
{
2377
if (flags & ~BCRYPT_BLOCK_PADDING)
2378
{
2379
FIXME( "flags %#lx not implemented\n", flags );
2380
return STATUS_NOT_IMPLEMENTED;
2381
}
2382
EnterCriticalSection( &key->u.s.cs );
2383
ret = key_symmetric_encrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
2384
LeaveCriticalSection( &key->u.s.cs );
2385
}
2386
else
2387
{
2388
if (flags & BCRYPT_PAD_NONE)
2389
{
2390
FIXME( "flags %#lx not implemented\n", flags );
2391
return STATUS_NOT_IMPLEMENTED;
2392
}
2393
if (!is_asymmetric_encryption_key( key )) return STATUS_NOT_SUPPORTED;
2394
2395
asymmetric_params.input = input;
2396
asymmetric_params.input_len = input_len;
2397
asymmetric_params.padding = padding;
2398
asymmetric_params.key = key;
2399
asymmetric_params.output = output;
2400
asymmetric_params.output_len = output_len;
2401
asymmetric_params.ret_len = ret_len;
2402
asymmetric_params.flags = flags;
2403
ret = UNIX_CALL(key_asymmetric_encrypt, &asymmetric_params);
2404
}
2405
2406
return ret;
2407
}
2408
2409
NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len, void *padding, UCHAR *iv,
2410
ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
2411
{
2412
struct key *key = get_key_object( handle );
2413
struct key_asymmetric_decrypt_params params;
2414
NTSTATUS ret;
2415
2416
TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle, input, input_len, padding, iv, iv_len, output,
2417
output_len, ret_len, flags );
2418
2419
if (!key) return STATUS_INVALID_HANDLE;
2420
2421
if (is_symmetric_key( key ))
2422
{
2423
if (flags & ~BCRYPT_BLOCK_PADDING)
2424
{
2425
FIXME( "flags %#lx not supported\n", flags );
2426
return STATUS_NOT_IMPLEMENTED;
2427
}
2428
2429
EnterCriticalSection( &key->u.s.cs );
2430
ret = key_symmetric_decrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
2431
LeaveCriticalSection( &key->u.s.cs );
2432
}
2433
else
2434
{
2435
if (flags & BCRYPT_PAD_NONE)
2436
{
2437
FIXME( "flags %#lx not implemented\n", flags );
2438
return STATUS_NOT_IMPLEMENTED;
2439
}
2440
if (!is_asymmetric_encryption_key( key )) return STATUS_NOT_SUPPORTED;
2441
2442
params.key = key;
2443
params.input = input;
2444
params.input_len = input_len;
2445
params.padding = padding;
2446
params.output = output;
2447
params.output_len = output_len;
2448
params.ret_len = ret_len;
2449
params.flags = flags;
2450
ret = UNIX_CALL(key_asymmetric_decrypt, &params);
2451
}
2452
2453
return ret;
2454
}
2455
2456
NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
2457
{
2458
struct object *object = get_object( handle, 0 );
2459
2460
TRACE( "%p, %s, %p, %lu, %#lx\n", handle, debugstr_w(prop), value, size, flags );
2461
2462
if (!handle) return STATUS_INVALID_HANDLE;
2463
if (is_alg_pseudo_handle( handle )) return STATUS_ACCESS_DENIED;
2464
2465
switch (object->magic)
2466
{
2467
case MAGIC_ALG:
2468
{
2469
struct algorithm *alg = (struct algorithm *)object;
2470
return set_alg_property( alg, prop, value, size, flags );
2471
}
2472
case MAGIC_KEY:
2473
{
2474
struct key *key = (struct key *)object;
2475
return set_key_property( key, prop, value, size, flags );
2476
}
2477
default:
2478
WARN( "unknown magic %#lx\n", object->magic );
2479
return STATUS_INVALID_HANDLE;
2480
}
2481
}
2482
2483
#define HMAC_PAD_LEN 64
2484
NTSTATUS WINAPI BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle, BCRYPT_ALG_HANDLE halg, UCHAR *key, ULONG keylen, ULONG flags )
2485
{
2486
struct hash *hash = get_hash_object( handle );
2487
UCHAR buf[MAX_HASH_OUTPUT_BYTES * 2];
2488
ULONG len;
2489
2490
TRACE( "%p, %p, %p, %lu, %#lx\n", handle, halg, key, keylen, flags );
2491
2492
if (!hash) return STATUS_INVALID_HANDLE;
2493
if (!key || !keylen) return STATUS_INVALID_PARAMETER;
2494
if (keylen > hash->desc->hashsize * 2) return STATUS_INVALID_PARAMETER;
2495
if (halg)
2496
{
2497
FIXME( "algorithm handle not supported\n" );
2498
return STATUS_NOT_IMPLEMENTED;
2499
}
2500
2501
hash_finalize( hash, buf );
2502
2503
len = hash->desc->hashsize;
2504
if (len < keylen)
2505
{
2506
UCHAR pad1[HMAC_PAD_LEN], pad2[HMAC_PAD_LEN];
2507
ULONG i;
2508
2509
for (i = 0; i < sizeof(pad1); i++)
2510
{
2511
pad1[i] = 0x36 ^ (i < len ? buf[i] : 0);
2512
pad2[i] = 0x5c ^ (i < len ? buf[i] : 0);
2513
}
2514
2515
hash_prepare( hash );
2516
hash->desc->process( &hash->inner, pad1, sizeof(pad1) );
2517
hash_finalize( hash, buf );
2518
2519
hash_prepare( hash );
2520
hash->desc->process( &hash->inner, pad2, sizeof(pad2) );
2521
hash_finalize( hash, buf + len );
2522
}
2523
memcpy( key, buf, keylen );
2524
return STATUS_SUCCESS;
2525
}
2526
2527
static NTSTATUS pbkdf2( struct hash *hash, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
2528
ULONGLONG iterations, ULONG i, UCHAR *dst, ULONG hash_len )
2529
{
2530
UCHAR bytes[4], *buf;
2531
ULONG j, k;
2532
2533
if (!iterations) return STATUS_INVALID_PARAMETER;
2534
if (!(buf = malloc( hash_len ))) return STATUS_NO_MEMORY;
2535
2536
for (j = 0; j < iterations; j++)
2537
{
2538
if (j == 0)
2539
{
2540
/* use salt || INT(i) */
2541
if (salt_len && hash->desc->process( &hash->inner, salt, salt_len ))
2542
{
2543
free( buf );
2544
return STATUS_INVALID_PARAMETER;
2545
}
2546
bytes[0] = (i >> 24) & 0xff;
2547
bytes[1] = (i >> 16) & 0xff;
2548
bytes[2] = (i >> 8) & 0xff;
2549
bytes[3] = i & 0xff;
2550
hash->desc->process( &hash->inner, bytes, 4 );
2551
}
2552
else hash->desc->process( &hash->inner, buf, hash_len ); /* use U_j */
2553
2554
hash_finalize( hash, buf );
2555
if (j == 0) memcpy( dst, buf, hash_len );
2556
else for (k = 0; k < hash_len; k++) dst[k] ^= buf[k];
2557
}
2558
2559
free( buf );
2560
return STATUS_SUCCESS;
2561
}
2562
2563
static NTSTATUS derive_key_pbkdf2( struct algorithm *alg, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
2564
ULONGLONG iterations, UCHAR *dk, ULONG dk_len )
2565
{
2566
ULONG hash_len, block_count, bytes_left, i;
2567
struct hash *hash;
2568
UCHAR *partial;
2569
NTSTATUS status;
2570
2571
hash_len = builtin_algorithms[alg->id].hash_length;
2572
if (dk_len <= 0 || dk_len > ((((ULONGLONG)1) << 32) - 1) * hash_len) return STATUS_INVALID_PARAMETER;
2573
2574
block_count = 1 + ((dk_len - 1) / hash_len); /* ceil(dk_len / hash_len) */
2575
bytes_left = dk_len - (block_count - 1) * hash_len;
2576
2577
if ((status = hash_create( alg, pwd, pwd_len, BCRYPT_HASH_REUSABLE_FLAG, &hash ))) return status;
2578
2579
/* full blocks */
2580
for (i = 1; i < block_count; i++)
2581
{
2582
if ((status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, i, dk + ((i - 1) * hash_len), hash_len )))
2583
{
2584
hash_destroy( hash );
2585
return status;
2586
}
2587
}
2588
2589
/* final partial block */
2590
if (!(partial = malloc( hash_len )))
2591
{
2592
hash_destroy( hash );
2593
return STATUS_NO_MEMORY;
2594
}
2595
2596
if ((status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, block_count, partial, hash_len )))
2597
{
2598
hash_destroy( hash );
2599
free( partial );
2600
return status;
2601
}
2602
memcpy( dk + ((block_count - 1) * hash_len), partial, bytes_left );
2603
2604
hash_destroy( hash );
2605
free( partial );
2606
return STATUS_SUCCESS;
2607
}
2608
2609
NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
2610
ULONGLONG iterations, UCHAR *dk, ULONG dk_len, ULONG flags )
2611
{
2612
struct algorithm *alg = get_alg_object( handle );
2613
2614
TRACE( "%p, %p, %lu, %p, %lu, %s, %p, %lu, %#lx\n", handle, pwd, pwd_len, salt, salt_len,
2615
wine_dbgstr_longlong(iterations), dk, dk_len, flags );
2616
2617
if (!alg) return STATUS_INVALID_HANDLE;
2618
return derive_key_pbkdf2( alg, pwd, pwd_len, salt, salt_len, iterations, dk, dk_len );
2619
}
2620
2621
NTSTATUS WINAPI BCryptSecretAgreement( BCRYPT_KEY_HANDLE privkey_handle, BCRYPT_KEY_HANDLE pubkey_handle,
2622
BCRYPT_SECRET_HANDLE *ret_handle, ULONG flags )
2623
{
2624
struct key *privkey = get_key_object( privkey_handle );
2625
struct key *pubkey = get_key_object( pubkey_handle );
2626
struct secret *secret;
2627
NTSTATUS status;
2628
2629
TRACE( "%p, %p, %p, %#lx\n", privkey_handle, pubkey_handle, ret_handle, flags );
2630
2631
if (!privkey || !pubkey) return STATUS_INVALID_HANDLE;
2632
if (!is_agreement_key( privkey ) || !is_agreement_key( pubkey )) return STATUS_NOT_SUPPORTED;
2633
if (!ret_handle) return STATUS_INVALID_PARAMETER;
2634
2635
if (!(secret = calloc( 1, sizeof(*secret) ))) return STATUS_NO_MEMORY;
2636
secret->hdr.magic = MAGIC_SECRET;
2637
if ((status = key_duplicate( privkey, &secret->privkey )))
2638
{
2639
free( secret );
2640
return status;
2641
}
2642
if ((status = key_duplicate( pubkey, &secret->pubkey )))
2643
{
2644
key_destroy( secret->privkey );
2645
free( secret );
2646
return status;
2647
}
2648
2649
*ret_handle = secret;
2650
TRACE( "returning handle %p\n", *ret_handle );
2651
return STATUS_SUCCESS;
2652
}
2653
2654
NTSTATUS WINAPI BCryptDestroySecret( BCRYPT_SECRET_HANDLE handle )
2655
{
2656
struct secret *secret = get_secret_object( handle );
2657
2658
TRACE( "%p\n", handle );
2659
2660
if (!secret) return STATUS_INVALID_HANDLE;
2661
key_destroy( secret->privkey );
2662
key_destroy( secret->pubkey );
2663
destroy_object( &secret->hdr );
2664
return STATUS_SUCCESS;
2665
}
2666
2667
static void reverse_bytes( UCHAR *buf, ULONG len )
2668
{
2669
ULONG i;
2670
for (i = 0; i < len / 2; i++)
2671
{
2672
UCHAR tmp = buf[i];
2673
buf[i] = buf[len - i - 1];
2674
buf[len - i - 1] = tmp;
2675
}
2676
}
2677
2678
static NTSTATUS derive_key_raw( struct secret *secret, UCHAR *output, ULONG output_len, ULONG *ret_len )
2679
{
2680
struct key_asymmetric_derive_key_params params;
2681
NTSTATUS status;
2682
2683
params.privkey = secret->privkey;
2684
params.pubkey = secret->pubkey;
2685
params.output = output;
2686
params.output_len = output_len;
2687
params.ret_len = ret_len;
2688
if (!(status = UNIX_CALL( key_asymmetric_derive_key, &params )) && output) reverse_bytes( output, *ret_len );
2689
return status;
2690
}
2691
2692
static struct algorithm *get_hash_alg( BCryptBuffer *buf, BOOL hmac )
2693
{
2694
const WCHAR *str = buf->pvBuffer;
2695
BCRYPT_ALG_HANDLE handle = NULL;
2696
2697
if (!wcscmp( str, BCRYPT_SHA1_ALGORITHM ))
2698
handle = hmac ? BCRYPT_HMAC_SHA1_ALG_HANDLE : BCRYPT_SHA1_ALG_HANDLE;
2699
else if (!wcscmp( str, BCRYPT_SHA256_ALGORITHM ))
2700
handle = hmac ? BCRYPT_HMAC_SHA256_ALG_HANDLE : BCRYPT_SHA256_ALG_HANDLE;
2701
else if (!wcscmp( str, BCRYPT_SHA384_ALGORITHM ))
2702
handle = hmac ? BCRYPT_HMAC_SHA384_ALG_HANDLE : BCRYPT_SHA384_ALG_HANDLE;
2703
else if (!wcscmp( str, BCRYPT_SHA512_ALGORITHM ))
2704
handle = hmac ? BCRYPT_HMAC_SHA512_ALG_HANDLE : BCRYPT_SHA512_ALG_HANDLE;
2705
2706
if (handle) return get_alg_object( handle );
2707
FIXME( "hash algorithm %s not supported\n", debugstr_w(str) );
2708
return NULL;
2709
}
2710
2711
static NTSTATUS derive_key_hash( struct secret *secret, BCryptBufferDesc *desc, UCHAR *output, ULONG output_len,
2712
ULONG *ret_len )
2713
{
2714
struct key_asymmetric_derive_key_params params;
2715
ULONG hash_len, derived_key_len = len_from_bitlen( secret->privkey->u.a.bitlen );
2716
UCHAR hash_buf[MAX_HASH_OUTPUT_BYTES];
2717
struct algorithm *alg = NULL;
2718
UCHAR *derived_key;
2719
NTSTATUS status;
2720
ULONG i;
2721
2722
for (i = 0; i < (desc ? desc->cBuffers : 0); i++)
2723
{
2724
if (desc->pBuffers[i].BufferType == KDF_HASH_ALGORITHM)
2725
{
2726
alg = get_hash_alg( desc->pBuffers + i, FALSE );
2727
if (!alg) return STATUS_NOT_SUPPORTED;
2728
}
2729
else FIXME( "buffer type %lu not supported\n", desc->pBuffers[i].BufferType );
2730
}
2731
if (!alg) alg = get_alg_object( BCRYPT_SHA1_ALG_HANDLE );
2732
2733
if (!(derived_key = malloc( derived_key_len ))) return STATUS_NO_MEMORY;
2734
2735
params.privkey = secret->privkey;
2736
params.pubkey = secret->pubkey;
2737
params.output = derived_key;
2738
params.output_len = derived_key_len;
2739
params.ret_len = ret_len;
2740
if ((status = UNIX_CALL( key_asymmetric_derive_key, &params )))
2741
{
2742
free( derived_key );
2743
return status;
2744
}
2745
2746
hash_len = builtin_algorithms[alg->id].hash_length;
2747
assert( hash_len <= sizeof(hash_buf) );
2748
if (!(status = hash_single( alg, NULL, 0, derived_key, *params.ret_len, hash_buf, hash_len )))
2749
{
2750
if (!output) *ret_len = hash_len;
2751
else
2752
{
2753
*ret_len = min( hash_len, output_len );
2754
memcpy( output, hash_buf, *ret_len );
2755
}
2756
}
2757
2758
free( derived_key );
2759
return status;
2760
}
2761
2762
NTSTATUS WINAPI BCryptDeriveKey( BCRYPT_SECRET_HANDLE handle, const WCHAR *kdf, BCryptBufferDesc *desc,
2763
UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
2764
{
2765
struct secret *secret = get_secret_object( handle );
2766
2767
TRACE( "%p, %s, %p, %p, %lu, %p, %#lx\n", secret, debugstr_w(kdf), desc, output, output_len,
2768
ret_len, flags );
2769
2770
if (!secret) return STATUS_INVALID_HANDLE;
2771
if (!kdf || !ret_len) return STATUS_INVALID_PARAMETER;
2772
2773
if (!wcscmp(kdf, BCRYPT_KDF_RAW_SECRET))
2774
{
2775
return derive_key_raw( secret, output, output_len, ret_len );
2776
}
2777
else if (!wcscmp(kdf, BCRYPT_KDF_HASH))
2778
{
2779
return derive_key_hash( secret, desc, output, output_len, ret_len );
2780
}
2781
2782
FIXME( "kdf %s not supportedi\n", debugstr_w(kdf) );
2783
return STATUS_NOT_SUPPORTED;
2784
}
2785
2786
NTSTATUS WINAPI BCryptKeyDerivation( BCRYPT_KEY_HANDLE handle, BCryptBufferDesc *desc,
2787
UCHAR *output, ULONG output_size, ULONG *ret_len, ULONG flags )
2788
{
2789
struct key *key = get_key_object( handle );
2790
struct algorithm *alg = NULL;
2791
ULONGLONG iter_count = 10000;
2792
ULONG salt_size = 0;
2793
UCHAR *salt = NULL;
2794
NTSTATUS status;
2795
ULONG i;
2796
2797
TRACE( "%p, %p, %p, %lu, %p, %#lx\n", key, desc, output, output_size, ret_len, flags );
2798
2799
if (!key || !desc || !ret_len) return STATUS_INVALID_PARAMETER;
2800
if (key->alg_id != ALG_ID_PBKDF2)
2801
{
2802
FIXME( "unsupported key %d\n", key->alg_id );
2803
return STATUS_NOT_IMPLEMENTED;
2804
}
2805
2806
for (i = 0; i < desc->cBuffers; i++)
2807
{
2808
switch (desc->pBuffers[i].BufferType)
2809
{
2810
case KDF_HASH_ALGORITHM:
2811
alg = get_hash_alg( desc->pBuffers + i, TRUE );
2812
break;
2813
case KDF_SALT:
2814
salt = desc->pBuffers[i].pvBuffer;
2815
salt_size = desc->pBuffers[i].cbBuffer;
2816
break;
2817
case KDF_ITERATION_COUNT:
2818
if (desc->pBuffers[i].cbBuffer != sizeof(ULONGLONG)) return STATUS_INVALID_PARAMETER;
2819
iter_count = *(ULONGLONG *)desc->pBuffers[i].pvBuffer;
2820
break;
2821
default:
2822
FIXME( "buffer type %lu not supported\n", desc->pBuffers[i].BufferType );
2823
break;
2824
}
2825
}
2826
2827
status = derive_key_pbkdf2( alg, key->u.s.secret, key->u.s.secret_len,
2828
salt, salt_size, iter_count, output, output_size );
2829
if (!status) *ret_len = output_size;
2830
return status;
2831
}
2832
2833
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
2834
{
2835
switch (reason)
2836
{
2837
case DLL_PROCESS_ATTACH:
2838
DisableThreadLibraryCalls( hinst );
2839
if (!__wine_init_unix_call())
2840
{
2841
if (UNIX_CALL( process_attach, NULL)) __wine_unixlib_handle = 0;
2842
}
2843
break;
2844
case DLL_PROCESS_DETACH:
2845
if (reserved) break;
2846
if (__wine_unixlib_handle) UNIX_CALL( process_detach, NULL );
2847
break;
2848
}
2849
return TRUE;
2850
}
2851
2852