Skip to content

Commit 6c00426

Browse files
committed
Add new crypto definitions + function for PEM encoding/decoding
1 parent d0e8443 commit 6c00426

File tree

12 files changed

+231
-6
lines changed

12 files changed

+231
-6
lines changed

ctypes_generation/definitions/defines/wintrust_crypt_def.txt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,28 @@
633633
#define CERT_NCRYPT_KEY_SPEC 0xFFFFFFFF
634634

635635

636-
#define CERT_REQUEST_V1 0
636+
#define CERT_REQUEST_V1 0
637+
638+
639+
// Include\10.0.10240.0\um\wincrypt.h
640+
641+
#define CRYPT_STRING_BASE64HEADER 0x00000000
642+
#define CRYPT_STRING_BASE64 0x00000001
643+
#define CRYPT_STRING_BINARY 0x00000002
644+
#define CRYPT_STRING_BASE64REQUESTHEADER 0x00000003
645+
#define CRYPT_STRING_HEX 0x00000004
646+
#define CRYPT_STRING_HEXASCII 0x00000005
647+
#define CRYPT_STRING_BASE64_ANY 0x00000006
648+
#define CRYPT_STRING_ANY 0x00000007
649+
#define CRYPT_STRING_HEX_ANY 0x00000008
650+
#define CRYPT_STRING_BASE64X509CRLHEADER 0x00000009
651+
#define CRYPT_STRING_HEXADDR 0x0000000a
652+
#define CRYPT_STRING_HEXASCIIADDR 0x0000000b
653+
#define CRYPT_STRING_HEXRAW 0x0000000c
654+
#define CRYPT_STRING_BASE64URI 0x0000000d
655+
656+
#define CRYPT_STRING_PERCENTESCAPE 0x08000000 // base64 formats only
657+
#define CRYPT_STRING_HASHDATA 0x10000000
658+
#define CRYPT_STRING_STRICT 0x20000000
659+
#define CRYPT_STRING_NOCRLF 0x40000000
660+
#define CRYPT_STRING_NOCR 0x80000000

ctypes_generation/definitions/functions/crypto_wintrust.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,4 +641,40 @@ BOOL CryptSignCertificate(
641641
[in] PVOID pvHashAuxInfo,
642642
[out] BYTE *pbSignature,
643643
[in, out] DWORD *pcbSignature
644+
);
645+
646+
BOOL CryptBinaryToStringA(
647+
[in] BYTE *pbBinary,
648+
[in] DWORD cbBinary,
649+
[in] DWORD dwFlags,
650+
[out, optional] LPSTR pszString,
651+
[in, out] DWORD *pcchString
652+
);
653+
654+
BOOL CryptBinaryToStringW(
655+
[in] BYTE *pbBinary,
656+
[in] DWORD cbBinary,
657+
[in] DWORD dwFlags,
658+
[out, optional] LPWSTR pszString,
659+
[in, out] DWORD *pcchString
660+
);
661+
662+
BOOL CryptStringToBinaryA(
663+
[in] LPCSTR pszString,
664+
[in] DWORD cchString,
665+
[in] DWORD dwFlags,
666+
[in] BYTE *pbBinary,
667+
[in, out] DWORD *pcbBinary,
668+
[out] DWORD *pdwSkip,
669+
[out] DWORD *pdwFlags
670+
);
671+
672+
BOOL CryptStringToBinaryW(
673+
[in] LPCWSTR pszString,
674+
[in] DWORD cchString,
675+
[in] DWORD dwFlags,
676+
[in] BYTE *pbBinary,
677+
[in, out] DWORD *pcbBinary,
678+
[out] DWORD *pdwSkip,
679+
[out] DWORD *pdwFlags
644680
);

docs/source/windef_generated.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3517,6 +3517,25 @@ WinDef
35173517
.. autodata:: CERT_SET_KEY_CONTEXT_PROP_ID
35183518
.. autodata:: CERT_NCRYPT_KEY_SPEC
35193519
.. autodata:: CERT_REQUEST_V1
3520+
.. autodata:: CRYPT_STRING_BASE64HEADER
3521+
.. autodata:: CRYPT_STRING_BASE64
3522+
.. autodata:: CRYPT_STRING_BINARY
3523+
.. autodata:: CRYPT_STRING_BASE64REQUESTHEADER
3524+
.. autodata:: CRYPT_STRING_HEX
3525+
.. autodata:: CRYPT_STRING_HEXASCII
3526+
.. autodata:: CRYPT_STRING_BASE64_ANY
3527+
.. autodata:: CRYPT_STRING_ANY
3528+
.. autodata:: CRYPT_STRING_HEX_ANY
3529+
.. autodata:: CRYPT_STRING_BASE64X509CRLHEADER
3530+
.. autodata:: CRYPT_STRING_HEXADDR
3531+
.. autodata:: CRYPT_STRING_HEXASCIIADDR
3532+
.. autodata:: CRYPT_STRING_HEXRAW
3533+
.. autodata:: CRYPT_STRING_BASE64URI
3534+
.. autodata:: CRYPT_STRING_PERCENTESCAPE
3535+
.. autodata:: CRYPT_STRING_HASHDATA
3536+
.. autodata:: CRYPT_STRING_STRICT
3537+
.. autodata:: CRYPT_STRING_NOCRLF
3538+
.. autodata:: CRYPT_STRING_NOCR
35203539
.. autodata:: WSADESCRIPTION_LEN
35213540
.. autodata:: WSASYS_STATUS_LEN
35223541
.. autodata:: WSAPROTOCOL_LEN

docs/source/winfuncs_generated.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,14 @@ Functions
330330

331331
.. function:: CryptSignCertificate(hBCryptKey, dwKeySpec, dwCertEncodingType, pbEncodedToBeSigned, cbEncodedToBeSigned, pSignatureAlgorithm, pvHashAuxInfo, pbSignature, pcbSignature)
332332

333+
.. function:: CryptBinaryToStringA(pbBinary, cbBinary, dwFlags, pszString, pcchString)
334+
335+
.. function:: CryptBinaryToStringW(pbBinary, cbBinary, dwFlags, pszString, pcchString)
336+
337+
.. function:: CryptStringToBinaryA(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
338+
339+
.. function:: CryptStringToBinaryW(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
340+
333341
.. function:: OpenVirtualDisk(VirtualStorageType, Path, VirtualDiskAccessMask, Flags, Parameters, Handle)
334342

335343
.. function:: AttachVirtualDisk(VirtualDiskHandle, SecurityDescriptor, Flags, ProviderSpecificFlags, Parameters, Overlapped)

windows/crypto/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
from windows.crypto.sign_verify import *
88
from windows.crypto.dpapi import *
99
from windows.crypto.cryptmsg import CryptMessage
10+
from windows.crypto.binary_string_conversion import string_to_binary, binary_to_string
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import windows.winproxy as winproxy
2+
import windows.generated_def as gdef
3+
4+
def binary_to_string(data, flags=gdef.CRYPT_STRING_BASE64, header=None):
5+
if header is not None:
6+
if flags != gdef.CRYPT_STRING_BASE64:
7+
raise ValueError("custom_header parameter can only be used with flags==CRYPT_STRING_BASE64")
8+
databuff = (gdef.BYTE * len(data))(*data)
9+
buffsize = gdef.DWORD(0)
10+
winproxy.CryptBinaryToStringW (databuff, len(databuff), flags, None, buffsize)
11+
12+
resbuff = (gdef.WCHAR * buffsize.value)()
13+
14+
winproxy.CryptBinaryToStringW(databuff, len(databuff), flags, resbuff, buffsize)
15+
strres = resbuff[:buffsize.value]
16+
if header:
17+
strres = "-----BEGIN {header}-----\r\n{0}-----END {header}-----".format(strres, header=header)
18+
return strres
19+
20+
def string_to_binary(data, flags=gdef.CRYPT_STRING_ANY):
21+
# Get the buffer size
22+
buffsize = gdef.DWORD(0)
23+
winproxy.CryptStringToBinaryW(data, len(data), flags, None, buffsize, None, None)
24+
25+
# Decode
26+
resbuff = (gdef.BYTE * buffsize.value)()
27+
skipped = gdef.DWORD()
28+
outflags = gdef.DWORD()
29+
30+
winproxy.CryptStringToBinaryW(data, len(data), flags, resbuff, buffsize, skipped, outflags)
31+
return bytearray(resbuff[:buffsize.value])

windows/crypto/certificate.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import windows.generated_def as gdef
77

88
from windows.crypto import DEFAULT_ENCODING
9-
from windows.pycompat import urepr_encode
9+
from windows.pycompat import urepr_encode, unicode_type
1010

1111
import windows.crypto.cryptmsg
1212

@@ -58,7 +58,8 @@ def __init__(self, filename, content_type=gdef.CERT_QUERY_CONTENT_FLAG_ALL):
5858
gdef.LPWSTR(filename),
5959
# filename,
6060
content_type,
61-
gdef.CERT_QUERY_FORMAT_FLAG_BINARY,
61+
# gdef.CERT_QUERY_FORMAT_FLAG_BINARY,
62+
gdef.CERT_QUERY_FORMAT_FLAG_ALL,
6263
0,
6364
dwEncoding,
6465
dwContentType,
@@ -149,15 +150,19 @@ def from_system_store(cls, store_name):
149150
"""Create a new :class:`CertificateStore` from system store ``store_name``
150151
(see `System Store Locations <https://msdn.microsoft.com/en-us/library/windows/desktop/aa388136(v=vs.85).aspx>`_)
151152
"""
152-
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_A, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_LOCAL_MACHINE | gdef.CERT_STORE_READONLY_FLAG, store_name)
153+
if not isinstance(store_name, unicode_type):
154+
raise ValueError("store_name should be an unicode string not {0}".format(type(store_name)))
155+
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_W, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_LOCAL_MACHINE | gdef.CERT_STORE_READONLY_FLAG, store_name)
153156
return ctypes.cast(res, cls)
154157

155158
@classmethod
156159
def from_user_store(cls, store_name, user=True):
157160
"""Create a new :class:`CertificateStore` from system store ``store_name``
158161
(see `System Store Locations <https://msdn.microsoft.com/en-us/library/windows/desktop/aa388136(v=vs.85).aspx>`_)
159162
"""
160-
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_A, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_CURRENT_USER | gdef.CERT_STORE_READONLY_FLAG, store_name)
163+
if not isinstance(store_name, unicode_type):
164+
raise ValueError("store_name should be an unicode string not {0}".format(type(store_name)))
165+
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_W, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_CURRENT_USER | gdef.CERT_STORE_READONLY_FLAG, store_name)
161166
return ctypes.cast(res, cls)
162167

163168
@classmethod
@@ -442,6 +447,19 @@ def get_property(self, prop):
442447
windows.winproxy.CertGetCertificateContextProperty(self, prop, buf, datasize)
443448
return bytearray(buf)
444449

450+
def get_private_key(self, flags):
451+
"""Tmp API: return value will change"""
452+
keyhandle = gdef.HCRYPTPROV_OR_NCRYPT_KEY_HANDLE()
453+
keyspec = gdef.DWORD()
454+
must_free_handle = gdef.BOOL()
455+
windows.winproxy.CryptAcquireCertificatePrivateKey(self, flags, None, keyhandle, keyspec, must_free_handle)
456+
return (keyhandle, keyspec, must_free_handle)
457+
458+
@property
459+
def private_key(self):
460+
"""Tmp API: return value will change"""
461+
return self.get_private_key(flags=gdef.CRYPT_ACQUIRE_COMPARE_KEY_FLAG | gdef.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | gdef.CRYPT_ACQUIRE_USE_PROV_INFO_FLAG)
462+
445463

446464
@property
447465
def encoded(self):

windows/crypto/cryptmsg.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,14 @@ def recipients(self):
106106
def content(self):
107107
return self.get_param(gdef.CMSG_CONTENT_PARAM)[:]
108108

109+
@property
110+
def bare_content(self):
111+
return self.get_param(gdef.CMSG_BARE_CONTENT_PARAM)[:]
112+
109113
@property
110114
def content_type(self):
111115
data = self.get_param(gdef.CMSG_INNER_CONTENT_TYPE_PARAM)
112-
assert data[-1] == "\x00", "CMSG_INNER_CONTENT_TYPE_PARAM not NULL TERMINATED"
116+
assert data[-1] == b"\x00", "CMSG_INNER_CONTENT_TYPE_PARAM not NULL TERMINATED"
113117
return data[:-1]
114118

115119

windows/generated_def/meta.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,25 @@
788788
'CRYPT_SF',
789789
'CRYPT_SGCKEY',
790790
'CRYPT_SILENT',
791+
'CRYPT_STRING_ANY',
792+
'CRYPT_STRING_BASE64',
793+
'CRYPT_STRING_BASE64HEADER',
794+
'CRYPT_STRING_BASE64REQUESTHEADER',
795+
'CRYPT_STRING_BASE64URI',
796+
'CRYPT_STRING_BASE64X509CRLHEADER',
797+
'CRYPT_STRING_BASE64_ANY',
798+
'CRYPT_STRING_BINARY',
799+
'CRYPT_STRING_HASHDATA',
800+
'CRYPT_STRING_HEX',
801+
'CRYPT_STRING_HEXADDR',
802+
'CRYPT_STRING_HEXASCII',
803+
'CRYPT_STRING_HEXASCIIADDR',
804+
'CRYPT_STRING_HEXRAW',
805+
'CRYPT_STRING_HEX_ANY',
806+
'CRYPT_STRING_NOCR',
807+
'CRYPT_STRING_NOCRLF',
808+
'CRYPT_STRING_PERCENTESCAPE',
809+
'CRYPT_STRING_STRICT',
791810
'CRYPT_UNICODE_NAME_DECODE_DISABLE_IE4_UTF8_FLAG',
792811
'CRYPT_UPDATE_KEY',
793812
'CRYPT_USER_KEYSET',
@@ -14757,6 +14776,8 @@
1475714776
'CryptAcquireCertificatePrivateKey',
1475814777
'CryptAcquireContextA',
1475914778
'CryptAcquireContextW',
14779+
'CryptBinaryToStringA',
14780+
'CryptBinaryToStringW',
1476014781
'CryptCATAdminAcquireContext',
1476114782
'CryptCATAdminAcquireContext2',
1476214783
'CryptCATAdminCalcHashFromFileHandle',
@@ -14806,6 +14827,8 @@
1480614827
'CryptSignHashA',
1480714828
'CryptSignHashW',
1480814829
'CryptSignMessage',
14830+
'CryptStringToBinaryA',
14831+
'CryptStringToBinaryW',
1480914832
'CryptUIDlgViewContext',
1481014833
'CryptUnprotectData',
1481114834
'CryptUnprotectMemory',

windows/generated_def/windef.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3557,6 +3557,25 @@ def ProcThreadAttributeValue(Number, Thread, Input, Additive):
35573557
CERT_SET_KEY_CONTEXT_PROP_ID = make_flag("CERT_SET_KEY_CONTEXT_PROP_ID", 0x00000001)
35583558
CERT_NCRYPT_KEY_SPEC = make_flag("CERT_NCRYPT_KEY_SPEC", 0xFFFFFFFF)
35593559
CERT_REQUEST_V1 = make_flag("CERT_REQUEST_V1", 0)
3560+
CRYPT_STRING_BASE64HEADER = make_flag("CRYPT_STRING_BASE64HEADER", 0x00000000)
3561+
CRYPT_STRING_BASE64 = make_flag("CRYPT_STRING_BASE64", 0x00000001)
3562+
CRYPT_STRING_BINARY = make_flag("CRYPT_STRING_BINARY", 0x00000002)
3563+
CRYPT_STRING_BASE64REQUESTHEADER = make_flag("CRYPT_STRING_BASE64REQUESTHEADER", 0x00000003)
3564+
CRYPT_STRING_HEX = make_flag("CRYPT_STRING_HEX", 0x00000004)
3565+
CRYPT_STRING_HEXASCII = make_flag("CRYPT_STRING_HEXASCII", 0x00000005)
3566+
CRYPT_STRING_BASE64_ANY = make_flag("CRYPT_STRING_BASE64_ANY", 0x00000006)
3567+
CRYPT_STRING_ANY = make_flag("CRYPT_STRING_ANY", 0x00000007)
3568+
CRYPT_STRING_HEX_ANY = make_flag("CRYPT_STRING_HEX_ANY", 0x00000008)
3569+
CRYPT_STRING_BASE64X509CRLHEADER = make_flag("CRYPT_STRING_BASE64X509CRLHEADER", 0x00000009)
3570+
CRYPT_STRING_HEXADDR = make_flag("CRYPT_STRING_HEXADDR", 0x0000000a)
3571+
CRYPT_STRING_HEXASCIIADDR = make_flag("CRYPT_STRING_HEXASCIIADDR", 0x0000000b)
3572+
CRYPT_STRING_HEXRAW = make_flag("CRYPT_STRING_HEXRAW", 0x0000000c)
3573+
CRYPT_STRING_BASE64URI = make_flag("CRYPT_STRING_BASE64URI", 0x0000000d)
3574+
CRYPT_STRING_PERCENTESCAPE = make_flag("CRYPT_STRING_PERCENTESCAPE", 0x08000000)
3575+
CRYPT_STRING_HASHDATA = make_flag("CRYPT_STRING_HASHDATA", 0x10000000)
3576+
CRYPT_STRING_STRICT = make_flag("CRYPT_STRING_STRICT", 0x20000000)
3577+
CRYPT_STRING_NOCRLF = make_flag("CRYPT_STRING_NOCRLF", 0x40000000)
3578+
CRYPT_STRING_NOCR = make_flag("CRYPT_STRING_NOCR", 0x80000000)
35603579
WSADESCRIPTION_LEN = make_flag("WSADESCRIPTION_LEN", 256)
35613580
WSASYS_STATUS_LEN = make_flag("WSASYS_STATUS_LEN", 128)
35623581
WSAPROTOCOL_LEN = make_flag("WSAPROTOCOL_LEN", 255)

0 commit comments

Comments
 (0)