Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
158ce169
Commit
158ce169
authored
Feb 13, 2019
by
Hans Leidekker
Committed by
Alexandre Julliard
Feb 13, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bcrypt: Add support for importing and exporting ECC private keys.
Signed-off-by:
Hans Leidekker
<
hans@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
5c2ac77a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
237 additions
and
5 deletions
+237
-5
bcrypt_internal.h
dlls/bcrypt/bcrypt_internal.h
+2
-0
bcrypt_main.c
dlls/bcrypt/bcrypt_main.c
+55
-0
gnutls.c
dlls/bcrypt/gnutls.c
+120
-1
macos.c
dlls/bcrypt/macos.c
+12
-0
bcrypt.c
dlls/bcrypt/tests/bcrypt.c
+48
-4
No files found.
dlls/bcrypt/bcrypt_internal.h
View file @
158ce169
...
...
@@ -230,6 +230,8 @@ NTSTATUS key_asymmetric_generate( struct key * ) DECLSPEC_HIDDEN;
NTSTATUS
key_asymmetric_verify
(
struct
key
*
,
void
*
,
UCHAR
*
,
ULONG
,
UCHAR
*
,
ULONG
,
DWORD
)
DECLSPEC_HIDDEN
;
NTSTATUS
key_destroy
(
struct
key
*
)
DECLSPEC_HIDDEN
;
BOOL
key_is_symmetric
(
struct
key
*
)
DECLSPEC_HIDDEN
;
NTSTATUS
key_export_ecc
(
struct
key
*
,
UCHAR
*
,
ULONG
,
ULONG
*
)
DECLSPEC_HIDDEN
;
NTSTATUS
key_import_ecc
(
struct
key
*
,
UCHAR
*
,
ULONG
)
DECLSPEC_HIDDEN
;
BOOL
gnutls_initialize
(
void
)
DECLSPEC_HIDDEN
;
void
gnutls_uninitialize
(
void
)
DECLSPEC_HIDDEN
;
...
...
dlls/bcrypt/bcrypt_main.c
View file @
158ce169
...
...
@@ -821,6 +821,10 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U
memcpy
(
output
,
key
->
u
.
a
.
pubkey
,
key
->
u
.
a
.
pubkey_len
);
return
STATUS_SUCCESS
;
}
else
if
(
!
strcmpW
(
type
,
BCRYPT_ECCPRIVATE_BLOB
))
{
return
key_export_ecc
(
key
,
output
,
output_len
,
size
);
}
FIXME
(
"unsupported key type %s
\n
"
,
debugstr_w
(
type
)
);
return
STATUS_NOT_IMPLEMENTED
;
...
...
@@ -1055,6 +1059,45 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
*
ret_key
=
key
;
return
STATUS_SUCCESS
;
}
else
if
(
!
strcmpW
(
type
,
BCRYPT_ECCPRIVATE_BLOB
))
{
BCRYPT_ECCKEY_BLOB
*
ecc_blob
=
(
BCRYPT_ECCKEY_BLOB
*
)
input
;
DWORD
key_size
,
magic
;
if
(
input_len
<
sizeof
(
*
ecc_blob
))
return
STATUS_INVALID_PARAMETER
;
switch
(
alg
->
id
)
{
case
ALG_ID_ECDH_P256
:
key_size
=
32
;
magic
=
BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
break
;
default:
FIXME
(
"algorithm %u does not yet support importing blob of type %s
\n
"
,
alg
->
id
,
debugstr_w
(
type
)
);
return
STATUS_NOT_SUPPORTED
;
}
if
(
ecc_blob
->
dwMagic
!=
magic
)
return
STATUS_NOT_SUPPORTED
;
if
(
ecc_blob
->
cbKey
!=
key_size
||
input_len
<
sizeof
(
*
ecc_blob
)
+
ecc_blob
->
cbKey
*
3
)
return
STATUS_INVALID_PARAMETER
;
if
(
!
(
key
=
heap_alloc_zero
(
sizeof
(
*
key
)
)))
return
STATUS_NO_MEMORY
;
key
->
hdr
.
magic
=
MAGIC_KEY
;
if
((
status
=
key_asymmetric_init
(
key
,
alg
,
NULL
,
0
)))
{
heap_free
(
key
);
return
status
;
}
if
((
status
=
key_import_ecc
(
key
,
input
,
input_len
)))
{
heap_free
(
key
);
return
status
;
}
*
ret_key
=
key
;
return
STATUS_SUCCESS
;
}
else
if
(
!
strcmpW
(
type
,
BCRYPT_RSAPUBLIC_BLOB
))
{
BCRYPT_RSAKEY_BLOB
*
rsa_blob
=
(
BCRYPT_RSAKEY_BLOB
*
)
input
;
...
...
@@ -1163,6 +1206,18 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
ERR
(
"support for keys not available at build time
\n
"
);
return
STATUS_NOT_IMPLEMENTED
;
}
NTSTATUS
key_export_ecc
(
struct
key
*
key
,
UCHAR
*
output
,
ULONG
len
,
ULONG
*
ret_len
)
{
ERR
(
"support for keys not available at build time
\n
"
);
return
STATUS_NOT_IMPLEMENTED
;
}
NTSTATUS
key_import_ecc
(
struct
key
*
key
,
UCHAR
*
input
,
ULONG
len
)
{
ERR
(
"support for keys not available at build time
\n
"
);
return
STATUS_NOT_IMPLEMENTED
;
}
#endif
NTSTATUS
WINAPI
BCryptGenerateSymmetricKey
(
BCRYPT_ALG_HANDLE
algorithm
,
BCRYPT_KEY_HANDLE
*
handle
,
...
...
dlls/bcrypt/gnutls.c
View file @
158ce169
...
...
@@ -70,6 +70,8 @@ static int (*pgnutls_cipher_add_auth)(gnutls_cipher_hd_t, const void *, size_t);
static
gnutls_sign_algorithm_t
(
*
pgnutls_pk_to_sign
)(
gnutls_pk_algorithm_t
,
gnutls_digest_algorithm_t
);
static
int
(
*
pgnutls_pubkey_import_ecc_raw
)(
gnutls_pubkey_t
,
gnutls_ecc_curve_t
,
const
gnutls_datum_t
*
,
const
gnutls_datum_t
*
);
static
int
(
*
pgnutls_privkey_import_ecc_raw
)(
gnutls_privkey_t
,
gnutls_ecc_curve_t
,
const
gnutls_datum_t
*
,
const
gnutls_datum_t
*
,
const
gnutls_datum_t
*
);
static
int
(
*
pgnutls_pubkey_verify_hash2
)(
gnutls_pubkey_t
,
gnutls_sign_algorithm_t
,
unsigned
int
,
const
gnutls_datum_t
*
,
const
gnutls_datum_t
*
);
...
...
@@ -120,6 +122,13 @@ static int compat_gnutls_privkey_export_ecc_raw(gnutls_privkey_t key, gnutls_ecc
return
GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
}
static
int
compat_gnutls_privkey_import_ecc_raw
(
gnutls_privkey_t
key
,
gnutls_ecc_curve_t
curve
,
const
gnutls_datum_t
*
x
,
const
gnutls_datum_t
*
y
,
const
gnutls_datum_t
*
k
)
{
return
GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
}
static
gnutls_sign_algorithm_t
compat_gnutls_pk_to_sign
(
gnutls_pk_algorithm_t
pk
,
gnutls_digest_algorithm_t
hash
)
{
return
GNUTLS_SIGN_UNKNOWN
;
...
...
@@ -206,6 +215,11 @@ BOOL gnutls_initialize(void)
WARN
(
"gnutls_privkey_export_ecc_raw not found
\n
"
);
pgnutls_privkey_export_ecc_raw
=
compat_gnutls_privkey_export_ecc_raw
;
}
if
(
!
(
pgnutls_privkey_import_ecc_raw
=
wine_dlsym
(
libgnutls_handle
,
"gnutls_privkey_import_ecc_raw"
,
NULL
,
0
)))
{
WARN
(
"gnutls_privkey_import_ecc_raw not found
\n
"
);
pgnutls_privkey_import_ecc_raw
=
compat_gnutls_privkey_import_ecc_raw
;
}
if
(
!
(
pgnutls_pk_to_sign
=
wine_dlsym
(
libgnutls_handle
,
"gnutls_pk_to_sign"
,
NULL
,
0
)))
{
WARN
(
"gnutls_pk_to_sign not found
\n
"
);
...
...
@@ -614,11 +628,116 @@ NTSTATUS key_asymmetric_generate( struct key *key )
if
((
status
=
export_gnutls_pubkey_ecc
(
handle
,
&
key
->
u
.
a
.
pubkey
,
&
key
->
u
.
a
.
pubkey_len
)))
{
pgnutls_privkey_deinit
(
handle
);
return
STATUS_INTERNAL_ERROR
;
return
status
;
}
key
->
u
.
a
.
handle
=
handle
;
return
STATUS_SUCCESS
;
}
NTSTATUS
key_export_ecc
(
struct
key
*
key
,
UCHAR
*
buf
,
ULONG
len
,
ULONG
*
ret_len
)
{
BCRYPT_ECCKEY_BLOB
*
ecc_blob
;
gnutls_ecc_curve_t
curve
;
gnutls_datum_t
x
,
y
,
d
;
DWORD
magic
,
size
;
UCHAR
*
src
,
*
dst
;
int
ret
;
if
((
ret
=
pgnutls_privkey_export_ecc_raw
(
key
->
u
.
a
.
handle
,
&
curve
,
&
x
,
&
y
,
&
d
)))
{
pgnutls_perror
(
ret
);
return
STATUS_INTERNAL_ERROR
;
}
switch
(
curve
)
{
case
GNUTLS_ECC_CURVE_SECP256R1
:
magic
=
BCRYPT_ECDH_PRIVATE_P256_MAGIC
;
size
=
32
;
break
;
default:
FIXME
(
"curve %u not supported
\n
"
,
curve
);
free
(
x
.
data
);
free
(
y
.
data
);
free
(
d
.
data
);
return
STATUS_NOT_IMPLEMENTED
;
}
*
ret_len
=
sizeof
(
*
ecc_blob
)
+
size
*
3
;
if
(
len
>=
*
ret_len
&&
buf
)
{
ecc_blob
=
(
BCRYPT_ECCKEY_BLOB
*
)
buf
;
ecc_blob
->
dwMagic
=
magic
;
ecc_blob
->
cbKey
=
size
;
dst
=
(
UCHAR
*
)(
ecc_blob
+
1
);
if
(
x
.
size
==
size
+
1
)
src
=
x
.
data
+
1
;
else
src
=
x
.
data
;
memcpy
(
dst
,
src
,
size
);
dst
+=
size
;
if
(
y
.
size
==
size
+
1
)
src
=
y
.
data
+
1
;
else
src
=
y
.
data
;
memcpy
(
dst
,
src
,
size
);
dst
+=
size
;
if
(
d
.
size
==
size
+
1
)
src
=
d
.
data
+
1
;
else
src
=
d
.
data
;
memcpy
(
dst
,
src
,
size
);
}
free
(
x
.
data
);
free
(
y
.
data
);
free
(
d
.
data
);
return
STATUS_SUCCESS
;
}
NTSTATUS
key_import_ecc
(
struct
key
*
key
,
UCHAR
*
buf
,
ULONG
len
)
{
BCRYPT_ECCKEY_BLOB
*
ecc_blob
;
gnutls_ecc_curve_t
curve
;
gnutls_privkey_t
handle
;
gnutls_datum_t
x
,
y
,
k
;
NTSTATUS
status
;
int
ret
;
switch
(
key
->
alg_id
)
{
case
ALG_ID_ECDH_P256
:
curve
=
GNUTLS_ECC_CURVE_SECP256R1
;
break
;
default:
FIXME
(
"algorithm %u not yet supported
\n
"
,
key
->
alg_id
);
return
STATUS_NOT_IMPLEMENTED
;
}
if
((
ret
=
pgnutls_privkey_init
(
&
handle
)))
{
pgnutls_perror
(
ret
);
return
STATUS_INTERNAL_ERROR
;
}
ecc_blob
=
(
BCRYPT_ECCKEY_BLOB
*
)
buf
;
x
.
data
=
(
unsigned
char
*
)(
ecc_blob
+
1
);
x
.
size
=
ecc_blob
->
cbKey
;
y
.
data
=
x
.
data
+
ecc_blob
->
cbKey
;
y
.
size
=
ecc_blob
->
cbKey
;
k
.
data
=
y
.
data
+
ecc_blob
->
cbKey
;
k
.
size
=
ecc_blob
->
cbKey
;
if
((
ret
=
pgnutls_privkey_import_ecc_raw
(
handle
,
curve
,
&
x
,
&
y
,
&
k
)))
{
pgnutls_perror
(
ret
);
pgnutls_privkey_deinit
(
handle
);
return
STATUS_INTERNAL_ERROR
;
}
if
((
status
=
export_gnutls_pubkey_ecc
(
handle
,
&
key
->
u
.
a
.
pubkey
,
&
key
->
u
.
a
.
pubkey_len
)))
{
pgnutls_privkey_deinit
(
handle
);
return
status
;
}
key
->
u
.
a
.
handle
=
handle
;
return
STATUS_SUCCESS
;
}
...
...
dlls/bcrypt/macos.c
View file @
158ce169
...
...
@@ -205,6 +205,18 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
return
STATUS_NOT_IMPLEMENTED
;
}
NTSTATUS
key_export_ecc
(
struct
key
*
key
,
UCHAR
*
output
,
ULONG
len
,
ULONG
*
ret_len
)
{
FIXME
(
"not implemented on Mac
\n
"
);
return
STATUS_NOT_IMPLEMENTED
;
}
NTSTATUS
key_import_ecc
(
struct
key
*
key
,
UCHAR
*
input
,
ULONG
len
)
{
FIXME
(
"not implemented on Mac
\n
"
);
return
STATUS_NOT_IMPLEMENTED
;
}
NTSTATUS
key_asymmetric_generate
(
struct
key
*
key
)
{
FIXME
(
"not implemented on Mac
\n
"
);
...
...
dlls/bcrypt/tests/bcrypt.c
View file @
158ce169
...
...
@@ -1657,12 +1657,23 @@ static void test_RSA(void)
ok
(
!
ret
,
"pBCryptCloseAlgorithmProvider failed: %08x
\n
"
,
ret
);
}
static
BYTE
eccprivkey
[]
=
{
0x45
,
0x43
,
0x4b
,
0x32
,
0x20
,
0x00
,
0x00
,
0x00
,
0xfb
,
0xbd
,
0x3d
,
0x20
,
0x1b
,
0x6d
,
0x66
,
0xb3
,
0x7c
,
0x9f
,
0x89
,
0xf3
,
0xe4
,
0x41
,
0x16
,
0xa5
,
0x68
,
0x52
,
0x77
,
0xac
,
0xab
,
0x55
,
0xb2
,
0x6c
,
0xb0
,
0x23
,
0x55
,
0xcb
,
0x96
,
0x14
,
0xfd
,
0x0b
,
0x1c
,
0xef
,
0xdf
,
0x07
,
0x6d
,
0x31
,
0xaf
,
0x39
,
0xce
,
0x8c
,
0x8f
,
0x9d
,
0x75
,
0xd0
,
0x7b
,
0xea
,
0x81
,
0xdc
,
0x40
,
0x21
,
0x1f
,
0x58
,
0x22
,
0x5f
,
0x72
,
0x55
,
0xfc
,
0x58
,
0x8a
,
0xeb
,
0x88
,
0x5d
,
0x02
,
0x09
,
0x90
,
0xd2
,
0xe3
,
0x36
,
0xac
,
0xfe
,
0x83
,
0x13
,
0x6c
,
0x88
,
0x1a
,
0xab
,
0x9b
,
0xdd
,
0xaa
,
0x8a
,
0xee
,
0x69
,
0x9a
,
0x6a
,
0x62
,
0x86
,
0x6a
,
0x13
,
0x69
,
0x88
,
0xb7
,
0xd5
,
0xa3
,
0xcd
};
static
void
test_ECDH
(
void
)
{
BYTE
*
buf
;
BCRYPT_ECCKEY_BLOB
*
ecckey
;
BCRYPT_ALG_HANDLE
alg
;
BCRYPT_KEY_HANDLE
key
;
BCRYPT_KEY_HANDLE
key
,
privkey
,
pubkey
;
NTSTATUS
status
;
ULONG
size
;
...
...
@@ -1682,7 +1693,6 @@ static void test_ECDH(void)
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
size
=
0
;
SetLastError
(
0xdeadbeef
);
status
=
pBCryptExportKey
(
key
,
NULL
,
BCRYPT_ECCPUBLIC_BLOB
,
NULL
,
0
,
&
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
ok
(
size
,
"size not set
\n
"
);
...
...
@@ -1694,13 +1704,47 @@ static void test_ECDH(void)
ok
(
ecckey
->
dwMagic
==
BCRYPT_ECDH_PUBLIC_P256_MAGIC
,
"got %08x
\n
"
,
ecckey
->
dwMagic
);
ok
(
ecckey
->
cbKey
==
32
,
"got %u
\n
"
,
ecckey
->
cbKey
);
ok
(
size
==
sizeof
(
*
ecckey
)
+
ecckey
->
cbKey
*
2
,
"got %u
\n
"
,
size
);
pBCryptDestroyKey
(
key
);
status
=
pBCryptImportKeyPair
(
alg
,
NULL
,
BCRYPT_ECCPUBLIC_BLOB
,
&
key
,
buf
,
size
,
0
);
status
=
pBCryptImportKeyPair
(
alg
,
NULL
,
BCRYPT_ECCPUBLIC_BLOB
,
&
pub
key
,
buf
,
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
size
=
0
;
status
=
pBCryptExportKey
(
key
,
NULL
,
BCRYPT_ECCPRIVATE_BLOB
,
NULL
,
0
,
&
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
ok
(
size
,
"size not set
\n
"
);
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
status
=
pBCryptExportKey
(
key
,
NULL
,
BCRYPT_ECCPRIVATE_BLOB
,
buf
,
size
,
&
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
ecckey
=
(
BCRYPT_ECCKEY_BLOB
*
)
buf
;
ok
(
ecckey
->
dwMagic
==
BCRYPT_ECDH_PRIVATE_P256_MAGIC
,
"got %08x
\n
"
,
ecckey
->
dwMagic
);
ok
(
ecckey
->
cbKey
==
32
,
"got %u
\n
"
,
ecckey
->
cbKey
);
ok
(
size
==
sizeof
(
*
ecckey
)
+
ecckey
->
cbKey
*
3
,
"got %u
\n
"
,
size
);
status
=
pBCryptImportKeyPair
(
alg
,
NULL
,
BCRYPT_ECCPRIVATE_BLOB
,
&
privkey
,
buf
,
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
pBCryptDestroyKey
(
pubkey
);
pBCryptDestroyKey
(
privkey
);
pBCryptDestroyKey
(
key
);
status
=
pBCryptImportKeyPair
(
alg
,
NULL
,
BCRYPT_ECCPRIVATE_BLOB
,
&
privkey
,
eccprivkey
,
sizeof
(
eccprivkey
),
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
size
=
0
;
status
=
pBCryptExportKey
(
privkey
,
NULL
,
BCRYPT_ECCPRIVATE_BLOB
,
NULL
,
0
,
&
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
ok
(
size
,
"size not set
\n
"
);
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
status
=
pBCryptExportKey
(
privkey
,
NULL
,
BCRYPT_ECCPRIVATE_BLOB
,
buf
,
size
,
&
size
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"got %08x
\n
"
,
status
);
ok
(
size
==
sizeof
(
eccprivkey
),
"got %u
\n
"
,
size
);
ok
(
!
memcmp
(
buf
,
eccprivkey
,
size
),
"wrong data
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
pBCryptDestroyKey
(
privkey
);
pBCryptCloseAlgorithmProvider
(
alg
,
0
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment