]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blobdiff - ctypescrypto/cms.py
Added explicit check for CMS functions in libcrypto
[oss/ctypescrypto.git] / ctypescrypto / cms.py
index 1e533875ded29e44f0604b7b95fffc8dca7a6f87..d92b7335f2dc4917352c0c422a6376332dd6f016 100644 (file)
@@ -17,6 +17,12 @@ from ctypescrypto.bio import Membio
 from ctypescrypto.oid import Oid
 from ctypescrypto.x509 import StackOfX509
 
+# Check for neccesary functionality in libcrypto
+# LibreSSL fails this check
+
+if not hasattr(libcrypto,"CMS_decrypt"):
+    raise OSError("libcrypto lacks CMS functionality. Try using different libcrypto")
+
 class CMSError(LibCryptoError):
     """
     Exception which is raised when error occurs
@@ -59,6 +65,8 @@ def CMS(data, format="PEM"):
         ptr = libcrypto.PEM_read_bio_CMS(bio.bio, None, None, None)
     else:
         ptr = libcrypto.d2i_CMS_bio(bio.bio, None)
+    if ptr is None:
+        raise CMSError("Error parsing CMS data")
     typeoid = Oid(libcrypto.OBJ_obj2nid(libcrypto.CMS_get0_type(ptr)))
     if typeoid.shortname() == "pkcs7-signedData":
         return SignedData(ptr)
@@ -82,7 +90,7 @@ class CMSBase(object):
         """
         bio = Membio()
         if not libcrypto.i2d_CMS_bio(bio.bio, self.ptr):
-            raise CMSError("writing CMS to PEM")
+            raise CMSError("writing CMS to DER")
         return str(bio)
 
     def pem(self):
@@ -118,10 +126,10 @@ class SignedData(CMSBase):
             raise ValueError("Certificate doesn't match public key")
         bio = Membio(data)
         if certs is not None and len(certs) > 0:
-            certstack = StackOfX509(certs)
+            certstack = StackOfX509(certs).ptr
         else:
             certstack = None
-        ptr = libcrypto.CMS_sign(cert.cert, pkey.ptr, certstack, bio.bio, flags)
+        ptr = libcrypto.CMS_sign(cert.cert, pkey.key, certstack, bio.bio, flags)
         if ptr is None:
             raise CMSError("signing message")
         return SignedData(ptr)
@@ -140,7 +148,7 @@ class SignedData(CMSBase):
             raise ValueError("Specified keypair has no private part")
         if cert.pubkey != pkey:
             raise ValueError("Certificate doesn't match public key")
-        if libcrypto.CMS_add1_signer(self.ptr, cert.cert, pkey.ptr,
+        if libcrypto.CMS_add1_signer(self.ptr, cert.cert, pkey.key,
                                           digest_type.digest, flags) is None:
             raise CMSError("adding signer")
         if flags & Flags.REUSE_DIGEST == 0:
@@ -241,7 +249,7 @@ class EnvelopedData(CMSBase):
         """
         recp = StackOfX509(recipients)
         bio = Membio(data)
-        cms_ptr = libcrypto.CMS_encrypt(recp.ptr, bio.bio, cipher.cipher_type,
+        cms_ptr = libcrypto.CMS_encrypt(recp.ptr, bio.bio, cipher.cipher,
                                         flags)
         if cms_ptr is None:
             raise CMSError("encrypt EnvelopedData")
@@ -261,7 +269,7 @@ class EnvelopedData(CMSBase):
         if pkey != cert.pubkey:
             raise ValueError("Certificate doesn't match private key")
         bio = Membio()
-        res = libcrypto.CMS_decrypt(self.ptr, pkey.ptr, cert.ccert, None,
+        res = libcrypto.CMS_decrypt(self.ptr, pkey.key, cert.cert, None,
                                     bio.bio, flags)
         if res <= 0:
             raise CMSError("decrypting CMS")
@@ -283,7 +291,7 @@ class EncryptedData(CMSBase):
         @param flags - OR-ed combination of Flags constant
         """
         bio = Membio(data)
-        ptr = libcrypto.CMS_EncryptedData_encrypt(bio.bio, cipher.cipher_type,
+        ptr = libcrypto.CMS_EncryptedData_encrypt(bio.bio, cipher.cipher,
                                                   key, len(key), flags)
         if ptr is None:
             raise CMSError("encrypt data")
@@ -304,6 +312,8 @@ class EncryptedData(CMSBase):
 __all__ = ['CMS', 'CMSError', 'Flags', 'SignedData', 'EnvelopedData',
            'EncryptedData']
 
+libcrypto.CMS_get0_type.restype = c_void_p
+libcrypto.CMS_get0_type.argtypes = (c_void_p,)
 libcrypto.CMS_add1_cert.restype = c_int
 libcrypto.CMS_add1_cert.argtypes = (c_void_p, c_void_p)
 libcrypto.CMS_decrypt.restype = c_int