Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import objc
- from ctypes import create_string_buffer, c_void_p, cast
- from Foundation import NSBundle
- Security = NSBundle.bundleWithIdentifier_('com.apple.security')
- # CMSDecoder.h
- kCMSSignerUnsigned = 0
- kCMSSignerValid = 1
- kCMSSignerNeedsDetachedContent = 2
- kCMSSignerInvalidSignature = 3
- kCMSSignerInvalidCert = 4
- kCMSSignerInvalidIndex = 5
- # cssmerr.h - you don't need all of these, only the ones you want to check for
- CSSMERR_TP_AUTHENTICATION_FAILED = -2147409657
- CSSMERR_TP_CERTGROUP_INCOMPLETE = -2147409656
- CSSMERR_TP_CERTIFICATE_CANT_OPERATE = -2147409655
- CSSMERR_TP_CERT_EXPIRED = -2147409654
- CSSMERR_TP_CERT_NOT_VALID_YET = -2147409653
- CSSMERR_TP_CERT_REVOKED = -2147409652
- CSSMERR_TP_CERT_SUSPENDED = -2147409651
- CSSMERR_TP_CRL_ALREADY_SIGNED = -2147409849
- CSSMERR_TP_DEVICE_FAILED = -2147409691
- CSSMERR_TP_DEVICE_RESET = -2147409692
- CSSMERR_TP_FUNCTION_FAILED = -2147409910
- CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED = -2147409913
- CSSMERR_TP_INSUFFICIENT_CLIENT_IDENTIFICATION = -2147409693
- CSSMERR_TP_INSUFFICIENT_CREDENTIALS = -2147409650
- CSSMERR_TP_INTERNAL_ERROR = -2147409919
- CSSMERR_TP_INVALID_ACTION = -2147409649
- CSSMERR_TP_INVALID_ACTION_DATA = -2147409648
- CSSMERR_TP_INVALID_ANCHOR_CERT = -2147409646
- CSSMERR_TP_INVALID_AUTHORITY = -2147409645
- CSSMERR_TP_INVALID_CALLBACK = -2147409625
- CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER = -2147409663
- CSSMERR_TP_INVALID_CERTGROUP = -2147409660
- CSSMERR_TP_INVALID_CERTGROUP_POINTER = -2147409854
- CSSMERR_TP_INVALID_CERTIFICATE = -2147409643
- CSSMERR_TP_INVALID_CERT_AUTHORITY = -2147409642
- CSSMERR_TP_INVALID_CERT_POINTER = -2147409853
- CSSMERR_TP_INVALID_CL_HANDLE = -2147409838
- CSSMERR_TP_INVALID_CONTEXT_HANDLE = -2147409856
- CSSMERR_TP_INVALID_CRL = -2147409638
- CSSMERR_TP_INVALID_CRLGROUP = -2147409659
- CSSMERR_TP_INVALID_CRLGROUP_POINTER = -2147409658
- CSSMERR_TP_INVALID_CRL_AUTHORITY = -2147409641
- CSSMERR_TP_INVALID_CRL_ENCODING = -2147409640
- CSSMERR_TP_INVALID_CRL_POINTER = -2147409852
- CSSMERR_TP_INVALID_CRL_TYPE = -2147409639
- CSSMERR_TP_INVALID_CSP_HANDLE = -2147409840
- CSSMERR_TP_INVALID_DATA = -2147409850
- CSSMERR_TP_INVALID_DB_HANDLE = -2147409846
- CSSMERR_TP_INVALID_DB_LIST = -2147409844
- CSSMERR_TP_INVALID_DB_LIST_POINTER = -2147409843
- CSSMERR_TP_INVALID_DL_HANDLE = -2147409839
- CSSMERR_TP_INVALID_FIELD_POINTER = -2147409851
- CSSMERR_TP_INVALID_FORM_TYPE = -2147409637
- CSSMERR_TP_INVALID_ID = -2147409636
- CSSMERR_TP_INVALID_IDENTIFIER = -2147409635
- CSSMERR_TP_INVALID_IDENTIFIER_POINTER = -2147409662
- CSSMERR_TP_INVALID_INDEX = -2147409634
- CSSMERR_TP_INVALID_INPUT_POINTER = -2147409915
- CSSMERR_TP_INVALID_KEYCACHE_HANDLE = -2147409661
- CSSMERR_TP_INVALID_NAME = -2147409633
- CSSMERR_TP_INVALID_NETWORK_ADDR = -2147409833
- CSSMERR_TP_INVALID_NUMBER_OF_FIELDS = -2147409848
- CSSMERR_TP_INVALID_OUTPUT_POINTER = -2147409914
- CSSMERR_TP_INVALID_PASSTHROUGH_ID = -2147409834
- CSSMERR_TP_INVALID_POINTER = -2147409916
- CSSMERR_TP_INVALID_POLICY_IDENTIFIERS = -2147409632
- CSSMERR_TP_INVALID_REASON = -2147409630
- CSSMERR_TP_INVALID_REQUEST_INPUTS = -2147409629
- CSSMERR_TP_INVALID_RESPONSE_VECTOR = -2147409628
- CSSMERR_TP_INVALID_SIGNATURE = -2147409627
- CSSMERR_TP_INVALID_STOP_ON_POLICY = -2147409626
- CSSMERR_TP_INVALID_TIMESTRING = -2147409631
- CSSMERR_TP_INVALID_TUPLE = -2147409624
- CSSMERR_TP_INVALID_TUPLEGROUP = -2147409614
- CSSMERR_TP_INVALID_TUPLEGROUP_POINTER = -2147409615
- CSSMERR_TP_IN_DARK_WAKE = -2147409690
- CSSMERR_TP_MDS_ERROR = -2147409917
- CSSMERR_TP_MEMORY_ERROR = -2147409918
- CSSMERR_TP_NOT_SIGNER = -2147409623
- CSSMERR_TP_NOT_TRUSTED = -2147409622
- CSSMERR_TP_NO_DEFAULT_AUTHORITY = -2147409621
- CSSMERR_TP_NO_USER_INTERACTION = -2147409696
- CSSMERR_TP_OS_ACCESS_DENIED = -2147409911
- CSSMERR_TP_REJECTED_FORM = -2147409620
- CSSMERR_TP_REQUEST_LOST = -2147409619
- CSSMERR_TP_REQUEST_REJECTED = -2147409618
- CSSMERR_TP_SELF_CHECK_FAILED = -2147409912
- CSSMERR_TP_SERVICE_NOT_AVAILABLE = -2147409694
- CSSMERR_TP_UNKNOWN_FORMAT = -2147409842
- CSSMERR_TP_UNKNOWN_TAG = -2147409841
- CSSMERR_TP_UNSUPPORTED_ADDR_TYPE = -2147409617
- CSSMERR_TP_UNSUPPORTED_SERVICE = -2147409616
- CSSMERR_TP_USER_CANCELED = -2147409695
- CSSMERR_TP_VERIFICATION_FAILURE = -2147409847
- CSSMERR_TP_VERIFY_ACTION_FAILED = -2147409644
- _ = [
- ('CMSDecoderGetTypeID', 'Q'),
- ('SecPolicyGetTypeID', 'Q'),
- ('SecTrustGetTypeID', 'Q'),
- ]
- objc.loadBundleFunctions(Security, globals(), _)
- CMSDecoderRef = objc.registerCFSignature('CMSDecoderRef', '^{_CMSDecoder=}', CMSDecoderGetTypeID())
- SecPolicyRef = objc.registerCFSignature('SecPolicyRef', '^{OpaqueSecPolicyRef=}', SecPolicyGetTypeID())
- SecTrustRef = objc.registerCFSignature('SecTrustRef', '^{__SecTrust=}', SecTrustGetTypeID())
- _ = [
- ('CMSDecoderCreate', 'io^^{_CMSDecoder}'),
- ('CMSDecoderSetDetachedContent', 'i^{_CMSDecoder=}^{__CFData=}'),
- ('CMSDecoderUpdateMessage', 'i^{_CMSDecoder=}^vQ'),
- ('CMSDecoderFinalizeMessage', 'i^{_CMSDecoder=}'),
- ('CMSDecoderCopySignerStatus', 'i^{_CMSDecoder=}Q@Bo^Io^^{__SecTrust}o^i'),
- ('SecPolicyCreateBasicX509', '^{OpaqueSecPolicyRef=}'),
- ]
- objc.loadBundleFunctions(Security, globals(), _)
- def check_detached_sig(message_path, signature_path, signer_index=0, trust_policy=None, evaluate=True):
- # Read in the message
- f = open(message_path, 'rb')
- message = f.read()
- f.close()
- message_bytes = buffer(message)
- # Read in the signature
- f = open(signature_path, 'rb')
- signature = f.read()
- f.close()
- signature_bytes = cast(create_string_buffer(signature), c_void_p)
- result, decoder = CMSDecoderCreate(None)
- result = CMSDecoderSetDetachedContent(decoder, message_bytes)
- # For some reason CMSDecoderUpdateMessage takes a freaking raw buffer
- result = CMSDecoderUpdateMessage(decoder, signature_bytes.value, len(signature))
- result = CMSDecoderFinalizeMessage(decoder)
- if trust_policy is None:
- trust_policy = SecPolicyCreateBasicX509()
- # returns: result, signer_status, sec_trust, cert_verify_result
- return CMSDecoderCopySignerStatus(decoder, signer_index, trust_policy, evaluate, None, None, None)
- # Example usage:
- result, signer_status, sec_trust, cert_verify_result = check_detached_sig('test.txt', 'test.txt.sig')
- # In testing, I was able to generate a self-signed cert and create a detached signature:
- # openssl smime -sign -signer signer_cert.pem -inkey signer_key.pem -binary -in test.txt -outform der -out test.txt.sig
- #
- # When tested against check_detached_sig, I received kCMSSignerInvalidCert (4) for signer_status
- # which indicates that the message was properly signed, but the signer's cert is unknown regarding trust.
- #
- # Modifying the test.txt (but re-using the same signature), I received kCMSSignerInvalidSignature (3) as expected.
- #
- # By importing the signer_cert.pem into the Keychain and then marking it as trusted (since it's self-signed), I was
- # able to achieve kCMSSignerValid (1).
Add Comment
Please, Sign In to add comment