diff --git a/ctypes_generation/extended_structs/_CRYPT_BIT_BLOB.py b/ctypes_generation/extended_structs/_CRYPT_BIT_BLOB.py index 17d3370..0d11306 100644 --- a/ctypes_generation/extended_structs/_CRYPT_BIT_BLOB.py +++ b/ctypes_generation/extended_structs/_CRYPT_BIT_BLOB.py @@ -1,5 +1,4 @@ class _CRYPT_BIT_BLOB(_CRYPT_BIT_BLOB): - @property def data(self): return bytearray(self.pbData[:self.cbData]) \ No newline at end of file diff --git a/windows/crypto/certificate.py b/windows/crypto/certificate.py index 0b115a5..49a756b 100644 --- a/windows/crypto/certificate.py +++ b/windows/crypto/certificate.py @@ -162,13 +162,18 @@ class CertificateStore(gdef.HCERTSTORE): def find(self, issuer, serialnumber): """Return the certificate that match `issuer` and `serialnumber` - :return: :class:`Certificate` + :return: :class:`Certificate` -- ``None`` if certificate is not found """ # data = self.get_signer_data(index) cert_info = gdef.CERT_INFO() cert_info.Issuer = issuer cert_info.SerialNumber = serialnumber - rawcertcontext = winproxy.CertFindCertificateInStore(self, DEFAULT_ENCODING, 0, gdef.CERT_FIND_SUBJECT_CERT, ctypes.byref(cert_info), None) + try: + rawcertcontext = winproxy.CertFindCertificateInStore(self, DEFAULT_ENCODING, 0, gdef.CERT_FIND_SUBJECT_CERT, ctypes.byref(cert_info), None) + except WindowsError as e: + if not e.winerror & 0xffffffff == gdef.CRYPT_E_NOT_FOUND: + raise + return None return Certificate.from_pointer(rawcertcontext) @@ -416,6 +421,14 @@ class Certificate(gdef.CERT_CONTEXT): # - Usefull: # CERT_SHA1_HASH_PROP_ID + def get_property(self, prop): + "TODO: DOC :D + auto-type ?" + datasize = gdef.DWORD() + windows.winproxy.CertGetCertificateContextProperty(self, prop, None, datasize) + buf = (gdef.BYTE * datasize.value)() + windows.winproxy.CertGetCertificateContextProperty(self, prop, buf, datasize) + return bytearray(buf) + @property def encoded(self): diff --git a/windows/crypto/cryptmsg.py b/windows/crypto/cryptmsg.py index 203a10c..078e83c 100644 --- a/windows/crypto/cryptmsg.py +++ b/windows/crypto/cryptmsg.py @@ -10,7 +10,11 @@ class CryptMessage(gdef.HCRYPTMSG): """ MSG_PARAM_KNOW_TYPES = {gdef.CMSG_SIGNER_INFO_PARAM: gdef.CMSG_SIGNER_INFO, gdef.CMSG_SIGNER_COUNT_PARAM: gdef.DWORD, - gdef.CMSG_CERT_COUNT_PARAM: gdef.DWORD} + gdef.CMSG_CERT_COUNT_PARAM: gdef.DWORD, + gdef.CMSG_ENVELOPE_ALGORITHM_PARAM: gdef.CRYPT_ALGORITHM_IDENTIFIER, + gdef.CMSG_RECIPIENT_COUNT_PARAM: gdef.DWORD, + gdef.CMSG_RECIPIENT_INFO_PARAM: gdef.CERT_INFO, + } def get_param(self, param_type, index=0, raw=False): @@ -81,4 +85,19 @@ class CryptMessage(gdef.HCRYPTMSG): @property def signers(self): """The list of :class:`~windows.generated_def.winstructs.CMSG_SIGNER_INFO` embed in the message""" - return [self.get_signer_data(i) for i in range(self.nb_signer)] \ No newline at end of file + return [self.get_signer_data(i) for i in range(self.nb_signer)] + + @property + def nb_recipient(self): + """TODO: DOC""" + return self.get_param(gdef.CMSG_RECIPIENT_COUNT_PARAM) + + + def get_recipient_data(self, index=0): + """TODO: DOC""" + return self.get_param(gdef.CMSG_RECIPIENT_INFO_PARAM, index) + + @property + def recipients(self): + """TODO: DOC""" + return [self.get_recipient_data(i) for i in range(self.nb_recipient)] \ No newline at end of file diff --git a/windows/crypto/encrypt_decrypt.py b/windows/crypto/encrypt_decrypt.py index 9936e1e..36d136c 100644 --- a/windows/crypto/encrypt_decrypt.py +++ b/windows/crypto/encrypt_decrypt.py @@ -2,13 +2,12 @@ from os import urandom from windows import winproxy from windows.crypto import DEFAULT_ENCODING -from windows.crypto.helper import ECRYPT_DATA_BLOB from windows.generated_def import * __all__ = ["encrypt", "decrypt"] def encode_init_vector(data): - blob = ECRYPT_DATA_BLOB.from_string(data) + blob = CRYPT_DATA_BLOB.from_string(data) size = DWORD() buf = None winproxy.CryptEncodeObjectEx(DEFAULT_ENCODING, X509_OCTET_STRING, ctypes.byref(blob), 0, None, buf, size) @@ -67,10 +66,10 @@ def encrypt(cert_or_certlist, msg, algo=szOID_NIST_AES256_CBC, initvector=genini if initvector is None: raise ValueError("I don't know how to generate an for <{0}> please provide one (or None)".format(algo)) initvector_encoded = encode_init_vector(initvector) - alg_ident.Parameters = ECRYPT_DATA_BLOB.from_string(initvector_encoded) + alg_ident.Parameters = CRYPT_DATA_BLOB.from_string(initvector_encoded) else: initvector_encoded = encode_init_vector(initvector) - alg_ident.Parameters = ECRYPT_DATA_BLOB.from_string(initvector_encoded) + alg_ident.Parameters = CRYPT_DATA_BLOB.from_string(initvector_encoded) # Setup encryption parameters param = CRYPT_ENCRYPT_MESSAGE_PARA() diff --git a/windows/crypto/generation.py b/windows/crypto/generation.py index 7433964..dc38af7 100644 --- a/windows/crypto/generation.py +++ b/windows/crypto/generation.py @@ -1,8 +1,6 @@ import windows from windows import winproxy from windows.generated_def import * - -from windows.crypto.helper import ECRYPT_DATA_BLOB from windows.crypto import DEFAULT_ENCODING, CertificateStore @@ -16,7 +14,7 @@ def generate_selfsigned_certificate(name="CN=DEFAULT", prov=None, key_info=None, size = ULONG(len(name) + 0x100) buffer = (ctypes.c_ubyte * size.value)() winproxy.CertStrToNameA(X509_ASN_ENCODING, name, CERT_OID_NAME_STR, None, buffer, size, None) - blobname = ECRYPT_DATA_BLOB(size.value, buffer) + blobname = CRYPT_DATA_BLOB(size.value, buffer) cert = winproxy.CertCreateSelfSignCertificate(prov, blobname, flags, key_info, signature_algo, None, None, None) return windows.crypto.Certificate.from_pointer(cert) @@ -48,7 +46,7 @@ def generate_pfx(hstore, password=None): :return: :class:`bytearray` -- The raw PFX """ - blob = ECRYPT_DATA_BLOB(0, None) + blob = CRYPT_DATA_BLOB(0, None) winproxy.PFXExportCertStoreEx(hstore, blob, password, None, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY) blob.pbData = (ctypes.c_ubyte * blob.cbData)() winproxy.PFXExportCertStoreEx(hstore, blob, password, None, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY) diff --git a/windows/crypto/helper.py b/windows/crypto/helper.py deleted file mode 100644 index 31985a0..0000000 --- a/windows/crypto/helper.py +++ /dev/null @@ -1,13 +0,0 @@ -from windows.generated_def import CRYPT_DATA_BLOB, BYTE - -class ECRYPT_DATA_BLOB(CRYPT_DATA_BLOB): - @classmethod - def from_string(cls, buf): - self = cls() - self.cbData = len(buf) - self.pbData = (BYTE * self.cbData)(*bytearray(buf)) - return self - - @property - def data(self): - return bytearray(self.pbData[:self.cbData]) diff --git a/windows/crypto/sign_verify.py b/windows/crypto/sign_verify.py index 126f911..45f1af7 100644 --- a/windows/crypto/sign_verify.py +++ b/windows/crypto/sign_verify.py @@ -1,7 +1,6 @@ import windows from windows import winproxy from windows.crypto import DEFAULT_ENCODING -from windows.crypto.helper import ECRYPT_DATA_BLOB import windows.generated_def as gdef import ctypes @@ -33,12 +32,20 @@ def sign(cert, msg, detached_signature=False): sign_para.HashEncryptionAlgorithm = alg_hash sign_para.pvHashEncryptionAuxInfo = None - # TODO: Clean - result_buffer = windows.utils.buffer(gdef.BYTE, len(msg) + 0x2000)() + ByteBuffer = windows.utils.BUFFER(gdef.BYTE) + + result_buffer = ByteBuffer(nbelt=0x2000) result_size = gdef.DWORD(len(result_buffer)) - buff_pr = windows.utils.buffer(gdef.LPBYTE)(windows.utils.CharBuffer.from_buffer_copy(msg).cast(gdef.LPBYTE)) + buff = ByteBuffer(*bytearray(msg)) + buff_pr = windows.utils.BUFFER(gdef.LPBYTE, nbelt=1)(buff) buff_size = gdef.DWORD(len(msg)) - windows.winproxy.CryptSignMessage(sign_para, False, 1, buff_pr, buff_size, result_buffer.cast(gdef.LPBYTE), result_size) + try: + windows.winproxy.CryptSignMessage(sign_para, False, 1, buff_pr, buff_size, result_buffer, result_size) + except WindowsError as e: + if not e.winerror == gdef.ERROR_MORE_DATA: + raise + result_buffer = ByteBuffer(nbelt=result_size.value) + windows.winproxy.CryptSignMessage(sign_para, False, 1, buff_pr, buff_size, result_buffer, result_size) return bytearray(result_buffer[:result_size.value]) @@ -51,13 +58,13 @@ def verify_signature(cert, encoded_blob): # The public key used pubkey = cert.pCertInfo[0].SubjectPublicKeyInfo # Preparing in/out buffer/size - signed_buffer = windows.utils.buffer(gdef.BYTE).from_buffer_copy(encoded_blob) - decoded_buffer = windows.utils.CharBuffer.from_buffer_copy(encoded_blob) + signed_buffer = windows.utils.BUFFER(gdef.BYTE).from_buffer_copy(encoded_blob) + decoded_buffer = windows.utils.BUFFER(gdef.BYTE).from_buffer_copy(encoded_blob) decoded_size = gdef.DWORD(len(decoded_buffer)) winproxy.CryptVerifyMessageSignatureWithKey(verif_param, pubkey, - signed_buffer.cast(gdef.LPBYTE), + signed_buffer, len(encoded_blob), - decoded_buffer.cast(gdef.LPBYTE), + decoded_buffer, decoded_size) - return decoded_buffer[:decoded_size.value] \ No newline at end of file + return bytearray(decoded_buffer[:decoded_size.value]) \ No newline at end of file