2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WIN32_NO_STATUS
32 #include "wine/debug.h"
33 #include "bcrypt_internal.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
37 #define UNIX_CALL( func, params ) WINE_UNIX_CALL( unix_ ## func, params )
40 NTSTATUS WINAPI
BCryptAddContextFunction( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
, ULONG pos
)
42 FIXME( "%#lx, %s, %#lx, %s, %lu: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
), pos
);
43 return STATUS_SUCCESS
;
46 NTSTATUS WINAPI
BCryptAddContextFunctionProvider( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
,
47 const WCHAR
*provider
, ULONG pos
)
49 FIXME( "%#lx, %s, %#lx, %s, %s, %lu: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
),
50 debugstr_w(provider
), pos
);
51 return STATUS_SUCCESS
;
54 NTSTATUS WINAPI
BCryptRemoveContextFunction( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
)
56 FIXME( "%#lx, %s, %#lx, %s: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
) );
57 return STATUS_NOT_IMPLEMENTED
;
60 NTSTATUS WINAPI
BCryptRemoveContextFunctionProvider( ULONG table
, const WCHAR
*ctx
, ULONG iface
, const WCHAR
*func
,
61 const WCHAR
*provider
)
63 FIXME( "%#lx, %s, %#lx, %s, %s: stub\n", table
, debugstr_w(ctx
), iface
, debugstr_w(func
), debugstr_w(provider
) );
64 return STATUS_NOT_IMPLEMENTED
;
67 NTSTATUS WINAPI
BCryptEnumContextFunctions( ULONG table
, const WCHAR
*ctx
, ULONG iface
, ULONG
*buflen
,
68 CRYPT_CONTEXT_FUNCTIONS
**buffer
)
70 FIXME( "%#lx, %s, %#lx, %p, %p\n", table
, debugstr_w(ctx
), iface
, buflen
, buffer
);
71 return STATUS_NOT_IMPLEMENTED
;
74 void WINAPI
BCryptFreeBuffer( void *buffer
)
79 NTSTATUS WINAPI
BCryptRegisterProvider( const WCHAR
*provider
, ULONG flags
, CRYPT_PROVIDER_REG
*reg
)
81 FIXME( "%s, %#lx, %p: stub\n", debugstr_w(provider
), flags
, reg
);
82 return STATUS_SUCCESS
;
85 NTSTATUS WINAPI
BCryptUnregisterProvider( const WCHAR
*provider
)
87 FIXME( "%s: stub\n", debugstr_w(provider
) );
88 return STATUS_NOT_IMPLEMENTED
;
91 #define MAX_HASH_OUTPUT_BYTES 64
92 #define MAX_HASH_BLOCK_BITS 1024
94 /* ordered by class, keep in sync with enum alg_id */
103 builtin_algorithms
[] =
105 { BCRYPT_3DES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 522, 0, 0 },
106 { BCRYPT_AES_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 654, 0, 0 },
107 { BCRYPT_RC4_ALGORITHM
, BCRYPT_CIPHER_INTERFACE
, 654, 0, 0 },
108 { BCRYPT_SHA256_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 286, 32, 512 },
109 { BCRYPT_SHA384_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 48, 1024 },
110 { BCRYPT_SHA512_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 382, 64, 1024 },
111 { BCRYPT_SHA1_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 278, 20, 512 },
112 { BCRYPT_MD5_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 274, 16, 512 },
113 { BCRYPT_MD4_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 512 },
114 { BCRYPT_MD2_ALGORITHM
, BCRYPT_HASH_INTERFACE
, 270, 16, 128 },
115 { BCRYPT_RSA_ALGORITHM
, BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
, 0, 0, 0 },
116 { BCRYPT_ECDH_P256_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
117 { BCRYPT_ECDH_P384_ALGORITHM
, BCRYPT_SECRET_AGREEMENT_INTERFACE
, 0, 0, 0 },
118 { BCRYPT_RSA_SIGN_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
119 { BCRYPT_ECDSA_P256_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
120 { BCRYPT_ECDSA_P384_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
121 { BCRYPT_DSA_ALGORITHM
, BCRYPT_SIGNATURE_INTERFACE
, 0, 0, 0 },
122 { BCRYPT_RNG_ALGORITHM
, BCRYPT_RNG_INTERFACE
, 0, 0, 0 },
125 static inline BOOL
is_symmetric_key( const struct key
*key
)
127 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_CIPHER_INTERFACE
;
130 static inline BOOL
is_asymmetric_encryption_key( struct key
*key
)
132 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
;
135 static inline BOOL
is_agreement_key( struct key
*key
)
137 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_SECRET_AGREEMENT_INTERFACE
;
140 static inline BOOL
is_signature_key( struct key
*key
)
142 return builtin_algorithms
[key
->alg_id
].class == BCRYPT_SIGNATURE_INTERFACE
|| key
->alg_id
== ALG_ID_RSA
;
145 static BOOL
match_operation_type( ULONG type
, ULONG
class )
147 if (!type
) return TRUE
;
150 case BCRYPT_CIPHER_INTERFACE
: return type
& BCRYPT_CIPHER_OPERATION
;
151 case BCRYPT_HASH_INTERFACE
: return type
& BCRYPT_HASH_OPERATION
;
152 case BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE
: return type
& BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
;
153 case BCRYPT_SECRET_AGREEMENT_INTERFACE
: return type
& BCRYPT_SECRET_AGREEMENT_OPERATION
;
154 case BCRYPT_SIGNATURE_INTERFACE
: return type
& BCRYPT_SIGNATURE_OPERATION
;
155 case BCRYPT_RNG_INTERFACE
: return type
& BCRYPT_RNG_OPERATION
;
161 NTSTATUS WINAPI
BCryptEnumAlgorithms( ULONG type
, ULONG
*ret_count
, BCRYPT_ALGORITHM_IDENTIFIER
**ret_list
, ULONG flags
)
163 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
164 BCRYPT_HASH_OPERATION
|\
165 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
166 BCRYPT_SECRET_AGREEMENT_OPERATION
|\
167 BCRYPT_SIGNATURE_OPERATION
|\
168 BCRYPT_RNG_OPERATION
;
169 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
170 ULONG i
, j
, count
= 0;
172 TRACE( "%#lx, %p, %p, %#lx\n", type
, ret_count
, ret_list
, flags
);
174 if (!ret_count
|| !ret_list
|| (type
& ~supported
)) return STATUS_INVALID_PARAMETER
;
176 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
178 if (match_operation_type( type
, builtin_algorithms
[i
].class )) count
++;
181 if (!(list
= malloc( count
* sizeof(*list
) ))) return STATUS_NO_MEMORY
;
183 for (i
= 0, j
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
185 if (!match_operation_type( type
, builtin_algorithms
[i
].class )) continue;
186 list
[j
].pszName
= (WCHAR
*)builtin_algorithms
[i
].name
;
187 list
[j
].dwClass
= builtin_algorithms
[i
].class;
194 return STATUS_SUCCESS
;
197 static const struct algorithm pseudo_algorithms
[] =
199 {{ MAGIC_ALG
}, ALG_ID_MD2
},
200 {{ MAGIC_ALG
}, ALG_ID_MD4
},
201 {{ MAGIC_ALG
}, ALG_ID_MD5
},
202 {{ MAGIC_ALG
}, ALG_ID_SHA1
},
203 {{ MAGIC_ALG
}, ALG_ID_SHA256
},
204 {{ MAGIC_ALG
}, ALG_ID_SHA384
},
205 {{ MAGIC_ALG
}, ALG_ID_SHA512
},
206 {{ MAGIC_ALG
}, ALG_ID_RC4
},
207 {{ MAGIC_ALG
}, ALG_ID_RNG
},
208 {{ MAGIC_ALG
}, ALG_ID_MD5
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
209 {{ MAGIC_ALG
}, ALG_ID_SHA1
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
210 {{ MAGIC_ALG
}, ALG_ID_SHA256
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
211 {{ MAGIC_ALG
}, ALG_ID_SHA384
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
212 {{ MAGIC_ALG
}, ALG_ID_SHA512
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
213 {{ MAGIC_ALG
}, ALG_ID_RSA
},
215 {{ 0 }}, /* AES_CMAC */
216 {{ 0 }}, /* AES_GMAC */
217 {{ MAGIC_ALG
}, ALG_ID_MD2
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
218 {{ MAGIC_ALG
}, ALG_ID_MD4
, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG
},
219 {{ MAGIC_ALG
}, ALG_ID_3DES
, CHAIN_MODE_CBC
},
220 {{ MAGIC_ALG
}, ALG_ID_3DES
, CHAIN_MODE_ECB
},
221 {{ MAGIC_ALG
}, ALG_ID_3DES
, CHAIN_MODE_CFB
},
222 {{ 0 }}, /* 3DES_112_CBC */
223 {{ 0 }}, /* 3DES_112_ECB */
224 {{ 0 }}, /* 3DES_112_CFB */
225 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_CBC
},
226 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_ECB
},
227 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_CFB
},
228 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_CCM
},
229 {{ MAGIC_ALG
}, ALG_ID_AES
, CHAIN_MODE_GCM
},
230 {{ 0 }}, /* DES_CBC */
231 {{ 0 }}, /* DES_ECB */
232 {{ 0 }}, /* DES_CFB */
233 {{ 0 }}, /* DESX_CBC */
234 {{ 0 }}, /* DESX_ECB */
235 {{ 0 }}, /* DESX_CFB */
236 {{ 0 }}, /* RC2_CBC */
237 {{ 0 }}, /* RC2_ECB */
238 {{ 0 }}, /* RC2_CFB */
241 {{ MAGIC_ALG
}, ALG_ID_ECDH_P256
},
242 {{ MAGIC_ALG
}, ALG_ID_ECDH_P384
},
243 {{ 0 }}, /* ECDH_P512 */
244 {{ MAGIC_ALG
}, ALG_ID_DSA
},
245 {{ MAGIC_ALG
}, ALG_ID_ECDSA_P256
},
246 {{ MAGIC_ALG
}, ALG_ID_ECDSA_P384
},
247 {{ 0 }}, /* ECDSA_P512 */
248 {{ MAGIC_ALG
}, ALG_ID_RSA_SIGN
},
251 /* Algorithm pseudo-handles are denoted by having the lowest bit set.
252 * An aligned algorithm pointer will never have this bit set.
254 static inline BOOL
is_alg_pseudo_handle( BCRYPT_ALG_HANDLE handle
)
256 return (((ULONG_PTR
)handle
& 1) == 1);
259 static struct object
*get_object( BCRYPT_HANDLE handle
, ULONG magic
)
263 if (!handle
) return NULL
;
265 if (!is_alg_pseudo_handle( handle
))
267 struct object
*obj
= handle
;
268 if (magic
&& obj
->magic
!= magic
) return NULL
;
272 idx
= (ULONG_PTR
)handle
>> 4;
273 if (idx
> ARRAY_SIZE(pseudo_algorithms
) || !pseudo_algorithms
[idx
].hdr
.magic
)
275 FIXME( "pseudo-handle %p not supported\n", handle
);
278 return (struct object
*)&pseudo_algorithms
[idx
];
281 static inline struct algorithm
*get_alg_object( BCRYPT_ALG_HANDLE handle
)
283 return (struct algorithm
*)get_object( handle
, MAGIC_ALG
);
286 static inline struct hash
*get_hash_object( BCRYPT_HASH_HANDLE handle
)
288 return (struct hash
*)get_object( handle
, MAGIC_HASH
);
291 static inline struct key
*get_key_object( BCRYPT_KEY_HANDLE handle
)
293 return (struct key
*)get_object( handle
, MAGIC_KEY
);
296 static inline struct secret
*get_secret_object( BCRYPT_SECRET_HANDLE handle
)
298 return (struct secret
*)get_object( handle
, MAGIC_SECRET
);
301 NTSTATUS WINAPI
BCryptGenRandom( BCRYPT_ALG_HANDLE handle
, UCHAR
*buffer
, ULONG count
, ULONG flags
)
303 const DWORD supported_flags
= BCRYPT_USE_SYSTEM_PREFERRED_RNG
;
304 struct algorithm
*alg
= get_alg_object( handle
);
306 TRACE("%p, %p, %lu, %#lx - semi-stub\n", handle
, buffer
, count
, flags
);
310 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
311 * is set. In this case the preferred system RNG is used.
313 if (!(flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
314 return STATUS_INVALID_HANDLE
;
316 else if (is_alg_pseudo_handle( handle
) && handle
!= BCRYPT_RNG_ALG_HANDLE
)
318 FIXME( "pseudo-handle %p not supported\n", handle
);
319 return STATUS_NOT_IMPLEMENTED
;
321 else if (!alg
|| alg
->id
!= ALG_ID_RNG
)
322 return STATUS_INVALID_HANDLE
;
325 return STATUS_INVALID_PARAMETER
;
327 if (flags
& ~supported_flags
)
328 FIXME("unsupported flags %#lx\n", flags
& ~supported_flags
);
331 FIXME("ignoring selected algorithm\n");
333 /* When zero bytes are requested the function returns success too. */
335 return STATUS_SUCCESS
;
337 if (alg
|| (flags
& BCRYPT_USE_SYSTEM_PREFERRED_RNG
))
339 if (RtlGenRandom(buffer
, count
)) return STATUS_SUCCESS
;
342 FIXME("called with unsupported parameters, returning error\n");
343 return STATUS_NOT_IMPLEMENTED
;
346 static struct algorithm
*create_algorithm( enum alg_id id
, enum chain_mode mode
, DWORD flags
)
348 struct algorithm
*ret
;
349 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
350 ret
->hdr
.magic
= MAGIC_ALG
;
357 NTSTATUS WINAPI
BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE
*handle
, const WCHAR
*id
, const WCHAR
*implementation
,
360 const DWORD supported_flags
= BCRYPT_ALG_HANDLE_HMAC_FLAG
| BCRYPT_HASH_REUSABLE_FLAG
;
361 struct algorithm
*alg
;
365 TRACE( "%p, %s, %s, %#lx\n", handle
, wine_dbgstr_w(id
), wine_dbgstr_w(implementation
), flags
);
367 if (!handle
|| !id
) return STATUS_INVALID_PARAMETER
;
368 if (flags
& ~supported_flags
)
370 FIXME( "unsupported flags %#lx\n", flags
& ~supported_flags
);
371 return STATUS_NOT_IMPLEMENTED
;
374 for (i
= 0; i
< ARRAY_SIZE( builtin_algorithms
); i
++)
376 if (!wcscmp( id
, builtin_algorithms
[i
].name
))
382 if (i
== ARRAY_SIZE( builtin_algorithms
))
384 FIXME( "algorithm %s not supported\n", debugstr_w(id
) );
385 return STATUS_NOT_IMPLEMENTED
;
388 if (implementation
&& wcscmp( implementation
, MS_PRIMITIVE_PROVIDER
))
390 FIXME( "implementation %s not supported\n", debugstr_w(implementation
) );
391 return STATUS_NOT_IMPLEMENTED
;
394 if (!(alg
= create_algorithm( alg_id
, 0, flags
))) return STATUS_NO_MEMORY
;
396 return STATUS_SUCCESS
;
399 static void destroy_object( struct object
*obj
)
401 SecureZeroMemory( &obj
->magic
, sizeof(obj
->magic
) );
405 NTSTATUS WINAPI
BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle
, DWORD flags
)
407 struct algorithm
*alg
= handle
;
409 TRACE( "%p, %#lx\n", handle
, flags
);
411 if (!handle
|| is_alg_pseudo_handle( handle
) || alg
->hdr
.magic
!= MAGIC_ALG
) return STATUS_INVALID_HANDLE
;
412 destroy_object( &alg
->hdr
);
413 return STATUS_SUCCESS
;
416 NTSTATUS WINAPI
BCryptGetFipsAlgorithmMode(BOOLEAN
*enabled
)
418 FIXME("%p - semi-stub\n", enabled
);
421 return STATUS_INVALID_PARAMETER
;
424 return STATUS_SUCCESS
;
440 static NTSTATUS
hash_init( struct hash_impl
*hash
, enum alg_id alg_id
)
445 md2_init( &hash
->u
.md2
);
449 MD4Init( &hash
->u
.md4
);
453 MD5Init( &hash
->u
.md5
);
457 A_SHAInit( &hash
->u
.sha1
);
461 sha256_init( &hash
->u
.sha256
);
465 sha384_init( &hash
->u
.sha512
);
469 sha512_init( &hash
->u
.sha512
);
473 ERR( "unhandled id %u\n", alg_id
);
474 return STATUS_NOT_IMPLEMENTED
;
476 return STATUS_SUCCESS
;
479 static NTSTATUS
hash_update( struct hash_impl
*hash
, enum alg_id alg_id
, UCHAR
*input
, ULONG size
)
484 md2_update( &hash
->u
.md2
, input
, size
);
488 MD4Update( &hash
->u
.md4
, input
, size
);
492 MD5Update( &hash
->u
.md5
, input
, size
);
496 A_SHAUpdate( &hash
->u
.sha1
, input
, size
);
500 sha256_update( &hash
->u
.sha256
, input
, size
);
504 sha384_update( &hash
->u
.sha512
, input
, size
);
508 sha512_update( &hash
->u
.sha512
, input
, size
);
512 ERR( "unhandled id %u\n", alg_id
);
513 return STATUS_NOT_IMPLEMENTED
;
515 return STATUS_SUCCESS
;
518 static NTSTATUS
hash_finish( struct hash_impl
*hash
, enum alg_id alg_id
, UCHAR
*output
)
523 md2_finalize( &hash
->u
.md2
, output
);
527 MD4Final( &hash
->u
.md4
);
528 memcpy( output
, hash
->u
.md4
.digest
, 16 );
532 MD5Final( &hash
->u
.md5
);
533 memcpy( output
, hash
->u
.md5
.digest
, 16 );
537 A_SHAFinal( &hash
->u
.sha1
, (ULONG
*)output
);
541 sha256_finalize( &hash
->u
.sha256
, output
);
545 sha384_finalize( &hash
->u
.sha512
, output
);
549 sha512_finalize( &hash
->u
.sha512
, output
);
553 ERR( "unhandled id %u\n", alg_id
);
554 return STATUS_NOT_IMPLEMENTED
;
556 return STATUS_SUCCESS
;
559 #define HASH_FLAG_HMAC 0x01
560 #define HASH_FLAG_REUSABLE 0x02
568 struct hash_impl outer
;
569 struct hash_impl inner
;
572 #define BLOCK_LENGTH_RC4 1
573 #define BLOCK_LENGTH_3DES 8
574 #define BLOCK_LENGTH_AES 16
576 static NTSTATUS
generic_alg_property( enum alg_id id
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
578 if (!wcscmp( prop
, BCRYPT_OBJECT_LENGTH
))
580 if (!builtin_algorithms
[id
].object_length
)
581 return STATUS_NOT_SUPPORTED
;
582 *ret_size
= sizeof(ULONG
);
583 if (size
< sizeof(ULONG
))
584 return STATUS_BUFFER_TOO_SMALL
;
586 *(ULONG
*)buf
= builtin_algorithms
[id
].object_length
;
587 return STATUS_SUCCESS
;
590 if (!wcscmp( prop
, BCRYPT_HASH_LENGTH
))
592 if (!builtin_algorithms
[id
].hash_length
)
593 return STATUS_NOT_SUPPORTED
;
594 *ret_size
= sizeof(ULONG
);
595 if (size
< sizeof(ULONG
))
596 return STATUS_BUFFER_TOO_SMALL
;
598 *(ULONG
*)buf
= builtin_algorithms
[id
].hash_length
;
599 return STATUS_SUCCESS
;
602 if (!wcscmp( prop
, BCRYPT_ALGORITHM_NAME
))
604 *ret_size
= (lstrlenW(builtin_algorithms
[id
].name
) + 1) * sizeof(WCHAR
);
605 if (size
< *ret_size
)
606 return STATUS_BUFFER_TOO_SMALL
;
608 memcpy(buf
, builtin_algorithms
[id
].name
, *ret_size
);
609 return STATUS_SUCCESS
;
612 return STATUS_NOT_IMPLEMENTED
;
615 static NTSTATUS
get_3des_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
617 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
619 *ret_size
= sizeof(ULONG
);
620 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
621 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_3DES
;
622 return STATUS_SUCCESS
;
624 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
629 case CHAIN_MODE_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
630 default: return STATUS_NOT_IMPLEMENTED
;
634 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
635 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
636 return STATUS_SUCCESS
;
638 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
640 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
641 *ret_size
= sizeof(*key_lengths
);
642 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
645 key_lengths
->dwMinLength
= 192;
646 key_lengths
->dwMaxLength
= 192;
647 key_lengths
->dwIncrement
= 0;
649 return STATUS_SUCCESS
;
651 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
652 return STATUS_NOT_IMPLEMENTED
;
655 static NTSTATUS
get_aes_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
657 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
659 *ret_size
= sizeof(ULONG
);
660 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
661 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_AES
;
662 return STATUS_SUCCESS
;
664 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
669 case CHAIN_MODE_ECB
: str
= BCRYPT_CHAIN_MODE_ECB
; break;
670 case CHAIN_MODE_CBC
: str
= BCRYPT_CHAIN_MODE_CBC
; break;
671 case CHAIN_MODE_GCM
: str
= BCRYPT_CHAIN_MODE_GCM
; break;
672 case CHAIN_MODE_CFB
: str
= BCRYPT_CHAIN_MODE_CFB
; break;
673 default: return STATUS_NOT_IMPLEMENTED
;
677 if (size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
678 memcpy( buf
, str
, (lstrlenW(str
) + 1) * sizeof(WCHAR
) );
679 return STATUS_SUCCESS
;
681 if (!wcscmp( prop
, BCRYPT_KEY_LENGTHS
))
683 BCRYPT_KEY_LENGTHS_STRUCT
*key_lengths
= (void *)buf
;
684 *ret_size
= sizeof(*key_lengths
);
685 if (key_lengths
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
688 key_lengths
->dwMinLength
= 128;
689 key_lengths
->dwMaxLength
= 256;
690 key_lengths
->dwIncrement
= 64;
692 return STATUS_SUCCESS
;
694 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
))
696 BCRYPT_AUTH_TAG_LENGTHS_STRUCT
*tag_length
= (void *)buf
;
697 if (mode
!= CHAIN_MODE_GCM
) return STATUS_NOT_SUPPORTED
;
698 *ret_size
= sizeof(*tag_length
);
699 if (tag_length
&& size
< *ret_size
) return STATUS_BUFFER_TOO_SMALL
;
702 tag_length
->dwMinLength
= 12;
703 tag_length
->dwMaxLength
= 16;
704 tag_length
->dwIncrement
= 1;
706 return STATUS_SUCCESS
;
709 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
710 return STATUS_NOT_IMPLEMENTED
;
713 static NTSTATUS
get_rc4_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
715 if (!wcscmp( prop
, BCRYPT_BLOCK_LENGTH
))
717 *ret_size
= sizeof(ULONG
);
718 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
719 if (buf
) *(ULONG
*)buf
= BLOCK_LENGTH_RC4
;
720 return STATUS_SUCCESS
;
723 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
724 return STATUS_NOT_IMPLEMENTED
;
727 static NTSTATUS
get_rsa_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
729 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
))
731 *ret_size
= sizeof(ULONG
);
732 if (size
< sizeof(ULONG
)) return STATUS_BUFFER_TOO_SMALL
;
733 if (buf
) *(ULONG
*)buf
= BCRYPT_SUPPORTED_PAD_PKCS1_SIG
;
734 return STATUS_SUCCESS
;
737 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
738 return STATUS_NOT_IMPLEMENTED
;
741 static NTSTATUS
get_dsa_property( enum chain_mode mode
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
743 if (!wcscmp( prop
, BCRYPT_PADDING_SCHEMES
)) return STATUS_NOT_SUPPORTED
;
744 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
745 return STATUS_NOT_IMPLEMENTED
;
748 static NTSTATUS
get_alg_property( const struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
,
753 status
= generic_alg_property( alg
->id
, prop
, buf
, size
, ret_size
);
754 if (status
!= STATUS_NOT_IMPLEMENTED
)
760 return get_3des_property( alg
->mode
, prop
, buf
, size
, ret_size
);
763 return get_aes_property( alg
->mode
, prop
, buf
, size
, ret_size
);
766 return get_rc4_property( alg
->mode
, prop
, buf
, size
, ret_size
);
769 return get_rsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
772 return get_dsa_property( alg
->mode
, prop
, buf
, size
, ret_size
);
778 FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop
), alg
->id
);
779 return STATUS_NOT_IMPLEMENTED
;
782 static NTSTATUS
set_alg_property( struct algorithm
*alg
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
787 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
789 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
791 alg
->mode
= CHAIN_MODE_CBC
;
792 return STATUS_SUCCESS
;
796 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
797 return STATUS_NOT_SUPPORTED
;
800 FIXME( "unsupported 3des algorithm property %s\n", debugstr_w(prop
) );
801 return STATUS_NOT_IMPLEMENTED
;
804 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
806 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
808 alg
->mode
= CHAIN_MODE_ECB
;
809 return STATUS_SUCCESS
;
811 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
813 alg
->mode
= CHAIN_MODE_CBC
;
814 return STATUS_SUCCESS
;
816 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
818 alg
->mode
= CHAIN_MODE_GCM
;
819 return STATUS_SUCCESS
;
821 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CFB
))
823 alg
->mode
= CHAIN_MODE_CFB
;
824 return STATUS_SUCCESS
;
828 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
829 return STATUS_NOT_IMPLEMENTED
;
832 FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop
) );
833 return STATUS_NOT_IMPLEMENTED
;
836 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
838 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_NA
)) return STATUS_SUCCESS
;
840 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
841 return STATUS_NOT_IMPLEMENTED
;
843 FIXME( "unsupported rc4 algorithm property %s\n", debugstr_w(prop
) );
844 return STATUS_NOT_IMPLEMENTED
;
847 FIXME( "unsupported algorithm %u\n", alg
->id
);
848 return STATUS_NOT_IMPLEMENTED
;
852 static NTSTATUS
set_key_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
854 if (!wcscmp( prop
, BCRYPT_CHAINING_MODE
))
856 if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
858 key
->u
.s
.mode
= CHAIN_MODE_ECB
;
859 return STATUS_SUCCESS
;
861 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
863 key
->u
.s
.mode
= CHAIN_MODE_CBC
;
864 return STATUS_SUCCESS
;
866 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_GCM
))
868 key
->u
.s
.mode
= CHAIN_MODE_GCM
;
869 return STATUS_SUCCESS
;
871 else if (!wcscmp( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CFB
))
873 key
->u
.s
.mode
= CHAIN_MODE_CFB
;
874 return STATUS_SUCCESS
;
878 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
879 return STATUS_NOT_IMPLEMENTED
;
882 else if (!wcscmp( prop
, BCRYPT_KEY_LENGTH
))
884 if (size
< sizeof(DWORD
)) return STATUS_INVALID_PARAMETER
;
885 key
->u
.a
.bitlen
= *(DWORD
*)value
;
886 return STATUS_SUCCESS
;
889 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
890 return STATUS_NOT_IMPLEMENTED
;
893 static NTSTATUS
get_hash_property( const struct hash
*hash
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
897 status
= generic_alg_property( hash
->alg_id
, prop
, buf
, size
, ret_size
);
898 if (status
== STATUS_NOT_IMPLEMENTED
)
899 FIXME( "unsupported property %s\n", debugstr_w(prop
) );
903 static NTSTATUS
get_key_property( const struct key
*key
, const WCHAR
*prop
, UCHAR
*buf
, ULONG size
, ULONG
*ret_size
)
905 if (!wcscmp( prop
, BCRYPT_KEY_STRENGTH
))
907 *ret_size
= sizeof(DWORD
);
908 if (size
< sizeof(DWORD
)) return STATUS_BUFFER_TOO_SMALL
;
911 if (is_symmetric_key(key
)) *(DWORD
*)buf
= key
->u
.s
.block_size
* 8;
912 else *(DWORD
*)buf
= key
->u
.a
.bitlen
;
914 return STATUS_SUCCESS
;
920 return get_3des_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
923 if (!wcscmp( prop
, BCRYPT_AUTH_TAG_LENGTH
)) return STATUS_NOT_SUPPORTED
;
924 return get_aes_property( key
->u
.s
.mode
, prop
, buf
, size
, ret_size
);
927 FIXME( "unsupported algorithm %u\n", key
->alg_id
);
928 return STATUS_NOT_IMPLEMENTED
;
932 NTSTATUS WINAPI
BCryptGetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*buffer
, ULONG count
, ULONG
*res
,
935 struct object
*object
= get_object( handle
, 0 );
937 TRACE( "%p, %s, %p, %lu, %p, %#lx\n", handle
, wine_dbgstr_w(prop
), buffer
, count
, res
, flags
);
939 if (!object
) return STATUS_INVALID_HANDLE
;
940 if (!prop
|| !res
) return STATUS_INVALID_PARAMETER
;
942 switch (object
->magic
)
946 const struct algorithm
*alg
= (const struct algorithm
*)object
;
947 return get_alg_property( alg
, prop
, buffer
, count
, res
);
951 const struct key
*key
= (const struct key
*)object
;
952 return get_key_property( key
, prop
, buffer
, count
, res
);
956 const struct hash
*hash
= (const struct hash
*)object
;
957 return get_hash_property( hash
, prop
, buffer
, count
, res
);
960 WARN( "unknown magic %#lx\n", object
->magic
);
961 return STATUS_INVALID_HANDLE
;
965 static NTSTATUS
hash_prepare( struct hash
*hash
)
967 UCHAR buffer
[MAX_HASH_BLOCK_BITS
/ 8] = {0};
971 /* initialize hash */
972 if ((status
= hash_init( &hash
->inner
, hash
->alg_id
))) return status
;
973 if (!(hash
->flags
& HASH_FLAG_HMAC
)) return STATUS_SUCCESS
;
975 /* initialize hmac */
976 if ((status
= hash_init( &hash
->outer
, hash
->alg_id
))) return status
;
977 block_bytes
= builtin_algorithms
[hash
->alg_id
].block_bits
/ 8;
978 if (hash
->secret_len
> block_bytes
)
980 struct hash_impl temp
;
981 if ((status
= hash_init( &temp
, hash
->alg_id
))) return status
;
982 if ((status
= hash_update( &temp
, hash
->alg_id
, hash
->secret
, hash
->secret_len
))) return status
;
983 if ((status
= hash_finish( &temp
, hash
->alg_id
, buffer
))) return status
;
985 else memcpy( buffer
, hash
->secret
, hash
->secret_len
);
987 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= 0x5c;
988 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, block_bytes
))) return status
;
989 for (i
= 0; i
< block_bytes
; i
++) buffer
[i
] ^= (0x5c ^ 0x36);
990 return hash_update( &hash
->inner
, hash
->alg_id
, buffer
, block_bytes
);
993 static NTSTATUS
hash_create( const struct algorithm
*alg
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
,
994 struct hash
**ret_hash
)
999 if (!(hash
= calloc( 1, sizeof(*hash
) ))) return STATUS_NO_MEMORY
;
1000 hash
->hdr
.magic
= MAGIC_HASH
;
1001 hash
->alg_id
= alg
->id
;
1002 if (alg
->flags
& BCRYPT_ALG_HANDLE_HMAC_FLAG
) hash
->flags
= HASH_FLAG_HMAC
;
1003 if ((alg
->flags
& BCRYPT_HASH_REUSABLE_FLAG
) || (flags
& BCRYPT_HASH_REUSABLE_FLAG
))
1004 hash
->flags
|= HASH_FLAG_REUSABLE
;
1006 if (secret_len
&& !(hash
->secret
= malloc( secret_len
)))
1009 return STATUS_NO_MEMORY
;
1011 memcpy( hash
->secret
, secret
, secret_len
);
1012 hash
->secret_len
= secret_len
;
1014 if ((status
= hash_prepare( hash
)))
1016 free( hash
->secret
);
1022 return STATUS_SUCCESS
;
1025 NTSTATUS WINAPI
BCryptCreateHash( BCRYPT_ALG_HANDLE handle
, BCRYPT_HASH_HANDLE
*ret_handle
, UCHAR
*object
,
1026 ULONG object_len
, UCHAR
*secret
, ULONG secret_len
, ULONG flags
)
1028 struct algorithm
*alg
= get_alg_object( handle
);
1032 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, ret_handle
, object
, object_len
, secret
, secret_len
, flags
);
1033 if (flags
& ~BCRYPT_HASH_REUSABLE_FLAG
)
1035 FIXME( "unimplemented flags %#lx\n", flags
);
1036 return STATUS_NOT_IMPLEMENTED
;
1038 if (object
) FIXME( "ignoring object buffer\n" );
1040 if (!alg
) return STATUS_INVALID_HANDLE
;
1041 if (!ret_handle
) return STATUS_INVALID_PARAMETER
;
1043 if ((status
= hash_create( alg
, secret
, secret_len
, flags
, &hash
))) return status
;
1045 return STATUS_SUCCESS
;
1048 NTSTATUS WINAPI
BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle
, BCRYPT_HASH_HANDLE
*handle_copy
,
1049 UCHAR
*object
, ULONG objectlen
, ULONG flags
)
1051 struct hash
*hash_orig
= get_hash_object( handle
);
1052 struct hash
*hash_copy
;
1054 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, handle_copy
, object
, objectlen
, flags
);
1056 if (!hash_orig
) return STATUS_INVALID_HANDLE
;
1057 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
1058 if (object
) FIXME( "ignoring object buffer\n" );
1060 if (!(hash_copy
= malloc( sizeof(*hash_copy
) ))) return STATUS_NO_MEMORY
;
1062 memcpy( hash_copy
, hash_orig
, sizeof(*hash_orig
) );
1063 if (hash_orig
->secret
&& !(hash_copy
->secret
= malloc( hash_orig
->secret_len
)))
1066 return STATUS_NO_MEMORY
;
1068 memcpy( hash_copy
->secret
, hash_orig
->secret
, hash_orig
->secret_len
);
1070 *handle_copy
= hash_copy
;
1071 return STATUS_SUCCESS
;
1074 static void hash_destroy( struct hash
*hash
)
1077 free( hash
->secret
);
1078 destroy_object( &hash
->hdr
);
1081 NTSTATUS WINAPI
BCryptDestroyHash( BCRYPT_HASH_HANDLE handle
)
1083 struct hash
*hash
= get_hash_object( handle
);
1085 TRACE( "%p\n", handle
);
1087 if (!hash
) return STATUS_INVALID_PARAMETER
;
1088 hash_destroy( hash
);
1089 return STATUS_SUCCESS
;
1092 NTSTATUS WINAPI
BCryptHashData( BCRYPT_HASH_HANDLE handle
, UCHAR
*input
, ULONG size
, ULONG flags
)
1094 struct hash
*hash
= get_hash_object( handle
);
1096 TRACE( "%p, %p, %lu, %#lx\n", handle
, input
, size
, flags
);
1098 if (!hash
) return STATUS_INVALID_HANDLE
;
1099 if (!input
) return STATUS_SUCCESS
;
1101 return hash_update( &hash
->inner
, hash
->alg_id
, input
, size
);
1104 static NTSTATUS
hash_finalize( struct hash
*hash
, UCHAR
*output
)
1106 UCHAR buffer
[MAX_HASH_OUTPUT_BYTES
];
1107 ULONG hash_length
= builtin_algorithms
[hash
->alg_id
].hash_length
;
1110 if (!(hash
->flags
& HASH_FLAG_HMAC
))
1112 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, output
))) return status
;
1113 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
1114 return STATUS_SUCCESS
;
1117 if ((status
= hash_finish( &hash
->inner
, hash
->alg_id
, buffer
))) return status
;
1118 if ((status
= hash_update( &hash
->outer
, hash
->alg_id
, buffer
, hash_length
))) return status
;
1119 if ((status
= hash_finish( &hash
->outer
, hash
->alg_id
, output
))) return status
;
1121 if (hash
->flags
& HASH_FLAG_REUSABLE
) return hash_prepare( hash
);
1122 return STATUS_SUCCESS
;
1125 NTSTATUS WINAPI
BCryptFinishHash( BCRYPT_HASH_HANDLE handle
, UCHAR
*output
, ULONG size
, ULONG flags
)
1127 struct hash
*hash
= get_hash_object( handle
);
1129 TRACE( "%p, %p, %lu, %#lx\n", handle
, output
, size
, flags
);
1131 if (!hash
) return STATUS_INVALID_HANDLE
;
1132 if (!output
|| size
!= builtin_algorithms
[hash
->alg_id
].hash_length
) return STATUS_INVALID_PARAMETER
;
1134 return hash_finalize( hash
, output
);
1137 NTSTATUS WINAPI
BCryptHash( BCRYPT_ALG_HANDLE handle
, UCHAR
*secret
, ULONG secret_len
,
1138 UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
1140 struct algorithm
*alg
= get_alg_object( handle
);
1144 TRACE( "%p, %p, %lu, %p, %lu, %p, %lu\n", handle
, secret
, secret_len
, input
, input_len
, output
, output_len
);
1146 if (!alg
) return STATUS_INVALID_HANDLE
;
1147 if (!output
) return STATUS_INVALID_PARAMETER
;
1149 if ((status
= hash_create( alg
, secret
, secret_len
, 0, &hash
))) return status
;
1150 if (output_len
!= builtin_algorithms
[hash
->alg_id
].hash_length
)
1152 hash_destroy( hash
);
1153 return STATUS_INVALID_PARAMETER
;
1155 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, input
, input_len
)))
1157 hash_destroy( hash
);
1160 status
= hash_finalize( hash
, output
);
1161 hash_destroy( hash
);
1165 static NTSTATUS
key_asymmetric_create( enum alg_id alg_id
, ULONG bitlen
, struct key
**ret_key
)
1169 if (!__wine_unixlib_handle
)
1171 ERR( "no encryption support\n" );
1172 return STATUS_NOT_IMPLEMENTED
;
1175 if (!(key
= calloc( 1, sizeof(*key
) ))) return STATUS_NO_MEMORY
;
1176 key
->hdr
.magic
= MAGIC_KEY
;
1177 key
->alg_id
= alg_id
;
1178 key
->u
.a
.bitlen
= bitlen
;
1181 return STATUS_SUCCESS
;
1184 static BOOL
is_equal_vector( const UCHAR
*vector
, ULONG len
, const UCHAR
*vector2
, ULONG len2
)
1186 if (!vector
&& !vector2
) return TRUE
;
1187 if (len
!= len2
) return FALSE
;
1188 return !memcmp( vector
, vector2
, len
);
1191 static NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
, BOOL force_reset
)
1193 BOOL needs_reset
= force_reset
|| !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
);
1196 free( key
->u
.s
.vector
);
1197 key
->u
.s
.vector
= NULL
;
1198 key
->u
.s
.vector_len
= 0;
1200 if (!(key
->u
.s
.vector
= malloc( vector_len
))) return STATUS_NO_MEMORY
;
1201 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
1202 key
->u
.s
.vector_len
= vector_len
;
1204 if (needs_reset
) UNIX_CALL( key_symmetric_vector_reset
, key
);
1205 return STATUS_SUCCESS
;
1208 static struct key
*create_symmetric_key( enum alg_id alg
, enum chain_mode mode
, ULONG block_size
, UCHAR
*secret
,
1213 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
1214 InitializeCriticalSection( &ret
->u
.s
.cs
);
1215 ret
->hdr
.magic
= MAGIC_KEY
;
1217 ret
->u
.s
.mode
= mode
;
1218 ret
->u
.s
.block_size
= block_size
;
1220 if (!(ret
->u
.s
.secret
= malloc( secret_len
)))
1222 DeleteCriticalSection( &ret
->u
.s
.cs
);
1226 memcpy( ret
->u
.s
.secret
, secret
, secret_len
);
1227 ret
->u
.s
.secret_len
= secret_len
;
1232 static ULONG
get_block_size( struct algorithm
*alg
)
1234 ULONG ret
= 0, size
= sizeof(ret
);
1235 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
1239 static NTSTATUS
generate_symmetric_key( struct algorithm
*alg
, BCRYPT_KEY_HANDLE
*ret_handle
, UCHAR
*secret
,
1242 BCRYPT_KEY_LENGTHS_STRUCT key_lengths
;
1243 ULONG block_size
, size
;
1247 if (!(block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
1248 if (!get_alg_property( alg
, BCRYPT_KEY_LENGTHS
, (UCHAR
*)&key_lengths
, sizeof(key_lengths
), &size
))
1250 if (secret_len
> (size
= key_lengths
.dwMaxLength
/ 8))
1252 WARN( "secret_len %lu exceeds key max length %lu, setting to maximum\n", secret_len
, size
);
1255 else if (secret_len
< (size
= key_lengths
.dwMinLength
/ 8))
1257 WARN( "secret_len %lu is less than minimum key length %lu\n", secret_len
, size
);
1258 return STATUS_INVALID_PARAMETER
;
1260 else if (key_lengths
.dwIncrement
&& (secret_len
* 8 - key_lengths
.dwMinLength
) % key_lengths
.dwIncrement
)
1262 WARN( "secret_len %lu is not a valid key length\n", secret_len
);
1263 return STATUS_INVALID_PARAMETER
;
1267 if (!(key
= create_symmetric_key( alg
->id
, alg
->mode
, block_size
, secret
, secret_len
))) status
= STATUS_NO_MEMORY
;
1271 status
= STATUS_SUCCESS
;
1277 static NTSTATUS
key_import( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*key
, UCHAR
*object
,
1278 ULONG object_len
, UCHAR
*input
, ULONG input_len
)
1282 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1284 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)input
;
1286 if (input_len
< sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
)) return STATUS_BUFFER_TOO_SMALL
;
1287 if (header
->dwMagic
!= BCRYPT_KEY_DATA_BLOB_MAGIC
) return STATUS_INVALID_PARAMETER
;
1288 if (header
->dwVersion
!= BCRYPT_KEY_DATA_BLOB_VERSION1
)
1290 FIXME( "unknown key data blob version %lu\n", header
->dwVersion
);
1291 return STATUS_INVALID_PARAMETER
;
1293 len
= header
->cbKeyData
;
1294 if (len
+ sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) > input_len
) return STATUS_INVALID_PARAMETER
;
1296 return generate_symmetric_key( alg
, key
, (UCHAR
*)&header
[1], len
);
1298 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1300 if (input_len
< sizeof(len
)) return STATUS_BUFFER_TOO_SMALL
;
1301 len
= *(ULONG
*)input
;
1302 if (len
+ sizeof(len
) > input_len
) return STATUS_INVALID_PARAMETER
;
1304 return generate_symmetric_key( alg
, key
, input
+ sizeof(len
), len
);
1307 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1308 return STATUS_NOT_IMPLEMENTED
;
1311 static NTSTATUS
key_export( struct key
*key
, const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
)
1313 struct key_asymmetric_export_params params
;
1315 if (!wcscmp( type
, BCRYPT_KEY_DATA_BLOB
))
1317 BCRYPT_KEY_DATA_BLOB_HEADER
*header
= (BCRYPT_KEY_DATA_BLOB_HEADER
*)output
;
1318 ULONG req_size
= sizeof(BCRYPT_KEY_DATA_BLOB_HEADER
) + key
->u
.s
.secret_len
;
1321 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1324 header
->dwMagic
= BCRYPT_KEY_DATA_BLOB_MAGIC
;
1325 header
->dwVersion
= BCRYPT_KEY_DATA_BLOB_VERSION1
;
1326 header
->cbKeyData
= key
->u
.s
.secret_len
;
1327 memcpy( &header
[1], key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1329 return STATUS_SUCCESS
;
1331 else if (!wcscmp( type
, BCRYPT_OPAQUE_KEY_BLOB
))
1333 ULONG len
, req_size
= sizeof(len
) + key
->u
.s
.secret_len
;
1336 if (output_len
< req_size
) return STATUS_BUFFER_TOO_SMALL
;
1339 *(ULONG
*)output
= key
->u
.s
.secret_len
;
1340 memcpy( output
+ sizeof(len
), key
->u
.s
.secret
, key
->u
.s
.secret_len
);
1342 return STATUS_SUCCESS
;
1344 else if (!wcscmp( type
, BCRYPT_DSA_PRIVATE_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
) ||
1345 !wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1349 params
.buf
= output
;
1350 params
.len
= output_len
;
1351 params
.ret_len
= size
;
1352 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1354 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1357 params
.flags
= (wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
)) ? KEY_EXPORT_FLAG_RSA_FULL
: 0;
1358 params
.buf
= output
;
1359 params
.len
= output_len
;
1360 params
.ret_len
= size
;
1361 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1363 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
) || !wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
) ||
1364 !wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
) || !wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1367 params
.flags
= KEY_EXPORT_FLAG_PUBLIC
;
1368 params
.buf
= output
;
1369 params
.len
= output_len
;
1370 params
.ret_len
= size
;
1371 return UNIX_CALL( key_asymmetric_export
, ¶ms
);
1374 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1375 return STATUS_NOT_IMPLEMENTED
;
1378 static NTSTATUS
key_symmetric_encrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1379 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1381 struct key_symmetric_set_auth_data_params auth_params
;
1382 struct key_symmetric_encrypt_params encrypt_params
;
1383 struct key_symmetric_get_tag_params tag_params
;
1384 ULONG bytes_left
= input_len
;
1388 if (key
->u
.s
.mode
== CHAIN_MODE_GCM
)
1390 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1392 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1393 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1394 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1395 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1396 if (auth_info
->dwFlags
& BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
)
1397 FIXME( "call chaining not implemented\n" );
1399 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
, TRUE
)))
1402 *ret_len
= input_len
;
1403 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1404 if (input
&& !output
) return STATUS_SUCCESS
;
1405 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1407 auth_params
.key
= key
;
1408 auth_params
.auth_data
= auth_info
->pbAuthData
;
1409 auth_params
.len
= auth_info
->cbAuthData
;
1410 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1412 encrypt_params
.key
= key
;
1413 encrypt_params
.input
= input
;
1414 encrypt_params
.input_len
= input_len
;
1415 encrypt_params
.output
= output
;
1416 encrypt_params
.output_len
= output_len
;
1417 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
))) return status
;
1419 tag_params
.key
= key
;
1420 tag_params
.tag
= auth_info
->pbTag
;
1421 tag_params
.len
= auth_info
->cbTag
;
1422 return UNIX_CALL( key_symmetric_get_tag
, &tag_params
);
1425 *ret_len
= input_len
;
1427 if (flags
& BCRYPT_BLOCK_PADDING
)
1428 *ret_len
= (input_len
+ key
->u
.s
.block_size
) & ~(key
->u
.s
.block_size
- 1);
1429 else if (input_len
& (key
->u
.s
.block_size
- 1))
1430 return STATUS_INVALID_BUFFER_SIZE
;
1432 if (!output
) return STATUS_SUCCESS
;
1433 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1434 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1435 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
, flags
& BCRYPT_BLOCK_PADDING
))) return status
;
1437 encrypt_params
.key
= key
;
1438 encrypt_params
.input
= input
;
1439 encrypt_params
.input_len
= key
->u
.s
.block_size
;
1440 encrypt_params
.output
= output
;
1441 encrypt_params
.output_len
= key
->u
.s
.block_size
;
1442 while (bytes_left
>= key
->u
.s
.block_size
)
1444 if ((status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
)))
1446 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0, TRUE
)))
1448 bytes_left
-= key
->u
.s
.block_size
;
1449 encrypt_params
.input
+= key
->u
.s
.block_size
;
1450 encrypt_params
.output
+= key
->u
.s
.block_size
;
1453 if (flags
& BCRYPT_BLOCK_PADDING
)
1455 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1456 memcpy( buf
, encrypt_params
.input
, bytes_left
);
1457 memset( buf
+ bytes_left
, key
->u
.s
.block_size
- bytes_left
, key
->u
.s
.block_size
- bytes_left
);
1458 encrypt_params
.input
= buf
;
1459 status
= UNIX_CALL( key_symmetric_encrypt
, &encrypt_params
);
1465 if (key
->u
.s
.vector
&& *ret_len
>= key
->u
.s
.vector_len
)
1467 memcpy( key
->u
.s
.vector
, output
+ *ret_len
- key
->u
.s
.vector_len
, key
->u
.s
.vector_len
);
1468 if (iv
) memcpy( iv
, key
->u
.s
.vector
, min( iv_len
, key
->u
.s
.vector_len
));
1470 else FIXME( "Unexpected vector len %lu, *ret_len %lu.\n", key
->u
.s
.vector_len
, *ret_len
);
1476 static NTSTATUS
key_symmetric_decrypt( struct key
*key
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
1477 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
1479 struct key_symmetric_set_auth_data_params auth_params
;
1480 struct key_symmetric_decrypt_params decrypt_params
;
1481 struct key_symmetric_get_tag_params tag_params
;
1482 ULONG bytes_left
= input_len
;
1485 if (key
->u
.s
.mode
== CHAIN_MODE_GCM
)
1487 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
*auth_info
= padding
;
1490 if (!auth_info
) return STATUS_INVALID_PARAMETER
;
1491 if (!auth_info
->pbNonce
) return STATUS_INVALID_PARAMETER
;
1492 if (!auth_info
->pbTag
) return STATUS_INVALID_PARAMETER
;
1493 if (auth_info
->cbTag
< 12 || auth_info
->cbTag
> 16) return STATUS_INVALID_PARAMETER
;
1495 if ((status
= key_symmetric_set_vector( key
, auth_info
->pbNonce
, auth_info
->cbNonce
, TRUE
)))
1498 *ret_len
= input_len
;
1499 if (flags
& BCRYPT_BLOCK_PADDING
) return STATUS_INVALID_PARAMETER
;
1500 if (!output
) return STATUS_SUCCESS
;
1501 if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1503 auth_params
.key
= key
;
1504 auth_params
.auth_data
= auth_info
->pbAuthData
;
1505 auth_params
.len
= auth_info
->cbAuthData
;
1506 if ((status
= UNIX_CALL( key_symmetric_set_auth_data
, &auth_params
))) return status
;
1508 decrypt_params
.key
= key
;
1509 decrypt_params
.input
= input
;
1510 decrypt_params
.input_len
= input_len
;
1511 decrypt_params
.output
= output
;
1512 decrypt_params
.output_len
= output_len
;
1513 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1515 tag_params
.key
= key
;
1516 tag_params
.tag
= tag
;
1517 tag_params
.len
= sizeof(tag
);
1518 if ((status
= UNIX_CALL( key_symmetric_get_tag
, &tag_params
))) return status
;
1519 if (memcmp( tag
, auth_info
->pbTag
, auth_info
->cbTag
)) return STATUS_AUTH_TAG_MISMATCH
;
1521 return STATUS_SUCCESS
;
1524 *ret_len
= input_len
;
1526 if (input_len
& (key
->u
.s
.block_size
- 1)) return STATUS_INVALID_BUFFER_SIZE
;
1527 if (!output
) return STATUS_SUCCESS
;
1528 if (flags
& BCRYPT_BLOCK_PADDING
)
1530 if (output_len
+ key
->u
.s
.block_size
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1531 if (input_len
< key
->u
.s
.block_size
) return STATUS_BUFFER_TOO_SMALL
;
1532 bytes_left
-= key
->u
.s
.block_size
;
1534 else if (output_len
< *ret_len
) return STATUS_BUFFER_TOO_SMALL
;
1536 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& iv
) return STATUS_INVALID_PARAMETER
;
1537 if ((status
= key_symmetric_set_vector( key
, iv
, iv_len
, flags
& BCRYPT_BLOCK_PADDING
))) return status
;
1539 decrypt_params
.key
= key
;
1540 decrypt_params
.input
= input
;
1541 decrypt_params
.input_len
= key
->u
.s
.block_size
;
1542 decrypt_params
.output
= output
;
1543 decrypt_params
.output_len
= key
->u
.s
.block_size
;
1544 while (bytes_left
>= key
->u
.s
.block_size
)
1546 if ((status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
))) return status
;
1547 if (key
->u
.s
.mode
== CHAIN_MODE_ECB
&& (status
= key_symmetric_set_vector( key
, NULL
, 0, TRUE
)))
1549 bytes_left
-= key
->u
.s
.block_size
;
1550 decrypt_params
.input
+= key
->u
.s
.block_size
;
1551 decrypt_params
.output
+= key
->u
.s
.block_size
;
1554 if (flags
& BCRYPT_BLOCK_PADDING
)
1556 UCHAR
*buf
, *dst
= decrypt_params
.output
;
1557 if (!(buf
= malloc( key
->u
.s
.block_size
))) return STATUS_NO_MEMORY
;
1558 decrypt_params
.output
= buf
;
1559 status
= UNIX_CALL( key_symmetric_decrypt
, &decrypt_params
);
1560 if (!status
&& buf
[ key
->u
.s
.block_size
- 1 ] <= key
->u
.s
.block_size
)
1562 *ret_len
-= buf
[ key
->u
.s
.block_size
- 1 ];
1563 if (output_len
< *ret_len
) status
= STATUS_BUFFER_TOO_SMALL
;
1564 else memcpy( dst
, buf
, key
->u
.s
.block_size
- buf
[ key
->u
.s
.block_size
- 1 ] );
1566 else status
= STATUS_UNSUCCESSFUL
; /* FIXME: invalid padding */
1572 if (key
->u
.s
.vector
&& input_len
>= key
->u
.s
.vector_len
)
1574 memcpy( key
->u
.s
.vector
, input
+ input_len
- key
->u
.s
.vector_len
, key
->u
.s
.vector_len
);
1575 if (iv
) memcpy( iv
, key
->u
.s
.vector
, min( iv_len
, key
->u
.s
.vector_len
));
1577 else FIXME( "Unexpected vector len %lu, *ret_len %lu.\n", key
->u
.s
.vector_len
, *ret_len
);
1583 static void key_destroy( struct key
*key
)
1585 if (is_symmetric_key( key
))
1587 UNIX_CALL( key_symmetric_destroy
, key
);
1588 free( key
->u
.s
.vector
);
1589 free( key
->u
.s
.secret
);
1590 DeleteCriticalSection( &key
->u
.s
.cs
);
1593 UNIX_CALL( key_asymmetric_destroy
, key
);
1595 destroy_object( &key
->hdr
);
1598 static NTSTATUS
convert_legacy_rsaprivate_blob( struct algorithm
*alg
, BCRYPT_RSAKEY_BLOB
**rsa_data
,
1599 ULONG
*rsa_len
, UCHAR
*input
, ULONG input_len
)
1602 PUBLICKEYSTRUC header
;
1603 RSAPUBKEY rsapubkey
;
1604 } *blob
= (void *)input
;
1609 if (alg
->id
!= ALG_ID_RSA
) return STATUS_NOT_SUPPORTED
;
1610 if (input_len
< sizeof(*blob
)) return NTE_BAD_DATA
;
1611 if (blob
->header
.bType
!= PRIVATEKEYBLOB
|| blob
->header
.bVersion
!= CUR_BLOB_VERSION
||
1612 blob
->header
.aiKeyAlg
!= CALG_RSA_KEYX
||
1613 blob
->rsapubkey
.magic
!= BCRYPT_RSAPRIVATE_MAGIC
||
1614 input_len
!= sizeof(*blob
) + blob
->rsapubkey
.bitlen
/ 16 * 9) return NTE_BAD_DATA
;
1615 if (blob
->rsapubkey
.bitlen
& 0xf) return STATUS_INVALID_PARAMETER
;
1617 len
= sizeof(**rsa_data
) + sizeof(blob
->rsapubkey
.pubexp
) + blob
->rsapubkey
.bitlen
/ 4;
1618 if (!(conv
= malloc( len
))) return STATUS_NO_MEMORY
;
1620 *rsa_data
= (BCRYPT_RSAKEY_BLOB
*)conv
;
1621 (*rsa_data
)->Magic
= blob
->rsapubkey
.magic
;
1622 (*rsa_data
)->BitLength
= blob
->rsapubkey
.bitlen
;
1623 (*rsa_data
)->cbPublicExp
= sizeof(blob
->rsapubkey
.pubexp
);
1624 (*rsa_data
)->cbModulus
= blob
->rsapubkey
.bitlen
/ 8;
1625 (*rsa_data
)->cbPrime1
= blob
->rsapubkey
.bitlen
/ 16;
1626 (*rsa_data
)->cbPrime2
= blob
->rsapubkey
.bitlen
/ 16;
1627 len
= sizeof(**rsa_data
);
1629 for(i
= 0; i
< (*rsa_data
)->cbPublicExp
; i
++)
1630 conv
[len
++] = ((UCHAR
*)&blob
->rsapubkey
.pubexp
)[(*rsa_data
)->cbPublicExp
- i
- 1];
1631 pos
= sizeof(*blob
);
1632 for(i
= 0; i
< (*rsa_data
)->cbModulus
; i
++)
1633 conv
[len
++] = input
[pos
+ (*rsa_data
)->cbModulus
- i
- 1];
1634 pos
+= (*rsa_data
)->cbModulus
;
1635 for(i
= 0; i
< (*rsa_data
)->cbPrime1
; i
++)
1636 conv
[len
++] = input
[pos
+ (*rsa_data
)->cbPrime1
- i
- 1];
1637 pos
+= (*rsa_data
)->cbPrime1
;
1638 for(i
= 0; i
< (*rsa_data
)->cbPrime2
; i
++)
1639 conv
[len
++] = input
[pos
+ (*rsa_data
)->cbPrime2
- i
- 1];
1642 return STATUS_SUCCESS
;
1645 static NTSTATUS
key_import_pair( struct algorithm
*alg
, const WCHAR
*type
, BCRYPT_KEY_HANDLE
*ret_key
, UCHAR
*input
,
1648 struct key_asymmetric_import_params params
;
1653 if (!wcscmp( type
, BCRYPT_ECCPUBLIC_BLOB
))
1655 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1656 DWORD key_size
, magic
;
1658 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1662 case ALG_ID_ECDH_P256
:
1664 magic
= BCRYPT_ECDH_PUBLIC_P256_MAGIC
;
1667 case ALG_ID_ECDH_P384
:
1669 magic
= BCRYPT_ECDH_PUBLIC_P384_MAGIC
;
1672 case ALG_ID_ECDSA_P256
:
1674 magic
= BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
1677 case ALG_ID_ECDSA_P384
:
1679 magic
= BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
1683 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1684 return STATUS_NOT_SUPPORTED
;
1687 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1688 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 2)
1689 return STATUS_INVALID_PARAMETER
;
1691 if ((status
= key_asymmetric_create( alg
->id
, key_size
* 8, &key
))) return status
;
1693 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1695 params
.len
= input_len
;
1696 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1703 return STATUS_SUCCESS
;
1705 else if (!wcscmp( type
, BCRYPT_ECCPRIVATE_BLOB
))
1707 BCRYPT_ECCKEY_BLOB
*ecc_blob
= (BCRYPT_ECCKEY_BLOB
*)input
;
1708 DWORD key_size
, magic
;
1710 if (input_len
< sizeof(*ecc_blob
)) return STATUS_INVALID_PARAMETER
;
1714 case ALG_ID_ECDH_P256
:
1716 magic
= BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
1719 case ALG_ID_ECDH_P384
:
1721 magic
= BCRYPT_ECDH_PRIVATE_P384_MAGIC
;
1724 case ALG_ID_ECDSA_P256
:
1726 magic
= BCRYPT_ECDSA_PRIVATE_P256_MAGIC
;
1730 FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1731 return STATUS_NOT_SUPPORTED
;
1734 if (ecc_blob
->dwMagic
!= magic
) return STATUS_INVALID_PARAMETER
;
1735 if (ecc_blob
->cbKey
!= key_size
|| input_len
< sizeof(*ecc_blob
) + ecc_blob
->cbKey
* 3)
1736 return STATUS_INVALID_PARAMETER
;
1738 if ((status
= key_asymmetric_create( alg
->id
, key_size
* 8, &key
))) return status
;
1742 params
.len
= input_len
;
1743 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1750 return STATUS_SUCCESS
;
1752 else if (!wcscmp( type
, BCRYPT_RSAPUBLIC_BLOB
))
1754 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1756 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1757 if ((alg
->id
!= ALG_ID_RSA
&& alg
->id
!= ALG_ID_RSA_SIGN
) || rsa_blob
->Magic
!= BCRYPT_RSAPUBLIC_MAGIC
)
1758 return STATUS_NOT_SUPPORTED
;
1760 size
= sizeof(*rsa_blob
) + rsa_blob
->cbPublicExp
+ rsa_blob
->cbModulus
;
1761 if (size
!= input_len
) return NTE_BAD_DATA
;
1763 if ((status
= key_asymmetric_create( alg
->id
, rsa_blob
->BitLength
, &key
))) return status
;
1765 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1767 params
.len
= input_len
;
1768 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1775 return STATUS_SUCCESS
;
1777 else if (!wcscmp( type
, BCRYPT_RSAPRIVATE_BLOB
) || !wcscmp( type
, BCRYPT_RSAFULLPRIVATE_BLOB
))
1779 BCRYPT_RSAKEY_BLOB
*rsa_blob
= (BCRYPT_RSAKEY_BLOB
*)input
;
1781 if (input_len
< sizeof(*rsa_blob
)) return STATUS_INVALID_PARAMETER
;
1782 if (alg
->id
!= ALG_ID_RSA
|| (rsa_blob
->Magic
!= BCRYPT_RSAPRIVATE_MAGIC
&&
1783 rsa_blob
->Magic
!= BCRYPT_RSAFULLPRIVATE_MAGIC
)) return STATUS_NOT_SUPPORTED
;
1785 if ((status
= key_asymmetric_create( alg
->id
, rsa_blob
->BitLength
, &key
))) return status
;
1789 params
.len
= input_len
;
1790 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1797 return STATUS_SUCCESS
;
1799 else if (!wcscmp( type
, LEGACY_RSAPRIVATE_BLOB
))
1801 BCRYPT_RSAKEY_BLOB
*rsa_blob
;
1803 status
= convert_legacy_rsaprivate_blob( alg
, &rsa_blob
, &input_len
, input
, input_len
);
1804 if (status
!= STATUS_SUCCESS
)
1807 status
= key_import_pair( alg
, BCRYPT_RSAPRIVATE_BLOB
, ret_key
, (UCHAR
*)rsa_blob
, input_len
);
1808 SecureZeroMemory( rsa_blob
, input_len
);
1812 else if (!wcscmp( type
, BCRYPT_DSA_PUBLIC_BLOB
))
1814 BCRYPT_DSA_KEY_BLOB
*dsa_blob
= (BCRYPT_DSA_KEY_BLOB
*)input
;
1816 if (input_len
< sizeof(*dsa_blob
)) return STATUS_INVALID_PARAMETER
;
1817 if ((alg
->id
!= ALG_ID_DSA
) || dsa_blob
->dwMagic
!= BCRYPT_DSA_PUBLIC_MAGIC
)
1818 return STATUS_NOT_SUPPORTED
;
1820 if ((status
= key_asymmetric_create( alg
->id
, dsa_blob
->cbKey
* 8, &key
))) return status
;
1822 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1824 params
.len
= input_len
;
1825 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1832 return STATUS_SUCCESS
;
1834 else if (!wcscmp( type
, LEGACY_DSA_V2_PRIVATE_BLOB
))
1836 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1839 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1841 if (hdr
->bType
!= PRIVATEKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1843 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1844 return STATUS_NOT_SUPPORTED
;
1846 if (alg
->id
!= ALG_ID_DSA
)
1848 FIXME( "algorithm %u does not support importing blob of type %s\n", alg
->id
, debugstr_w(type
) );
1849 return STATUS_NOT_SUPPORTED
;
1852 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1853 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1854 if (pubkey
->magic
!= MAGIC_DSS2
) return STATUS_NOT_SUPPORTED
;
1856 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 2 + 40 + sizeof(DSSSEED
))
1857 return STATUS_INVALID_PARAMETER
;
1859 if ((status
= key_asymmetric_create( alg
->id
, pubkey
->bitlen
, &key
))) return status
;
1860 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1864 params
.len
= input_len
;
1865 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1872 return STATUS_SUCCESS
;
1874 else if (!wcscmp( type
, LEGACY_DSA_V2_PUBLIC_BLOB
)) /* not supported on native */
1876 BLOBHEADER
*hdr
= (BLOBHEADER
*)input
;
1879 if (alg
->id
!= ALG_ID_DSA
) return STATUS_NOT_SUPPORTED
;
1880 if (input_len
< sizeof(*hdr
)) return STATUS_INVALID_PARAMETER
;
1882 if (hdr
->bType
!= PUBLICKEYBLOB
&& hdr
->bVersion
!= 2 && hdr
->aiKeyAlg
!= CALG_DSS_SIGN
)
1884 FIXME( "blob type %u version %u alg id %u not supported\n", hdr
->bType
, hdr
->bVersion
, hdr
->aiKeyAlg
);
1885 return STATUS_NOT_SUPPORTED
;
1888 if (input_len
< sizeof(*hdr
) + sizeof(*pubkey
)) return STATUS_INVALID_PARAMETER
;
1889 pubkey
= (DSSPUBKEY
*)(hdr
+ 1);
1890 if (pubkey
->magic
!= MAGIC_DSS1
) return STATUS_NOT_SUPPORTED
;
1892 size
= sizeof(*hdr
) + sizeof(*pubkey
) + (pubkey
->bitlen
/ 8) * 3 + 20 + sizeof(DSSSEED
);
1893 if (input_len
< size
) return STATUS_INVALID_PARAMETER
;
1895 if ((status
= key_asymmetric_create( alg
->id
, pubkey
->bitlen
, &key
))) return status
;
1896 key
->u
.a
.flags
|= KEY_FLAG_LEGACY_DSA_V2
;
1898 params
.flags
= KEY_IMPORT_FLAG_PUBLIC
;
1900 params
.len
= input_len
;
1901 if ((status
= UNIX_CALL( key_asymmetric_import
, ¶ms
)))
1908 return STATUS_SUCCESS
;
1911 FIXME( "unsupported key type %s\n", debugstr_w(type
) );
1912 return STATUS_NOT_SUPPORTED
;
1915 NTSTATUS WINAPI
BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE
*ret_handle
,
1916 UCHAR
*object
, ULONG object_len
, UCHAR
*secret
, ULONG secret_len
,
1919 struct algorithm
*alg
= get_alg_object( handle
);
1921 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, ret_handle
, object
, object_len
, secret
, secret_len
, flags
);
1922 if (object
) FIXME( "ignoring object buffer\n" );
1923 if (!__wine_unixlib_handle
)
1925 ERR( "no encryption support\n" );
1926 return STATUS_NOT_IMPLEMENTED
;
1929 if (!alg
) return STATUS_INVALID_HANDLE
;
1930 return generate_symmetric_key( alg
, ret_handle
, secret
, secret_len
);
1933 NTSTATUS WINAPI
BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE
*ret_handle
, ULONG key_len
,
1936 struct algorithm
*alg
= get_alg_object( handle
);
1940 TRACE( "%p, %p, %lu, %#lx\n", handle
, ret_handle
, key_len
, flags
);
1942 if (!alg
) return STATUS_INVALID_HANDLE
;
1943 if (!ret_handle
) return STATUS_INVALID_PARAMETER
;
1945 if ((status
= key_asymmetric_create( alg
->id
, key_len
, &key
))) return status
;
1947 return STATUS_SUCCESS
;
1950 NTSTATUS WINAPI
BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle
, ULONG flags
)
1952 struct key
*key
= get_key_object( handle
);
1954 TRACE( "%p, %#lx\n", key
, flags
);
1956 if (!key
) return STATUS_INVALID_HANDLE
;
1957 return UNIX_CALL( key_asymmetric_generate
, key
);
1960 NTSTATUS WINAPI
BCryptImportKey( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE decrypt_key
, const WCHAR
*type
,
1961 BCRYPT_KEY_HANDLE
*ret_handle
, UCHAR
*object
, ULONG object_len
, UCHAR
*input
,
1962 ULONG input_len
, ULONG flags
)
1964 struct algorithm
*alg
= get_alg_object( handle
);
1966 TRACE( "%p, %p, %s, %p, %p, %lu, %p, %lu, %#lx\n", handle
, decrypt_key
, debugstr_w(type
), ret_handle
, object
,
1967 object_len
, input
, input_len
, flags
);
1969 if (!alg
) return STATUS_INVALID_HANDLE
;
1970 if (!ret_handle
|| !type
|| !input
) return STATUS_INVALID_PARAMETER
;
1973 FIXME( "decryption of key not yet supported\n" );
1974 return STATUS_NOT_IMPLEMENTED
;
1977 return key_import( alg
, type
, ret_handle
, object
, object_len
, input
, input_len
);
1980 NTSTATUS WINAPI
BCryptExportKey( BCRYPT_KEY_HANDLE export_key_handle
, BCRYPT_KEY_HANDLE encrypt_key_handle
,
1981 const WCHAR
*type
, UCHAR
*output
, ULONG output_len
, ULONG
*size
, ULONG flags
)
1983 struct key
*key
= get_key_object( export_key_handle
);
1985 TRACE( "%p, %p, %s, %p, %lu, %p, %#lx\n", export_key_handle
, encrypt_key_handle
, debugstr_w(type
), output
,
1986 output_len
, size
, flags
);
1988 if (!key
) return STATUS_INVALID_HANDLE
;
1989 if (!type
|| !size
) return STATUS_INVALID_PARAMETER
;
1990 if (encrypt_key_handle
)
1992 FIXME( "encryption of key not yet supported\n" );
1993 return STATUS_NOT_IMPLEMENTED
;
1996 return key_export( key
, type
, output
, output_len
, size
);
1999 static NTSTATUS
key_duplicate( struct key
*key_orig
, struct key
*key_copy
)
2004 memset( key_copy
, 0, sizeof(*key_copy
) );
2005 key_copy
->hdr
= key_orig
->hdr
;
2006 key_copy
->alg_id
= key_orig
->alg_id
;
2008 if (is_symmetric_key( key_orig
))
2010 if (!(buffer
= malloc( key_orig
->u
.s
.secret_len
))) return STATUS_NO_MEMORY
;
2011 memcpy( buffer
, key_orig
->u
.s
.secret
, key_orig
->u
.s
.secret_len
);
2013 key_copy
->u
.s
.mode
= key_orig
->u
.s
.mode
;
2014 key_copy
->u
.s
.block_size
= key_orig
->u
.s
.block_size
;
2015 key_copy
->u
.s
.secret
= buffer
;
2016 key_copy
->u
.s
.secret_len
= key_orig
->u
.s
.secret_len
;
2017 InitializeCriticalSection( &key_copy
->u
.s
.cs
);
2021 struct key_asymmetric_duplicate_params params
;
2023 key_copy
->u
.a
.bitlen
= key_orig
->u
.a
.bitlen
;
2024 key_copy
->u
.a
.flags
= key_orig
->u
.a
.flags
;
2025 key_copy
->u
.a
.dss_seed
= key_orig
->u
.a
.dss_seed
;
2027 params
.key_orig
= key_orig
;
2028 params
.key_copy
= key_copy
;
2029 if ((status
= UNIX_CALL( key_asymmetric_duplicate
, ¶ms
))) return status
;
2032 return STATUS_SUCCESS
;
2035 NTSTATUS WINAPI
BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle
, BCRYPT_KEY_HANDLE
*handle_copy
,
2036 UCHAR
*object
, ULONG object_len
, ULONG flags
)
2038 struct key
*key_orig
= get_key_object( handle
);
2039 struct key
*key_copy
;
2042 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, handle_copy
, object
, object_len
, flags
);
2043 if (object
) FIXME( "ignoring object buffer\n" );
2045 if (!key_orig
) return STATUS_INVALID_HANDLE
;
2046 if (!handle_copy
) return STATUS_INVALID_PARAMETER
;
2047 if (!(key_copy
= malloc( sizeof(*key_copy
) ))) return STATUS_NO_MEMORY
;
2049 if ((status
= key_duplicate( key_orig
, key_copy
)))
2051 key_destroy( key_copy
);
2055 *handle_copy
= key_copy
;
2056 return STATUS_SUCCESS
;
2059 static const WCHAR
*resolve_blob_type( const WCHAR
*type
, UCHAR
*input
, ULONG input_len
)
2061 BCRYPT_KEY_BLOB
*blob
= (BCRYPT_KEY_BLOB
*)input
;
2063 if (!type
) return NULL
;
2064 if (wcscmp( type
, BCRYPT_PUBLIC_KEY_BLOB
)) return type
;
2065 if (input_len
< sizeof(*blob
)) return NULL
;
2067 switch (blob
->Magic
)
2069 case BCRYPT_ECDH_PUBLIC_P256_MAGIC
:
2070 case BCRYPT_ECDH_PUBLIC_P384_MAGIC
:
2071 case BCRYPT_ECDSA_PUBLIC_P256_MAGIC
:
2072 case BCRYPT_ECDSA_PUBLIC_P384_MAGIC
:
2073 return BCRYPT_ECCPUBLIC_BLOB
;
2075 case BCRYPT_RSAPUBLIC_MAGIC
:
2076 return BCRYPT_RSAPUBLIC_BLOB
;
2078 case BCRYPT_DSA_PUBLIC_MAGIC
:
2079 return BCRYPT_DSA_PUBLIC_BLOB
;
2082 FIXME( "unsupported key magic %#lx\n", blob
->Magic
);
2087 NTSTATUS WINAPI
BCryptImportKeyPair( BCRYPT_ALG_HANDLE handle
, BCRYPT_KEY_HANDLE decrypt_key_handle
, const WCHAR
*type
,
2088 BCRYPT_KEY_HANDLE
*ret_handle
, UCHAR
*input
, ULONG input_len
, ULONG flags
)
2090 struct algorithm
*alg
= get_alg_object( handle
);
2092 TRACE( "%p, %p, %s, %p, %p, %lu, %#lx\n", handle
, decrypt_key_handle
, debugstr_w(type
), ret_handle
, input
,
2095 if (!alg
) return STATUS_INVALID_HANDLE
;
2096 if (!ret_handle
|| !input
|| !(type
= resolve_blob_type( type
, input
, input_len
)))
2097 return STATUS_INVALID_PARAMETER
;
2098 if (decrypt_key_handle
)
2100 FIXME( "decryption of key not yet supported\n" );
2101 return STATUS_NOT_IMPLEMENTED
;
2104 return key_import_pair( alg
, type
, ret_handle
, input
, input_len
);
2107 NTSTATUS WINAPI
BCryptSignHash( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*input
, ULONG input_len
,
2108 UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
2110 struct key_asymmetric_sign_params params
;
2111 struct key
*key
= get_key_object( handle
);
2113 TRACE( "%p, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, padding
, input
, input_len
, output
, output_len
,
2116 if (!key
) return STATUS_INVALID_HANDLE
;
2117 if (!is_signature_key( key
)) return STATUS_NOT_SUPPORTED
;
2120 params
.padding
= padding
;
2121 params
.input
= input
;
2122 params
.input_len
= input_len
;
2123 params
.output
= output
;
2124 params
.output_len
= output_len
;
2125 params
.ret_len
= ret_len
;
2126 params
.flags
= flags
;
2127 return UNIX_CALL( key_asymmetric_sign
, ¶ms
);
2130 NTSTATUS WINAPI
BCryptVerifySignature( BCRYPT_KEY_HANDLE handle
, void *padding
, UCHAR
*hash
, ULONG hash_len
,
2131 UCHAR
*signature
, ULONG signature_len
, ULONG flags
)
2133 struct key_asymmetric_verify_params params
;
2134 struct key
*key
= get_key_object( handle
);
2136 TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle
, padding
, hash
, hash_len
, signature
, signature_len
, flags
);
2138 if (!key
) return STATUS_INVALID_HANDLE
;
2139 if (!is_signature_key( key
)) return STATUS_NOT_SUPPORTED
;
2140 if (!hash
|| !hash_len
|| !signature
|| !signature_len
) return STATUS_INVALID_PARAMETER
;
2143 params
.padding
= padding
;
2145 params
.hash_len
= hash_len
;
2146 params
.signature
= signature
;
2147 params
.signature_len
= signature_len
;
2148 params
.flags
= flags
;
2149 return UNIX_CALL( key_asymmetric_verify
, ¶ms
);
2152 NTSTATUS WINAPI
BCryptDestroyKey( BCRYPT_KEY_HANDLE handle
)
2154 struct key
*key
= get_key_object( handle
);
2156 TRACE( "%p\n", handle
);
2158 if (!key
) return STATUS_INVALID_HANDLE
;
2160 return STATUS_SUCCESS
;
2163 NTSTATUS WINAPI
BCryptEncrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
2164 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
2166 struct key
*key
= get_key_object( handle
);
2167 struct key_asymmetric_encrypt_params asymmetric_params
;
2170 TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
2171 output_len
, ret_len
, flags
);
2173 if (!key
) return STATUS_INVALID_HANDLE
;
2175 if (is_symmetric_key( key
))
2177 if (flags
& ~BCRYPT_BLOCK_PADDING
)
2179 FIXME( "flags %#lx not implemented\n", flags
);
2180 return STATUS_NOT_IMPLEMENTED
;
2182 EnterCriticalSection( &key
->u
.s
.cs
);
2183 ret
= key_symmetric_encrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
2184 LeaveCriticalSection( &key
->u
.s
.cs
);
2188 if (flags
& BCRYPT_PAD_NONE
|| flags
& BCRYPT_PAD_OAEP
)
2190 FIXME( "flags %#lx not implemented\n", flags
);
2191 return STATUS_NOT_IMPLEMENTED
;
2193 if (!is_asymmetric_encryption_key( key
)) return STATUS_NOT_SUPPORTED
;
2195 asymmetric_params
.input
= input
;
2196 asymmetric_params
.input_len
= input_len
;
2197 asymmetric_params
.key
= key
;
2198 asymmetric_params
.output
= output
;
2199 asymmetric_params
.output_len
= output_len
;
2200 asymmetric_params
.ret_len
= ret_len
;
2201 ret
= UNIX_CALL(key_asymmetric_encrypt
, &asymmetric_params
);
2207 NTSTATUS WINAPI
BCryptDecrypt( BCRYPT_KEY_HANDLE handle
, UCHAR
*input
, ULONG input_len
, void *padding
, UCHAR
*iv
,
2208 ULONG iv_len
, UCHAR
*output
, ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
2210 struct key
*key
= get_key_object( handle
);
2211 struct key_asymmetric_decrypt_params params
;
2214 TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle
, input
, input_len
, padding
, iv
, iv_len
, output
,
2215 output_len
, ret_len
, flags
);
2217 if (!key
) return STATUS_INVALID_HANDLE
;
2219 if (is_symmetric_key( key
))
2221 if (flags
& ~BCRYPT_BLOCK_PADDING
)
2223 FIXME( "flags %#lx not supported\n", flags
);
2224 return STATUS_NOT_IMPLEMENTED
;
2227 EnterCriticalSection( &key
->u
.s
.cs
);
2228 ret
= key_symmetric_decrypt( key
, input
, input_len
, padding
, iv
, iv_len
, output
, output_len
, ret_len
, flags
);
2229 LeaveCriticalSection( &key
->u
.s
.cs
);
2233 if (flags
& BCRYPT_PAD_NONE
|| flags
& BCRYPT_PAD_OAEP
)
2235 FIXME( "flags %#lx not implemented\n", flags
);
2236 return STATUS_NOT_IMPLEMENTED
;
2238 if (!is_asymmetric_encryption_key( key
)) return STATUS_NOT_SUPPORTED
;
2241 params
.input
= input
;
2242 params
.input_len
= input_len
;
2243 params
.output
= output
;
2244 params
.output_len
= output_len
;
2245 params
.ret_len
= ret_len
;
2246 ret
= UNIX_CALL(key_asymmetric_decrypt
, ¶ms
);
2252 NTSTATUS WINAPI
BCryptSetProperty( BCRYPT_HANDLE handle
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
2254 struct object
*object
= get_object( handle
, 0 );
2256 TRACE( "%p, %s, %p, %lu, %#lx\n", handle
, debugstr_w(prop
), value
, size
, flags
);
2258 if (!handle
) return STATUS_INVALID_HANDLE
;
2259 if (is_alg_pseudo_handle( handle
)) return STATUS_ACCESS_DENIED
;
2261 switch (object
->magic
)
2265 struct algorithm
*alg
= (struct algorithm
*)object
;
2266 return set_alg_property( alg
, prop
, value
, size
, flags
);
2270 struct key
*key
= (struct key
*)object
;
2271 return set_key_property( key
, prop
, value
, size
, flags
);
2274 WARN( "unknown magic %#lx\n", object
->magic
);
2275 return STATUS_INVALID_HANDLE
;
2279 #define HMAC_PAD_LEN 64
2280 NTSTATUS WINAPI
BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle
, BCRYPT_ALG_HANDLE halg
, UCHAR
*key
, ULONG keylen
, ULONG flags
)
2282 struct hash
*hash
= get_hash_object( handle
);
2283 UCHAR buf
[MAX_HASH_OUTPUT_BYTES
* 2];
2287 TRACE( "%p, %p, %p, %lu, %#lx\n", handle
, halg
, key
, keylen
, flags
);
2289 if (!hash
) return STATUS_INVALID_HANDLE
;
2290 if (!key
|| !keylen
) return STATUS_INVALID_PARAMETER
;
2291 if (keylen
> builtin_algorithms
[hash
->alg_id
].hash_length
* 2) return STATUS_INVALID_PARAMETER
;
2294 FIXME( "algorithm handle not supported\n" );
2295 return STATUS_NOT_IMPLEMENTED
;
2298 if ((status
= hash_finalize( hash
, buf
))) return status
;
2300 len
= builtin_algorithms
[hash
->alg_id
].hash_length
;
2303 UCHAR pad1
[HMAC_PAD_LEN
], pad2
[HMAC_PAD_LEN
];
2306 for (i
= 0; i
< sizeof(pad1
); i
++)
2308 pad1
[i
] = 0x36 ^ (i
< len
? buf
[i
] : 0);
2309 pad2
[i
] = 0x5c ^ (i
< len
? buf
[i
] : 0);
2312 if ((status
= hash_prepare( hash
)) ||
2313 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad1
, sizeof(pad1
) )) ||
2314 (status
= hash_finalize( hash
, buf
))) return status
;
2316 if ((status
= hash_prepare( hash
)) ||
2317 (status
= hash_update( &hash
->inner
, hash
->alg_id
, pad2
, sizeof(pad2
) )) ||
2318 (status
= hash_finalize( hash
, buf
+ len
))) return status
;
2321 memcpy( key
, buf
, keylen
);
2322 return STATUS_SUCCESS
;
2325 static NTSTATUS
pbkdf2( struct hash
*hash
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2326 ULONGLONG iterations
, ULONG i
, UCHAR
*dst
, ULONG hash_len
)
2328 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
2329 UCHAR bytes
[4], *buf
;
2332 if (!(buf
= malloc( hash_len
))) return STATUS_NO_MEMORY
;
2334 for (j
= 0; j
< iterations
; j
++)
2338 /* use salt || INT(i) */
2339 if ((status
= hash_update( &hash
->inner
, hash
->alg_id
, salt
, salt_len
)))
2344 bytes
[0] = (i
>> 24) & 0xff;
2345 bytes
[1] = (i
>> 16) & 0xff;
2346 bytes
[2] = (i
>> 8) & 0xff;
2347 bytes
[3] = i
& 0xff;
2348 status
= hash_update( &hash
->inner
, hash
->alg_id
, bytes
, 4 );
2350 else status
= hash_update( &hash
->inner
, hash
->alg_id
, buf
, hash_len
); /* use U_j */
2358 if ((status
= hash_finalize( hash
, buf
)))
2364 if (j
== 0) memcpy( dst
, buf
, hash_len
);
2365 else for (k
= 0; k
< hash_len
; k
++) dst
[k
] ^= buf
[k
];
2372 static NTSTATUS
derive_key_pbkdf2( struct algorithm
*alg
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2373 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
)
2375 ULONG hash_len
, block_count
, bytes_left
, i
;
2380 hash_len
= builtin_algorithms
[alg
->id
].hash_length
;
2381 if (dk_len
<= 0 || dk_len
> ((((ULONGLONG
)1) << 32) - 1) * hash_len
) return STATUS_INVALID_PARAMETER
;
2383 block_count
= 1 + ((dk_len
- 1) / hash_len
); /* ceil(dk_len / hash_len) */
2384 bytes_left
= dk_len
- (block_count
- 1) * hash_len
;
2386 if ((status
= hash_create( alg
, pwd
, pwd_len
, BCRYPT_HASH_REUSABLE_FLAG
, &hash
))) return status
;
2389 for (i
= 1; i
< block_count
; i
++)
2391 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, i
, dk
+ ((i
- 1) * hash_len
), hash_len
)))
2393 hash_destroy( hash
);
2398 /* final partial block */
2399 if (!(partial
= malloc( hash_len
)))
2401 hash_destroy( hash
);
2402 return STATUS_NO_MEMORY
;
2405 if ((status
= pbkdf2( hash
, pwd
, pwd_len
, salt
, salt_len
, iterations
, block_count
, partial
, hash_len
)))
2407 hash_destroy( hash
);
2411 memcpy( dk
+ ((block_count
- 1) * hash_len
), partial
, bytes_left
);
2413 hash_destroy( hash
);
2415 return STATUS_SUCCESS
;
2418 NTSTATUS WINAPI
BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle
, UCHAR
*pwd
, ULONG pwd_len
, UCHAR
*salt
, ULONG salt_len
,
2419 ULONGLONG iterations
, UCHAR
*dk
, ULONG dk_len
, ULONG flags
)
2421 struct algorithm
*alg
= get_alg_object( handle
);
2423 TRACE( "%p, %p, %lu, %p, %lu, %s, %p, %lu, %#lx\n", handle
, pwd
, pwd_len
, salt
, salt_len
,
2424 wine_dbgstr_longlong(iterations
), dk
, dk_len
, flags
);
2426 if (!alg
) return STATUS_INVALID_HANDLE
;
2427 return derive_key_pbkdf2( alg
, pwd
, pwd_len
, salt
, salt_len
, iterations
, dk
, dk_len
);
2430 NTSTATUS WINAPI
BCryptSecretAgreement( BCRYPT_KEY_HANDLE privkey_handle
, BCRYPT_KEY_HANDLE pubkey_handle
,
2431 BCRYPT_SECRET_HANDLE
*ret_handle
, ULONG flags
)
2433 struct key
*privkey
= get_key_object( privkey_handle
);
2434 struct key
*pubkey
= get_key_object( pubkey_handle
);
2435 struct secret
*secret
;
2437 FIXME( "%p, %p, %p, %#lx\n", privkey_handle
, pubkey_handle
, ret_handle
, flags
);
2439 if (!privkey
|| !pubkey
) return STATUS_INVALID_HANDLE
;
2440 if (!is_agreement_key( privkey
) || !is_agreement_key( pubkey
)) return STATUS_NOT_SUPPORTED
;
2441 if (!ret_handle
) return STATUS_INVALID_PARAMETER
;
2443 if (!(secret
= calloc( 1, sizeof(*secret
) ))) return STATUS_NO_MEMORY
;
2444 secret
->hdr
.magic
= MAGIC_SECRET
;
2446 *ret_handle
= secret
;
2447 return STATUS_SUCCESS
;
2450 NTSTATUS WINAPI
BCryptDestroySecret( BCRYPT_SECRET_HANDLE handle
)
2452 struct secret
*secret
= get_secret_object( handle
);
2454 FIXME( "%p\n", handle
);
2456 if (!secret
) return STATUS_INVALID_HANDLE
;
2457 destroy_object( &secret
->hdr
);
2458 return STATUS_SUCCESS
;
2461 NTSTATUS WINAPI
BCryptDeriveKey( BCRYPT_SECRET_HANDLE handle
, const WCHAR
*kdf
, BCryptBufferDesc
*parameter
,
2462 UCHAR
*derived
, ULONG derived_size
, ULONG
*result
, ULONG flags
)
2464 struct secret
*secret
= get_secret_object( handle
);
2466 FIXME( "%p, %s, %p, %p, %lu, %p, %#lx\n", secret
, debugstr_w(kdf
), parameter
, derived
, derived_size
, result
, flags
);
2468 if (!secret
) return STATUS_INVALID_HANDLE
;
2469 if (!kdf
) return STATUS_INVALID_PARAMETER
;
2471 return STATUS_INTERNAL_ERROR
;
2474 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
2478 case DLL_PROCESS_ATTACH
:
2479 DisableThreadLibraryCalls( hinst
);
2480 if (!__wine_init_unix_call())
2482 if (UNIX_CALL( process_attach
, NULL
)) __wine_unixlib_handle
= 0;
2485 case DLL_PROCESS_DETACH
:
2486 if (reserved
) break;
2487 if (__wine_unixlib_handle
) UNIX_CALL( process_detach
, NULL
);