def load_pkcs7(p7file): bio = m2.bio_new_file(p7file, 'r') if bio is None: raise BIO.BIOError(Err.get_error()) try: p7_ptr = m2.pkcs7_read_bio(bio) finally: m2.bio_free(bio) if p7_ptr is None: raise PKCS7_Error(Err.get_error()) return PKCS7(p7_ptr, 1)
def load_pkcs7_bio_der(p7_der): """ Load a PKCS7 object from a PKCS7 DER blob. Return PKCS7 object. """ bio = BIO.MemoryBuffer(p7_der) if bio is None: raise PKCS7VerifyError(Err.get_error()) p7_ptr = m2.pkcs7_read_bio_der(bio._ptr()) if p7_ptr is None: raise PKCS7VerifyError(Err.get_error()) return PKCS7(p7_ptr, 1)
def text_crlf(text): bio_in = BIO.MemoryBuffer(text) bio_out = BIO.MemoryBuffer() if m2.smime_crlf_copy(bio_in._ptr(), bio_out._ptr()): return bio_out.read() else: raise SMIME_Error(Err.get_error())
def _ValidatePubkeyGeneric(self, signing_cert, digest_alg, payload, enc_digest): m2_cert = M2_X509.load_cert_der_string( der_encoder.encode(signing_cert)) pubkey = m2_cert.get_pubkey() pubkey.reset_context(digest_alg().name) pubkey.verify_init() pubkey.verify_update(payload) v = pubkey.verify_final(enc_digest) if v != 1: self.openssl_error = M2_Err.get_error() # Let's try a special case. I have no idea how I would determine when # to use this instead of the above code, so I'll always try. The # observed problem was that for one countersignature (RSA on MD5), # the encrypted digest did not contain an ASN.1 structure, but the # raw hash value instead. try: rsa = pubkey.get_rsa() except ValueError: # It's not an RSA key, just fall through... pass else: clear = rsa.public_decrypt(enc_digest, M2_RSA.pkcs1_padding) if digest_alg(payload).digest() == clear: return 1 return v
def text_crlf_bio(bio_in): # type: (BIO.BIO) -> BIO.BIO bio_out = BIO.MemoryBuffer() if m2.smime_crlf_copy(bio_in._ptr(), bio_out._ptr()): return bio_out else: raise SMIME_Error(Err.get_error())
def smime_load_pkcs7(p7file): bio = m2.bio_new_file(p7file, 'r') if bio is None: raise BIO.BIOError(Err.get_error()) try: p7_ptr, bio_ptr = m2.smime_read_pkcs7(bio) finally: m2.bio_free(bio) if p7_ptr is None: raise SMIME_Error(Err.get_error()) if bio_ptr is None: return PKCS7(p7_ptr, 1), None else: return PKCS7(p7_ptr, 1), BIO.BIO(bio_ptr, 1)
def _validatepubkeygeneric(self, signing_cert, digest_alg, payload, enc_digest): m2_cert = M2_X509.load_cert_der_string(der_encoder.encode(signing_cert)) pubkey = m2_cert.get_pubkey() pubkey.reset_context(digest_alg().name) pubkey.verify_init() pubkey.verify_update(payload) v = pubkey.verify_final(enc_digest) if v != 1: self.openssl_error = M2_Err.get_error() # Let's try a special case. I have no idea how I would determine when # to use this instead of the above code, so I'll always try. The # observed problem was that for one countersignature (RSA on MD5), # the encrypted digest did not contain an ASN.1 structure, but the # raw hash value instead. try: rsa = pubkey.get_rsa() except ValueError: # It's not an RSA key, just fall through... pass else: clear = rsa.public_decrypt(enc_digest, M2_RSA.pkcs1_padding) if digest_alg(payload).digest() == clear: return 1 return v
def load_session(pemfile): f = BIO.openfile(pemfile) cptr = m2.ssl_session_read_pem(f.bio_ptr()) f.close() if cptr is None: raise Err.get_error() return Session(cptr, 1)
def load_cert(file, format=FORMAT_PEM): """ Load certificate from file. @type file: string @param file: Name of file containing certificate in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the file to be loaded, either PEM or DER. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ bio = BIO.openfile(file) if format == FORMAT_PEM: return load_cert_bio(bio) elif format == FORMAT_DER: cptr = m2.d2i_x509(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1) else: raise ValueError( "Unknown format. Must be either FORMAT_DER or FORMAT_PEM")
def load_request(file, format=FORMAT_PEM): """ Load certificate request from file. @type file: string @param file: Name of file containing certificate request in either PEM or DER format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the file to be loaded, either PEM or DER. @rtype: M2Crypto.X509.Request @return: M2Crypto.X509.Request object. """ f = BIO.openfile(file) if format == FORMAT_PEM: cptr = m2.x509_req_read_pem(f.bio_ptr()) elif format == FORMAT_DER: cptr = m2.d2i_x509_req(f.bio_ptr()) else: raise ValueError( "Unknown filetype. Must be either FORMAT_PEM or FORMAT_DER") f.close() if cptr is None: raise X509Error(Err.get_error()) return Request(cptr, 1)
def run(self): ctx = SSL.Context() ctx.load_cert_chain("tests/server.pem") conn = SSL.Connection(ctx) cipher_list = conn.get_cipher_list() sslbio = BIO.SSLBio() readbio = BIO.MemoryBuffer() writebio = BIO.MemoryBuffer() sslbio.set_ssl(conn) conn.set_bio(readbio, writebio) conn.set_connect_state() sock = socket.socket() sock.connect((self.host, self.port)) handshake_complete = False while not handshake_complete: ret = sslbio.do_handshake() if ret <= 0: if not sslbio.should_retry() or not sslbio.should_read(): err_string = Err.get_error() print(err_string) sys.exit("unrecoverable error in handshake - client") else: output_token = writebio.read() if output_token is not None: sock.sendall(output_token) else: input_token = sock.recv(1024) readbio.write(input_token) else: handshake_complete = True sock.close()
def sign(self, data_bio, flags=0): if not hasattr(self, 'pkey'): raise SMIME_Error('no private key: use load_key()') if hasattr(self, 'x509_stack'): pkcs7 = m2.pkcs7_sign1(self.x509._ptr(), self.pkey._ptr(), self.x509_stack._ptr(), data_bio._ptr(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1) else: pkcs7 = m2.pkcs7_sign0(self.x509._ptr(), self.pkey._ptr(), data_bio._ptr(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1)
def load_session(pemfile): # type: (AnyStr) -> Session with BIO.openfile(pemfile) as f: cptr = m2.ssl_session_read_pem(f.bio_ptr()) if cptr is None: raise SSLError(Err.get_error()) return Session(cptr, 1)
def _get_proxy_request(self, delegation_id): request_url = '/delegation/' + delegation_id + '/request' request_pem = self.context.get(request_url) x509_request = X509.load_request_string(request_pem) if x509_request.verify(x509_request.get_pubkey()) != 1: raise ServerError('Error verifying signature on the request:', Err.get_error()) # Return return x509_request
def smime_load_pkcs7_bio(p7_bio): p7_ptr, bio_ptr = m2.smime_read_pkcs7(p7_bio._ptr()) if p7_ptr is None: raise SMIME_Error(Err.get_error()) if bio_ptr is None: return PKCS7(p7_ptr, 1), None else: return PKCS7(p7_ptr, 1), BIO.BIO(bio_ptr, 1)
def load_session(pemfile): f = BIO.openfile(pemfile) cptr = m2.ssl_session_read_pem(f.bio_ptr()) f.close() if cptr is None: from M2Crypto.SSL import SSLError raise SSLError(Err.get_error()) return Session(cptr, 1)
def load_pkcs7_der(p7file): """ Load a PKCS7 object from a PKCS7 DER file. Return PKCS7 object. """ bio = m2.bio_new_file(p7file, 'r') if bio is None: raise PKCS7VerifyError(Err.get_error()) try: p7_ptr = m2.pkcs7_read_bio_der(bio) finally: m2.bio_free(bio) if p7_ptr is None: raise PKCS7VerifyError(Err.get_error()) return PKCS7(p7_ptr, 1)
def ctrl_cmd_string(self, cmd, arg, optional=0): # type: (AnyStr, Optional[AnyStr], int) -> None """Call ENGINE_ctrl_cmd_string""" cmd = six.ensure_str(cmd) if arg is not None: arg = six.ensure_str(arg) if not m2.engine_ctrl_cmd_string(self._ptr, cmd, arg, optional): raise EngineError(Err.get_error())
def test_makefile_err(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e f = s.makefile() data = self.http_get(s) s.close() del f del s err_code = Err.peek_error_code() assert not err_code, 'Unexpected error: %s' % err_code err = Err.get_error() assert not err, 'Unexpected error: %s' % err
def _do_ssl_handshake(self): try: self._handshake_reading = False self._handshake_writing = False if not self._done_setup: self.socket.setup_ssl() # This server_side was added when creating the Connection # it is not a standard attribute if self.socket.server_side: self.socket.set_accept_state() else: self.socket.set_connect_state() self._done_setup = True # Actual accept/connect logic if self.socket.server_side: res = self.socket.accept_ssl() else: res = self.socket.connect_ssl() if res == 0: # TODO: We should somehow get SSL_WANT_READ/WRITE here # and then set the correct flag, although it does # work as long as one of them gets set self._handshake_reading = True #self._handshake_writing = True return if res < 0: err_num = self.socket.ssl_get_error(res) gen_log.error("Err: %s" % err_num) gen_log.error("Err Str: %s" % Err.get_error_reason(err_num)) return self.close() except SSL.SSLError as e: raise except socket.error as err: gen_log.error("Socket error!") # Some port scans (e.g. nmap in -sT mode) have been known # to cause do_handshake to raise EBADF and ENOTCONN, so make # those errors quiet as well. # https://groups.google.com/forum/?fromgroups#!topic/python-tornado/ApucKJat1_0 if (self._is_connreset(err) or err.args[0] in (errno.EBADF, errno.ENOTCONN)): return self.close(exc_info=err) raise except AttributeError as err: # On Linux, if the connection was reset before the call to # wrap_socket, do_handshake will fail with an # AttributeError. return self.close(exc_info=err) else: self._ssl_accepting = False if not self._verify_cert(self.socket.get_peer_cert()): gen_log.error("VALIDATION FAILED!") self.close() return gen_log.debug("Connect complete! (Sever: %s)!" % self.socket.server_side) self._run_ssl_connect_callback()
def new_stack_from_der(der_string): """ Create a new X509_Stack from DER string. @return: X509_Stack """ stack_ptr = m2.make_stack_from_der_sequence(der_string) if stack_ptr is None: raise X509Error(Err.get_error()) return X509_Stack(stack_ptr, 1, 1)
def ValidateCertificateSignature(self, signed_cert, signing_cert): """Given a cert signed by another cert, validates the signature.""" # First the naive way -- note this does not check expiry / use etc. signed_m2 = M2_X509.load_cert_der_string(der_encoder.encode(signed_cert)) signing_m2 = M2_X509.load_cert_der_string(der_encoder.encode(signing_cert)) pubkey = signing_m2.get_pubkey() v = signed_m2.verify(pubkey) if v != 1: self.openssl_error = M2_Err.get_error() raise Asn1Error('1: Validation of cert signature failed.')
def encrypt(self, data_bio, flags=0): if not hasattr(self, 'cipher'): raise SMIME_Error('no cipher: use set_cipher()') if not hasattr(self, 'x509_stack'): raise SMIME_Error('no recipient certs: use set_x509_stack()') pkcs7 = m2.pkcs7_encrypt(self.x509_stack._ptr(), data_bio._ptr(), self.cipher._ptr(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1)
def decrypt(self, pkcs7, flags=0): if not hasattr(self, 'pkey'): raise SMIME_Error('no private key: use load_key()') if not hasattr(self, 'x509'): raise SMIME_Error('no certificate: load_key() used incorrectly?') blob = m2.pkcs7_decrypt(pkcs7._ptr(), self.pkey._ptr(), self.x509._ptr(), flags) if blob is None: raise SMIME_Error(Err.get_error()) return blob
def __init__(self, request=None, path=None, dn=None, keySize=2048, key=None, extensions=None): self._signed = False # Create public key object if key and not request: self._key = key else: self._key = Key(keySize=keySize) # Create certificate._request if request: self._request = request if isinstance(request, str): if request.startswith("-----BEGIN CERTIFICATE REQUEST-----"): bio = BIO.MemoryBuffer(request) cptr = m2.x509_req_read_pem(bio._ptr()) if cptr is None: raise X509.X509Error(Err.get_error()) self._request = X509.Request(cptr, _pyfree=1) elif ord(request[0]) == 48: bio = BIO.MemoryBuffer(request) cptr = m2.d2i_x509_req(bio._ptr()) if cptr is None: raise X509.X509Error(Err.get_error()) self._request = X509.Request(cptr, _pyfree=1) elif path.exists(request): reqfile = open(request) bio = BIO.File(reqfile) self._request = X509.load_request_bio(bio) else: raise ValueError('WFT') else: self._request = X509.Request() self._request.set_pubkey(self._key) self._request.set_version(0) if dn: self.set_dn(dn) if extensions: self.add_extensions(extensions)
def load_info(self, file): # type: (AnyStr) -> int """ @param file: filename @return: 1 on success, 0 on failure """ ret = m2.x509_store_load_locations(self.store, file) if ret < 1: raise X509Error(Err.get_error()) return ret
def load_key(file, callback=util.passphrase_callback): # type: (AnyStr, Callable) -> PKey """ Load an M2Crypto.EVP.PKey from file. @param file: Name of file containing the key in PEM format. @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. @return: M2Crypto.EVP.PKey object. """ bio = m2.bio_new_file(file, 'r') if bio is None: raise BIO.BIOError(Err.get_error()) cptr = m2.pkey_read_pem(bio, callback) m2.bio_free(bio) if cptr is None: raise EVPError(Err.get_error()) return PKey(cptr, 1)
def set_session_id_ctx(self, id): # type: (bytes) -> None """Sets the session id for the SSL.Context w/in a session can be reused. @param id: Sessions are generated within a certain context. When exporting/importing sessions with i2d_SSL_SESSION/d2i_SSL_SESSION it would be possible, to re-import a session generated from another context (e.g. another application), which might lead to malfunctions. Therefore each application must set its own session id context sid_ctx which is used to distinguish the contexts and is stored in exported sessions. The sid_ctx can be any kind of binary data with a given length, it is therefore possible to use e.g. the name of the application and/or the hostname and/or service name. """ ret = m2.ssl_ctx_set_session_id_context(self.ctx, id) if not ret: raise Err.SSLError(Err.get_error_code(), '')
def new_stack_from_der(der_string): # type: (bytes) -> X509_Stack """ Create a new X509_Stack from DER string. @return: X509_Stack """ stack_ptr = m2.make_stack_from_der_sequence(util.py3bytes(der_string)) if stack_ptr is None: raise X509Error(Err.get_error()) return X509_Stack(stack_ptr, 1, 1)
def _engine_load_key(self, func, name, pin=None): """Helper function for loading keys""" ui = m2.ui_openssl() cbd = m2.engine_pkcs11_data_new(pin) try: kptr = func(self._ptr, name, ui, cbd) if not kptr: raise EngineError(Err.get_error()) key = EVP.PKey(kptr, _pyfree=1) finally: m2.engine_pkcs11_data_free(cbd) return key
def _engine_load_key(self, func, name, pin = None): """Helper function for loading keys""" ui = m2.ui_openssl() cbd = m2.engine_pkcs11_data_new(pin) try: kptr = func(self._ptr, name, ui, cbd) if not kptr: raise EngineError(Err.get_error()) key = EVP.PKey(kptr, _pyfree = 1) finally: m2.engine_pkcs11_data_free(cbd) return key
def test_makefile_err(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError as e: self.fail(e) f = s.makefile() data = self.http_get(s) s.close() del f del s err_code = Err.peek_error_code() self.assertEqual(err_code, 0, 'Unexpected error: %s' % err_code) err = Err.get_error() self.assertIsNone(err, 'Unexpected error: %s' % err) finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data)
def load_key(file, callback=util.passphrase_callback): """ Load an M2Crypto.EVP.PKey from file. @type file: string @param file: Name of file containing the key in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. @rtype: M2Crypto.EVP.PKey @return: M2Crypto.EVP.PKey object. """ bio = m2.bio_new_file(file, "r") if bio is None: raise Err.get_error() cptr = m2.pkey_read_pem(bio, callback) m2.bio_free(bio) if cptr is None: raise Err.get_error() return PKey(cptr, 1)
def load_cert_der_string(string): # type: (AnyStr) -> X509 """ Load certificate from a string. @param string: String containing a certificate in DER format. @return: M2Crypto.X509.X509 object. """ bio = BIO.MemoryBuffer(util.py3bytes(string)) cptr = m2.d2i_x509(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1)
def sign(self, data_bio, flags=0, algo='sha1'): # type: (BIO.BIO, int, Optional[str]) -> PKCS7 if not hasattr(self, 'pkey'): raise SMIME_Error('no private key: use load_key()') hash = getattr(m2, algo, None) if hash is None: raise SMIME_Error('no such hash algorithm %s' % algo) if hasattr(self, 'x509_stack'): pkcs7 = m2.pkcs7_sign1(self.x509._ptr(), self.pkey._ptr(), self.x509_stack._ptr(), data_bio._ptr(), hash(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1) else: pkcs7 = m2.pkcs7_sign0(self.x509._ptr(), self.pkey._ptr(), data_bio._ptr(), hash(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1)
def load_crl_string(crl_string): """ Load CRL from a string. @type string: string @param string: String containing a CRL in PEM format. @rtype: M2Crypto.X509.X509_CRL @return: M2Crypto.X509.X509_CRL object. """ bio = BIO.MemoryBuffer(crl_string) cptr=m2.x509_crl_read_pem(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return CRL(cptr, 1)
def load_cert_der_string(string): """ Load certificate from a string. @type string: string @param string: String containing a certificate in DER format. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ bio = BIO.MemoryBuffer(string) cptr = m2.d2i_x509(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1)
def load_key_bio_pubkey(bio, callback=util.passphrase_callback): # type: (BIO.BIO, Callable) -> PKey """ Load an M2Crypto.EVP.PKey from a public key as a M2Crypto.BIO object. @param bio: M2Crypto.BIO object containing the key in PEM format. @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. @return: M2Crypto.EVP.PKey object. """ cptr = m2.pkey_read_pem_pubkey(bio._ptr(), callback) if cptr is None: raise EVPError(Err.get_error()) return PKey(cptr, 1)
def load_crl(file): """ Load CRL from file. @type file: string @param file: Name of file containing CRL in PEM format. @rtype: M2Crypto.X509.CRL @return: M2Crypto.X509.CRL object. """ f=BIO.openfile(file) cptr=m2.x509_crl_read_pem(f.bio_ptr()) f.close() if cptr is None: raise X509Error(Err.get_error()) return CRL(cptr, 1)
def verify(self, pkcs7, data_bio=None, flags=0): if not hasattr(self, 'x509_stack'): raise SMIME_Error('no signer certs: use set_x509_stack()') if not hasattr(self, 'x509_store'): raise SMIME_Error('no x509 cert store: use set_x509_store()') assert isinstance(pkcs7, PKCS7), 'pkcs7 not an instance of PKCS7' p7 = pkcs7._ptr() if data_bio is None: blob = m2.pkcs7_verify0(p7, self.x509_stack._ptr(), self.x509_store._ptr(), flags) else: blob = m2.pkcs7_verify1(p7, self.x509_stack._ptr(), self.x509_store._ptr(), data_bio._ptr(), flags) if blob is None: raise SMIME_Error(Err.get_error()) return blob