Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
4d1190f5
Commit
4d1190f5
authored
Jun 26, 2018
by
Michael Müller
Committed by
Alexandre Julliard
Jun 26, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypt32: Implement verification of ECDSA signatures.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
314a276f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
250 additions
and
12 deletions
+250
-12
Makefile.in
dlls/crypt32/Makefile.in
+1
-1
cert.c
dlls/crypt32/cert.c
+249
-11
No files found.
dlls/crypt32/Makefile.in
View file @
4d1190f5
EXTRADEFS
=
-D_CRYPT32_
MODULE
=
crypt32.dll
IMPORTLIB
=
crypt32
IMPORTS
=
user32 advapi32
IMPORTS
=
user32 advapi32
bcrypt
DELAYIMPORTS
=
cryptnet
EXTRALIBS
=
$(SECURITY_LIBS)
...
...
dlls/crypt32/cert.c
View file @
4d1190f5
...
...
@@ -21,9 +21,14 @@
#include <stdarg.h>
#define NONAMELESSUNION
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#define CRYPT_OID_INFO_HAS_EXTRA_FIELDS
#include "wincrypt.h"
#include "bcrypt.h"
#include "winnls.h"
#include "rpc.h"
#include "wine/debug.h"
...
...
@@ -2408,22 +2413,13 @@ BOOL WINAPI CryptVerifyCertificateSignature(HCRYPTPROV_LEGACY hCryptProv,
CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY
,
pPublicKey
,
0
,
NULL
);
}
static
BOOL
CRYPT_VerifyCertSignatureFromPublicKeyInfo
(
HCRYPTPROV_LEGACY
hCryptProv
,
DWORD
dwCertEncodingType
,
PCERT_PUBLIC_KEY_INFO
pubKeyInfo
,
const
CERT_SIGNED_CONTENT_INFO
*
signedCert
)
static
BOOL
CRYPT_VerifySignature
(
HCRYPTPROV_LEGACY
hCryptProv
,
DWORD
dwCertEncodingType
,
CERT_PUBLIC_KEY_INFO
*
pubKeyInfo
,
const
CERT_SIGNED_CONTENT_INFO
*
signedCert
,
const
CRYPT_OID_INFO
*
info
)
{
BOOL
ret
;
HCRYPTKEY
key
;
PCCRYPT_OID_INFO
info
;
ALG_ID
pubKeyID
,
hashID
;
info
=
CryptFindOIDInfo
(
CRYPT_OID_INFO_OID_KEY
,
signedCert
->
SignatureAlgorithm
.
pszObjId
,
0
);
if
(
!
info
||
info
->
dwGroupId
!=
CRYPT_SIGN_ALG_OID_GROUP_ID
)
{
SetLastError
(
NTE_BAD_ALGID
);
return
FALSE
;
}
hashID
=
info
->
u
.
Algid
;
if
(
info
->
ExtraInfo
.
cbData
>=
sizeof
(
ALG_ID
))
pubKeyID
=
*
(
ALG_ID
*
)
info
->
ExtraInfo
.
pbData
;
...
...
@@ -2453,6 +2449,248 @@ static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptP
return
ret
;
}
static
BOOL
CNG_CalcHash
(
const
WCHAR
*
algorithm
,
const
CERT_SIGNED_CONTENT_INFO
*
signedCert
,
BYTE
**
hash_value
,
DWORD
*
hash_len
)
{
BCRYPT_HASH_HANDLE
hash
=
NULL
;
BCRYPT_ALG_HANDLE
alg
=
NULL
;
NTSTATUS
status
;
DWORD
size
;
if
((
status
=
BCryptOpenAlgorithmProvider
(
&
alg
,
algorithm
,
NULL
,
0
)))
goto
done
;
if
((
status
=
BCryptCreateHash
(
alg
,
&
hash
,
NULL
,
0
,
NULL
,
0
,
0
)))
goto
done
;
if
((
status
=
BCryptHashData
(
hash
,
signedCert
->
ToBeSigned
.
pbData
,
signedCert
->
ToBeSigned
.
cbData
,
0
)))
goto
done
;
if
((
status
=
BCryptGetProperty
(
hash
,
BCRYPT_HASH_LENGTH
,
(
BYTE
*
)
hash_len
,
sizeof
(
*
hash_len
),
&
size
,
0
)))
goto
done
;
if
(
!
(
*
hash_value
=
CryptMemAlloc
(
*
hash_len
)))
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
}
if
((
status
=
BCryptFinishHash
(
hash
,
*
hash_value
,
*
hash_len
,
0
)))
{
CryptMemFree
(
*
hash_value
);
goto
done
;
}
done:
if
(
hash
)
BCryptDestroyHash
(
hash
);
if
(
alg
)
BCryptCloseAlgorithmProvider
(
alg
,
0
);
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
));
return
status
==
0
;
}
static
BOOL
CNG_ImportECCPubKey
(
CERT_PUBLIC_KEY_INFO
*
pubKeyInfo
,
BCRYPT_KEY_HANDLE
*
key
)
{
DWORD
blob_magic
,
ecckey_len
,
size
;
BCRYPT_ALG_HANDLE
alg
=
NULL
;
BCRYPT_ECCKEY_BLOB
*
ecckey
;
const
WCHAR
*
sign_algo
;
char
**
ecc_curve
;
NTSTATUS
status
;
if
(
!
pubKeyInfo
->
PublicKey
.
cbData
)
{
SetLastError
(
NTE_BAD_ALGID
);
return
FALSE
;
}
if
(
pubKeyInfo
->
PublicKey
.
pbData
[
0
]
!=
0x4
)
{
FIXME
(
"Compressed ECC curves (%02x) not yet supported
\n
"
,
pubKeyInfo
->
PublicKey
.
pbData
[
0
]);
SetLastError
(
NTE_BAD_ALGID
);
return
FALSE
;
}
if
(
!
CryptDecodeObjectEx
(
X509_ASN_ENCODING
,
X509_OBJECT_IDENTIFIER
,
pubKeyInfo
->
Algorithm
.
Parameters
.
pbData
,
pubKeyInfo
->
Algorithm
.
Parameters
.
cbData
,
CRYPT_DECODE_ALLOC_FLAG
,
NULL
,
&
ecc_curve
,
&
size
))
return
FALSE
;
if
(
!
strcmp
(
*
ecc_curve
,
szOID_ECC_CURVE_P256
))
{
sign_algo
=
BCRYPT_ECDSA_P256_ALGORITHM
;
blob_magic
=
BCRYPT_ECDSA_PUBLIC_P256_MAGIC
;
}
else
if
(
!
strcmp
(
*
ecc_curve
,
szOID_ECC_CURVE_P384
))
{
sign_algo
=
BCRYPT_ECDSA_P384_ALGORITHM
;
blob_magic
=
BCRYPT_ECDSA_PUBLIC_P384_MAGIC
;
}
else
{
FIXME
(
"Unsupported ecc curve type: %s
\n
"
,
*
ecc_curve
);
sign_algo
=
NULL
;
blob_magic
=
0
;
}
LocalFree
(
ecc_curve
);
if
(
!
sign_algo
)
{
SetLastError
(
NTE_BAD_ALGID
);
return
FALSE
;
}
if
((
status
=
BCryptOpenAlgorithmProvider
(
&
alg
,
sign_algo
,
NULL
,
0
)))
goto
done
;
ecckey_len
=
sizeof
(
BCRYPT_ECCKEY_BLOB
)
+
pubKeyInfo
->
PublicKey
.
cbData
-
1
;
if
(
!
(
ecckey
=
CryptMemAlloc
(
ecckey_len
)))
{
status
=
STATUS_NO_MEMORY
;
goto
done
;
}
ecckey
->
dwMagic
=
blob_magic
;
ecckey
->
cbKey
=
(
pubKeyInfo
->
PublicKey
.
cbData
-
1
)
/
2
;
memcpy
(
ecckey
+
1
,
pubKeyInfo
->
PublicKey
.
pbData
+
1
,
pubKeyInfo
->
PublicKey
.
cbData
-
1
);
status
=
BCryptImportKeyPair
(
alg
,
NULL
,
BCRYPT_ECCPUBLIC_BLOB
,
key
,
(
BYTE
*
)
ecckey
,
ecckey_len
,
0
);
done:
if
(
alg
)
BCryptCloseAlgorithmProvider
(
alg
,
0
);
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
));
return
!
status
;
}
static
BOOL
CNG_ImportPubKey
(
CERT_PUBLIC_KEY_INFO
*
pubKeyInfo
,
BCRYPT_KEY_HANDLE
*
key
)
{
if
(
!
strcmp
(
pubKeyInfo
->
Algorithm
.
pszObjId
,
szOID_ECC_PUBLIC_KEY
))
return
CNG_ImportECCPubKey
(
pubKeyInfo
,
key
);
FIXME
(
"Unsupported public key type: %s
\n
"
,
debugstr_a
(
pubKeyInfo
->
Algorithm
.
pszObjId
));
SetLastError
(
NTE_BAD_ALGID
);
return
FALSE
;
}
static
BOOL
CNG_PrepareSignatureECC
(
BYTE
*
encoded_sig
,
DWORD
encoded_size
,
BYTE
**
sig_value
,
DWORD
*
sig_len
)
{
CERT_ECC_SIGNATURE
*
ecc_sig
;
DWORD
size
;
int
i
;
if
(
!
CryptDecodeObjectEx
(
X509_ASN_ENCODING
,
X509_ECC_SIGNATURE
,
encoded_sig
,
encoded_size
,
CRYPT_DECODE_ALLOC_FLAG
,
NULL
,
&
ecc_sig
,
&
size
))
return
FALSE
;
if
(
!
ecc_sig
->
r
.
cbData
||
!
ecc_sig
->
s
.
cbData
)
{
LocalFree
(
ecc_sig
);
SetLastError
(
ERROR_INVALID_DATA
);
return
FALSE
;
}
*
sig_len
=
ecc_sig
->
r
.
cbData
+
ecc_sig
->
s
.
cbData
;
if
(
!
(
*
sig_value
=
CryptMemAlloc
(
*
sig_len
)))
{
LocalFree
(
ecc_sig
);
SetLastError
(
ERROR_OUTOFMEMORY
);
return
FALSE
;
}
for
(
i
=
0
;
i
<
ecc_sig
->
r
.
cbData
;
i
++
)
(
*
sig_value
)[
i
]
=
ecc_sig
->
r
.
pbData
[
ecc_sig
->
r
.
cbData
-
i
-
1
];
for
(
i
=
0
;
i
<
ecc_sig
->
s
.
cbData
;
i
++
)
(
*
sig_value
)[
ecc_sig
->
r
.
cbData
+
i
]
=
ecc_sig
->
s
.
pbData
[
ecc_sig
->
s
.
cbData
-
i
-
1
];
LocalFree
(
ecc_sig
);
return
TRUE
;
}
static
BOOL
CNG_PrepareSignature
(
CERT_PUBLIC_KEY_INFO
*
pubKeyInfo
,
const
CERT_SIGNED_CONTENT_INFO
*
signedCert
,
BYTE
**
sig_value
,
DWORD
*
sig_len
)
{
BYTE
*
encoded_sig
;
BOOL
ret
=
FALSE
;
int
i
;
if
(
!
signedCert
->
Signature
.
cbData
)
{
SetLastError
(
ERROR_INVALID_DATA
);
return
FALSE
;
}
if
(
!
(
encoded_sig
=
CryptMemAlloc
(
signedCert
->
Signature
.
cbData
)))
{
SetLastError
(
ERROR_OUTOFMEMORY
);
return
FALSE
;
}
for
(
i
=
0
;
i
<
signedCert
->
Signature
.
cbData
;
i
++
)
encoded_sig
[
i
]
=
signedCert
->
Signature
.
pbData
[
signedCert
->
Signature
.
cbData
-
i
-
1
];
if
(
!
strcmp
(
pubKeyInfo
->
Algorithm
.
pszObjId
,
szOID_ECC_PUBLIC_KEY
))
ret
=
CNG_PrepareSignatureECC
(
encoded_sig
,
signedCert
->
Signature
.
cbData
,
sig_value
,
sig_len
);
else
{
FIXME
(
"Unsupported public key type: %s
\n
"
,
debugstr_a
(
pubKeyInfo
->
Algorithm
.
pszObjId
));
SetLastError
(
NTE_BAD_ALGID
);
}
CryptMemFree
(
encoded_sig
);
return
ret
;
}
static
BOOL
CNG_VerifySignature
(
HCRYPTPROV_LEGACY
hCryptProv
,
DWORD
dwCertEncodingType
,
CERT_PUBLIC_KEY_INFO
*
pubKeyInfo
,
const
CERT_SIGNED_CONTENT_INFO
*
signedCert
,
const
CRYPT_OID_INFO
*
info
)
{
BCRYPT_KEY_HANDLE
key
=
NULL
;
BYTE
*
hash_value
=
NULL
,
*
sig_value
;
DWORD
hash_len
,
sig_len
;
NTSTATUS
status
;
BOOL
ret
;
ret
=
CNG_ImportPubKey
(
pubKeyInfo
,
&
key
);
if
(
ret
)
{
ret
=
CNG_CalcHash
(
info
->
pwszCNGAlgid
,
signedCert
,
&
hash_value
,
&
hash_len
);
if
(
ret
)
{
ret
=
CNG_PrepareSignature
(
pubKeyInfo
,
signedCert
,
&
sig_value
,
&
sig_len
);
if
(
ret
)
{
status
=
BCryptVerifySignature
(
key
,
NULL
,
hash_value
,
hash_len
,
sig_value
,
sig_len
,
0
);
if
(
status
)
{
FIXME
(
"Failed to verify signature: %08x
\n
"
,
status
);
SetLastError
(
RtlNtStatusToDosError
(
status
));
ret
=
FALSE
;
}
CryptMemFree
(
sig_value
);
}
CryptMemFree
(
hash_value
);
}
BCryptDestroyKey
(
key
);
}
return
ret
;
}
static
BOOL
CRYPT_VerifyCertSignatureFromPublicKeyInfo
(
HCRYPTPROV_LEGACY
hCryptProv
,
DWORD
dwCertEncodingType
,
CERT_PUBLIC_KEY_INFO
*
pubKeyInfo
,
const
CERT_SIGNED_CONTENT_INFO
*
signedCert
)
{
CCRYPT_OID_INFO
*
info
;
info
=
CryptFindOIDInfo
(
CRYPT_OID_INFO_OID_KEY
,
signedCert
->
SignatureAlgorithm
.
pszObjId
,
0
);
if
(
!
info
||
info
->
dwGroupId
!=
CRYPT_SIGN_ALG_OID_GROUP_ID
)
{
SetLastError
(
NTE_BAD_ALGID
);
return
FALSE
;
}
if
(
info
->
u
.
Algid
==
CALG_OID_INFO_CNG_ONLY
)
return
CNG_VerifySignature
(
hCryptProv
,
dwCertEncodingType
,
pubKeyInfo
,
signedCert
,
info
);
else
return
CRYPT_VerifySignature
(
hCryptProv
,
dwCertEncodingType
,
pubKeyInfo
,
signedCert
,
info
);
}
BOOL
WINAPI
CryptVerifyCertificateSignatureEx
(
HCRYPTPROV_LEGACY
hCryptProv
,
DWORD
dwCertEncodingType
,
DWORD
dwSubjectType
,
void
*
pvSubject
,
DWORD
dwIssuerType
,
void
*
pvIssuer
,
DWORD
dwFlags
,
void
*
pvReserved
)
...
...
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