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
a36ff690
Commit
a36ff690
authored
Nov 09, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypt32: Move the GnuTLS code to a new Unix library.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
3b531c06
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
360 additions
and
271 deletions
+360
-271
Makefile.in
dlls/crypt32/Makefile.in
+2
-1
crypt32_private.h
dlls/crypt32/crypt32_private.h
+8
-2
main.c
dlls/crypt32/main.c
+6
-8
pfx.c
dlls/crypt32/pfx.c
+24
-260
unixlib.c
dlls/crypt32/unixlib.c
+320
-0
No files found.
dlls/crypt32/Makefile.in
View file @
a36ff690
...
...
@@ -31,6 +31,7 @@ C_SRCS = \
serialize.c
\
sip.c
\
store.c
\
str.c
str.c
\
unixlib.c
RC_SRCS
=
crypt32.rc
dlls/crypt32/crypt32_private.h
View file @
a36ff690
...
...
@@ -459,7 +459,13 @@ void init_empty_store(void) DECLSPEC_HIDDEN;
*/
#define IS_INTOID(x) (((ULONG_PTR)(x) >> 16) == 0)
BOOL
gnutls_initialize
(
void
)
DECLSPEC_HIDDEN
;
void
gnutls_uninitialize
(
void
)
DECLSPEC_HIDDEN
;
/* Unix interface */
struct
unix_funcs
{
BOOL
(
WINAPI
*
import_cert_store
)(
CRYPT_DATA_BLOB
*
pfx
,
const
WCHAR
*
password
,
DWORD
flags
,
void
**
key_ret
,
void
***
chain_ret
,
DWORD
*
count_ret
);
};
extern
const
struct
unix_funcs
*
unix_funcs
DECLSPEC_HIDDEN
;
#endif
dlls/crypt32/main.c
View file @
a36ff690
...
...
@@ -23,6 +23,7 @@
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "wincrypt.h"
#include "winreg.h"
#include "winuser.h"
...
...
@@ -34,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
static
HCRYPTPROV
hDefProv
;
HINSTANCE
hInstance
;
const
struct
unix_funcs
*
unix_funcs
=
NULL
;
static
CRITICAL_SECTION
prov_param_cs
;
static
CRITICAL_SECTION_DEBUG
prov_param_cs_debug
=
...
...
@@ -45,18 +47,16 @@ static CRITICAL_SECTION_DEBUG prov_param_cs_debug =
};
static
CRITICAL_SECTION
prov_param_cs
=
{
&
prov_param_cs_debug
,
-
1
,
0
,
0
,
0
,
0
};
BOOL
WINAPI
DllMain
(
HINSTANCE
hInst
,
DWORD
fdwR
eason
,
PVOID
pvReserved
)
BOOL
WINAPI
DllMain
(
HINSTANCE
hInst
,
DWORD
r
eason
,
PVOID
pvReserved
)
{
switch
(
fdwR
eason
)
switch
(
r
eason
)
{
case
DLL_PROCESS_ATTACH
:
hInstance
=
hInst
;
DisableThreadLibraryCalls
(
hInst
);
init_empty_store
();
crypt_oid_init
();
#ifdef SONAME_LIBGNUTLS
gnutls_initialize
();
#endif
__wine_init_unix_lib
(
hInst
,
reason
,
NULL
,
&
unix_funcs
);
break
;
case
DLL_PROCESS_DETACH
:
if
(
pvReserved
)
break
;
...
...
@@ -64,9 +64,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved)
crypt_sip_free
();
default_chain_engine_free
();
if
(
hDefProv
)
CryptReleaseContext
(
hDefProv
,
0
);
#ifdef SONAME_LIBGNUTLS
gnutls_uninitialize
();
#endif
__wine_init_unix_lib
(
hInst
,
reason
,
NULL
,
NULL
);
break
;
}
return
TRUE
;
...
...
dlls/crypt32/pfx.c
View file @
a36ff690
...
...
@@ -20,14 +20,12 @@
#include "wine/port.h"
#include <stdarg.h>
#ifdef SONAME_LIBGNUTLS
#include <gnutls/pkcs12.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
#include "snmp.h"
#include "crypt32_private.h"
#include "wine/debug.h"
#include "wine/heap.h"
...
...
@@ -35,228 +33,36 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
crypt
);
#ifdef SONAME_LIBGNUTLS
WINE_DECLARE_DEBUG_CHANNEL
(
winediag
);
/* Not present in gnutls version < 3.0 */
int
gnutls_pkcs12_simple_parse
(
gnutls_pkcs12_t
p12
,
const
char
*
password
,
gnutls_x509_privkey_t
*
key
,
gnutls_x509_crt_t
**
chain
,
unsigned
int
*
chain_len
,
gnutls_x509_crt_t
**
extra_certs
,
unsigned
int
*
extra_certs_len
,
gnutls_x509_crl_t
*
crl
,
unsigned
int
flags
);
int
gnutls_x509_privkey_get_pk_algorithm2
(
gnutls_x509_privkey_t
,
unsigned
int
*
);
static
void
*
libgnutls_handle
;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR
(
gnutls_global_deinit
);
MAKE_FUNCPTR
(
gnutls_global_init
);
MAKE_FUNCPTR
(
gnutls_global_set_log_function
);
MAKE_FUNCPTR
(
gnutls_global_set_log_level
);
MAKE_FUNCPTR
(
gnutls_perror
);
MAKE_FUNCPTR
(
gnutls_pkcs12_deinit
);
MAKE_FUNCPTR
(
gnutls_pkcs12_import
);
MAKE_FUNCPTR
(
gnutls_pkcs12_init
);
MAKE_FUNCPTR
(
gnutls_pkcs12_simple_parse
);
MAKE_FUNCPTR
(
gnutls_x509_crt_export
);
MAKE_FUNCPTR
(
gnutls_x509_privkey_export_rsa_raw2
);
MAKE_FUNCPTR
(
gnutls_x509_privkey_get_pk_algorithm2
);
#undef MAKE_FUNCPTR
static
void
gnutls_log
(
int
level
,
const
char
*
msg
)
{
TRACE
(
"<%d> %s"
,
level
,
msg
);
}
BOOL
gnutls_initialize
(
void
)
{
int
ret
;
if
(
!
(
libgnutls_handle
=
dlopen
(
SONAME_LIBGNUTLS
,
RTLD_NOW
)))
{
ERR_
(
winediag
)(
"failed to load libgnutls, no support for pfx import/export
\n
"
);
return
FALSE
;
}
#define LOAD_FUNCPTR(f) \
if (!(p##f = dlsym( libgnutls_handle, #f ))) \
{ \
ERR( "failed to load %s\n", #f ); \
goto fail; \
}
LOAD_FUNCPTR
(
gnutls_global_deinit
)
LOAD_FUNCPTR
(
gnutls_global_init
)
LOAD_FUNCPTR
(
gnutls_global_set_log_function
)
LOAD_FUNCPTR
(
gnutls_global_set_log_level
)
LOAD_FUNCPTR
(
gnutls_perror
)
LOAD_FUNCPTR
(
gnutls_pkcs12_deinit
)
LOAD_FUNCPTR
(
gnutls_pkcs12_import
)
LOAD_FUNCPTR
(
gnutls_pkcs12_init
)
LOAD_FUNCPTR
(
gnutls_pkcs12_simple_parse
)
LOAD_FUNCPTR
(
gnutls_x509_crt_export
)
LOAD_FUNCPTR
(
gnutls_x509_privkey_export_rsa_raw2
)
LOAD_FUNCPTR
(
gnutls_x509_privkey_get_pk_algorithm2
)
#undef LOAD_FUNCPTR
if
((
ret
=
pgnutls_global_init
())
!=
GNUTLS_E_SUCCESS
)
{
pgnutls_perror
(
ret
);
goto
fail
;
}
if
(
TRACE_ON
(
crypt
))
{
pgnutls_global_set_log_level
(
4
);
pgnutls_global_set_log_function
(
gnutls_log
);
}
return
TRUE
;
fail:
dlclose
(
libgnutls_handle
);
libgnutls_handle
=
NULL
;
return
FALSE
;
}
void
gnutls_uninitialize
(
void
)
static
HCRYPTPROV
import_key
(
void
*
key
,
DWORD
flags
)
{
pgnutls_global_deinit
();
dlclose
(
libgnutls_handle
);
libgnutls_handle
=
NULL
;
}
#define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24))
#define RSA_PUBEXP 65537
static
HCRYPTPROV
import_key
(
gnutls_x509_privkey_t
key
,
DWORD
flags
)
{
int
i
,
ret
;
unsigned
int
bitlen
;
gnutls_datum_t
m
,
e
,
d
,
p
,
q
,
u
,
e1
,
e2
;
BLOBHEADER
*
hdr
;
RSAPUBKEY
*
rsakey
;
HCRYPTPROV
prov
=
0
;
HCRYPTKEY
cryptkey
;
BYTE
*
buf
,
*
src
,
*
dst
;
DWORD
size
,
acquire_flags
;
if
((
ret
=
pgnutls_x509_privkey_get_pk_algorithm2
(
key
,
&
bitlen
))
<
0
)
{
pgnutls_perror
(
ret
);
return
0
;
}
if
(
ret
!=
GNUTLS_PK_RSA
)
{
FIXME
(
"key algorithm %u not supported
\n
"
,
ret
);
return
0
;
}
if
((
ret
=
pgnutls_x509_privkey_export_rsa_raw2
(
key
,
&
m
,
&
e
,
&
d
,
&
p
,
&
q
,
&
u
,
&
e1
,
&
e2
))
<
0
)
{
pgnutls_perror
(
ret
);
return
0
;
}
size
=
sizeof
(
*
hdr
)
+
sizeof
(
*
rsakey
)
+
(
bitlen
*
9
/
16
);
if
(
!
(
buf
=
heap_alloc
(
size
)))
goto
done
;
hdr
=
(
BLOBHEADER
*
)
buf
;
hdr
->
bType
=
PRIVATEKEYBLOB
;
hdr
->
bVersion
=
CUR_BLOB_VERSION
;
hdr
->
reserved
=
0
;
hdr
->
aiKeyAlg
=
CALG_RSA_KEYX
;
rsakey
=
(
RSAPUBKEY
*
)(
hdr
+
1
);
rsakey
->
magic
=
RSA_MAGIC_KEY
;
rsakey
->
bitlen
=
bitlen
;
rsakey
->
pubexp
=
RSA_PUBEXP
;
dst
=
(
BYTE
*
)(
rsakey
+
1
);
if
(
m
.
size
==
bitlen
/
8
+
1
&&
!
m
.
data
[
0
])
src
=
m
.
data
+
1
;
else
if
(
m
.
size
!=
bitlen
/
8
)
goto
done
;
else
src
=
m
.
data
;
for
(
i
=
bitlen
/
8
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
p
.
size
==
bitlen
/
16
+
1
&&
!
p
.
data
[
0
])
src
=
p
.
data
+
1
;
else
if
(
p
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
p
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
q
.
size
==
bitlen
/
16
+
1
&&
!
q
.
data
[
0
])
src
=
q
.
data
+
1
;
else
if
(
q
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
q
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
e1
.
size
==
bitlen
/
16
+
1
&&
!
e1
.
data
[
0
])
src
=
e1
.
data
+
1
;
else
if
(
e1
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
e1
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
e2
.
size
==
bitlen
/
16
+
1
&&
!
e2
.
data
[
0
])
src
=
e2
.
data
+
1
;
else
if
(
e2
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
e2
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
u
.
size
==
bitlen
/
16
+
1
&&
!
u
.
data
[
0
])
src
=
u
.
data
+
1
;
else
if
(
u
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
u
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
d
.
size
==
bitlen
/
8
+
1
&&
!
d
.
data
[
0
])
src
=
d
.
data
+
1
;
else
if
(
d
.
size
!=
bitlen
/
8
)
goto
done
;
else
src
=
d
.
data
;
for
(
i
=
bitlen
/
8
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
size
=
HeapSize
(
GetProcessHeap
(),
0
,
key
);
acquire_flags
=
(
flags
&
CRYPT_MACHINE_KEYSET
)
|
CRYPT_NEWKEYSET
;
if
(
!
CryptAcquireContextW
(
&
prov
,
NULL
,
MS_ENHANCED_PROV_W
,
PROV_RSA_FULL
,
acquire_flags
))
{
if
(
GetLastError
()
!=
NTE_EXISTS
)
goto
done
;
if
(
GetLastError
()
!=
NTE_EXISTS
)
return
0
;
acquire_flags
&=
~
CRYPT_NEWKEYSET
;
if
(
!
CryptAcquireContextW
(
&
prov
,
NULL
,
MS_ENHANCED_PROV_W
,
PROV_RSA_FULL
,
acquire_flags
))
{
WARN
(
"CryptAcquireContextW failed %08x
\n
"
,
GetLastError
()
);
goto
done
;
return
0
;
}
}
if
(
!
CryptImportKey
(
prov
,
buf
,
size
,
0
,
flags
&
CRYPT_EXPORTABLE
,
&
cryptkey
))
if
(
!
CryptImportKey
(
prov
,
key
,
size
,
0
,
flags
&
CRYPT_EXPORTABLE
,
&
cryptkey
))
{
WARN
(
"CryptImportKey failed %08x
\n
"
,
GetLastError
()
);
CryptReleaseContext
(
prov
,
0
);
prov
=
0
;
return
0
;
}
else
CryptDestroyKey
(
cryptkey
);
done:
free
(
m
.
data
);
free
(
e
.
data
);
free
(
d
.
data
);
free
(
p
.
data
);
free
(
q
.
data
);
free
(
u
.
data
);
free
(
e1
.
data
);
free
(
e2
.
data
);
heap_free
(
buf
);
CryptDestroyKey
(
cryptkey
);
return
prov
;
}
static
char
*
password_to_ascii
(
const
WCHAR
*
str
)
{
char
*
ret
;
unsigned
int
i
=
0
;
if
(
!
(
ret
=
heap_alloc
(
(
strlenW
(
str
)
+
1
)
*
sizeof
(
*
ret
)
)))
return
NULL
;
while
(
*
str
)
{
if
(
*
str
>
0x7f
)
WARN
(
"password contains non-ascii characters
\n
"
);
ret
[
i
++
]
=
*
str
++
;
}
ret
[
i
]
=
0
;
return
ret
;
}
static
BOOL
set_key_context
(
const
void
*
ctx
,
HCRYPTPROV
prov
)
{
CERT_KEY_CONTEXT
key_ctx
;
...
...
@@ -328,22 +134,13 @@ static BOOL set_key_prov_info( const void *ctx, HCRYPTPROV prov )
return
ret
;
}
#endif
HCERTSTORE
WINAPI
PFXImportCertStore
(
CRYPT_DATA_BLOB
*
pfx
,
const
WCHAR
*
password
,
DWORD
flags
)
{
#ifdef SONAME_LIBGNUTLS
gnutls_pkcs12_t
p12
;
gnutls_datum_t
pfx_data
;
gnutls_x509_privkey_t
key
;
gnutls_x509_crt_t
*
chain
;
unsigned
int
chain_len
,
i
;
void
*
key
,
**
chain
;
DWORD
i
,
chain_len
=
0
;
HCERTSTORE
store
=
NULL
;
HCRYPTPROV
prov
=
0
;
char
*
pwd
=
NULL
;
int
ret
;
TRACE
(
"(%p, %p, %08x)
\n
"
,
pfx
,
password
,
flags
);
if
(
!
pfx
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
...
...
@@ -354,29 +151,17 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
FIXME
(
"flags %08x not supported
\n
"
,
flags
);
return
NULL
;
}
if
(
password
&&
!
(
pwd
=
password_to_ascii
(
password
)))
return
NULL
;
if
((
ret
=
pgnutls_pkcs12_init
(
&
p12
))
<
0
)
{
pgnutls_perror
(
ret
);
goto
error
;
}
pfx_data
.
data
=
pfx
->
pbData
;
pfx_data
.
size
=
pfx
->
cbData
;
if
((
ret
=
pgnutls_pkcs12_import
(
p12
,
&
pfx_data
,
GNUTLS_X509_FMT_DER
,
0
))
<
0
)
if
(
!
unix_funcs
)
{
pgnutls_perror
(
ret
);
goto
error
;
FIXME
(
"(%p, %p, %08x)
\n
"
,
pfx
,
password
,
flags
);
return
NULL
;
}
if
(
!
unix_funcs
->
import_cert_store
(
pfx
,
password
,
flags
,
&
key
,
&
chain
,
&
chain_len
))
return
NULL
;
if
((
ret
=
pgnutls_pkcs12_simple_parse
(
p12
,
pwd
?
pwd
:
""
,
&
key
,
&
chain
,
&
chain_len
,
NULL
,
NULL
,
NULL
,
0
))
<
0
)
{
pgnutls_perror
(
ret
);
goto
error
;
}
prov
=
import_key
(
key
,
flags
);
heap_free
(
key
);
if
(
!
prov
)
goto
error
;
if
(
!
(
prov
=
import_key
(
key
,
flags
)))
goto
error
;
if
(
!
(
store
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
0
,
0
,
NULL
)))
{
WARN
(
"CertOpenStore failed %08x
\n
"
,
GetLastError
()
);
...
...
@@ -387,31 +172,14 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
for
(
i
=
0
;
i
<
chain_len
;
i
++
)
{
const
void
*
ctx
;
BYTE
*
crt_data
;
size_t
size
=
0
;
size_t
size
=
HeapSize
(
GetProcessHeap
(),
0
,
chain
[
i
]
);
if
((
ret
=
pgnutls_x509_crt_export
(
chain
[
i
],
GNUTLS_X509_FMT_DER
,
NULL
,
&
size
))
!=
GNUTLS_E_SHORT_MEMORY_BUFFER
)
{
pgnutls_perror
(
ret
);
goto
error
;
}
if
(
!
(
crt_data
=
heap_alloc
(
size
)))
goto
error
;
if
((
ret
=
pgnutls_x509_crt_export
(
chain
[
i
],
GNUTLS_X509_FMT_DER
,
crt_data
,
&
size
))
<
0
)
{
pgnutls_perror
(
ret
);
heap_free
(
crt_data
);
goto
error
;
}
if
(
!
(
ctx
=
CertCreateContext
(
CERT_STORE_CERTIFICATE_CONTEXT
,
X509_ASN_ENCODING
,
crt_data
,
size
,
0
,
NULL
)))
if
(
!
(
ctx
=
CertCreateContext
(
CERT_STORE_CERTIFICATE_CONTEXT
,
X509_ASN_ENCODING
,
chain
[
i
],
size
,
0
,
NULL
)))
{
WARN
(
"CertCreateContext failed %08x
\n
"
,
GetLastError
()
);
heap_free
(
crt_data
);
goto
error
;
}
heap_free
(
crt_data
);
if
(
flags
&
PKCS12_NO_PERSIST_KEY
)
{
if
(
!
set_key_context
(
ctx
,
prov
))
...
...
@@ -435,19 +203,15 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor
}
CertFreeCertificateContext
(
ctx
);
}
pgnutls_pkcs12_deinit
(
p12
);
while
(
chain_len
)
heap_free
(
chain
[
--
chain_len
]
);
heap_free
(
chain
);
return
store
;
error:
CryptReleaseContext
(
prov
,
0
);
CertCloseStore
(
store
,
0
);
pgnutls_pkcs12_deinit
(
p12
);
heap_free
(
pwd
);
return
NULL
;
#endif
FIXME
(
"(%p, %p, %08x)
\n
"
,
pfx
,
password
,
flags
);
while
(
chain_len
)
heap_free
(
chain
[
--
chain_len
]
);
heap_free
(
chain
);
return
NULL
;
}
...
...
dlls/crypt32/unixlib.c
0 → 100644
View file @
a36ff690
/*
* Copyright 2019 Hans Leidekker for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#if 0
#pragma makedep unix
#endif
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#ifdef SONAME_LIBGNUTLS
#include <gnutls/pkcs12.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "wincrypt.h"
#include "snmp.h"
#include "crypt32_private.h"
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
crypt
);
#ifdef SONAME_LIBGNUTLS
WINE_DECLARE_DEBUG_CHANNEL
(
winediag
);
/* Not present in gnutls version < 3.0 */
int
gnutls_pkcs12_simple_parse
(
gnutls_pkcs12_t
p12
,
const
char
*
password
,
gnutls_x509_privkey_t
*
key
,
gnutls_x509_crt_t
**
chain
,
unsigned
int
*
chain_len
,
gnutls_x509_crt_t
**
extra_certs
,
unsigned
int
*
extra_certs_len
,
gnutls_x509_crl_t
*
crl
,
unsigned
int
flags
);
int
gnutls_x509_privkey_get_pk_algorithm2
(
gnutls_x509_privkey_t
,
unsigned
int
*
);
static
void
*
libgnutls_handle
;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR
(
gnutls_global_deinit
);
MAKE_FUNCPTR
(
gnutls_global_init
);
MAKE_FUNCPTR
(
gnutls_global_set_log_function
);
MAKE_FUNCPTR
(
gnutls_global_set_log_level
);
MAKE_FUNCPTR
(
gnutls_perror
);
MAKE_FUNCPTR
(
gnutls_pkcs12_deinit
);
MAKE_FUNCPTR
(
gnutls_pkcs12_import
);
MAKE_FUNCPTR
(
gnutls_pkcs12_init
);
MAKE_FUNCPTR
(
gnutls_pkcs12_simple_parse
);
MAKE_FUNCPTR
(
gnutls_x509_crt_export
);
MAKE_FUNCPTR
(
gnutls_x509_privkey_export_rsa_raw2
);
MAKE_FUNCPTR
(
gnutls_x509_privkey_get_pk_algorithm2
);
#undef MAKE_FUNCPTR
static
void
gnutls_log
(
int
level
,
const
char
*
msg
)
{
TRACE
(
"<%d> %s"
,
level
,
msg
);
}
BOOL
gnutls_initialize
(
void
)
{
int
ret
;
if
(
!
(
libgnutls_handle
=
dlopen
(
SONAME_LIBGNUTLS
,
RTLD_NOW
)))
{
ERR_
(
winediag
)(
"failed to load libgnutls, no support for pfx import/export
\n
"
);
return
FALSE
;
}
#define LOAD_FUNCPTR(f) \
if (!(p##f = dlsym( libgnutls_handle, #f ))) \
{ \
ERR( "failed to load %s\n", #f ); \
goto fail; \
}
LOAD_FUNCPTR
(
gnutls_global_deinit
)
LOAD_FUNCPTR
(
gnutls_global_init
)
LOAD_FUNCPTR
(
gnutls_global_set_log_function
)
LOAD_FUNCPTR
(
gnutls_global_set_log_level
)
LOAD_FUNCPTR
(
gnutls_perror
)
LOAD_FUNCPTR
(
gnutls_pkcs12_deinit
)
LOAD_FUNCPTR
(
gnutls_pkcs12_import
)
LOAD_FUNCPTR
(
gnutls_pkcs12_init
)
LOAD_FUNCPTR
(
gnutls_pkcs12_simple_parse
)
LOAD_FUNCPTR
(
gnutls_x509_crt_export
)
LOAD_FUNCPTR
(
gnutls_x509_privkey_export_rsa_raw2
)
LOAD_FUNCPTR
(
gnutls_x509_privkey_get_pk_algorithm2
)
#undef LOAD_FUNCPTR
if
((
ret
=
pgnutls_global_init
())
!=
GNUTLS_E_SUCCESS
)
{
pgnutls_perror
(
ret
);
goto
fail
;
}
if
(
TRACE_ON
(
crypt
))
{
pgnutls_global_set_log_level
(
4
);
pgnutls_global_set_log_function
(
gnutls_log
);
}
return
TRUE
;
fail:
dlclose
(
libgnutls_handle
);
libgnutls_handle
=
NULL
;
return
FALSE
;
}
void
gnutls_uninitialize
(
void
)
{
pgnutls_global_deinit
();
dlclose
(
libgnutls_handle
);
libgnutls_handle
=
NULL
;
}
#define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24))
#define RSA_PUBEXP 65537
static
DWORD
import_key
(
gnutls_x509_privkey_t
key
,
DWORD
flags
,
void
**
data_ret
)
{
int
i
,
ret
;
unsigned
int
bitlen
;
gnutls_datum_t
m
,
e
,
d
,
p
,
q
,
u
,
e1
,
e2
;
BLOBHEADER
*
hdr
;
RSAPUBKEY
*
rsakey
;
BYTE
*
buf
,
*
src
,
*
dst
;
DWORD
size
;
*
data_ret
=
NULL
;
if
((
ret
=
pgnutls_x509_privkey_get_pk_algorithm2
(
key
,
&
bitlen
))
<
0
)
{
pgnutls_perror
(
ret
);
return
0
;
}
if
(
ret
!=
GNUTLS_PK_RSA
)
{
FIXME
(
"key algorithm %u not supported
\n
"
,
ret
);
return
0
;
}
if
((
ret
=
pgnutls_x509_privkey_export_rsa_raw2
(
key
,
&
m
,
&
e
,
&
d
,
&
p
,
&
q
,
&
u
,
&
e1
,
&
e2
))
<
0
)
{
pgnutls_perror
(
ret
);
return
0
;
}
size
=
sizeof
(
*
hdr
)
+
sizeof
(
*
rsakey
)
+
(
bitlen
*
9
/
16
);
if
(
!
(
buf
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
size
)))
goto
done
;
hdr
=
(
BLOBHEADER
*
)
buf
;
hdr
->
bType
=
PRIVATEKEYBLOB
;
hdr
->
bVersion
=
CUR_BLOB_VERSION
;
hdr
->
reserved
=
0
;
hdr
->
aiKeyAlg
=
CALG_RSA_KEYX
;
rsakey
=
(
RSAPUBKEY
*
)(
hdr
+
1
);
rsakey
->
magic
=
RSA_MAGIC_KEY
;
rsakey
->
bitlen
=
bitlen
;
rsakey
->
pubexp
=
RSA_PUBEXP
;
dst
=
(
BYTE
*
)(
rsakey
+
1
);
if
(
m
.
size
==
bitlen
/
8
+
1
&&
!
m
.
data
[
0
])
src
=
m
.
data
+
1
;
else
if
(
m
.
size
!=
bitlen
/
8
)
goto
done
;
else
src
=
m
.
data
;
for
(
i
=
bitlen
/
8
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
p
.
size
==
bitlen
/
16
+
1
&&
!
p
.
data
[
0
])
src
=
p
.
data
+
1
;
else
if
(
p
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
p
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
q
.
size
==
bitlen
/
16
+
1
&&
!
q
.
data
[
0
])
src
=
q
.
data
+
1
;
else
if
(
q
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
q
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
e1
.
size
==
bitlen
/
16
+
1
&&
!
e1
.
data
[
0
])
src
=
e1
.
data
+
1
;
else
if
(
e1
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
e1
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
e2
.
size
==
bitlen
/
16
+
1
&&
!
e2
.
data
[
0
])
src
=
e2
.
data
+
1
;
else
if
(
e2
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
e2
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
u
.
size
==
bitlen
/
16
+
1
&&
!
u
.
data
[
0
])
src
=
u
.
data
+
1
;
else
if
(
u
.
size
!=
bitlen
/
16
)
goto
done
;
else
src
=
u
.
data
;
for
(
i
=
bitlen
/
16
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
if
(
d
.
size
==
bitlen
/
8
+
1
&&
!
d
.
data
[
0
])
src
=
d
.
data
+
1
;
else
if
(
d
.
size
!=
bitlen
/
8
)
goto
done
;
else
src
=
d
.
data
;
for
(
i
=
bitlen
/
8
-
1
;
i
>=
0
;
i
--
)
*
dst
++
=
src
[
i
];
*
data_ret
=
buf
;
done:
free
(
m
.
data
);
free
(
e
.
data
);
free
(
d
.
data
);
free
(
p
.
data
);
free
(
q
.
data
);
free
(
u
.
data
);
free
(
e1
.
data
);
free
(
e2
.
data
);
if
(
!*
data_ret
)
RtlFreeHeap
(
GetProcessHeap
(),
0
,
buf
);
return
size
;
}
static
char
*
password_to_ascii
(
const
WCHAR
*
str
)
{
char
*
ret
;
unsigned
int
i
=
0
;
if
(
!
(
ret
=
malloc
(
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
*
ret
)
)))
return
NULL
;
while
(
*
str
)
{
if
(
*
str
>
0x7f
)
WARN
(
"password contains non-ascii characters
\n
"
);
ret
[
i
++
]
=
*
str
++
;
}
ret
[
i
]
=
0
;
return
ret
;
}
static
BOOL
WINAPI
import_cert_store
(
CRYPT_DATA_BLOB
*
pfx
,
const
WCHAR
*
password
,
DWORD
flags
,
void
**
key_ret
,
void
***
chain_ret
,
DWORD
*
count_ret
)
{
gnutls_pkcs12_t
p12
;
gnutls_datum_t
pfx_data
;
gnutls_x509_privkey_t
key
;
gnutls_x509_crt_t
*
chain
;
unsigned
int
chain_len
,
i
;
char
*
pwd
=
NULL
;
int
ret
;
if
(
password
&&
!
(
pwd
=
password_to_ascii
(
password
)))
return
FALSE
;
if
((
ret
=
pgnutls_pkcs12_init
(
&
p12
))
<
0
)
goto
error
;
pfx_data
.
data
=
pfx
->
pbData
;
pfx_data
.
size
=
pfx
->
cbData
;
if
((
ret
=
pgnutls_pkcs12_import
(
p12
,
&
pfx_data
,
GNUTLS_X509_FMT_DER
,
0
))
<
0
)
goto
error
;
if
((
ret
=
pgnutls_pkcs12_simple_parse
(
p12
,
pwd
?
pwd
:
""
,
&
key
,
&
chain
,
&
chain_len
,
NULL
,
NULL
,
NULL
,
0
))
<
0
)
goto
error
;
if
(
!
import_key
(
key
,
flags
,
key_ret
))
goto
error
;
*
chain_ret
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
chain_len
*
sizeof
(
*
chain_ret
)
);
*
count_ret
=
chain_len
;
for
(
i
=
0
;
i
<
chain_len
;
i
++
)
{
size_t
size
=
0
;
if
((
ret
=
pgnutls_x509_crt_export
(
chain
[
i
],
GNUTLS_X509_FMT_DER
,
NULL
,
&
size
))
!=
GNUTLS_E_SHORT_MEMORY_BUFFER
)
goto
error
;
(
*
chain_ret
)[
i
]
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
size
);
if
((
ret
=
pgnutls_x509_crt_export
(
chain
[
i
],
GNUTLS_X509_FMT_DER
,
(
*
chain_ret
)[
i
],
&
size
))
<
0
)
{
i
++
;
while
(
i
)
RtlFreeHeap
(
GetProcessHeap
(),
0
,
(
*
chain_ret
)[
--
i
]
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
*
chain_ret
);
goto
error
;
}
}
pgnutls_pkcs12_deinit
(
p12
);
return
TRUE
;
error:
pgnutls_perror
(
ret
);
pgnutls_pkcs12_deinit
(
p12
);
free
(
pwd
);
return
FALSE
;
}
static
const
struct
unix_funcs
funcs
=
{
import_cert_store
};
NTSTATUS
CDECL
__wine_init_unix_lib
(
HMODULE
module
,
DWORD
reason
,
const
void
*
ptr_in
,
void
*
ptr_out
)
{
switch
(
reason
)
{
case
DLL_PROCESS_ATTACH
:
if
(
!
gnutls_initialize
())
return
STATUS_DLL_NOT_FOUND
;
*
(
const
struct
unix_funcs
**
)
ptr_out
=
&
funcs
;
break
;
case
DLL_PROCESS_DETACH
:
if
(
libgnutls_handle
)
gnutls_uninitialize
();
break
;
}
return
STATUS_SUCCESS
;
}
#endif
/* SONAME_LIBGNUTLS */
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