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