From 9590d0bb421cb7fdf7dd04d4b1d0d77e3f06f13b Mon Sep 17 00:00:00 2001 From: Narayan Desai Date: Wed, 6 May 2009 01:26:53 +0000 Subject: more to python 2.6 ssl git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5187 ce84e21b-d406-0410-9b95-82705330c041 --- src/lib/Component.py | 584 ++++--- src/lib/SSLServer.py | 326 ++++ src/lib/tlslite/BaseDB.py | 120 -- src/lib/tlslite/Checker.py | 146 -- src/lib/tlslite/FileObject.py | 220 --- src/lib/tlslite/HandshakeSettings.py | 159 -- src/lib/tlslite/Session.py | 131 -- src/lib/tlslite/SessionCache.py | 103 -- src/lib/tlslite/SharedKeyDB.py | 58 - src/lib/tlslite/TLSConnection.py | 1600 -------------------- src/lib/tlslite/TLSRecordLayer.py | 1131 -------------- src/lib/tlslite/VerifierDB.py | 90 -- src/lib/tlslite/X509.py | 133 -- src/lib/tlslite/X509CertChain.py | 181 --- src/lib/tlslite/__init__.py | 39 - src/lib/tlslite/api.py | 75 - src/lib/tlslite/constants.py | 225 --- src/lib/tlslite/errors.py | 149 -- src/lib/tlslite/integration/AsyncStateMachine.py | 235 --- src/lib/tlslite/integration/ClientHelper.py | 163 -- src/lib/tlslite/integration/HTTPTLSConnection.py | 169 --- src/lib/tlslite/integration/IMAP4_TLS.py | 132 -- src/lib/tlslite/integration/IntegrationHelper.py | 52 - src/lib/tlslite/integration/POP3_TLS.py | 142 -- src/lib/tlslite/integration/SMTP_TLS.py | 114 -- .../tlslite/integration/TLSAsyncDispatcherMixIn.py | 139 -- .../tlslite/integration/TLSSocketServerMixIn.py | 59 - .../integration/TLSTwistedProtocolWrapper.py | 196 --- src/lib/tlslite/integration/XMLRPCTransport.py | 137 -- src/lib/tlslite/integration/__init__.py | 17 - src/lib/tlslite/mathtls.py | 170 --- src/lib/tlslite/messages.py | 561 ------- src/lib/tlslite/utils/AES.py | 31 - src/lib/tlslite/utils/ASN1Parser.py | 34 - src/lib/tlslite/utils/Cryptlib_AES.py | 34 - src/lib/tlslite/utils/Cryptlib_RC4.py | 28 - src/lib/tlslite/utils/Cryptlib_TripleDES.py | 35 - src/lib/tlslite/utils/OpenSSL_AES.py | 49 - src/lib/tlslite/utils/OpenSSL_RC4.py | 25 - src/lib/tlslite/utils/OpenSSL_RSAKey.py | 148 -- src/lib/tlslite/utils/OpenSSL_TripleDES.py | 44 - src/lib/tlslite/utils/PyCrypto_AES.py | 22 - src/lib/tlslite/utils/PyCrypto_RC4.py | 22 - src/lib/tlslite/utils/PyCrypto_RSAKey.py | 61 - src/lib/tlslite/utils/PyCrypto_TripleDES.py | 22 - src/lib/tlslite/utils/Python_AES.py | 68 - src/lib/tlslite/utils/Python_RC4.py | 39 - src/lib/tlslite/utils/Python_RSAKey.py | 209 --- src/lib/tlslite/utils/RC4.py | 17 - src/lib/tlslite/utils/RSAKey.py | 264 ---- src/lib/tlslite/utils/TripleDES.py | 26 - src/lib/tlslite/utils/__init__.py | 32 - src/lib/tlslite/utils/cipherfactory.py | 111 -- src/lib/tlslite/utils/codec.py | 94 -- src/lib/tlslite/utils/compat.py | 140 -- src/lib/tlslite/utils/cryptomath.py | 411 ----- src/lib/tlslite/utils/dateFuncs.py | 75 - src/lib/tlslite/utils/entropy.c | 173 --- src/lib/tlslite/utils/hmac.py | 104 -- src/lib/tlslite/utils/jython_compat.py | 195 --- src/lib/tlslite/utils/keyfactory.py | 243 --- src/lib/tlslite/utils/prngd.py | 62 - src/lib/tlslite/utils/rijndael.py | 392 ----- src/lib/tlslite/utils/win32prng.c | 63 - src/lib/tlslite/utils/xmltools.py | 201 --- 65 files changed, 606 insertions(+), 10624 deletions(-) create mode 100644 src/lib/SSLServer.py delete mode 100755 src/lib/tlslite/BaseDB.py delete mode 100755 src/lib/tlslite/Checker.py delete mode 100755 src/lib/tlslite/FileObject.py delete mode 100755 src/lib/tlslite/HandshakeSettings.py delete mode 100755 src/lib/tlslite/Session.py delete mode 100755 src/lib/tlslite/SessionCache.py delete mode 100755 src/lib/tlslite/SharedKeyDB.py delete mode 100755 src/lib/tlslite/TLSConnection.py delete mode 100755 src/lib/tlslite/TLSRecordLayer.py delete mode 100755 src/lib/tlslite/VerifierDB.py delete mode 100755 src/lib/tlslite/X509.py delete mode 100755 src/lib/tlslite/X509CertChain.py delete mode 100755 src/lib/tlslite/__init__.py delete mode 100755 src/lib/tlslite/api.py delete mode 100755 src/lib/tlslite/constants.py delete mode 100755 src/lib/tlslite/errors.py delete mode 100755 src/lib/tlslite/integration/AsyncStateMachine.py delete mode 100755 src/lib/tlslite/integration/ClientHelper.py delete mode 100755 src/lib/tlslite/integration/HTTPTLSConnection.py delete mode 100755 src/lib/tlslite/integration/IMAP4_TLS.py delete mode 100755 src/lib/tlslite/integration/IntegrationHelper.py delete mode 100755 src/lib/tlslite/integration/POP3_TLS.py delete mode 100755 src/lib/tlslite/integration/SMTP_TLS.py delete mode 100755 src/lib/tlslite/integration/TLSAsyncDispatcherMixIn.py delete mode 100755 src/lib/tlslite/integration/TLSSocketServerMixIn.py delete mode 100755 src/lib/tlslite/integration/TLSTwistedProtocolWrapper.py delete mode 100755 src/lib/tlslite/integration/XMLRPCTransport.py delete mode 100755 src/lib/tlslite/integration/__init__.py delete mode 100755 src/lib/tlslite/mathtls.py delete mode 100755 src/lib/tlslite/messages.py delete mode 100755 src/lib/tlslite/utils/AES.py delete mode 100755 src/lib/tlslite/utils/ASN1Parser.py delete mode 100755 src/lib/tlslite/utils/Cryptlib_AES.py delete mode 100755 src/lib/tlslite/utils/Cryptlib_RC4.py delete mode 100755 src/lib/tlslite/utils/Cryptlib_TripleDES.py delete mode 100755 src/lib/tlslite/utils/OpenSSL_AES.py delete mode 100755 src/lib/tlslite/utils/OpenSSL_RC4.py delete mode 100755 src/lib/tlslite/utils/OpenSSL_RSAKey.py delete mode 100755 src/lib/tlslite/utils/OpenSSL_TripleDES.py delete mode 100755 src/lib/tlslite/utils/PyCrypto_AES.py delete mode 100755 src/lib/tlslite/utils/PyCrypto_RC4.py delete mode 100755 src/lib/tlslite/utils/PyCrypto_RSAKey.py delete mode 100755 src/lib/tlslite/utils/PyCrypto_TripleDES.py delete mode 100755 src/lib/tlslite/utils/Python_AES.py delete mode 100755 src/lib/tlslite/utils/Python_RC4.py delete mode 100755 src/lib/tlslite/utils/Python_RSAKey.py delete mode 100755 src/lib/tlslite/utils/RC4.py delete mode 100755 src/lib/tlslite/utils/RSAKey.py delete mode 100755 src/lib/tlslite/utils/TripleDES.py delete mode 100755 src/lib/tlslite/utils/__init__.py delete mode 100755 src/lib/tlslite/utils/cipherfactory.py delete mode 100755 src/lib/tlslite/utils/codec.py delete mode 100755 src/lib/tlslite/utils/compat.py delete mode 100755 src/lib/tlslite/utils/cryptomath.py delete mode 100755 src/lib/tlslite/utils/dateFuncs.py delete mode 100755 src/lib/tlslite/utils/entropy.c delete mode 100755 src/lib/tlslite/utils/hmac.py delete mode 100755 src/lib/tlslite/utils/jython_compat.py delete mode 100755 src/lib/tlslite/utils/keyfactory.py delete mode 100644 src/lib/tlslite/utils/prngd.py delete mode 100755 src/lib/tlslite/utils/rijndael.py delete mode 100755 src/lib/tlslite/utils/win32prng.c delete mode 100755 src/lib/tlslite/utils/xmltools.py (limited to 'src/lib') diff --git a/src/lib/Component.py b/src/lib/Component.py index 7cfd3b8c8..d35759603 100644 --- a/src/lib/Component.py +++ b/src/lib/Component.py @@ -1,330 +1,306 @@ -'''Cobalt component base classes''' -__revision__ = '$Revision$' +"""Cobalt component base.""" -import logging, select, signal, socket, sys, urlparse, xmlrpclib, cPickle, os, traceback -from base64 import decodestring +__revision__ = '$Revision$' -import BaseHTTPServer, SimpleXMLRPCServer -import Bcfg2.tlslite.errors -import Bcfg2.tlslite.api -from Bcfg2.tlslite.TLSConnection import TLSConnection +__all__ = ["Component", "exposed", "automatic", "run_component"] -log = logging.getLogger('Component') +import inspect +import os +import cPickle +import pydoc +import sys +import getopt +import logging +import time +import threading +import xmlrpclib -class ComponentInitError(Exception): - '''Raised in case of component initialization failure''' - pass +import Bcfg2.Logger +from Bcfg2.SSLServer import XMLRPCServer -class ComponentKeyError(Exception): - '''raised in case of key parse fails''' - pass +def run_component (component_cls, argv=None, register=True, state_name=False, + cls_kwargs={}, extra_getopt='', time_out=10): + if argv is None: + argv = sys.argv + try: + (opts, arg) = getopt.getopt(argv[1:], 'C:D:d' + extra_getopt) + except getopt.GetoptError, e: + print >> sys.stderr, e + print >> sys.stderr, "Usage:" + print >> sys.stderr, "%s [-d] [-D pidfile] [-C config file]" % (os.path.basename(argv[0])) + sys.exit(1) + + # default settings + daemon = False + pidfile = "" + level = logging.INFO + # get user input + for item in opts: + if item[0] == '-C': + #FIXME + cf = (item[1], ) + elif item[0] == '-D': + daemon = True + pidfile_name = item[1] + elif item[0] == '-d': + level = logging.DEBUG + + logging.getLogger().setLevel(level) + Bcfg2.Logger.log_to_stderr(logging.getLogger()) + Bcfg2.Logger.setup_logging(component_cls.implementation, True, True) -class ForkedChild(Exception): - '''raised after child has been forked''' - pass + if daemon: + child_pid = os.fork() + if child_pid != 0: + return + + os.setsid() + + child_pid = os.fork() + if child_pid != 0: + os._exit(0) + + redirect_file = open("/dev/null", "w+") + os.dup2(redirect_file.fileno(), sys.__stdin__.fileno()) + os.dup2(redirect_file.fileno(), sys.__stdout__.fileno()) + os.dup2(redirect_file.fileno(), sys.__stderr__.fileno()) + + os.chdir(os.sep) + os.umask(0) + + pidfile = open(pidfile_name or "/dev/null", "w") + print >> pidfile, os.getpid() + pidfile.close() -class CobaltXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - '''CobaltXMLRPCRequestHandler takes care of ssl xmlrpc requests''' - masterpid = os.getpid() + component = component_cls(**cls_kwargs) + + location = ('', 6789) + keypath = '/etc/bcfg2.key' + certfile = '/etc/bcfg2.key' - def __init__(self, request, client_address, server): - self.cleanup = True - SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.__init__(self, request, - client_address, - server) + server = XMLRPCServer(location, keyfile=keypath, certfile=keypath, + register=register, timeout=time_out) + server.register_instance(component) + + try: + server.serve_forever() + finally: + server.server_close() - def do_POST(self): - '''Overload do_POST to pass through client address information''' - try: - # get arguments - data = self.rfile.read(int(self.headers["content-length"])) +def exposed (func): + """Mark a method to be exposed publically. + + Examples: + class MyComponent (Component): + @expose + def my_method (self, param1, param2): + do_stuff() + + class MyComponent (Component): + def my_method (self, param1, param2): + do_stuff() + my_method = expose(my_method) + """ + func.exposed = True + return func - authenticated = False - #try x509 cert auth (will have been completed, just checking status) - authenticated = self.request.authenticated - #TLSConnection can be accessed by self.request? - - #try httpauth - if not authenticated and "Authorization" in self.headers: - binauth = self.headers['Authorization'].replace("Basic ", "") - namepass = decodestring(binauth).split(':') - if self.server._authenticate_connection("bogus-method", - namepass[0], - namepass[1], - self.client_address): - authenticated = True +def automatic (func, period=10): + """Mark a method to be run periodically.""" + func.automatic = True + func.automatic_period = period + func.automatic_ts = -1 + return func - response = self.server._cobalt_marshalled_dispatch(data, self.client_address, authenticated) - except ForkedChild: - self.cleanup = False - return - except: # This should only happen if the module is buggy - # internal error, report as HTTP server error - log.error("Unexcepted handler failure in do_POST", exc_info=1) - self.send_response(500) - self.end_headers() - else: - # got a valid XML RPC response - if os.getpid() != self.masterpid: - pid = os.fork() - if pid: - self.cleanup = False - return - try: - self.send_response(200) - self.send_header("Content-type", "text/xml") - self.send_header("Content-length", str(len(response))) - self.end_headers() - self.wfile.write(response) - - # shut down the connection - self.wfile.flush() - self.rfile.close() - self.wfile.close() - self.connection.sock.shutdown(2) - #self.wfile.close() - except socket.error: - pass +def locking (func): + """Mark a function as being internally thread safe""" + func.locking = True + return func - def setup(self): - '''Setup a working connection''' - self.cleanup = True - self.connection = self.request - self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) - self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) +def readonly (func): + """Mark a function as read-only -- no data effects in component inst""" + func.readonly = True + return func -class TLSServer(Bcfg2.tlslite.api.TLSSocketServerMixIn, - BaseHTTPServer.HTTPServer): - '''This class is an tlslite-using SSLServer''' - def __init__(self, address, keyfile, certfile, handler, checker=None, - reqCert=False): - print keyfile, certfile - self.sc = Bcfg2.tlslite.api.SessionCache() - self.rc = reqCert - self.master = os.getpid() - x509 = Bcfg2.tlslite.api.X509() - cdata = open(certfile).read() - x509.parse(cdata) - self.checker = checker - kdata = open(keyfile).read() - try: - self.key = Bcfg2.tlslite.api.parsePEMKey(kdata, private=True) - except: - raise ComponentKeyError - self.chain = Bcfg2.tlslite.api.X509CertChain([x509]) - BaseHTTPServer.HTTPServer.__init__(self, address, handler) +def query (func=None, **kwargs): + """Mark a method to be marshalled as a query.""" + def _query (func): + if kwargs.get("all_fields", True): + func.query_all_fields = True + func.query = True + return func + if func is not None: + return _query(func) + return _query - def finish_request(self, sock, address): - sock.settimeout(90) - tlsConnection = TLSConnection(sock) - if self.handshake(tlsConnection) == True: - req = self.RequestHandlerClass(tlsConnection, address, self) - if req.cleanup: - tlsConnection.close() - if os.getpid() != self.master: - os._exit(0) - else: - log.error("Handshake failed") +def marshal_query_result (items, specs=None): + if specs is not None: + fields = get_spec_fields(specs) + else: + fields = None + return [item.to_rx(fields) for item in items] - def handshake(self, tlsConnection): - try: - tlsConnection.handshakeServer(certChain=self.chain, - privateKey=self.key, - sessionCache=self.sc, - checker=self.checker, - reqCert=self.rc) - tlsConnection.ignoreAbruptClose = True - #Connection authenticated during TLS handshake, no need for passwords - if not self.checker == None: - tlsConnection.authenticated = True +class Component (object): + + """Base component. + + Intended to be served as an instance by Cobalt.Component.XMLRPCServer + >>> server = Cobalt.Component.XMLRPCServer(location, keyfile) + >>> component = Cobalt.Component.Component() + >>> server.serve_instance(component) + + Class attributes: + name -- logical component name (e.g., "queue-manager", "process-manager") + implementation -- implementation identifier (e.g., "BlueGene/L", "BlueGene/P") + + Methods: + save -- pickle the component to a file + do_tasks -- perform automatic tasks for the component + """ + + name = "component" + implementation = "generic" + + def __init__ (self, **kwargs): + """Initialize a new component. + + Keyword arguments: + statefile -- file in which to save state automatically + """ + self.statefile = kwargs.get("statefile", None) + self.logger = logging.getLogger("%s %s" % (self.implementation, self.name)) + self.lock = threading.Lock() + + def save (self, statefile=None): + """Pickle the component. + + Arguments: + statefile -- use this file, rather than component.statefile + """ + statefile = statefile or self.statefile + if statefile: + temp_statefile = statefile + ".temp" + data = cPickle.dumps(self) + try: + fd = file(temp_statefile, "wb") + fd.write(data) + fd.close() + except IOError, e: + self.logger.error("statefile failure : %s" % e) + return str(e) else: - tlsConnection.authenticated = False - return True - except Bcfg2.tlslite.errors.TLSError, error: - return False - except socket.error: - return False - -class Component(TLSServer, - SimpleXMLRPCServer.SimpleXMLRPCDispatcher): - """Cobalt component providing XML-RPC access""" - __name__ = 'Component' - __implementation__ = 'Generic' - __statefields__ = [] - async_funcs = [] - fork_funcs = [] - child_limit = 32 - - def __init__(self, keyfile, certfile, password, location): - # need to get addr - self.shut = False - signal.signal(signal.SIGINT, self.start_shutdown) - signal.signal(signal.SIGTERM, self.start_shutdown) - self.logger = logging.getLogger('Component') - self.children = [] - self.static = True - uparsed = urlparse.urlparse(location)[1].split(':') - sock_loc = (uparsed[0], int(uparsed[1])) + os.rename(temp_statefile, statefile) + return "state saved to file: %s" % statefile + save = exposed(save) + + def do_tasks (self): + """Perform automatic tasks for the component. + + Automatic tasks are member callables with an attribute + automatic == True. + """ + for name, func in inspect.getmembers(self, callable): + if getattr(func, "automatic", False): + need_to_lock = not getattr(func, 'locking', False) + if (time.time() - func.automatic_ts) > \ + func.automatic_period: + if need_to_lock: + self.lock.acquire() + try: + mt1 = time.time() + func() + except: + self.logger.error("Automatic method %s failed" \ + % (name), exc_info=1) + finally: + mt2 = time.time() - self.password = password + if need_to_lock: + self.lock.release() + func.__dict__['automatic_ts'] = time.time() + def _resolve_exposed_method (self, method_name): + """Resolve an exposed method. + + Arguments: + method_name -- name of the method to resolve + """ try: - TLSServer.__init__(self, sock_loc, keyfile, certfile, - CobaltXMLRPCRequestHandler) - except socket.error: - self.logger.error("Failed to bind to socket") - raise ComponentInitError - except ComponentKeyError: - self.logger.error("Failed to parse key" % (keyfile)) - raise ComponentInitError - except: - self.logger.error("Failed to load ssl key '%s'" % (keyfile), exc_info=1) - raise ComponentInitError - try: - SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self) - except TypeError: - SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self, False, None) - self.logRequests = 0 - self.port = self.socket.getsockname()[1] - self.url = "https://%s:%s" % (socket.gethostname(), self.port) - self.logger.info("Bound to port %s" % self.port) - self.funcs.update({'system.listMethods':self.addr_system_listMethods}) - self.atime = 0 + func = getattr(self, method_name) + except AttributeError: + raise NoExposedMethod(method_name) + if not getattr(func, "exposed", False): + raise NoExposedMethod(method_name) + return func - def _cobalt_marshalled_dispatch(self, data, address, authenticated=False): - """Decode and dispatch XMLRPC requests. Overloaded to pass through - client address information + def _dispatch (self, method, args, dispatch_dict): + """Custom XML-RPC dispatcher for components. + + method -- XML-RPC method name + args -- tuple of paramaters to method """ - try: - rawparams, method = xmlrpclib.loads(data) - except: - self.logger.error("Failed to parse request from %s" \ - % (address[0])) - #open('/tmp/badreq', 'w').write(data) - return xmlrpclib.dumps(xmlrpclib.Fault(4, "Bad Request")) - if not authenticated: - if len(rawparams) < 2: - self.logger.error("No authentication included with request from %s" % address[0]) - return xmlrpclib.dumps(xmlrpclib.Fault(2, "No Authentication Info")) - user = rawparams[0] - password = rawparams[1] - params = rawparams[2:] - # check authentication - if not self._authenticate_connection(method, user, password, address): - return xmlrpclib.dumps(xmlrpclib.Fault(3, "Authentication Failure")) + need_to_lock = True + if method in dispatch_dict: + method_func = dispatch_dict[method] else: - #there is no prefixed auth info in this case - params = rawparams[0:] - # generate response - try: - # need to add waitpid code here to enforce maxchild - if method in self.fork_funcs: - self.clean_up_children() - self.check_for_free_slot() - pid = os.fork() - if pid: - self.children.append(pid) - raise ForkedChild - # all handlers must take address as the first argument - response = self._dispatch(method, (address, ) + params) - # wrap response in a singleton tuple - response = (response,) - response = xmlrpclib.dumps(response, methodresponse=1) - except xmlrpclib.Fault, fault: - response = xmlrpclib.dumps(fault) - except TypeError, terror: - self.logger.error("Client %s called function %s with wrong argument count" % - (address[0], method), exc_info=1) - response = xmlrpclib.dumps(xmlrpclib.Fault(4, terror.args[0])) - except ForkedChild: - raise - except: - self.logger.error("Unexpected handler failure") - trace = sys.exc_info() - self.logger.error("%s : %s" % (str(trace[0]), str(trace[1]))) - for line in traceback.format_exc().splitlines(): - self.logger.error(line) - del trace - # report exception back to server - response = xmlrpclib.dumps(xmlrpclib.Fault(1, - "%s:%s" % (sys.exc_type, sys.exc_value))) - return response - - def clean_up_children(self): - while True: try: - pid = os.waitpid(0, os.WNOHANG)[0] - if pid: - if pid in self.children: - self.children.remove(pid) - else: - break - except OSError: - break - - def check_for_free_slot(self): - if len(self.children) >= self.child_limit: - self.logger.info("Reached child_limit; waiting for child exit") - pid = os.waitpid(0, 0)[0] - self.children.remove(pid) - - def _authenticate_connection(self, method, user, password, address): - '''Authenticate new connection''' - (user, address, method) - return password == self.password - - def save_state(self): - '''Save fields defined in __statefields__ in /var/spool/cobalt/__implementation__''' - if self.__statefields__: - savedata = tuple([getattr(self, field) for field in self.__statefields__]) + method_func = self._resolve_exposed_method(method) + except Exception, e: + if getattr(e, "log", True): + self.logger.error(e, exc_info=True) + raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e)) + + if getattr(method_func, 'locking', False): + need_to_lock = False + if need_to_lock: + lock_start = time.time() + self.lock.acquire() + lock_done = time.time() try: - statefile = open("/var/spool/cobalt/%s" % self.__implementation__, 'w') - # need to flock here - statefile.write(cPickle.dumps(savedata)) - except: - self.logger.info("Statefile save failed; data persistence disabled") - self.__statefields__ = [] - - def load_state(self): - '''Load fields defined in __statefields__ from /var/spool/cobalt/__implementation__''' - if self.__statefields__: - try: - loaddata = cPickle.loads(open("/var/spool/cobalt/%s" % self.__implementation__).read()) - except: - self.logger.info("Statefile load failed") - return - for field in self.__statefields__: - setattr(self, field, loaddata[self.__statefields__.index(field)]) - - def addr_system_listMethods(self, address): - """get rid of the address argument and call the underlying dispatcher method""" - return SimpleXMLRPCServer.SimpleXMLRPCDispatcher.system_listMethods(self) - - def get_request(self): - '''We need to do work between requests, so select with timeout instead of blocking in accept''' - rsockinfo = [] - while self.socket not in rsockinfo: - if self.shut: - raise socket.error - for funcname in self.async_funcs: - func = getattr(self, funcname, False) - if callable(func): - func() - else: - self.logger.error("Cannot call uncallable method %s" % (funcname)) - try: - rsockinfo = select.select([self.socket], [], [], 10)[0] - except select.error: - continue - if self.socket in rsockinfo: - return self.socket.accept() - - def serve_forever(self): - """Handle one request at a time until doomsday.""" - while not self.shut: - self.handle_request() + method_start = time.time() + result = method_func(*args) + method_done = time.time() + except Exception, e: + if getattr(e, "log", True): + self.logger.error(e, exc_info=True) + raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e)) + finally: + if need_to_lock: + self.lock.release() + if getattr(method_func, "query", False): + if not getattr(method_func, "query_all_methods", False): + margs = args[:1] + else: + margs = [] + result = marshal_query_result(result, *margs) + return result - def start_shutdown(self, signum, frame): - '''Shutdown on unexpected signals''' - self.shut = True + @exposed + def listMethods (self): + """Custom XML-RPC introspective method list.""" + return [ + name for name, func in inspect.getmembers(self, callable) + if getattr(func, "exposed", False) + ] + @exposed + def methodHelp (self, method_name): + """Custom XML-RPC introspective method help. + + Arguments: + method_name -- name of method to get help on + """ + try: + func = self._resolve_exposed_method(method_name) + except NoExposedMethod: + return "" + return pydoc.getdoc(func) + + def get_name (self): + """The name of the component.""" + return self.name + get_name = exposed(get_name) + + def get_implementation (self): + """The implementation of the component.""" + return self.implementation + get_implementation = exposed(get_implementation) diff --git a/src/lib/SSLServer.py b/src/lib/SSLServer.py new file mode 100644 index 000000000..1ee642ce9 --- /dev/null +++ b/src/lib/SSLServer.py @@ -0,0 +1,326 @@ +"""Bcfg2 SSL server.""" + +__revision__ = '$Revision$' + +__all__ = [ + "SSLServer", "XMLRPCRequestHandler", "XMLRPCServer", + "find_intended_location", +] + +import sys +import xmlrpclib +import socket +import SocketServer +import SimpleXMLRPCServer +import base64 +import signal +import logging +import ssl +import threading +import time + +class ForkedChild(Exception): + pass + +class XMLRPCDispatcher (SimpleXMLRPCServer.SimpleXMLRPCDispatcher): + logger = logging.getLogger("Cobalt.Server.XMLRPCDispatcher") + def __init__ (self, allow_none, encoding): + SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self, + allow_none, + encoding) + self.allow_none = allow_none + self.encoding = encoding + + def _marshaled_dispatch (self, data): + method_func = None + params, method = xmlrpclib.loads(data) + try: + response = self.instance._dispatch(method, params, self.funcs) + response = (response,) + raw_response = xmlrpclib.dumps(response, methodresponse=1, + allow_none=self.allow_none, + encoding=self.encoding) + except xmlrpclib.Fault, fault: + raw_response = xmlrpclib.dumps(fault, + allow_none=self.allow_none, + encoding=self.encoding) + except: + # report exception back to server + raw_response = xmlrpclib.dumps( + xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), + allow_none=self.allow_none, encoding=self.encoding) + return raw_response + +class SSLServer (SocketServer.TCPServer, object): + + """TCP server supporting SSL encryption. + + Methods: + handshake -- perform a SSL/TLS handshake + + Properties: + url -- A url pointing to this server. + """ + + allow_reuse_address = True + logger = logging.getLogger("Cobalt.Server.TCPServer") + + def __init__ (self, server_address, RequestHandlerClass, keyfile=None, + certfile=None, reqCert=False, ca=None, timeout=None): + + """Initialize the SSL-TCP server. + + Arguments: + server_address -- address to bind to the server + RequestHandlerClass -- class to handle requests + + Keyword arguments: + keyfile -- private encryption key filename (enables ssl encryption) + certfile -- certificate file (enables ssl encryption) + reqCert -- client must present certificate + timeout -- timeout for non-blocking request handling + """ + + all_iface_address = ('', server_address[1]) + SocketServer.TCPServer.__init__(self, all_iface_address, + RequestHandlerClass) + + self.socket.settimeout(timeout) + self.keyfile = keyfile + self.certfile = certfile + self.ca = ca + self.reqCert = reqCert + + def get_request(self): + (sock, sockinfo) = self.socket.accept() + sslsock = ssl.wrap_socket(sock, server_side=True, certfile=self.certfile, + keyfile=self.keyfile) + return sslsock, sockinfo + + def _get_url (self): + port = self.socket.getsockname()[1] + hostname = socket.gethostname() + protocol = "https" + return "%s://%s:%i" % (protocol, hostname, port) + url = property(_get_url) + + +class XMLRPCRequestHandler (SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): + + """Component XML-RPC request handler. + + Adds support for HTTP authentication. + + Exceptions: + CouldNotAuthenticate -- client did not present acceptable authentication information + + Methods: + authenticate -- prompt a check of a client's provided username and password + handle_one_request -- handle a single rpc (optionally authenticating) + """ + logger = logging.getLogger("Cobalt.Server.XMLRPCRequestHandler") + + class CouldNotAuthenticate (Exception): + """Client did not present acceptible authentication information.""" + + require_auth = True + credentials = {'root':'default'} + + def authenticate (self): + """Authenticate the credentials of the latest client.""" + try: + header = self.headers['Authorization'] + except KeyError: + self.logger.error("No authentication data presented") + raise self.CouldNotAuthenticate("client did not present credentials") + auth_type, auth_content = header.split() + auth_content = base64.standard_b64decode(auth_content) + try: + username, password = auth_content.split(":") + except ValueError: + username = auth_content + password = "" + try: + valid_password = self.credentials[username] + except KeyError: + raise self.CouldNotAuthenticate("unknown user: %s" % username) + if password != valid_password: + raise self.CouldNotAuthenticate("invalid password for %s" % username) + + def parse_request (self): + """Extends parse_request. + + Optionally check HTTP authentication when parsing.""" + if not SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.parse_request(self): + return False + if self.require_auth: + try: + self.authenticate() + except self.CouldNotAuthenticate, e: + self.logger.error("Authentication failed: %s" % e.args[0]) + code = 401 + message, _ = self.responses[401] + self.send_error(code, message) + return False + return True + + ### FIXME need to override do_POST here + def do_POST(self): + try: + max_chunk_size = 10*1024*1024 + size_remaining = int(self.headers["content-length"]) + L = [] + while size_remaining: + chunk_size = min(size_remaining, max_chunk_size) + L.append(self.rfile.read(chunk_size)) + size_remaining -= len(L[-1]) + data = ''.join(L) + + response = self.server._marshaled_dispatch(data) + except: + raise + self.send_response(500) + self.end_headers() + else: + # got a valid XML RPC response + self.send_response(200) + self.send_header("Content-type", "text/xml") + self.send_header("Content-length", str(len(response))) + self.end_headers() + self.wfile.write(response) + + # shut down the connection + self.wfile.flush() + self.connection.shutdown(1) + + +class XMLRPCServer (SocketServer.ThreadingMixIn, SSLServer, + XMLRPCDispatcher, object): + + """Component XMLRPCServer. + + Methods: + serve_daemon -- serve_forever in a daemonized process + serve_forever -- handle_one_request until not self.serve + shutdown -- stop serve_forever (by setting self.serve = False) + ping -- return all arguments received + + RPC methods: + ping + + (additional system.* methods are inherited from base dispatcher) + + Properties: + require_auth -- the request handler is requiring authorization + credentials -- valid credentials being used for authentication + """ + + def __init__ (self, server_address, RequestHandlerClass=None, + keyfile=None, certfile=None, + timeout=10, + logRequests=False, + register=True, allow_none=True, encoding=None): + + """Initialize the XML-RPC server. + + Arguments: + server_address -- address to bind to the server + RequestHandlerClass -- request handler used by TCP server (optional) + + Keyword arguments: + keyfile -- private encryption key filename + certfile -- certificate file + logRequests -- log all requests (default False) + register -- presence should be reported to service-location (default True) + allow_none -- allow None values in xml-rpc + encoding -- encoding to use for xml-rpc (default UTF-8) + """ + + XMLRPCDispatcher.__init__(self, allow_none, encoding) + + if not RequestHandlerClass: + class RequestHandlerClass (XMLRPCRequestHandler): + """A subclassed request handler to prevent class-attribute conflicts.""" + + SSLServer.__init__(self, + server_address, RequestHandlerClass, + timeout=timeout, keyfile=keyfile, certfile=certfile) + self.logRequests = logRequests + self.serve = False + self.register = register + self.register_introspection_functions() + self.register_function(self.ping) + self.task_thread = threading.Thread(target=self._tasks_thread) + self.logger.info("service available at %s" % self.url) + self.timeout = timeout + + def _tasks_thread (self): + try: + while self.serve: + try: + if self.instance and hasattr(self.instance, 'do_tasks'): + self.instance.do_tasks() + except: + self.logger.error("Unexpected task failure", exc_info=1) + time.sleep(self.timeout) + except: + self.logger.error("tasks_thread failed", exc_info=1) + + def server_close (self): + SSLServer.server_close(self) + self.logger.info("server_close()") + + def _get_require_auth (self): + return getattr(self.RequestHandlerClass, "require_auth", False) + def _set_require_auth (self, value): + self.RequestHandlerClass.require_auth = value + require_auth = property(_get_require_auth, _set_require_auth) + + def _get_credentials (self): + try: + return self.RequestHandlerClass.credentials + except AttributeError: + return dict() + def _set_credentials (self, value): + self.RequestHandlerClass.credentials = value + credentials = property(_get_credentials, _set_credentials) + + def register_instance (self, instance, *args, **kwargs): + XMLRPCDispatcher.register_instance(self, instance, *args, **kwargs) + try: + name = instance.name + except AttributeError: + name = "unknown" + self.logger.info("serving %s at %s" % (name, self.url)) + + def serve_forever (self): + """Serve single requests until (self.serve == False).""" + self.serve = True + self.task_thread.start() + self.logger.info("serve_forever() [start]") + signal.signal(signal.SIGINT, self._handle_shutdown_signal) + signal.signal(signal.SIGTERM, self._handle_shutdown_signal) + + try: + while self.serve: + try: + self.handle_request() + except socket.timeout: + pass + except: + self.logger.error("Got unexpected error in handle_request", + exc_info=1) + finally: + self.logger.info("serve_forever() [stop]") + + def shutdown (self): + """Signal that automatic service should stop.""" + self.serve = False + + def _handle_shutdown_signal (self, *_): + self.shutdown() + + def ping (self, *args): + """Echo response.""" + self.logger.info("ping(%s)" % (", ".join([repr(arg) for arg in args]))) + return args diff --git a/src/lib/tlslite/BaseDB.py b/src/lib/tlslite/BaseDB.py deleted file mode 100755 index f4914fb7e..000000000 --- a/src/lib/tlslite/BaseDB.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Base class for SharedKeyDB and VerifierDB.""" - -import anydbm -import thread - -class BaseDB: - def __init__(self, filename, type): - self.type = type - self.filename = filename - if self.filename: - self.db = None - else: - self.db = {} - self.lock = thread.allocate_lock() - - def create(self): - """Create a new on-disk database. - - @raise anydbm.error: If there's a problem creating the database. - """ - if self.filename: - self.db = anydbm.open(self.filename, "n") #raises anydbm.error - self.db["--Reserved--type"] = self.type - self.db.sync() - else: - self.db = {} - - def open(self): - """Open a pre-existing on-disk database. - - @raise anydbm.error: If there's a problem opening the database. - @raise ValueError: If the database is not of the right type. - """ - if not self.filename: - raise ValueError("Can only open on-disk databases") - self.db = anydbm.open(self.filename, "w") #raises anydbm.error - try: - if self.db["--Reserved--type"] != self.type: - raise ValueError("Not a %s database" % self.type) - except KeyError: - raise ValueError("Not a recognized database") - - def __getitem__(self, username): - if self.db == None: - raise AssertionError("DB not open") - - self.lock.acquire() - try: - valueStr = self.db[username] - finally: - self.lock.release() - - return self._getItem(username, valueStr) - - def __setitem__(self, username, value): - if self.db == None: - raise AssertionError("DB not open") - - valueStr = self._setItem(username, value) - - self.lock.acquire() - try: - self.db[username] = valueStr - if self.filename: - self.db.sync() - finally: - self.lock.release() - - def __delitem__(self, username): - if self.db == None: - raise AssertionError("DB not open") - - self.lock.acquire() - try: - del(self.db[username]) - if self.filename: - self.db.sync() - finally: - self.lock.release() - - def __contains__(self, username): - """Check if the database contains the specified username. - - @type username: str - @param username: The username to check for. - - @rtype: bool - @return: True if the database contains the username, False - otherwise. - - """ - if self.db == None: - raise AssertionError("DB not open") - - self.lock.acquire() - try: - return username in self.db - finally: - self.lock.release() - - def check(self, username, param): - value = self.__getitem__(username) - return self._checkItem(value, username, param) - - def keys(self): - """Return a list of usernames in the database. - - @rtype: list - @return: The usernames in the database. - """ - if self.db == None: - raise AssertionError("DB not open") - - self.lock.acquire() - try: - usernames = self.db.keys() - finally: - self.lock.release() - usernames = [u for u in usernames if not u.startswith("--Reserved--")] - return usernames diff --git a/src/lib/tlslite/Checker.py b/src/lib/tlslite/Checker.py deleted file mode 100755 index f97869762..000000000 --- a/src/lib/tlslite/Checker.py +++ /dev/null @@ -1,146 +0,0 @@ -"""Class for post-handshake certificate checking.""" - -from utils.cryptomath import hashAndBase64 -from X509 import X509 -from X509CertChain import X509CertChain -from errors import * - - -class Checker: - """This class is passed to a handshake function to check the other - party's certificate chain. - - If a handshake function completes successfully, but the Checker - judges the other party's certificate chain to be missing or - inadequate, a subclass of - L{tlslite.errors.TLSAuthenticationError} will be raised. - - Currently, the Checker can check either an X.509 or a cryptoID - chain (for the latter, cryptoIDlib must be installed). - """ - - def __init__(self, cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - checkResumedSession=False): - """Create a new Checker instance. - - You must pass in one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - @type cryptoID: str - @param cryptoID: A cryptoID which the other party's certificate - chain must match. The cryptoIDlib module must be installed. - Mutually exclusive with all of the 'x509...' arguments. - - @type protocol: str - @param protocol: A cryptoID protocol URI which the other - party's certificate chain must match. Requires the 'cryptoID' - argument. - - @type x509Fingerprint: str - @param x509Fingerprint: A hex-encoded X.509 end-entity - fingerprint which the other party's end-entity certificate must - match. Mutually exclusive with the 'cryptoID' and - 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed. Mutually exclusive with the 'cryptoID' and - 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type checkResumedSession: bool - @param checkResumedSession: If resumed sessions should be - checked. This defaults to False, on the theory that if the - session was checked once, we don't need to bother - re-checking it. - """ - - if cryptoID and (x509Fingerprint or x509TrustList): - raise ValueError() - if x509Fingerprint and x509TrustList: - raise ValueError() - if x509CommonName and not x509TrustList: - raise ValueError() - if protocol and not cryptoID: - raise ValueError() - if cryptoID: - import cryptoIDlib #So we raise an error here - if x509TrustList: - import cryptlib_py #So we raise an error here - self.cryptoID = cryptoID - self.protocol = protocol - self.x509Fingerprint = x509Fingerprint - self.x509TrustList = x509TrustList - self.x509CommonName = x509CommonName - self.checkResumedSession = checkResumedSession - - def __call__(self, connection): - """Check a TLSConnection. - - When a Checker is passed to a handshake function, this will - be called at the end of the function. - - @type connection: L{tlslite.TLSConnection.TLSConnection} - @param connection: The TLSConnection to examine. - - @raise tlslite.errors.TLSAuthenticationError: If the other - party's certificate chain is missing or bad. - """ - if not self.checkResumedSession and connection.resumed: - return - - if self.cryptoID or self.x509Fingerprint or self.x509TrustList: - if connection._client: - chain = connection.session.serverCertChain - else: - chain = connection.session.clientCertChain - - if self.x509Fingerprint or self.x509TrustList: - if isinstance(chain, X509CertChain): - if self.x509Fingerprint: - if chain.getFingerprint() != self.x509Fingerprint: - raise TLSFingerprintError(\ - "X.509 fingerprint mismatch: %s, %s" % \ - (chain.getFingerprint(), self.x509Fingerprint)) - else: #self.x509TrustList - if not chain.validate(self.x509TrustList): - raise TLSValidationError("X.509 validation failure") - if self.x509CommonName and \ - (chain.getCommonName() != self.x509CommonName): - raise TLSAuthorizationError(\ - "X.509 Common Name mismatch: %s, %s" % \ - (chain.getCommonName(), self.x509CommonName)) - elif chain: - raise TLSAuthenticationTypeError() - else: - raise TLSNoAuthenticationError() - elif self.cryptoID: - import cryptoIDlib.CertChain - if isinstance(chain, cryptoIDlib.CertChain.CertChain): - if chain.cryptoID != self.cryptoID: - raise TLSFingerprintError(\ - "cryptoID mismatch: %s, %s" % \ - (chain.cryptoID, self.cryptoID)) - if self.protocol: - if not chain.checkProtocol(self.protocol): - raise TLSAuthorizationError(\ - "cryptoID protocol mismatch") - if not chain.validate(): - raise TLSValidationError("cryptoID validation failure") - elif chain: - raise TLSAuthenticationTypeError() - else: - raise TLSNoAuthenticationError() - diff --git a/src/lib/tlslite/FileObject.py b/src/lib/tlslite/FileObject.py deleted file mode 100755 index 6ee02b243..000000000 --- a/src/lib/tlslite/FileObject.py +++ /dev/null @@ -1,220 +0,0 @@ -"""Class returned by TLSConnection.makefile().""" - -class FileObject: - """This class provides a file object interface to a - L{tlslite.TLSConnection.TLSConnection}. - - Call makefile() on a TLSConnection to create a FileObject instance. - - This class was copied, with minor modifications, from the - _fileobject class in socket.py. Note that fileno() is not - implemented.""" - - default_bufsize = 16384 #TREV: changed from 8192 - - def __init__(self, sock, mode='rb', bufsize=-1): - self._sock = sock - self.mode = mode # Not actually used in this version - if bufsize < 0: - bufsize = self.default_bufsize - self.bufsize = bufsize - self.softspace = False - if bufsize == 0: - self._rbufsize = 1 - elif bufsize == 1: - self._rbufsize = self.default_bufsize - else: - self._rbufsize = bufsize - self._wbufsize = bufsize - self._rbuf = "" # A string - self._wbuf = [] # A list of strings - - def _getclosed(self): - return self._sock is not None - closed = property(_getclosed, doc="True if the file is closed") - - def close(self): - try: - if self._sock: - for result in self._sock._decrefAsync(): #TREV - pass - finally: - self._sock = None - - def __del__(self): - try: - self.close() - except: - # close() may fail if __init__ didn't complete - pass - - def flush(self): - if self._wbuf: - buffer = "".join(self._wbuf) - self._wbuf = [] - self._sock.sendall(buffer) - - #def fileno(self): - # raise NotImplementedError() #TREV - - def write(self, data): - data = str(data) # XXX Should really reject non-string non-buffers - if not data: - return - self._wbuf.append(data) - if (self._wbufsize == 0 or - self._wbufsize == 1 and '\n' in data or - self._get_wbuf_len() >= self._wbufsize): - self.flush() - - def writelines(self, list): - # XXX We could do better here for very long lists - # XXX Should really reject non-string non-buffers - self._wbuf.extend(filter(None, map(str, list))) - if (self._wbufsize <= 1 or - self._get_wbuf_len() >= self._wbufsize): - self.flush() - - def _get_wbuf_len(self): - buf_len = 0 - for x in self._wbuf: - buf_len += len(x) - return buf_len - - def read(self, size=-1): - data = self._rbuf - if size < 0: - # Read until EOF - buffers = [] - if data: - buffers.append(data) - self._rbuf = "" - if self._rbufsize <= 1: - recv_size = self.default_bufsize - else: - recv_size = self._rbufsize - while True: - data = self._sock.recv(recv_size) - if not data: - break - buffers.append(data) - return "".join(buffers) - else: - # Read until size bytes or EOF seen, whichever comes first - buf_len = len(data) - if buf_len >= size: - self._rbuf = data[size:] - return data[:size] - buffers = [] - if data: - buffers.append(data) - self._rbuf = "" - while True: - left = size - buf_len - recv_size = max(self._rbufsize, left) - data = self._sock.recv(recv_size) - if not data: - break - buffers.append(data) - n = len(data) - if n >= left: - self._rbuf = data[left:] - buffers[-1] = data[:left] - break - buf_len += n - return "".join(buffers) - - def readline(self, size=-1): - data = self._rbuf - if size < 0: - # Read until \n or EOF, whichever comes first - if self._rbufsize <= 1: - # Speed up unbuffered case - assert data == "" - buffers = [] - recv = self._sock.recv - while data != "\n": - data = recv(1) - if not data: - break - buffers.append(data) - return "".join(buffers) - nl = data.find('\n') - if nl >= 0: - nl += 1 - self._rbuf = data[nl:] - return data[:nl] - buffers = [] - if data: - buffers.append(data) - self._rbuf = "" - while True: - data = self._sock.recv(self._rbufsize) - if not data: - break - buffers.append(data) - nl = data.find('\n') - if nl >= 0: - nl += 1 - self._rbuf = data[nl:] - buffers[-1] = data[:nl] - break - return "".join(buffers) - else: - # Read until size bytes or \n or EOF seen, whichever comes first - nl = data.find('\n', 0, size) - if nl >= 0: - nl += 1 - self._rbuf = data[nl:] - return data[:nl] - buf_len = len(data) - if buf_len >= size: - self._rbuf = data[size:] - return data[:size] - buffers = [] - if data: - buffers.append(data) - self._rbuf = "" - while True: - data = self._sock.recv(self._rbufsize) - if not data: - break - buffers.append(data) - left = size - buf_len - nl = data.find('\n', 0, left) - if nl >= 0: - nl += 1 - self._rbuf = data[nl:] - buffers[-1] = data[:nl] - break - n = len(data) - if n >= left: - self._rbuf = data[left:] - buffers[-1] = data[:left] - break - buf_len += n - return "".join(buffers) - - def readlines(self, sizehint=0): - total = 0 - list = [] - while True: - line = self.readline() - if not line: - break - list.append(line) - total += len(line) - if sizehint and total >= sizehint: - break - return list - - # Iterator protocols - - def __iter__(self): - return self - - def next(self): - line = self.readline() - if not line: - raise StopIteration - return line diff --git a/src/lib/tlslite/HandshakeSettings.py b/src/lib/tlslite/HandshakeSettings.py deleted file mode 100755 index c7c3223e5..000000000 --- a/src/lib/tlslite/HandshakeSettings.py +++ /dev/null @@ -1,159 +0,0 @@ -"""Class for setting handshake parameters.""" - -from constants import CertificateType -from utils import cryptomath -from utils import cipherfactory - -class HandshakeSettings: - """This class encapsulates various parameters that can be used with - a TLS handshake. - @sort: minKeySize, maxKeySize, cipherNames, certificateTypes, - minVersion, maxVersion - - @type minKeySize: int - @ivar minKeySize: The minimum bit length for asymmetric keys. - - If the other party tries to use SRP, RSA, or Diffie-Hellman - parameters smaller than this length, an alert will be - signalled. The default is 1023. - - @type maxKeySize: int - @ivar maxKeySize: The maximum bit length for asymmetric keys. - - If the other party tries to use SRP, RSA, or Diffie-Hellman - parameters larger than this length, an alert will be signalled. - The default is 8193. - - @type cipherNames: list - @ivar cipherNames: The allowed ciphers, in order of preference. - - The allowed values in this list are 'aes256', 'aes128', '3des', and - 'rc4'. If these settings are used with a client handshake, they - determine the order of the ciphersuites offered in the ClientHello - message. - - If these settings are used with a server handshake, the server will - choose whichever ciphersuite matches the earliest entry in this - list. - - NOTE: If '3des' is used in this list, but TLS Lite can't find an - add-on library that supports 3DES, then '3des' will be silently - removed. - - The default value is ['aes256', 'aes128', '3des', 'rc4']. - - @type certificateTypes: list - @ivar certificateTypes: The allowed certificate types, in order of - preference. - - The allowed values in this list are 'x509' and 'cryptoID'. This - list is only used with a client handshake. The client will - advertise to the server which certificate types are supported, and - will check that the server uses one of the appropriate types. - - NOTE: If 'cryptoID' is used in this list, but cryptoIDlib is not - installed, then 'cryptoID' will be silently removed. - - @type minVersion: tuple - @ivar minVersion: The minimum allowed SSL/TLS version. - - This variable can be set to (3,0) for SSL 3.0, (3,1) for - TLS 1.0, or (3,2) for TLS 1.1. If the other party wishes to - use a lower version, a protocol_version alert will be signalled. - The default is (3,0). - - @type maxVersion: tuple - @ivar maxVersion: The maximum allowed SSL/TLS version. - - This variable can be set to (3,0) for SSL 3.0, (3,1) for - TLS 1.0, or (3,2) for TLS 1.1. If the other party wishes to - use a higher version, a protocol_version alert will be signalled. - The default is (3,2). (WARNING: Some servers may (improperly) - reject clients which offer support for TLS 1.1. In this case, - try lowering maxVersion to (3,1)). - """ - def __init__(self): - self.minKeySize = 1023 - self.maxKeySize = 8193 - self.cipherNames = ["aes256", "aes128", "3des", "rc4"] - self.cipherImplementations = ["cryptlib", "openssl", "pycrypto", - "python"] - self.certificateTypes = ["x509", "cryptoID"] - self.minVersion = (3,0) - self.maxVersion = (3,2) - - #Filters out options that are not supported - def _filter(self): - other = HandshakeSettings() - other.minKeySize = self.minKeySize - other.maxKeySize = self.maxKeySize - other.cipherNames = self.cipherNames - other.cipherImplementations = self.cipherImplementations - other.certificateTypes = self.certificateTypes - other.minVersion = self.minVersion - other.maxVersion = self.maxVersion - - if not cipherfactory.tripleDESPresent: - other.cipherNames = [e for e in self.cipherNames if e != "3des"] - if len(other.cipherNames)==0: - raise ValueError("No supported ciphers") - - try: - import cryptoIDlib - except ImportError: - other.certificateTypes = [e for e in self.certificateTypes \ - if e != "cryptoID"] - if len(other.certificateTypes)==0: - raise ValueError("No supported certificate types") - - if not cryptomath.cryptlibpyLoaded: - other.cipherImplementations = [e for e in \ - self.cipherImplementations if e != "cryptlib"] - if not cryptomath.m2cryptoLoaded: - other.cipherImplementations = [e for e in \ - other.cipherImplementations if e != "openssl"] - if not cryptomath.pycryptoLoaded: - other.cipherImplementations = [e for e in \ - other.cipherImplementations if e != "pycrypto"] - if len(other.cipherImplementations)==0: - raise ValueError("No supported cipher implementations") - - if other.minKeySize<512: - raise ValueError("minKeySize too small") - if other.minKeySize>16384: - raise ValueError("minKeySize too large") - if other.maxKeySize<512: - raise ValueError("maxKeySize too small") - if other.maxKeySize>16384: - raise ValueError("maxKeySize too large") - for s in other.cipherNames: - if s not in ("aes256", "aes128", "rc4", "3des"): - raise ValueError("Unknown cipher name: '%s'" % s) - for s in other.cipherImplementations: - if s not in ("cryptlib", "openssl", "python", "pycrypto"): - raise ValueError("Unknown cipher implementation: '%s'" % s) - for s in other.certificateTypes: - if s not in ("x509", "cryptoID"): - raise ValueError("Unknown certificate type: '%s'" % s) - - if other.minVersion > other.maxVersion: - raise ValueError("Versions set incorrectly") - - if not other.minVersion in ((3,0), (3,1), (3,2)): - raise ValueError("minVersion set incorrectly") - - if not other.maxVersion in ((3,0), (3,1), (3,2)): - raise ValueError("maxVersion set incorrectly") - - return other - - def _getCertificateTypes(self): - l = [] - for ct in self.certificateTypes: - if ct == "x509": - l.append(CertificateType.x509) - elif ct == "cryptoID": - l.append(CertificateType.cryptoID) - else: - raise AssertionError() - return l diff --git a/src/lib/tlslite/Session.py b/src/lib/tlslite/Session.py deleted file mode 100755 index a951f4589..000000000 --- a/src/lib/tlslite/Session.py +++ /dev/null @@ -1,131 +0,0 @@ -"""Class representing a TLS session.""" - -from utils.compat import * -from mathtls import * -from constants import * - -class Session: - """ - This class represents a TLS session. - - TLS distinguishes between connections and sessions. A new - handshake creates both a connection and a session. Data is - transmitted over the connection. - - The session contains a more permanent record of the handshake. The - session can be inspected to determine handshake results. The - session can also be used to create a new connection through - "session resumption". If the client and server both support this, - they can create a new connection based on an old session without - the overhead of a full handshake. - - The session for a L{tlslite.TLSConnection.TLSConnection} can be - retrieved from the connection's 'session' attribute. - - @type srpUsername: str - @ivar srpUsername: The client's SRP username (or None). - - @type sharedKeyUsername: str - @ivar sharedKeyUsername: The client's shared-key username (or - None). - - @type clientCertChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @ivar clientCertChain: The client's certificate chain (or None). - - @type serverCertChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @ivar serverCertChain: The server's certificate chain (or None). - """ - - def __init__(self): - self.masterSecret = createByteArraySequence([]) - self.sessionID = createByteArraySequence([]) - self.cipherSuite = 0 - self.srpUsername = None - self.sharedKeyUsername = None - self.clientCertChain = None - self.serverCertChain = None - self.resumable = False - self.sharedKey = False - - def _clone(self): - other = Session() - other.masterSecret = self.masterSecret - other.sessionID = self.sessionID - other.cipherSuite = self.cipherSuite - other.srpUsername = self.srpUsername - other.sharedKeyUsername = self.sharedKeyUsername - other.clientCertChain = self.clientCertChain - other.serverCertChain = self.serverCertChain - other.resumable = self.resumable - other.sharedKey = self.sharedKey - return other - - def _calcMasterSecret(self, version, premasterSecret, clientRandom, - serverRandom): - if version == (3,0): - self.masterSecret = PRF_SSL(premasterSecret, - concatArrays(clientRandom, serverRandom), 48) - elif version in ((3,1), (3,2)): - self.masterSecret = PRF(premasterSecret, "master secret", - concatArrays(clientRandom, serverRandom), 48) - else: - raise AssertionError() - - def valid(self): - """If this session can be used for session resumption. - - @rtype: bool - @return: If this session can be used for session resumption. - """ - return self.resumable or self.sharedKey - - def _setResumable(self, boolean): - #Only let it be set if this isn't a shared key - if not self.sharedKey: - #Only let it be set to True if the sessionID is non-null - if (not boolean) or (boolean and self.sessionID): - self.resumable = boolean - - def getCipherName(self): - """Get the name of the cipher used with this connection. - - @rtype: str - @return: The name of the cipher used with this connection. - Either 'aes128', 'aes256', 'rc4', or '3des'. - """ - if self.cipherSuite in CipherSuite.aes128Suites: - return "aes128" - elif self.cipherSuite in CipherSuite.aes256Suites: - return "aes256" - elif self.cipherSuite in CipherSuite.rc4Suites: - return "rc4" - elif self.cipherSuite in CipherSuite.tripleDESSuites: - return "3des" - else: - return None - - def _createSharedKey(self, sharedKeyUsername, sharedKey): - if len(sharedKeyUsername)>16: - raise ValueError() - if len(sharedKey)>47: - raise ValueError() - - self.sharedKeyUsername = sharedKeyUsername - - self.sessionID = createByteArrayZeros(16) - for x in range(len(sharedKeyUsername)): - self.sessionID[x] = ord(sharedKeyUsername[x]) - - premasterSecret = createByteArrayZeros(48) - sharedKey = chr(len(sharedKey)) + sharedKey - for x in range(48): - premasterSecret[x] = ord(sharedKey[x % len(sharedKey)]) - - self.masterSecret = PRF(premasterSecret, "shared secret", - createByteArraySequence([]), 48) - self.sharedKey = True - return self - - diff --git a/src/lib/tlslite/SessionCache.py b/src/lib/tlslite/SessionCache.py deleted file mode 100755 index 34cf0b0ec..000000000 --- a/src/lib/tlslite/SessionCache.py +++ /dev/null @@ -1,103 +0,0 @@ -"""Class for caching TLS sessions.""" - -import thread -import time - -class SessionCache: - """This class is used by the server to cache TLS sessions. - - Caching sessions allows the client to use TLS session resumption - and avoid the expense of a full handshake. To use this class, - simply pass a SessionCache instance into the server handshake - function. - - This class is thread-safe. - """ - - #References to these instances - #are also held by the caller, who may change the 'resumable' - #flag, so the SessionCache must return the same instances - #it was passed in. - - def __init__(self, maxEntries=10000, maxAge=14400): - """Create a new SessionCache. - - @type maxEntries: int - @param maxEntries: The maximum size of the cache. When this - limit is reached, the oldest sessions will be deleted as - necessary to make room for new ones. The default is 10000. - - @type maxAge: int - @param maxAge: The number of seconds before a session expires - from the cache. The default is 14400 (i.e. 4 hours).""" - - self.lock = thread.allocate_lock() - - # Maps sessionIDs to sessions - self.entriesDict = {} - - #Circular list of (sessionID, timestamp) pairs - self.entriesList = [(None,None)] * maxEntries - - self.firstIndex = 0 - self.lastIndex = 0 - self.maxAge = maxAge - - def __getitem__(self, sessionID): - self.lock.acquire() - try: - self._purge() #Delete old items, so we're assured of a new one - session = self.entriesDict[sessionID] - - #When we add sessions they're resumable, but it's possible - #for the session to be invalidated later on (if a fatal alert - #is returned), so we have to check for resumability before - #returning the session. - - if session.valid(): - return session - else: - raise KeyError() - finally: - self.lock.release() - - - def __setitem__(self, sessionID, session): - self.lock.acquire() - try: - #Add the new element - self.entriesDict[sessionID] = session - self.entriesList[self.lastIndex] = (sessionID, time.time()) - self.lastIndex = (self.lastIndex+1) % len(self.entriesList) - - #If the cache is full, we delete the oldest element to make an - #empty space - if self.lastIndex == self.firstIndex: - del(self.entriesDict[self.entriesList[self.firstIndex][0]]) - self.firstIndex = (self.firstIndex+1) % len(self.entriesList) - finally: - self.lock.release() - - #Delete expired items - def _purge(self): - currentTime = time.time() - - #Search through the circular list, deleting expired elements until - #we reach a non-expired element. Since elements in list are - #ordered in time, we can break once we reach the first non-expired - #element - index = self.firstIndex - while index != self.lastIndex: - if currentTime - self.entriesList[index][1] > self.maxAge: - del(self.entriesDict[self.entriesList[index][0]]) - index = (index+1) % len(self.entriesList) - else: - break - self.firstIndex = index - -def _test(): - import doctest, SessionCache - return doctest.testmod(SessionCache) - -if __name__ == "__main__": - _test() diff --git a/src/lib/tlslite/SharedKeyDB.py b/src/lib/tlslite/SharedKeyDB.py deleted file mode 100755 index 3246ec7f1..000000000 --- a/src/lib/tlslite/SharedKeyDB.py +++ /dev/null @@ -1,58 +0,0 @@ -"""Class for storing shared keys.""" - -from utils.cryptomath import * -from utils.compat import * -from mathtls import * -from Session import Session -from BaseDB import BaseDB - -class SharedKeyDB(BaseDB): - """This class represent an in-memory or on-disk database of shared - keys. - - A SharedKeyDB can be passed to a server handshake function to - authenticate a client based on one of the shared keys. - - This class is thread-safe. - """ - - def __init__(self, filename=None): - """Create a new SharedKeyDB. - - @type filename: str - @param filename: Filename for an on-disk database, or None for - an in-memory database. If the filename already exists, follow - this with a call to open(). To create a new on-disk database, - follow this with a call to create(). - """ - BaseDB.__init__(self, filename, "shared key") - - def _getItem(self, username, valueStr): - session = Session() - session._createSharedKey(username, valueStr) - return session - - def __setitem__(self, username, sharedKey): - """Add a shared key to the database. - - @type username: str - @param username: The username to associate the shared key with. - Must be less than or equal to 16 characters in length, and must - not already be in the database. - - @type sharedKey: str - @param sharedKey: The shared key to add. Must be less than 48 - characters in length. - """ - BaseDB.__setitem__(self, username, sharedKey) - - def _setItem(self, username, value): - if len(username)>16: - raise ValueError("username too long") - if len(value)>=48: - raise ValueError("shared key too long") - return value - - def _checkItem(self, value, username, param): - newSession = self._getItem(username, param) - return value.masterSecret == newSession.masterSecret \ No newline at end of file diff --git a/src/lib/tlslite/TLSConnection.py b/src/lib/tlslite/TLSConnection.py deleted file mode 100755 index d125f8f0a..000000000 --- a/src/lib/tlslite/TLSConnection.py +++ /dev/null @@ -1,1600 +0,0 @@ -""" -MAIN CLASS FOR TLS LITE (START HERE!). -""" -from __future__ import generators - -import socket -from utils.compat import formatExceptionTrace -from TLSRecordLayer import TLSRecordLayer -from Session import Session -from constants import * -from utils.cryptomath import getRandomBytes -from errors import * -from messages import * -from mathtls import * -from HandshakeSettings import HandshakeSettings - - -class TLSConnection(TLSRecordLayer): - """ - This class wraps a socket and provides TLS handshaking and data - transfer. - - To use this class, create a new instance, passing a connected - socket into the constructor. Then call some handshake function. - If the handshake completes without raising an exception, then a TLS - connection has been negotiated. You can transfer data over this - connection as if it were a socket. - - This class provides both synchronous and asynchronous versions of - its key functions. The synchronous versions should be used when - writing single-or multi-threaded code using blocking sockets. The - asynchronous versions should be used when performing asynchronous, - event-based I/O with non-blocking sockets. - - Asynchronous I/O is a complicated subject; typically, you should - not use the asynchronous functions directly, but should use some - framework like asyncore or Twisted which TLS Lite integrates with - (see - L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or - L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}). - """ - - - def __init__(self, sock): - """Create a new TLSConnection instance. - - @param sock: The socket data will be transmitted on. The - socket should already be connected. It may be in blocking or - non-blocking mode. - - @type sock: L{socket.socket} - """ - TLSRecordLayer.__init__(self, sock) - - def handshakeClientSRP(self, username, password, session=None, - settings=None, checker=None, async=False): - """Perform an SRP handshake in the role of client. - - This function performs a TLS/SRP handshake. SRP mutually - authenticates both parties to each other using only a - username and password. This function may also perform a - combined SRP and server-certificate handshake, if the server - chooses to authenticate itself with a certificate chain in - addition to doing SRP. - - TLS/SRP is non-standard. Most TLS implementations don't - support it. See - U{http://www.ietf.org/html.charters/tls-charter.html} or - U{http://trevp.net/tlssrp/} for the latest information on - TLS/SRP. - - Like any handshake function, this can be called on a closed - TLS connection, or on a TLS connection that is already open. - If called on an open connection it performs a re-handshake. - - If the function completes without raising an exception, the - TLS connection will be open and available for data transfer. - - If an exception is raised, the connection will have been - automatically closed (if it was ever open). - - @type username: str - @param username: The SRP username. - - @type password: str - @param password: The SRP password. - - @type session: L{tlslite.Session.Session} - @param session: A TLS session to attempt to resume. This - session must be an SRP session performed with the same username - and password as were passed in. If the resumption does not - succeed, a full SRP handshake will be performed. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - - @type checker: L{tlslite.Checker.Checker} - @param checker: A Checker instance. This instance will be - invoked to examine the other party's authentication - credentials, if the handshake completes succesfully. - - @type async: bool - @param async: If False, this function will block until the - handshake is completed. If True, this function will return a - generator. Successive invocations of the generator will - return 0 if it is waiting to read from the socket, 1 if it is - waiting to write to the socket, or will raise StopIteration if - the handshake operation is completed. - - @rtype: None or an iterable - @return: If 'async' is True, a generator object will be - returned. - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - @raise tlslite.errors.TLSAuthenticationError: If the checker - doesn't like the other party's authentication credentials. - """ - handshaker = self._handshakeClientAsync(srpParams=(username, password), - session=session, settings=settings, checker=checker) - if async: - return handshaker - for result in handshaker: - pass - - def handshakeClientCert(self, certChain=None, privateKey=None, - session=None, settings=None, checker=None, - async=False): - """Perform a certificate-based handshake in the role of client. - - This function performs an SSL or TLS handshake. The server - will authenticate itself using an X.509 or cryptoID certificate - chain. If the handshake succeeds, the server's certificate - chain will be stored in the session's serverCertChain attribute. - Unless a checker object is passed in, this function does no - validation or checking of the server's certificate chain. - - If the server requests client authentication, the - client will send the passed-in certificate chain, and use the - passed-in private key to authenticate itself. If no - certificate chain and private key were passed in, the client - will attempt to proceed without client authentication. The - server may or may not allow this. - - Like any handshake function, this can be called on a closed - TLS connection, or on a TLS connection that is already open. - If called on an open connection it performs a re-handshake. - - If the function completes without raising an exception, the - TLS connection will be open and available for data transfer. - - If an exception is raised, the connection will have been - automatically closed (if it was ever open). - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: The certificate chain to be used if the - server requests client authentication. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: The private key to be used if the server - requests client authentication. - - @type session: L{tlslite.Session.Session} - @param session: A TLS session to attempt to resume. If the - resumption does not succeed, a full handshake will be - performed. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - - @type checker: L{tlslite.Checker.Checker} - @param checker: A Checker instance. This instance will be - invoked to examine the other party's authentication - credentials, if the handshake completes succesfully. - - @type async: bool - @param async: If False, this function will block until the - handshake is completed. If True, this function will return a - generator. Successive invocations of the generator will - return 0 if it is waiting to read from the socket, 1 if it is - waiting to write to the socket, or will raise StopIteration if - the handshake operation is completed. - - @rtype: None or an iterable - @return: If 'async' is True, a generator object will be - returned. - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - @raise tlslite.errors.TLSAuthenticationError: If the checker - doesn't like the other party's authentication credentials. - """ - handshaker = self._handshakeClientAsync(certParams=(certChain, - privateKey), session=session, settings=settings, - checker=checker) - if async: - return handshaker - for result in handshaker: - pass - - def handshakeClientUnknown(self, srpCallback=None, certCallback=None, - session=None, settings=None, checker=None, - async=False): - """Perform a to-be-determined type of handshake in the role of client. - - This function performs an SSL or TLS handshake. If the server - requests client certificate authentication, the - certCallback will be invoked and should return a (certChain, - privateKey) pair. If the callback returns None, the library - will attempt to proceed without client authentication. The - server may or may not allow this. - - If the server requests SRP authentication, the srpCallback - will be invoked and should return a (username, password) pair. - If the callback returns None, the local implementation will - signal a user_canceled error alert. - - After the handshake completes, the client can inspect the - connection's session attribute to determine what type of - authentication was performed. - - Like any handshake function, this can be called on a closed - TLS connection, or on a TLS connection that is already open. - If called on an open connection it performs a re-handshake. - - If the function completes without raising an exception, the - TLS connection will be open and available for data transfer. - - If an exception is raised, the connection will have been - automatically closed (if it was ever open). - - @type srpCallback: callable - @param srpCallback: The callback to be used if the server - requests SRP authentication. If None, the client will not - offer support for SRP ciphersuites. - - @type certCallback: callable - @param certCallback: The callback to be used if the server - requests client certificate authentication. - - @type session: L{tlslite.Session.Session} - @param session: A TLS session to attempt to resume. If the - resumption does not succeed, a full handshake will be - performed. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - - @type checker: L{tlslite.Checker.Checker} - @param checker: A Checker instance. This instance will be - invoked to examine the other party's authentication - credentials, if the handshake completes succesfully. - - @type async: bool - @param async: If False, this function will block until the - handshake is completed. If True, this function will return a - generator. Successive invocations of the generator will - return 0 if it is waiting to read from the socket, 1 if it is - waiting to write to the socket, or will raise StopIteration if - the handshake operation is completed. - - @rtype: None or an iterable - @return: If 'async' is True, a generator object will be - returned. - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - @raise tlslite.errors.TLSAuthenticationError: If the checker - doesn't like the other party's authentication credentials. - """ - handshaker = self._handshakeClientAsync(unknownParams=(srpCallback, - certCallback), session=session, settings=settings, - checker=checker) - if async: - return handshaker - for result in handshaker: - pass - - def handshakeClientSharedKey(self, username, sharedKey, settings=None, - checker=None, async=False): - """Perform a shared-key handshake in the role of client. - - This function performs a shared-key handshake. Using shared - symmetric keys of high entropy (128 bits or greater) mutually - authenticates both parties to each other. - - TLS with shared-keys is non-standard. Most TLS - implementations don't support it. See - U{http://www.ietf.org/html.charters/tls-charter.html} for the - latest information on TLS with shared-keys. If the shared-keys - Internet-Draft changes or is superceded, TLS Lite will track - those changes, so the shared-key support in later versions of - TLS Lite may become incompatible with this version. - - Like any handshake function, this can be called on a closed - TLS connection, or on a TLS connection that is already open. - If called on an open connection it performs a re-handshake. - - If the function completes without raising an exception, the - TLS connection will be open and available for data transfer. - - If an exception is raised, the connection will have been - automatically closed (if it was ever open). - - @type username: str - @param username: The shared-key username. - - @type sharedKey: str - @param sharedKey: The shared key. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - - @type checker: L{tlslite.Checker.Checker} - @param checker: A Checker instance. This instance will be - invoked to examine the other party's authentication - credentials, if the handshake completes succesfully. - - @type async: bool - @param async: If False, this function will block until the - handshake is completed. If True, this function will return a - generator. Successive invocations of the generator will - return 0 if it is waiting to read from the socket, 1 if it is - waiting to write to the socket, or will raise StopIteration if - the handshake operation is completed. - - @rtype: None or an iterable - @return: If 'async' is True, a generator object will be - returned. - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - @raise tlslite.errors.TLSAuthenticationError: If the checker - doesn't like the other party's authentication credentials. - """ - handshaker = self._handshakeClientAsync(sharedKeyParams=(username, - sharedKey), settings=settings, checker=checker) - if async: - return handshaker - for result in handshaker: - pass - - def _handshakeClientAsync(self, srpParams=(), certParams=(), - unknownParams=(), sharedKeyParams=(), - session=None, settings=None, checker=None, - recursive=False): - - handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, - certParams=certParams, unknownParams=unknownParams, - sharedKeyParams=sharedKeyParams, session=session, - settings=settings, recursive=recursive) - for result in self._handshakeWrapperAsync(handshaker, checker): - yield result - - - def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams, - sharedKeyParams, session, settings, recursive): - if not recursive: - self._handshakeStart(client=True) - - #Unpack parameters - srpUsername = None # srpParams - password = None # srpParams - clientCertChain = None # certParams - privateKey = None # certParams - srpCallback = None # unknownParams - certCallback = None # unknownParams - #session # sharedKeyParams (or session) - #settings # settings - - if srpParams: - srpUsername, password = srpParams - elif certParams: - clientCertChain, privateKey = certParams - elif unknownParams: - srpCallback, certCallback = unknownParams - elif sharedKeyParams: - session = Session()._createSharedKey(*sharedKeyParams) - - if not settings: - settings = HandshakeSettings() - settings = settings._filter() - - #Validate parameters - if srpUsername and not password: - raise ValueError("Caller passed a username but no password") - if password and not srpUsername: - raise ValueError("Caller passed a password but no username") - - if clientCertChain and not privateKey: - raise ValueError("Caller passed a certChain but no privateKey") - if privateKey and not clientCertChain: - raise ValueError("Caller passed a privateKey but no certChain") - - if clientCertChain: - foundType = False - try: - import cryptoIDlib.CertChain - if isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain): - if "cryptoID" not in settings.certificateTypes: - raise ValueError("Client certificate doesn't "\ - "match Handshake Settings") - settings.certificateTypes = ["cryptoID"] - foundType = True - except ImportError: - pass - if not foundType and isinstance(clientCertChain, - X509CertChain): - if "x509" not in settings.certificateTypes: - raise ValueError("Client certificate doesn't match "\ - "Handshake Settings") - settings.certificateTypes = ["x509"] - foundType = True - if not foundType: - raise ValueError("Unrecognized certificate type") - - - if session: - if not session.valid(): - session = None #ignore non-resumable sessions... - elif session.resumable and \ - (session.srpUsername != srpUsername): - raise ValueError("Session username doesn't match") - - #Add Faults to parameters - if srpUsername and self.fault == Fault.badUsername: - srpUsername += "GARBAGE" - if password and self.fault == Fault.badPassword: - password += "GARBAGE" - if sharedKeyParams: - identifier = sharedKeyParams[0] - sharedKey = sharedKeyParams[1] - if self.fault == Fault.badIdentifier: - identifier += "GARBAGE" - session = Session()._createSharedKey(identifier, sharedKey) - elif self.fault == Fault.badSharedKey: - sharedKey += "GARBAGE" - session = Session()._createSharedKey(identifier, sharedKey) - - - #Initialize locals - serverCertChain = None - cipherSuite = 0 - certificateType = CertificateType.x509 - premasterSecret = None - - #Get client nonce - clientRandom = getRandomBytes(32) - - #Initialize acceptable ciphersuites - cipherSuites = [] - if srpParams: - cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames) - cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) - elif certParams: - cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) - elif unknownParams: - if srpCallback: - cipherSuites += \ - CipherSuite.getSrpRsaSuites(settings.cipherNames) - cipherSuites += \ - CipherSuite.getSrpSuites(settings.cipherNames) - cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) - elif sharedKeyParams: - cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) - else: - cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) - - #Initialize acceptable certificate types - certificateTypes = settings._getCertificateTypes() - - #Tentatively set the version to the client's minimum version. - #We'll use this for the ClientHello, and if an error occurs - #parsing the Server Hello, we'll use this version for the response - self.version = settings.maxVersion - - #Either send ClientHello (with a resumable session)... - if session: - #If it's a resumable (i.e. not a shared-key session), then its - #ciphersuite must be one of the acceptable ciphersuites - if (not sharedKeyParams) and \ - session.cipherSuite not in cipherSuites: - raise ValueError("Session's cipher suite not consistent "\ - "with parameters") - else: - clientHello = ClientHello() - clientHello.create(settings.maxVersion, clientRandom, - session.sessionID, cipherSuites, - certificateTypes, session.srpUsername) - - #Or send ClientHello (without) - else: - clientHello = ClientHello() - clientHello.create(settings.maxVersion, clientRandom, - createByteArraySequence([]), cipherSuites, - certificateTypes, srpUsername) - for result in self._sendMsg(clientHello): - yield result - - #Get ServerHello (or missing_srp_username) - for result in self._getMsg((ContentType.handshake, - ContentType.alert), - HandshakeType.server_hello): - if result in (0,1): - yield result - else: - break - msg = result - - if isinstance(msg, ServerHello): - serverHello = msg - elif isinstance(msg, Alert): - alert = msg - - #If it's not a missing_srp_username, re-raise - if alert.description != AlertDescription.missing_srp_username: - self._shutdown(False) - raise TLSRemoteAlert(alert) - - #If we're not in SRP callback mode, we won't have offered SRP - #without a username, so we shouldn't get this alert - if not srpCallback: - for result in self._sendError(\ - AlertDescription.unexpected_message): - yield result - srpParams = srpCallback() - #If the callback returns None, cancel the handshake - if srpParams == None: - for result in self._sendError(AlertDescription.user_canceled): - yield result - - #Recursively perform handshake - for result in self._handshakeClientAsyncHelper(srpParams, - None, None, None, None, settings, True): - yield result - return - - #Get the server version. Do this before anything else, so any - #error alerts will use the server's version - self.version = serverHello.server_version - - #Future responses from server must use this version - self._versionCheck = True - - #Check ServerHello - if serverHello.server_version < settings.minVersion: - for result in self._sendError(\ - AlertDescription.protocol_version, - "Too old version: %s" % str(serverHello.server_version)): - yield result - if serverHello.server_version > settings.maxVersion: - for result in self._sendError(\ - AlertDescription.protocol_version, - "Too new version: %s" % str(serverHello.server_version)): - yield result - if serverHello.cipher_suite not in cipherSuites: - for result in self._sendError(\ - AlertDescription.illegal_parameter, - "Server responded with incorrect ciphersuite"): - yield result - if serverHello.certificate_type not in certificateTypes: - for result in self._sendError(\ - AlertDescription.illegal_parameter, - "Server responded with incorrect certificate type"): - yield result - if serverHello.compression_method != 0: - for result in self._sendError(\ - AlertDescription.illegal_parameter, - "Server responded with incorrect compression method"): - yield result - - #Get the server nonce - serverRandom = serverHello.random - - #If the server agrees to resume - if session and session.sessionID and \ - serverHello.session_id == session.sessionID: - - #If a shared-key, we're flexible about suites; otherwise the - #server-chosen suite has to match the session's suite - if sharedKeyParams: - session.cipherSuite = serverHello.cipher_suite - elif serverHello.cipher_suite != session.cipherSuite: - for result in self._sendError(\ - AlertDescription.illegal_parameter,\ - "Server's ciphersuite doesn't match session"): - yield result - - #Set the session for this connection - self.session = session - - #Calculate pending connection states - self._calcPendingStates(clientRandom, serverRandom, - settings.cipherImplementations) - - #Exchange ChangeCipherSpec and Finished messages - for result in self._getFinished(): - yield result - for result in self._sendFinished(): - yield result - - #Mark the connection as open - self._handshakeDone(resumed=True) - - #If server DOES NOT agree to resume - else: - - if sharedKeyParams: - for result in self._sendError(\ - AlertDescription.user_canceled, - "Was expecting a shared-key resumption"): - yield result - - #We've already validated these - cipherSuite = serverHello.cipher_suite - certificateType = serverHello.certificate_type - - #If the server chose an SRP suite... - if cipherSuite in CipherSuite.srpSuites: - #Get ServerKeyExchange, ServerHelloDone - for result in self._getMsg(ContentType.handshake, - HandshakeType.server_key_exchange, cipherSuite): - if result in (0,1): - yield result - else: - break - serverKeyExchange = result - - for result in self._getMsg(ContentType.handshake, - HandshakeType.server_hello_done): - if result in (0,1): - yield result - else: - break - serverHelloDone = result - - #If the server chose an SRP+RSA suite... - elif cipherSuite in CipherSuite.srpRsaSuites: - #Get Certificate, ServerKeyExchange, ServerHelloDone - for result in self._getMsg(ContentType.handshake, - HandshakeType.certificate, certificateType): - if result in (0,1): - yield result - else: - break - serverCertificate = result - - for result in self._getMsg(ContentType.handshake, - HandshakeType.server_key_exchange, cipherSuite): - if result in (0,1): - yield result - else: - break - serverKeyExchange = result - - for result in self._getMsg(ContentType.handshake, - HandshakeType.server_hello_done): - if result in (0,1): - yield result - else: - break - serverHelloDone = result - - #If the server chose an RSA suite... - elif cipherSuite in CipherSuite.rsaSuites: - #Get Certificate[, CertificateRequest], ServerHelloDone - for result in self._getMsg(ContentType.handshake, - HandshakeType.certificate, certificateType): - if result in (0,1): - yield result - else: - break - serverCertificate = result - - for result in self._getMsg(ContentType.handshake, - (HandshakeType.server_hello_done, - HandshakeType.certificate_request)): - if result in (0,1): - yield result - else: - break - msg = result - - certificateRequest = None - if isinstance(msg, CertificateRequest): - certificateRequest = msg - for result in self._getMsg(ContentType.handshake, - HandshakeType.server_hello_done): - if result in (0,1): - yield result - else: - break - serverHelloDone = result - elif isinstance(msg, ServerHelloDone): - serverHelloDone = msg - else: - raise AssertionError() - - - #Calculate SRP premaster secret, if server chose an SRP or - #SRP+RSA suite - if cipherSuite in CipherSuite.srpSuites + \ - CipherSuite.srpRsaSuites: - #Get and check the server's group parameters and B value - N = serverKeyExchange.srp_N - g = serverKeyExchange.srp_g - s = serverKeyExchange.srp_s - B = serverKeyExchange.srp_B - - if (g,N) not in goodGroupParameters: - for result in self._sendError(\ - AlertDescription.untrusted_srp_parameters, - "Unknown group parameters"): - yield result - if numBits(N) < settings.minKeySize: - for result in self._sendError(\ - AlertDescription.untrusted_srp_parameters, - "N value is too small: %d" % numBits(N)): - yield result - if numBits(N) > settings.maxKeySize: - for result in self._sendError(\ - AlertDescription.untrusted_srp_parameters, - "N value is too large: %d" % numBits(N)): - yield result - if B % N == 0: - for result in self._sendError(\ - AlertDescription.illegal_parameter, - "Suspicious B value"): - yield result - - #Check the server's signature, if server chose an - #SRP+RSA suite - if cipherSuite in CipherSuite.srpRsaSuites: - #Hash ServerKeyExchange/ServerSRPParams - hashBytes = serverKeyExchange.hash(clientRandom, - serverRandom) - - #Extract signature bytes from ServerKeyExchange - sigBytes = serverKeyExchange.signature - if len(sigBytes) == 0: - for result in self._sendError(\ - AlertDescription.illegal_parameter, - "Server sent an SRP ServerKeyExchange "\ - "message without a signature"): - yield result - - #Get server's public key from the Certificate message - for result in self._getKeyFromChain(serverCertificate, - settings): - if result in (0,1): - yield result - else: - break - publicKey, serverCertChain = result - - #Verify signature - if not publicKey.verify(sigBytes, hashBytes): - for result in self._sendError(\ - AlertDescription.decrypt_error, - "Signature failed to verify"): - yield result - - - #Calculate client's ephemeral DH values (a, A) - a = bytesToNumber(getRandomBytes(32)) - A = powMod(g, a, N) - - #Calculate client's static DH values (x, v) - x = makeX(bytesToString(s), srpUsername, password) - v = powMod(g, x, N) - - #Calculate u - u = makeU(N, A, B) - - #Calculate premaster secret - k = makeK(N, g) - S = powMod((B - (k*v)) % N, a+(u*x), N) - - if self.fault == Fault.badA: - A = N - S = 0 - premasterSecret = numberToBytes(S) - - #Send ClientKeyExchange - for result in self._sendMsg(\ - ClientKeyExchange(cipherSuite).createSRP(A)): - yield result - - - #Calculate RSA premaster secret, if server chose an RSA suite - elif cipherSuite in CipherSuite.rsaSuites: - - #Handle the presence of a CertificateRequest - if certificateRequest: - if unknownParams and certCallback: - certParamsNew = certCallback() - if certParamsNew: - clientCertChain, privateKey = certParamsNew - - #Get server's public key from the Certificate message - for result in self._getKeyFromChain(serverCertificate, - settings): - if result in (0,1): - yield result - else: - break - publicKey, serverCertChain = result - - - #Calculate premaster secret - premasterSecret = getRandomBytes(48) - premasterSecret[0] = settings.maxVersion[0] - premasterSecret[1] = settings.maxVersion[1] - - if self.fault == Fault.badPremasterPadding: - premasterSecret[0] = 5 - if self.fault == Fault.shortPremasterSecret: - premasterSecret = premasterSecret[:-1] - - #Encrypt premaster secret to server's public key - encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) - - #If client authentication was requested, send Certificate - #message, either with certificates or empty - if certificateRequest: - clientCertificate = Certificate(certificateType) - - if clientCertChain: - #Check to make sure we have the same type of - #certificates the server requested - wrongType = False - if certificateType == CertificateType.x509: - if not isinstance(clientCertChain, X509CertChain): - wrongType = True - elif certificateType == CertificateType.cryptoID: - if not isinstance(clientCertChain, - cryptoIDlib.CertChain.CertChain): - wrongType = True - if wrongType: - for result in self._sendError(\ - AlertDescription.handshake_failure, - "Client certificate is of wrong type"): - yield result - - clientCertificate.create(clientCertChain) - - for result in self._sendMsg(clientCertificate): - yield result - else: - #The server didn't request client auth, so we - #zeroize these so the clientCertChain won't be - #stored in the session. - privateKey = None - clientCertChain = None - - #Send ClientKeyExchange - clientKeyExchange = ClientKeyExchange(cipherSuite, - self.version) - clientKeyExchange.createRSA(encryptedPreMasterSecret) - for result in self._sendMsg(clientKeyExchange): - yield result - - #If client authentication was requested and we have a - #private key, send CertificateVerify - if certificateRequest and privateKey: - if self.version == (3,0): - #Create a temporary session object, just for the - #purpose of creating the CertificateVerify - session = Session() - session._calcMasterSecret(self.version, - premasterSecret, - clientRandom, - serverRandom) - verifyBytes = self._calcSSLHandshakeHash(\ - session.masterSecret, "") - elif self.version in ((3,1), (3,2)): - verifyBytes = stringToBytes(\ - self._handshake_md5.digest() + \ - self._handshake_sha.digest()) - if self.fault == Fault.badVerifyMessage: - verifyBytes[0] = ((verifyBytes[0]+1) % 256) - signedBytes = privateKey.sign(verifyBytes) - certificateVerify = CertificateVerify() - certificateVerify.create(signedBytes) - for result in self._sendMsg(certificateVerify): - yield result - - - #Create the session object - self.session = Session() - self.session._calcMasterSecret(self.version, premasterSecret, - clientRandom, serverRandom) - self.session.sessionID = serverHello.session_id - self.session.cipherSuite = cipherSuite - self.session.srpUsername = srpUsername - self.session.clientCertChain = clientCertChain - self.session.serverCertChain = serverCertChain - - #Calculate pending connection states - self._calcPendingStates(clientRandom, serverRandom, - settings.cipherImplementations) - - #Exchange ChangeCipherSpec and Finished messages - for result in self._sendFinished(): - yield result - for result in self._getFinished(): - yield result - - #Mark the connection as open - self.session._setResumable(True) - self._handshakeDone(resumed=False) - - - - def handshakeServer(self, sharedKeyDB=None, verifierDB=None, - certChain=None, privateKey=None, reqCert=False, - sessionCache=None, settings=None, checker=None): - """Perform a handshake in the role of server. - - This function performs an SSL or TLS handshake. Depending on - the arguments and the behavior of the client, this function can - perform a shared-key, SRP, or certificate-based handshake. It - can also perform a combined SRP and server-certificate - handshake. - - Like any handshake function, this can be called on a closed - TLS connection, or on a TLS connection that is already open. - If called on an open connection it performs a re-handshake. - This function does not send a Hello Request message before - performing the handshake, so if re-handshaking is required, - the server must signal the client to begin the re-handshake - through some other means. - - If the function completes without raising an exception, the - TLS connection will be open and available for data transfer. - - If an exception is raised, the connection will have been - automatically closed (if it was ever open). - - @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB} - @param sharedKeyDB: A database of shared symmetric keys - associated with usernames. If the client performs a - shared-key handshake, the session's sharedKeyUsername - attribute will be set. - - @type verifierDB: L{tlslite.VerifierDB.VerifierDB} - @param verifierDB: A database of SRP password verifiers - associated with usernames. If the client performs an SRP - handshake, the session's srpUsername attribute will be set. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: The certificate chain to be used if the - client requests server certificate authentication. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: The private key to be used if the client - requests server certificate authentication. - - @type reqCert: bool - @param reqCert: Whether to request client certificate - authentication. This only applies if the client chooses server - certificate authentication; if the client chooses SRP or - shared-key authentication, this will be ignored. If the client - performs a client certificate authentication, the sessions's - clientCertChain attribute will be set. - - @type sessionCache: L{tlslite.SessionCache.SessionCache} - @param sessionCache: An in-memory cache of resumable sessions. - The client can resume sessions from this cache. Alternatively, - if the client performs a full handshake, a new session will be - added to the cache. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites and SSL/TLS version chosen by the server. - - @type checker: L{tlslite.Checker.Checker} - @param checker: A Checker instance. This instance will be - invoked to examine the other party's authentication - credentials, if the handshake completes succesfully. - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - @raise tlslite.errors.TLSAuthenticationError: If the checker - doesn't like the other party's authentication credentials. - """ - for result in self.handshakeServerAsync(sharedKeyDB, verifierDB, - certChain, privateKey, reqCert, sessionCache, settings, - checker): - pass - - - def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None, - certChain=None, privateKey=None, reqCert=False, - sessionCache=None, settings=None, checker=None): - """Start a server handshake operation on the TLS connection. - - This function returns a generator which behaves similarly to - handshakeServer(). Successive invocations of the generator - will return 0 if it is waiting to read from the socket, 1 if it is - waiting to write to the socket, or it will raise StopIteration - if the handshake operation is complete. - - @rtype: iterable - @return: A generator; see above for details. - """ - handshaker = self._handshakeServerAsyncHelper(\ - sharedKeyDB=sharedKeyDB, - verifierDB=verifierDB, certChain=certChain, - privateKey=privateKey, reqCert=reqCert, - sessionCache=sessionCache, settings=settings) - for result in self._handshakeWrapperAsync(handshaker, checker): - yield result - - - def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB, - certChain, privateKey, reqCert, sessionCache, - settings): - - self._handshakeStart(client=False) - - if (not sharedKeyDB) and (not verifierDB) and (not certChain): - raise ValueError("Caller passed no authentication credentials") - if certChain and not privateKey: - raise ValueError("Caller passed a certChain but no privateKey") - if privateKey and not certChain: - raise ValueError("Caller passed a privateKey but no certChain") - - if not settings: - settings = HandshakeSettings() - settings = settings._filter() - - #Initialize acceptable cipher suites - cipherSuites = [] - if verifierDB: - if certChain: - cipherSuites += \ - CipherSuite.getSrpRsaSuites(settings.cipherNames) - cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) - if sharedKeyDB or certChain: - cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) - - #Initialize acceptable certificate type - certificateType = None - if certChain: - try: - import cryptoIDlib.CertChain - if isinstance(certChain, cryptoIDlib.CertChain.CertChain): - certificateType = CertificateType.cryptoID - except ImportError: - pass - if isinstance(certChain, X509CertChain): - certificateType = CertificateType.x509 - if certificateType == None: - raise ValueError("Unrecognized certificate type") - - #Initialize locals - clientCertChain = None - serverCertChain = None #We may set certChain to this later - postFinishedError = None - - #Tentatively set version to most-desirable version, so if an error - #occurs parsing the ClientHello, this is what we'll use for the - #error alert - self.version = settings.maxVersion - - #Get ClientHello - for result in self._getMsg(ContentType.handshake, - HandshakeType.client_hello): - if result in (0,1): - yield result - else: - break - clientHello = result - - #If client's version is too low, reject it - if clientHello.client_version < settings.minVersion: - self.version = settings.minVersion - for result in self._sendError(\ - AlertDescription.protocol_version, - "Too old version: %s" % str(clientHello.client_version)): - yield result - - #If client's version is too high, propose my highest version - elif clientHello.client_version > settings.maxVersion: - self.version = settings.maxVersion - - else: - #Set the version to the client's version - self.version = clientHello.client_version - - #Get the client nonce; create server nonce - clientRandom = clientHello.random - serverRandom = getRandomBytes(32) - - #Calculate the first cipher suite intersection. - #This is the 'privileged' ciphersuite. We'll use it if we're - #doing a shared-key resumption or a new negotiation. In fact, - #the only time we won't use it is if we're resuming a non-sharedkey - #session, in which case we use the ciphersuite from the session. - # - #Given the current ciphersuite ordering, this means we prefer SRP - #over non-SRP. - for cipherSuite in cipherSuites: - if cipherSuite in clientHello.cipher_suites: - break - else: - for result in self._sendError(\ - AlertDescription.handshake_failure): - yield result - - #If resumption was requested... - if clientHello.session_id and (sharedKeyDB or sessionCache): - session = None - - #Check in the sharedKeys container - if sharedKeyDB and len(clientHello.session_id)==16: - try: - #Trim off zero padding, if any - for x in range(16): - if clientHello.session_id[x]==0: - break - self.allegedSharedKeyUsername = bytesToString(\ - clientHello.session_id[:x]) - session = sharedKeyDB[self.allegedSharedKeyUsername] - if not session.sharedKey: - raise AssertionError() - #use privileged ciphersuite - session.cipherSuite = cipherSuite - except KeyError: - pass - - #Then check in the session cache - if sessionCache and not session: - try: - session = sessionCache[bytesToString(\ - clientHello.session_id)] - if session.sharedKey: - raise AssertionError() - if not session.resumable: - raise AssertionError() - #Check for consistency with ClientHello - if session.cipherSuite not in cipherSuites: - for result in self._sendError(\ - AlertDescription.handshake_failure): - yield result - if session.cipherSuite not in clientHello.cipher_suites: - for result in self._sendError(\ - AlertDescription.handshake_failure): - yield result - if clientHello.srp_username: - if clientHello.srp_username != session.srpUsername: - for result in self._sendError(\ - AlertDescription.handshake_failure): - yield result - except KeyError: - pass - - #If a session is found.. - if session: - #Set the session - self.session = session - - #Send ServerHello - serverHello = ServerHello() - serverHello.create(self.version, serverRandom, - session.sessionID, session.cipherSuite, - certificateType) - for result in self._sendMsg(serverHello): - yield result - - #From here on, the client's messages must have the right version - self._versionCheck = True - - #Calculate pending connection states - self._calcPendingStates(clientRandom, serverRandom, - settings.cipherImplementations) - - #Exchange ChangeCipherSpec and Finished messages - for result in self._sendFinished(): - yield result - for result in self._getFinished(): - yield result - - #Mark the connection as open - self._handshakeDone(resumed=True) - return - - - #If not a resumption... - - #TRICKY: we might have chosen an RSA suite that was only deemed - #acceptable because of the shared-key resumption. If the shared- - #key resumption failed, because the identifier wasn't recognized, - #we might fall through to here, where we have an RSA suite - #chosen, but no certificate. - if cipherSuite in CipherSuite.rsaSuites and not certChain: - for result in self._sendError(\ - AlertDescription.handshake_failure): - yield result - - #If an RSA suite is chosen, check for certificate type intersection - #(We do this check down here because if the mismatch occurs but the - # client is using a shared-key session, it's okay) - if cipherSuite in CipherSuite.rsaSuites + \ - CipherSuite.srpRsaSuites: - if certificateType not in clientHello.certificate_types: - for result in self._sendError(\ - AlertDescription.handshake_failure, - "the client doesn't support my certificate type"): - yield result - - #Move certChain -> serverCertChain, now that we're using it - serverCertChain = certChain - - - #Create sessionID - if sessionCache: - sessionID = getRandomBytes(32) - else: - sessionID = createByteArraySequence([]) - - #If we've selected an SRP suite, exchange keys and calculate - #premaster secret: - if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites: - - #If there's no SRP username... - if not clientHello.srp_username: - - #Ask the client to re-send ClientHello with one - for result in self._sendMsg(Alert().create(\ - AlertDescription.missing_srp_username, - AlertLevel.warning)): - yield result - - #Get ClientHello - for result in self._getMsg(ContentType.handshake, - HandshakeType.client_hello): - if result in (0,1): - yield result - else: - break - clientHello = result - - #Check ClientHello - #If client's version is too low, reject it (COPIED CODE; BAD!) - if clientHello.client_version < settings.minVersion: - self.version = settings.minVersion - for result in self._sendError(\ - AlertDescription.protocol_version, - "Too old version: %s" % str(clientHello.client_version)): - yield result - - #If client's version is too high, propose my highest version - elif clientHello.client_version > settings.maxVersion: - self.version = settings.maxVersion - - else: - #Set the version to the client's version - self.version = clientHello.client_version - - #Recalculate the privileged cipher suite, making sure to - #pick an SRP suite - cipherSuites = [c for c in cipherSuites if c in \ - CipherSuite.srpSuites + \ - CipherSuite.srpRsaSuites] - for cipherSuite in cipherSuites: - if cipherSuite in clientHello.cipher_suites: - break - else: - for result in self._sendError(\ - AlertDescription.handshake_failure): - yield result - - #Get the client nonce; create server nonce - clientRandom = clientHello.random - serverRandom = getRandomBytes(32) - - #The username better be there, this time - if not clientHello.srp_username: - for result in self._sendError(\ - AlertDescription.illegal_parameter, - "Client resent a hello, but without the SRP"\ - " username"): - yield result - - - #Get username - self.allegedSrpUsername = clientHello.srp_username - - #Get parameters from username - try: - entry = verifierDB[self.allegedSrpUsername] - except KeyError: - for result in self._sendError(\ - AlertDescription.unknown_srp_username): - yield result - (N, g, s, v) = entry - - #Calculate server's ephemeral DH values (b, B) - b = bytesToNumber(getRandomBytes(32)) - k = makeK(N, g) - B = (powMod(g, b, N) + (k*v)) % N - - #Create ServerKeyExchange, signing it if necessary - serverKeyExchange = ServerKeyExchange(cipherSuite) - serverKeyExchange.createSRP(N, g, stringToBytes(s), B) - if cipherSuite in CipherSuite.srpRsaSuites: - hashBytes = serverKeyExchange.hash(clientRandom, - serverRandom) - serverKeyExchange.signature = privateKey.sign(hashBytes) - - #Send ServerHello[, Certificate], ServerKeyExchange, - #ServerHelloDone - msgs = [] - serverHello = ServerHello() - serverHello.create(self.version, serverRandom, sessionID, - cipherSuite, certificateType) - msgs.append(serverHello) - if cipherSuite in CipherSuite.srpRsaSuites: - certificateMsg = Certificate(certificateType) - certificateMsg.create(serverCertChain) - msgs.append(certificateMsg) - msgs.append(serverKeyExchange) - msgs.append(ServerHelloDone()) - for result in self._sendMsgs(msgs): - yield result - - #From here on, the client's messages must have the right version - self._versionCheck = True - - #Get and check ClientKeyExchange - for result in self._getMsg(ContentType.handshake, - HandshakeType.client_key_exchange, - cipherSuite): - if result in (0,1): - yield result - else: - break - clientKeyExchange = result - A = clientKeyExchange.srp_A - if A % N == 0: - postFinishedError = (AlertDescription.illegal_parameter, - "Suspicious A value") - #Calculate u - u = makeU(N, A, B) - - #Calculate premaster secret - S = powMod((A * powMod(v,u,N)) % N, b, N) - premasterSecret = numberToBytes(S) - - - #If we've selected an RSA suite, exchange keys and calculate - #premaster secret: - elif cipherSuite in CipherSuite.rsaSuites: - - #Send ServerHello, Certificate[, CertificateRequest], - #ServerHelloDone - msgs = [] - msgs.append(ServerHello().create(self.version, serverRandom, - sessionID, cipherSuite, certificateType)) - msgs.append(Certificate(certificateType).create(serverCertChain)) - if reqCert: - msgs.append(CertificateRequest()) - msgs.append(ServerHelloDone()) - for result in self._sendMsgs(msgs): - yield result - - #From here on, the client's messages must have the right version - self._versionCheck = True - - #Get [Certificate,] (if was requested) - if reqCert: - if self.version == (3,0): - for result in self._getMsg((ContentType.handshake, - ContentType.alert), - HandshakeType.certificate, - certificateType): - if result in (0,1): - yield result - else: - break - msg = result - - if isinstance(msg, Alert): - #If it's not a no_certificate alert, re-raise - alert = msg - if alert.description != \ - AlertDescription.no_certificate: - self._shutdown(False) - raise TLSRemoteAlert(alert) - elif isinstance(msg, Certificate): - clientCertificate = msg - if clientCertificate.certChain and \ - clientCertificate.certChain.getNumCerts()!=0: - clientCertChain = clientCertificate.certChain - else: - raise AssertionError() - elif self.version in ((3,1), (3,2)): - for result in self._getMsg(ContentType.handshake, - HandshakeType.certificate, - certificateType): - if result in (0,1): - yield result - else: - break - clientCertificate = result - if clientCertificate.certChain and \ - clientCertificate.certChain.getNumCerts()!=0: - clientCertChain = clientCertificate.certChain - else: - raise AssertionError() - - #Get ClientKeyExchange - for result in self._getMsg(ContentType.handshake, - HandshakeType.client_key_exchange, - cipherSuite): - if result in (0,1): - yield result - else: - break - clientKeyExchange = result - - #Decrypt ClientKeyExchange - premasterSecret = privateKey.decrypt(\ - clientKeyExchange.encryptedPreMasterSecret) - - randomPreMasterSecret = getRandomBytes(48) - versionCheck = (premasterSecret[0], premasterSecret[1]) - if not premasterSecret: - premasterSecret = randomPreMasterSecret - elif len(premasterSecret)!=48: - premasterSecret = randomPreMasterSecret - elif versionCheck != clientHello.client_version: - if versionCheck != self.version: #Tolerate buggy IE clients - premasterSecret = randomPreMasterSecret - - #Get and check CertificateVerify, if relevant - if clientCertChain: - if self.version == (3,0): - #Create a temporary session object, just for the purpose - #of checking the CertificateVerify - session = Session() - session._calcMasterSecret(self.version, premasterSecret, - clientRandom, serverRandom) - verifyBytes = self._calcSSLHandshakeHash(\ - session.masterSecret, "") - elif self.version in ((3,1), (3,2)): - verifyBytes = stringToBytes(self._handshake_md5.digest() +\ - self._handshake_sha.digest()) - for result in self._getMsg(ContentType.handshake, - HandshakeType.certificate_verify): - if result in (0,1): - yield result - else: - break - certificateVerify = result - publicKey = clientCertChain.getEndEntityPublicKey() - if len(publicKey) < settings.minKeySize: - postFinishedError = (AlertDescription.handshake_failure, - "Client's public key too small: %d" % len(publicKey)) - if len(publicKey) > settings.maxKeySize: - postFinishedError = (AlertDescription.handshake_failure, - "Client's public key too large: %d" % len(publicKey)) - - if not publicKey.verify(certificateVerify.signature, - verifyBytes): - postFinishedError = (AlertDescription.decrypt_error, - "Signature failed to verify") - - - #Create the session object - self.session = Session() - self.session._calcMasterSecret(self.version, premasterSecret, - clientRandom, serverRandom) - self.session.sessionID = sessionID - self.session.cipherSuite = cipherSuite - self.session.srpUsername = self.allegedSrpUsername - self.session.clientCertChain = clientCertChain - self.session.serverCertChain = serverCertChain - - #Calculate pending connection states - self._calcPendingStates(clientRandom, serverRandom, - settings.cipherImplementations) - - #Exchange ChangeCipherSpec and Finished messages - for result in self._getFinished(): - yield result - - #If we were holding a post-finished error until receiving the client - #finished message, send it now. We delay the call until this point - #because calling sendError() throws an exception, and our caller might - #shut down the socket upon receiving the exception. If he did, and the - #client was still sending its ChangeCipherSpec or Finished messages, it - #would cause a socket error on the client side. This is a lot of - #consideration to show to misbehaving clients, but this would also - #cause problems with fault-testing. - if postFinishedError: - for result in self._sendError(*postFinishedError): - yield result - - for result in self._sendFinished(): - yield result - - #Add the session object to the session cache - if sessionCache and sessionID: - sessionCache[bytesToString(sessionID)] = self.session - - #Mark the connection as open - self.session._setResumable(True) - self._handshakeDone(resumed=False) - - - def _handshakeWrapperAsync(self, handshaker, checker): - if not self.fault: - try: - for result in handshaker: - yield result - if checker: - try: - checker(self) - except TLSAuthenticationError: - alert = Alert().create(AlertDescription.close_notify, - AlertLevel.fatal) - for result in self._sendMsg(alert): - yield result - raise - except: - self._shutdown(False) - raise - else: - try: - for result in handshaker: - yield result - if checker: - try: - checker(self) - except TLSAuthenticationError: - alert = Alert().create(AlertDescription.close_notify, - AlertLevel.fatal) - for result in self._sendMsg(alert): - yield result - raise - except socket.error, e: - raise TLSFaultError("socket error!") - except TLSAbruptCloseError, e: - raise TLSFaultError("abrupt close error!") - except TLSAlert, alert: - if alert.description not in Fault.faultAlerts[self.fault]: - raise TLSFaultError(str(alert)) - else: - pass - except: - self._shutdown(False) - raise - else: - raise TLSFaultError("No error!") - - - def _getKeyFromChain(self, certificate, settings): - #Get and check cert chain from the Certificate message - certChain = certificate.certChain - if not certChain or certChain.getNumCerts() == 0: - for result in self._sendError(AlertDescription.illegal_parameter, - "Other party sent a Certificate message without "\ - "certificates"): - yield result - - #Get and check public key from the cert chain - publicKey = certChain.getEndEntityPublicKey() - if len(publicKey) < settings.minKeySize: - for result in self._sendError(AlertDescription.handshake_failure, - "Other party's public key too small: %d" % len(publicKey)): - yield result - if len(publicKey) > settings.maxKeySize: - for result in self._sendError(AlertDescription.handshake_failure, - "Other party's public key too large: %d" % len(publicKey)): - yield result - - yield publicKey, certChain diff --git a/src/lib/tlslite/TLSRecordLayer.py b/src/lib/tlslite/TLSRecordLayer.py deleted file mode 100755 index 002a56862..000000000 --- a/src/lib/tlslite/TLSRecordLayer.py +++ /dev/null @@ -1,1131 +0,0 @@ -"""Helper class for TLSConnection.""" -from __future__ import generators - -from utils.compat import * -from utils.cryptomath import * -from utils.cipherfactory import createAES, createRC4, createTripleDES -from utils.codec import * -from errors import * -from messages import * -from mathtls import * -from constants import * -from utils.cryptomath import getRandomBytes -from utils import hmac -from FileObject import FileObject -import sha -import md5 -import socket -import errno -import traceback - -try: - GeneratorExit -except NameError: - class GeneratorExit(Exception): - pass - -class _ConnectionState: - def __init__(self): - self.macContext = None - self.encContext = None - self.seqnum = 0 - - def getSeqNumStr(self): - w = Writer(8) - w.add(self.seqnum, 8) - seqnumStr = bytesToString(w.bytes) - self.seqnum += 1 - return seqnumStr - - -class TLSRecordLayer: - """ - This class handles data transmission for a TLS connection. - - Its only subclass is L{tlslite.TLSConnection.TLSConnection}. We've - separated the code in this class from TLSConnection to make things - more readable. - - - @type sock: socket.socket - @ivar sock: The underlying socket object. - - @type session: L{tlslite.Session.Session} - @ivar session: The session corresponding to this connection. - - Due to TLS session resumption, multiple connections can correspond - to the same underlying session. - - @type version: tuple - @ivar version: The TLS version being used for this connection. - - (3,0) means SSL 3.0, and (3,1) means TLS 1.0. - - @type closed: bool - @ivar closed: If this connection is closed. - - @type resumed: bool - @ivar resumed: If this connection is based on a resumed session. - - @type allegedSharedKeyUsername: str or None - @ivar allegedSharedKeyUsername: This is set to the shared-key - username asserted by the client, whether the handshake succeeded or - not. If the handshake fails, this can be inspected to - determine if a guessing attack is in progress against a particular - user account. - - @type allegedSrpUsername: str or None - @ivar allegedSrpUsername: This is set to the SRP username - asserted by the client, whether the handshake succeeded or not. - If the handshake fails, this can be inspected to determine - if a guessing attack is in progress against a particular user - account. - - @type closeSocket: bool - @ivar closeSocket: If the socket should be closed when the - connection is closed (writable). - - If you set this to True, TLS Lite will assume the responsibility of - closing the socket when the TLS Connection is shutdown (either - through an error or through the user calling close()). The default - is False. - - @type ignoreAbruptClose: bool - @ivar ignoreAbruptClose: If an abrupt close of the socket should - raise an error (writable). - - If you set this to True, TLS Lite will not raise a - L{tlslite.errors.TLSAbruptCloseError} exception if the underlying - socket is unexpectedly closed. Such an unexpected closure could be - caused by an attacker. However, it also occurs with some incorrect - TLS implementations. - - You should set this to True only if you're not worried about an - attacker truncating the connection, and only if necessary to avoid - spurious errors. The default is False. - - @sort: __init__, read, readAsync, write, writeAsync, close, closeAsync, - getCipherImplementation, getCipherName - """ - - def __init__(self, sock): - self.sock = sock - - #My session object (Session instance; read-only) - self.session = None - - #Am I a client or server? - self._client = None - - #Buffers for processing messages - self._handshakeBuffer = [] - self._readBuffer = "" - - #Handshake digests - self._handshake_md5 = md5.md5() - self._handshake_sha = sha.sha() - - #TLS Protocol Version - self.version = (0,0) #read-only - self._versionCheck = False #Once we choose a version, this is True - - #Current and Pending connection states - self._writeState = _ConnectionState() - self._readState = _ConnectionState() - self._pendingWriteState = _ConnectionState() - self._pendingReadState = _ConnectionState() - - #Is the connection open? - self.closed = True #read-only - self._refCount = 0 #Used to trigger closure - - #Is this a resumed (or shared-key) session? - self.resumed = False #read-only - - #What username did the client claim in his handshake? - self.allegedSharedKeyUsername = None - self.allegedSrpUsername = None - - #On a call to close(), do we close the socket? (writeable) - self.closeSocket = False - - #If the socket is abruptly closed, do we ignore it - #and pretend the connection was shut down properly? (writeable) - self.ignoreAbruptClose = False - - #Fault we will induce, for testing purposes - self.fault = None - - #********************************************************* - # Public Functions START - #********************************************************* - - def read(self, max=None, min=1): - """Read some data from the TLS connection. - - This function will block until at least 'min' bytes are - available (or the connection is closed). - - If an exception is raised, the connection will have been - automatically closed. - - @type max: int - @param max: The maximum number of bytes to return. - - @type min: int - @param min: The minimum number of bytes to return - - @rtype: str - @return: A string of no more than 'max' bytes, and no fewer - than 'min' (unless the connection has been closed, in which - case fewer than 'min' bytes may be returned). - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - """ - for result in self.readAsync(max, min): - pass - return result - - def readAsync(self, max=None, min=1): - """Start a read operation on the TLS connection. - - This function returns a generator which behaves similarly to - read(). Successive invocations of the generator will return 0 - if it is waiting to read from the socket, 1 if it is waiting - to write to the socket, or a string if the read operation has - completed. - - @rtype: iterable - @return: A generator; see above for details. - """ - try: - while len(self._readBuffer)= len(s): - break - if endIndex > len(s): - endIndex = len(s) - block = stringToBytes(s[startIndex : endIndex]) - applicationData = ApplicationData().create(block) - for result in self._sendMsg(applicationData, skipEmptyFrag): - yield result - skipEmptyFrag = True #only send an empy fragment on 1st message - index += 1 - except: - self._shutdown(False) - raise - - def close(self): - """Close the TLS connection. - - This function will block until it has exchanged close_notify - alerts with the other party. After doing so, it will shut down the - TLS connection. Further attempts to read through this connection - will return "". Further attempts to write through this connection - will raise ValueError. - - If makefile() has been called on this connection, the connection - will be not be closed until the connection object and all file - objects have been closed. - - Even if an exception is raised, the connection will have been - closed. - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - """ - if not self.closed: - for result in self._decrefAsync(): - pass - - def closeAsync(self): - """Start a close operation on the TLS connection. - - This function returns a generator which behaves similarly to - close(). Successive invocations of the generator will return 0 - if it is waiting to read from the socket, 1 if it is waiting - to write to the socket, or will raise StopIteration if the - close operation has completed. - - @rtype: iterable - @return: A generator; see above for details. - """ - if not self.closed: - for result in self._decrefAsync(): - yield result - - def _decrefAsync(self): - self._refCount -= 1 - if self._refCount == 0 and not self.closed: - try: - for result in self._sendMsg(Alert().create(\ - AlertDescription.close_notify, AlertLevel.warning)): - yield result - alert = None - while not alert: - for result in self._getMsg((ContentType.alert, \ - ContentType.application_data)): - if result in (0,1): - yield result - if result.contentType == ContentType.alert: - alert = result - if alert.description == AlertDescription.close_notify: - self._shutdown(True) - else: - raise TLSRemoteAlert(alert) - except (socket.error, TLSAbruptCloseError): - #If the other side closes the socket, that's okay - self._shutdown(True) - except: - self._shutdown(False) - raise - - def getCipherName(self): - """Get the name of the cipher used with this connection. - - @rtype: str - @return: The name of the cipher used with this connection. - Either 'aes128', 'aes256', 'rc4', or '3des'. - """ - if not self._writeState.encContext: - return None - return self._writeState.encContext.name - - def getCipherImplementation(self): - """Get the name of the cipher implementation used with - this connection. - - @rtype: str - @return: The name of the cipher implementation used with - this connection. Either 'python', 'cryptlib', 'openssl', - or 'pycrypto'. - """ - if not self._writeState.encContext: - return None - return self._writeState.encContext.implementation - - - - #Emulate a socket, somewhat - - def send(self, s): - """Send data to the TLS connection (socket emulation). - - @raise socket.error: If a socket error occurs. - """ - self.write(s) - return len(s) - - def sendall(self, s): - """Send data to the TLS connection (socket emulation). - - @raise socket.error: If a socket error occurs. - """ - self.write(s) - - def recv(self, bufsize): - """Get some data from the TLS connection (socket emulation). - - @raise socket.error: If a socket error occurs. - @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed - without a preceding alert. - @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. - """ - return self.read(bufsize) - - def makefile(self, mode='r', bufsize=-1): - """Create a file object for the TLS connection (socket emulation). - - @rtype: L{tlslite.FileObject.FileObject} - """ - self._refCount += 1 - return FileObject(self, mode, bufsize) - - def getsockname(self): - """Return the socket's own address (socket emulation).""" - return self.sock.getsockname() - - def getpeername(self): - """Return the remote address to which the socket is connected - (socket emulation).""" - return self.sock.getpeername() - - def settimeout(self, value): - """Set a timeout on blocking socket operations (socket emulation).""" - return self.sock.settimeout(value) - - def gettimeout(self): - """Return the timeout associated with socket operations (socket - emulation).""" - return self.sock.gettimeout() - - def setsockopt(self, level, optname, value): - """Set the value of the given socket option (socket emulation).""" - return self.sock.setsockopt(level, optname, value) - - - #********************************************************* - # Public Functions END - #********************************************************* - - def _shutdown(self, resumable): - self._writeState = _ConnectionState() - self._readState = _ConnectionState() - #Don't do this: self._readBuffer = "" - self.version = (0,0) - self._versionCheck = False - self.closed = True - if self.closeSocket: - self.sock.close() - - #Even if resumable is False, we'll never toggle this on - if not resumable and self.session: - self.session.resumable = False - - - def _sendError(self, alertDescription, errorStr=None): - alert = Alert().create(alertDescription, AlertLevel.fatal) - for result in self._sendMsg(alert): - yield result - self._shutdown(False) - raise TLSLocalAlert(alert, errorStr) - - def _sendMsgs(self, msgs): - skipEmptyFrag = False - for msg in msgs: - for result in self._sendMsg(msg, skipEmptyFrag): - yield result - skipEmptyFrag = True - - def _sendMsg(self, msg, skipEmptyFrag=False): - bytes = msg.write() - contentType = msg.contentType - - #Whenever we're connected and asked to send a message, - #we first send an empty Application Data message. This prevents - #an attacker from launching a chosen-plaintext attack based on - #knowing the next IV. - if not self.closed and not skipEmptyFrag and self.version == (3,1): - if self._writeState.encContext: - if self._writeState.encContext.isBlockCipher: - for result in self._sendMsg(ApplicationData(), - skipEmptyFrag=True): - yield result - - #Update handshake hashes - if contentType == ContentType.handshake: - bytesStr = bytesToString(bytes) - self._handshake_md5.update(bytesStr) - self._handshake_sha.update(bytesStr) - - #Calculate MAC - if self._writeState.macContext: - seqnumStr = self._writeState.getSeqNumStr() - bytesStr = bytesToString(bytes) - mac = self._writeState.macContext.copy() - mac.update(seqnumStr) - mac.update(chr(contentType)) - if self.version == (3,0): - mac.update( chr( int(len(bytes)/256) ) ) - mac.update( chr( int(len(bytes)%256) ) ) - elif self.version in ((3,1), (3,2)): - mac.update(chr(self.version[0])) - mac.update(chr(self.version[1])) - mac.update( chr( int(len(bytes)/256) ) ) - mac.update( chr( int(len(bytes)%256) ) ) - else: - raise AssertionError() - mac.update(bytesStr) - macString = mac.digest() - macBytes = stringToBytes(macString) - if self.fault == Fault.badMAC: - macBytes[0] = (macBytes[0]+1) % 256 - - #Encrypt for Block or Stream Cipher - if self._writeState.encContext: - #Add padding and encrypt (for Block Cipher): - if self._writeState.encContext.isBlockCipher: - - #Add TLS 1.1 fixed block - if self.version == (3,2): - bytes = self.fixedIVBlock + bytes - - #Add padding: bytes = bytes + (macBytes + paddingBytes) - currentLength = len(bytes) + len(macBytes) + 1 - blockLength = self._writeState.encContext.block_size - paddingLength = blockLength-(currentLength % blockLength) - - paddingBytes = createByteArraySequence([paddingLength] * \ - (paddingLength+1)) - if self.fault == Fault.badPadding: - paddingBytes[0] = (paddingBytes[0]+1) % 256 - endBytes = concatArrays(macBytes, paddingBytes) - bytes = concatArrays(bytes, endBytes) - #Encrypt - plaintext = stringToBytes(bytes) - ciphertext = self._writeState.encContext.encrypt(plaintext) - bytes = stringToBytes(ciphertext) - - #Encrypt (for Stream Cipher) - else: - bytes = concatArrays(bytes, macBytes) - plaintext = bytesToString(bytes) - ciphertext = self._writeState.encContext.encrypt(plaintext) - bytes = stringToBytes(ciphertext) - - #Add record header and send - r = RecordHeader3().create(self.version, contentType, len(bytes)) - s = bytesToString(concatArrays(r.write(), bytes)) - while 1: - try: - bytesSent = self.sock.send(s) #Might raise socket.error - except socket.error, why: - if why[0] == errno.EWOULDBLOCK: - yield 1 - continue - else: - raise - if bytesSent == len(s): - return - s = s[bytesSent:] - yield 1 - - - def _getMsg(self, expectedType, secondaryType=None, constructorType=None): - try: - if not isinstance(expectedType, tuple): - expectedType = (expectedType,) - - #Spin in a loop, until we've got a non-empty record of a type we - #expect. The loop will be repeated if: - # - we receive a renegotiation attempt; we send no_renegotiation, - # then try again - # - we receive an empty application-data fragment; we try again - while 1: - for result in self._getNextRecord(): - if result in (0,1): - yield result - recordHeader, p = result - - #If this is an empty application-data fragment, try again - if recordHeader.type == ContentType.application_data: - if p.index == len(p.bytes): - continue - - #If we received an unexpected record type... - if recordHeader.type not in expectedType: - - #If we received an alert... - if recordHeader.type == ContentType.alert: - alert = Alert().parse(p) - - #We either received a fatal error, a warning, or a - #close_notify. In any case, we're going to close the - #connection. In the latter two cases we respond with - #a close_notify, but ignore any socket errors, since - #the other side might have already closed the socket. - if alert.level == AlertLevel.warning or \ - alert.description == AlertDescription.close_notify: - - #If the sendMsg() call fails because the socket has - #already been closed, we will be forgiving and not - #report the error nor invalidate the "resumability" - #of the session. - try: - alertMsg = Alert() - alertMsg.create(AlertDescription.close_notify, - AlertLevel.warning) - for result in self._sendMsg(alertMsg): - yield result - except socket.error: - pass - - if alert.description == \ - AlertDescription.close_notify: - self._shutdown(True) - elif alert.level == AlertLevel.warning: - self._shutdown(False) - - else: #Fatal alert: - self._shutdown(False) - - #Raise the alert as an exception - raise TLSRemoteAlert(alert) - - #If we received a renegotiation attempt... - if recordHeader.type == ContentType.handshake: - subType = p.get(1) - reneg = False - if self._client: - if subType == HandshakeType.hello_request: - reneg = True - else: - if subType == HandshakeType.client_hello: - reneg = True - #Send no_renegotiation, then try again - if reneg: - alertMsg = Alert() - alertMsg.create(AlertDescription.no_renegotiation, - AlertLevel.warning) - for result in self._sendMsg(alertMsg): - yield result - continue - - #Otherwise: this is an unexpected record, but neither an - #alert nor renegotiation - for result in self._sendError(\ - AlertDescription.unexpected_message, - "received type=%d" % recordHeader.type): - yield result - - break - - #Parse based on content_type - if recordHeader.type == ContentType.change_cipher_spec: - yield ChangeCipherSpec().parse(p) - elif recordHeader.type == ContentType.alert: - yield Alert().parse(p) - elif recordHeader.type == ContentType.application_data: - yield ApplicationData().parse(p) - elif recordHeader.type == ContentType.handshake: - #Convert secondaryType to tuple, if it isn't already - if not isinstance(secondaryType, tuple): - secondaryType = (secondaryType,) - - #If it's a handshake message, check handshake header - if recordHeader.ssl2: - subType = p.get(1) - if subType != HandshakeType.client_hello: - for result in self._sendError(\ - AlertDescription.unexpected_message, - "Can only handle SSLv2 ClientHello messages"): - yield result - if HandshakeType.client_hello not in secondaryType: - for result in self._sendError(\ - AlertDescription.unexpected_message): - yield result - subType = HandshakeType.client_hello - else: - subType = p.get(1) - if subType not in secondaryType: - for result in self._sendError(\ - AlertDescription.unexpected_message, - "Expecting %s, got %s" % (str(secondaryType), subType)): - yield result - - #Update handshake hashes - sToHash = bytesToString(p.bytes) - self._handshake_md5.update(sToHash) - self._handshake_sha.update(sToHash) - - #Parse based on handshake type - if subType == HandshakeType.client_hello: - yield ClientHello(recordHeader.ssl2).parse(p) - elif subType == HandshakeType.server_hello: - yield ServerHello().parse(p) - elif subType == HandshakeType.certificate: - yield Certificate(constructorType).parse(p) - elif subType == HandshakeType.certificate_request: - yield CertificateRequest().parse(p) - elif subType == HandshakeType.certificate_verify: - yield CertificateVerify().parse(p) - elif subType == HandshakeType.server_key_exchange: - yield ServerKeyExchange(constructorType).parse(p) - elif subType == HandshakeType.server_hello_done: - yield ServerHelloDone().parse(p) - elif subType == HandshakeType.client_key_exchange: - yield ClientKeyExchange(constructorType, \ - self.version).parse(p) - elif subType == HandshakeType.finished: - yield Finished(self.version).parse(p) - else: - raise AssertionError() - - #If an exception was raised by a Parser or Message instance: - except SyntaxError, e: - for result in self._sendError(AlertDescription.decode_error, - formatExceptionTrace(e)): - yield result - - - #Returns next record or next handshake message - def _getNextRecord(self): - - #If there's a handshake message waiting, return it - if self._handshakeBuffer: - recordHeader, bytes = self._handshakeBuffer[0] - self._handshakeBuffer = self._handshakeBuffer[1:] - yield (recordHeader, Parser(bytes)) - return - - #Otherwise... - #Read the next record header - bytes = createByteArraySequence([]) - recordHeaderLength = 1 - ssl2 = False - while 1: - try: - s = self.sock.recv(recordHeaderLength-len(bytes)) - except socket.error, why: - if why[0] == errno.EWOULDBLOCK: - yield 0 - continue - else: - raise - - #If the connection was abruptly closed, raise an error - if len(s)==0: - raise TLSAbruptCloseError() - - bytes += stringToBytes(s) - if len(bytes)==1: - if bytes[0] in ContentType.all: - ssl2 = False - recordHeaderLength = 5 - elif bytes[0] == 128: - ssl2 = True - recordHeaderLength = 2 - else: - raise SyntaxError() - if len(bytes) == recordHeaderLength: - break - - #Parse the record header - if ssl2: - r = RecordHeader2().parse(Parser(bytes)) - else: - r = RecordHeader3().parse(Parser(bytes)) - - #Check the record header fields - if r.length > 18432: - for result in self._sendError(AlertDescription.record_overflow): - yield result - - #Read the record contents - bytes = createByteArraySequence([]) - while 1: - try: - s = self.sock.recv(r.length - len(bytes)) - except socket.error, why: - if why[0] == errno.EWOULDBLOCK: - yield 0 - continue - else: - raise - - #If the connection is closed, raise a socket error - if len(s)==0: - raise TLSAbruptCloseError() - - bytes += stringToBytes(s) - if len(bytes) == r.length: - break - - #Check the record header fields (2) - #We do this after reading the contents from the socket, so that - #if there's an error, we at least don't leave extra bytes in the - #socket.. - # - # THIS CHECK HAS NO SECURITY RELEVANCE (?), BUT COULD HURT INTEROP. - # SO WE LEAVE IT OUT FOR NOW. - # - #if self._versionCheck and r.version != self.version: - # for result in self._sendError(AlertDescription.protocol_version, - # "Version in header field: %s, should be %s" % (str(r.version), - # str(self.version))): - # yield result - - #Decrypt the record - for result in self._decryptRecord(r.type, bytes): - if result in (0,1): - yield result - else: - break - bytes = result - p = Parser(bytes) - - #If it doesn't contain handshake messages, we can just return it - if r.type != ContentType.handshake: - yield (r, p) - #If it's an SSLv2 ClientHello, we can return it as well - elif r.ssl2: - yield (r, p) - else: - #Otherwise, we loop through and add the handshake messages to the - #handshake buffer - while 1: - if p.index == len(bytes): #If we're at the end - if not self._handshakeBuffer: - for result in self._sendError(\ - AlertDescription.decode_error, \ - "Received empty handshake record"): - yield result - break - #There needs to be at least 4 bytes to get a header - if p.index+4 > len(bytes): - for result in self._sendError(\ - AlertDescription.decode_error, - "A record has a partial handshake message (1)"): - yield result - p.get(1) # skip handshake type - msgLength = p.get(3) - if p.index+msgLength > len(bytes): - for result in self._sendError(\ - AlertDescription.decode_error, - "A record has a partial handshake message (2)"): - yield result - - handshakePair = (r, bytes[p.index-4 : p.index+msgLength]) - self._handshakeBuffer.append(handshakePair) - p.index += msgLength - - #We've moved at least one handshake message into the - #handshakeBuffer, return the first one - recordHeader, bytes = self._handshakeBuffer[0] - self._handshakeBuffer = self._handshakeBuffer[1:] - yield (recordHeader, Parser(bytes)) - - - def _decryptRecord(self, recordType, bytes): - if self._readState.encContext: - - #Decrypt if it's a block cipher - if self._readState.encContext.isBlockCipher: - blockLength = self._readState.encContext.block_size - if len(bytes) % blockLength != 0: - for result in self._sendError(\ - AlertDescription.decryption_failed, - "Encrypted data not a multiple of blocksize"): - yield result - ciphertext = bytesToString(bytes) - plaintext = self._readState.encContext.decrypt(ciphertext) - if self.version == (3,2): #For TLS 1.1, remove explicit IV - plaintext = plaintext[self._readState.encContext.block_size : ] - bytes = stringToBytes(plaintext) - - #Check padding - paddingGood = True - paddingLength = bytes[-1] - if (paddingLength+1) > len(bytes): - paddingGood=False - totalPaddingLength = 0 - else: - if self.version == (3,0): - totalPaddingLength = paddingLength+1 - elif self.version in ((3,1), (3,2)): - totalPaddingLength = paddingLength+1 - paddingBytes = bytes[-totalPaddingLength:-1] - for byte in paddingBytes: - if byte != paddingLength: - paddingGood = False - totalPaddingLength = 0 - else: - raise AssertionError() - - #Decrypt if it's a stream cipher - else: - paddingGood = True - ciphertext = bytesToString(bytes) - plaintext = self._readState.encContext.decrypt(ciphertext) - bytes = stringToBytes(plaintext) - totalPaddingLength = 0 - - #Check MAC - macGood = True - macLength = self._readState.macContext.digest_size - endLength = macLength + totalPaddingLength - if endLength > len(bytes): - macGood = False - else: - #Read MAC - startIndex = len(bytes) - endLength - endIndex = startIndex + macLength - checkBytes = bytes[startIndex : endIndex] - - #Calculate MAC - seqnumStr = self._readState.getSeqNumStr() - bytes = bytes[:-endLength] - bytesStr = bytesToString(bytes) - mac = self._readState.macContext.copy() - mac.update(seqnumStr) - mac.update(chr(recordType)) - if self.version == (3,0): - mac.update( chr( int(len(bytes)/256) ) ) - mac.update( chr( int(len(bytes)%256) ) ) - elif self.version in ((3,1), (3,2)): - mac.update(chr(self.version[0])) - mac.update(chr(self.version[1])) - mac.update( chr( int(len(bytes)/256) ) ) - mac.update( chr( int(len(bytes)%256) ) ) - else: - raise AssertionError() - mac.update(bytesStr) - macString = mac.digest() - macBytes = stringToBytes(macString) - - #Compare MACs - if macBytes != checkBytes: - macGood = False - - if not (paddingGood and macGood): - for result in self._sendError(AlertDescription.bad_record_mac, - "MAC failure (or padding failure)"): - yield result - - yield bytes - - def _handshakeStart(self, client): - self._client = client - self._handshake_md5 = md5.md5() - self._handshake_sha = sha.sha() - self._handshakeBuffer = [] - self.allegedSharedKeyUsername = None - self.allegedSrpUsername = None - self._refCount = 1 - - def _handshakeDone(self, resumed): - self.resumed = resumed - self.closed = False - - def _calcPendingStates(self, clientRandom, serverRandom, implementations): - if self.session.cipherSuite in CipherSuite.aes128Suites: - macLength = 20 - keyLength = 16 - ivLength = 16 - createCipherFunc = createAES - elif self.session.cipherSuite in CipherSuite.aes256Suites: - macLength = 20 - keyLength = 32 - ivLength = 16 - createCipherFunc = createAES - elif self.session.cipherSuite in CipherSuite.rc4Suites: - macLength = 20 - keyLength = 16 - ivLength = 0 - createCipherFunc = createRC4 - elif self.session.cipherSuite in CipherSuite.tripleDESSuites: - macLength = 20 - keyLength = 24 - ivLength = 8 - createCipherFunc = createTripleDES - else: - raise AssertionError() - - if self.version == (3,0): - createMACFunc = MAC_SSL - elif self.version in ((3,1), (3,2)): - createMACFunc = hmac.HMAC - - outputLength = (macLength*2) + (keyLength*2) + (ivLength*2) - - #Calculate Keying Material from Master Secret - if self.version == (3,0): - keyBlock = PRF_SSL(self.session.masterSecret, - concatArrays(serverRandom, clientRandom), - outputLength) - elif self.version in ((3,1), (3,2)): - keyBlock = PRF(self.session.masterSecret, - "key expansion", - concatArrays(serverRandom,clientRandom), - outputLength) - else: - raise AssertionError() - - #Slice up Keying Material - clientPendingState = _ConnectionState() - serverPendingState = _ConnectionState() - p = Parser(keyBlock) - clientMACBlock = bytesToString(p.getFixBytes(macLength)) - serverMACBlock = bytesToString(p.getFixBytes(macLength)) - clientKeyBlock = bytesToString(p.getFixBytes(keyLength)) - serverKeyBlock = bytesToString(p.getFixBytes(keyLength)) - clientIVBlock = bytesToString(p.getFixBytes(ivLength)) - serverIVBlock = bytesToString(p.getFixBytes(ivLength)) - clientPendingState.macContext = createMACFunc(clientMACBlock, - digestmod=sha) - serverPendingState.macContext = createMACFunc(serverMACBlock, - digestmod=sha) - clientPendingState.encContext = createCipherFunc(clientKeyBlock, - clientIVBlock, - implementations) - serverPendingState.encContext = createCipherFunc(serverKeyBlock, - serverIVBlock, - implementations) - - #Assign new connection states to pending states - if self._client: - self._pendingWriteState = clientPendingState - self._pendingReadState = serverPendingState - else: - self._pendingWriteState = serverPendingState - self._pendingReadState = clientPendingState - - if self.version == (3,2) and ivLength: - #Choose fixedIVBlock for TLS 1.1 (this is encrypted with the CBC - #residue to create the IV for each sent block) - self.fixedIVBlock = getRandomBytes(ivLength) - - def _changeWriteState(self): - self._writeState = self._pendingWriteState - self._pendingWriteState = _ConnectionState() - - def _changeReadState(self): - self._readState = self._pendingReadState - self._pendingReadState = _ConnectionState() - - def _sendFinished(self): - #Send ChangeCipherSpec - for result in self._sendMsg(ChangeCipherSpec()): - yield result - - #Switch to pending write state - self._changeWriteState() - - #Calculate verification data - verifyData = self._calcFinished(True) - if self.fault == Fault.badFinished: - verifyData[0] = (verifyData[0]+1)%256 - - #Send Finished message under new state - finished = Finished(self.version).create(verifyData) - for result in self._sendMsg(finished): - yield result - - def _getFinished(self): - #Get and check ChangeCipherSpec - for result in self._getMsg(ContentType.change_cipher_spec): - if result in (0,1): - yield result - changeCipherSpec = result - - if changeCipherSpec.type != 1: - for result in self._sendError(AlertDescription.illegal_parameter, - "ChangeCipherSpec type incorrect"): - yield result - - #Switch to pending read state - self._changeReadState() - - #Calculate verification data - verifyData = self._calcFinished(False) - - #Get and check Finished message under new state - for result in self._getMsg(ContentType.handshake, - HandshakeType.finished): - if result in (0,1): - yield result - finished = result - if finished.verify_data != verifyData: - for result in self._sendError(AlertDescription.decrypt_error, - "Finished message is incorrect"): - yield result - - def _calcFinished(self, send=True): - if self.version == (3,0): - if (self._client and send) or (not self._client and not send): - senderStr = "\x43\x4C\x4E\x54" - else: - senderStr = "\x53\x52\x56\x52" - - verifyData = self._calcSSLHandshakeHash(self.session.masterSecret, - senderStr) - return verifyData - - elif self.version in ((3,1), (3,2)): - if (self._client and send) or (not self._client and not send): - label = "client finished" - else: - label = "server finished" - - handshakeHashes = stringToBytes(self._handshake_md5.digest() + \ - self._handshake_sha.digest()) - verifyData = PRF(self.session.masterSecret, label, handshakeHashes, - 12) - return verifyData - else: - raise AssertionError() - - #Used for Finished messages and CertificateVerify messages in SSL v3 - def _calcSSLHandshakeHash(self, masterSecret, label): - masterSecretStr = bytesToString(masterSecret) - - imac_md5 = self._handshake_md5.copy() - imac_sha = self._handshake_sha.copy() - - imac_md5.update(label + masterSecretStr + '\x36'*48) - imac_sha.update(label + masterSecretStr + '\x36'*40) - - md5Str = md5.md5(masterSecretStr + ('\x5c'*48) + \ - imac_md5.digest()).digest() - shaStr = sha.sha(masterSecretStr + ('\x5c'*40) + \ - imac_sha.digest()).digest() - - return stringToBytes(md5Str + shaStr) - diff --git a/src/lib/tlslite/VerifierDB.py b/src/lib/tlslite/VerifierDB.py deleted file mode 100755 index f706b1796..000000000 --- a/src/lib/tlslite/VerifierDB.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Class for storing SRP password verifiers.""" - -from utils.cryptomath import * -from utils.compat import * -import mathtls -from BaseDB import BaseDB - -class VerifierDB(BaseDB): - """This class represent an in-memory or on-disk database of SRP - password verifiers. - - A VerifierDB can be passed to a server handshake to authenticate - a client based on one of the verifiers. - - This class is thread-safe. - """ - def __init__(self, filename=None): - """Create a new VerifierDB instance. - - @type filename: str - @param filename: Filename for an on-disk database, or None for - an in-memory database. If the filename already exists, follow - this with a call to open(). To create a new on-disk database, - follow this with a call to create(). - """ - BaseDB.__init__(self, filename, "verifier") - - def _getItem(self, username, valueStr): - (N, g, salt, verifier) = valueStr.split(" ") - N = base64ToNumber(N) - g = base64ToNumber(g) - salt = base64ToString(salt) - verifier = base64ToNumber(verifier) - return (N, g, salt, verifier) - - def __setitem__(self, username, verifierEntry): - """Add a verifier entry to the database. - - @type username: str - @param username: The username to associate the verifier with. - Must be less than 256 characters in length. Must not already - be in the database. - - @type verifierEntry: tuple - @param verifierEntry: The verifier entry to add. Use - L{tlslite.VerifierDB.VerifierDB.makeVerifier} to create a - verifier entry. - """ - BaseDB.__setitem__(self, username, verifierEntry) - - - def _setItem(self, username, value): - if len(username)>=256: - raise ValueError("username too long") - N, g, salt, verifier = value - N = numberToBase64(N) - g = numberToBase64(g) - salt = stringToBase64(salt) - verifier = numberToBase64(verifier) - valueStr = " ".join( (N, g, salt, verifier) ) - return valueStr - - def _checkItem(self, value, username, param): - (N, g, salt, verifier) = value - x = mathtls.makeX(salt, username, param) - v = powMod(g, x, N) - return (verifier == v) - - - def makeVerifier(username, password, bits): - """Create a verifier entry which can be stored in a VerifierDB. - - @type username: str - @param username: The username for this verifier. Must be less - than 256 characters in length. - - @type password: str - @param password: The password for this verifier. - - @type bits: int - @param bits: This values specifies which SRP group parameters - to use. It must be one of (1024, 1536, 2048, 3072, 4096, 6144, - 8192). Larger values are more secure but slower. 2048 is a - good compromise between safety and speed. - - @rtype: tuple - @return: A tuple which may be stored in a VerifierDB. - """ - return mathtls.makeVerifier(username, password, bits) - makeVerifier = staticmethod(makeVerifier) \ No newline at end of file diff --git a/src/lib/tlslite/X509.py b/src/lib/tlslite/X509.py deleted file mode 100755 index a47ddcfa2..000000000 --- a/src/lib/tlslite/X509.py +++ /dev/null @@ -1,133 +0,0 @@ -"""Class representing an X.509 certificate.""" - -from utils.ASN1Parser import ASN1Parser -from utils.cryptomath import * -from utils.keyfactory import _createPublicRSAKey - - -class X509: - """This class represents an X.509 certificate. - - @type bytes: L{array.array} of unsigned bytes - @ivar bytes: The DER-encoded ASN.1 certificate - - @type publicKey: L{tlslite.utils.RSAKey.RSAKey} - @ivar publicKey: The subject public key from the certificate. - """ - - def __init__(self): - self.bytes = createByteArraySequence([]) - self.publicKey = None - - def parse(self, s): - """Parse a PEM-encoded X.509 certificate. - - @type s: str - @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded - certificate wrapped with "-----BEGIN CERTIFICATE-----" and - "-----END CERTIFICATE-----" tags). - """ - - start = s.find("-----BEGIN CERTIFICATE-----") - end = s.find("-----END CERTIFICATE-----") - if start == -1: - raise SyntaxError("Missing PEM prefix") - if end == -1: - raise SyntaxError("Missing PEM postfix") - s = s[start+len("-----BEGIN CERTIFICATE-----") : end] - - bytes = base64ToBytes(s) - self.parseBinary(bytes) - return self - - def parseBinary(self, bytes): - """Parse a DER-encoded X.509 certificate. - - @type bytes: str or L{array.array} of unsigned bytes - @param bytes: A DER-encoded X.509 certificate. - """ - - if isinstance(bytes, type("")): - bytes = stringToBytes(bytes) - - self.bytes = bytes - p = ASN1Parser(bytes) - - #Get the tbsCertificate - tbsCertificateP = p.getChild(0) - - #Is the optional version field present? - #This determines which index the key is at. - if tbsCertificateP.value[0]==0xA0: - subjectPublicKeyInfoIndex = 6 - else: - subjectPublicKeyInfoIndex = 5 - - #Get the subjectPublicKeyInfo - subjectPublicKeyInfoP = tbsCertificateP.getChild(\ - subjectPublicKeyInfoIndex) - - #Get the algorithm - algorithmP = subjectPublicKeyInfoP.getChild(0) - rsaOID = algorithmP.value - if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]: - raise SyntaxError("Unrecognized AlgorithmIdentifier") - - #Get the subjectPublicKey - subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1) - - #Adjust for BIT STRING encapsulation - if (subjectPublicKeyP.value[0] !=0): - raise SyntaxError() - subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:]) - - #Get the modulus and exponent - modulusP = subjectPublicKeyP.getChild(0) - publicExponentP = subjectPublicKeyP.getChild(1) - - #Decode them into numbers - n = bytesToNumber(modulusP.value) - e = bytesToNumber(publicExponentP.value) - - #Create a public key instance - self.publicKey = _createPublicRSAKey(n, e) - - def getFingerprint(self): - """Get the hex-encoded fingerprint of this certificate. - - @rtype: str - @return: A hex-encoded fingerprint. - """ - return sha.sha(self.bytes).hexdigest() - - def getCommonName(self): - """Get the Subject's Common Name from the certificate. - - The cryptlib_py module must be installed in order to use this - function. - - @rtype: str or None - @return: The CN component of the certificate's subject DN, if - present. - """ - import cryptlib_py - import array - c = cryptlib_py.cryptImportCert(self.bytes, cryptlib_py.CRYPT_UNUSED) - name = cryptlib_py.CRYPT_CERTINFO_COMMONNAME - try: - try: - length = cryptlib_py.cryptGetAttributeString(c, name, None) - returnVal = array.array('B', [0] * length) - cryptlib_py.cryptGetAttributeString(c, name, returnVal) - returnVal = returnVal.tostring() - except cryptlib_py.CryptException, e: - if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND: - returnVal = None - return returnVal - finally: - cryptlib_py.cryptDestroyCert(c) - - def writeBytes(self): - return self.bytes - - diff --git a/src/lib/tlslite/X509CertChain.py b/src/lib/tlslite/X509CertChain.py deleted file mode 100755 index d5f0b4d42..000000000 --- a/src/lib/tlslite/X509CertChain.py +++ /dev/null @@ -1,181 +0,0 @@ -"""Class representing an X.509 certificate chain.""" - -from utils import cryptomath - -class X509CertChain: - """This class represents a chain of X.509 certificates. - - @type x509List: list - @ivar x509List: A list of L{tlslite.X509.X509} instances, - starting with the end-entity certificate and with every - subsequent certificate certifying the previous. - """ - - def __init__(self, x509List=None): - """Create a new X509CertChain. - - @type x509List: list - @param x509List: A list of L{tlslite.X509.X509} instances, - starting with the end-entity certificate and with every - subsequent certificate certifying the previous. - """ - if x509List: - self.x509List = x509List - else: - self.x509List = [] - - def getNumCerts(self): - """Get the number of certificates in this chain. - - @rtype: int - """ - return len(self.x509List) - - def getEndEntityPublicKey(self): - """Get the public key from the end-entity certificate. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - """ - if self.getNumCerts() == 0: - raise AssertionError() - return self.x509List[0].publicKey - - def getFingerprint(self): - """Get the hex-encoded fingerprint of the end-entity certificate. - - @rtype: str - @return: A hex-encoded fingerprint. - """ - if self.getNumCerts() == 0: - raise AssertionError() - return self.x509List[0].getFingerprint() - - def getCommonName(self): - """Get the Subject's Common Name from the end-entity certificate. - - The cryptlib_py module must be installed in order to use this - function. - - @rtype: str or None - @return: The CN component of the certificate's subject DN, if - present. - """ - if self.getNumCerts() == 0: - raise AssertionError() - return self.x509List[0].getCommonName() - - def validate(self, x509TrustList): - """Check the validity of the certificate chain. - - This checks that every certificate in the chain validates with - the subsequent one, until some certificate validates with (or - is identical to) one of the passed-in root certificates. - - The cryptlib_py module must be installed in order to use this - function. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - certificate chain must extend to one of these certificates to - be considered valid. - """ - - import cryptlib_py - c1 = None - c2 = None - lastC = None - rootC = None - - try: - rootFingerprints = [c.getFingerprint() for c in x509TrustList] - - #Check that every certificate in the chain validates with the - #next one - for cert1, cert2 in zip(self.x509List, self.x509List[1:]): - - #If we come upon a root certificate, we're done. - if cert1.getFingerprint() in rootFingerprints: - return True - - c1 = cryptlib_py.cryptImportCert(cert1.writeBytes(), - cryptlib_py.CRYPT_UNUSED) - c2 = cryptlib_py.cryptImportCert(cert2.writeBytes(), - cryptlib_py.CRYPT_UNUSED) - try: - cryptlib_py.cryptCheckCert(c1, c2) - except: - return False - cryptlib_py.cryptDestroyCert(c1) - c1 = None - cryptlib_py.cryptDestroyCert(c2) - c2 = None - - #If the last certificate is one of the root certificates, we're - #done. - if self.x509List[-1].getFingerprint() in rootFingerprints: - return True - - #Otherwise, find a root certificate that the last certificate - #chains to, and validate them. - lastC = cryptlib_py.cryptImportCert(self.x509List[-1].writeBytes(), - cryptlib_py.CRYPT_UNUSED) - for rootCert in x509TrustList: - rootC = cryptlib_py.cryptImportCert(rootCert.writeBytes(), - cryptlib_py.CRYPT_UNUSED) - if self._checkChaining(lastC, rootC): - try: - cryptlib_py.cryptCheckCert(lastC, rootC) - return True - except: - return False - return False - finally: - if not (c1 is None): - cryptlib_py.cryptDestroyCert(c1) - if not (c2 is None): - cryptlib_py.cryptDestroyCert(c2) - if not (lastC is None): - cryptlib_py.cryptDestroyCert(lastC) - if not (rootC is None): - cryptlib_py.cryptDestroyCert(rootC) - - - - def _checkChaining(self, lastC, rootC): - import cryptlib_py - import array - def compareNames(name): - try: - length = cryptlib_py.cryptGetAttributeString(lastC, name, None) - lastName = array.array('B', [0] * length) - cryptlib_py.cryptGetAttributeString(lastC, name, lastName) - lastName = lastName.tostring() - except cryptlib_py.CryptException, e: - if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND: - lastName = None - try: - length = cryptlib_py.cryptGetAttributeString(rootC, name, None) - rootName = array.array('B', [0] * length) - cryptlib_py.cryptGetAttributeString(rootC, name, rootName) - rootName = rootName.tostring() - except cryptlib_py.CryptException, e: - if e[0] == cryptlib_py.CRYPT_ERROR_NOTFOUND: - rootName = None - - return lastName == rootName - - cryptlib_py.cryptSetAttribute(lastC, - cryptlib_py.CRYPT_CERTINFO_ISSUERNAME, - cryptlib_py.CRYPT_UNUSED) - - if not compareNames(cryptlib_py.CRYPT_CERTINFO_COUNTRYNAME): - return False - if not compareNames(cryptlib_py.CRYPT_CERTINFO_LOCALITYNAME): - return False - if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONNAME): - return False - if not compareNames(cryptlib_py.CRYPT_CERTINFO_ORGANIZATIONALUNITNAME): - return False - if not compareNames(cryptlib_py.CRYPT_CERTINFO_COMMONNAME): - return False - return True \ No newline at end of file diff --git a/src/lib/tlslite/__init__.py b/src/lib/tlslite/__init__.py deleted file mode 100755 index 47cfd1c6f..000000000 --- a/src/lib/tlslite/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -TLS Lite is a free python library that implements SSL v3, TLS v1, and -TLS v1.1. TLS Lite supports non-traditional authentication methods -such as SRP, shared keys, and cryptoIDs, in addition to X.509 -certificates. TLS Lite is pure python, however it can access OpenSSL, -cryptlib, pycrypto, and GMPY for faster crypto operations. TLS Lite -integrates with httplib, xmlrpclib, poplib, imaplib, smtplib, -SocketServer, asyncore, and Twisted. - -To use, do:: - - from tlslite.api import * - -Then use the L{tlslite.TLSConnection.TLSConnection} class with a socket, -or use one of the integration classes in L{tlslite.integration}. - -@version: 0.3.8 -""" -__version__ = "0.3.8" - -__all__ = ["api", - "BaseDB", - "Checker", - "constants", - "errors", - "FileObject", - "HandshakeSettings", - "mathtls", - "messages", - "Session", - "SessionCache", - "SharedKeyDB", - "TLSConnection", - "TLSRecordLayer", - "VerifierDB", - "X509", - "X509CertChain", - "integration", - "utils"] diff --git a/src/lib/tlslite/api.py b/src/lib/tlslite/api.py deleted file mode 100755 index eebfbc609..000000000 --- a/src/lib/tlslite/api.py +++ /dev/null @@ -1,75 +0,0 @@ -"""Import this module for easy access to TLS Lite objects. - -The TLS Lite API consists of classes, functions, and variables spread -throughout this package. Instead of importing them individually with:: - - from tlslite.TLSConnection import TLSConnection - from tlslite.HandshakeSettings import HandshakeSettings - from tlslite.errors import * - . - . - -It's easier to do:: - - from tlslite.api import * - -This imports all the important objects (TLSConnection, Checker, -HandshakeSettings, etc.) into the global namespace. In particular, it -imports:: - - from constants import AlertLevel, AlertDescription, Fault - from errors import * - from Checker import Checker - from HandshakeSettings import HandshakeSettings - from Session import Session - from SessionCache import SessionCache - from SharedKeyDB import SharedKeyDB - from TLSConnection import TLSConnection - from VerifierDB import VerifierDB - from X509 import X509 - from X509CertChain import X509CertChain - - from integration.HTTPTLSConnection import HTTPTLSConnection - from integration.POP3_TLS import POP3_TLS - from integration.IMAP4_TLS import IMAP4_TLS - from integration.SMTP_TLS import SMTP_TLS - from integration.XMLRPCTransport import XMLRPCTransport - from integration.TLSSocketServerMixIn import TLSSocketServerMixIn - from integration.TLSAsyncDispatcherMixIn import TLSAsyncDispatcherMixIn - from integration.TLSTwistedProtocolWrapper import TLSTwistedProtocolWrapper - from utils.cryptomath import cryptlibpyLoaded, m2cryptoLoaded, - gmpyLoaded, pycryptoLoaded, prngName - from utils.keyfactory import generateRSAKey, parsePEMKey, parseXMLKey, - parseAsPublicKey, parsePrivateKey -""" - -from constants import AlertLevel, AlertDescription, Fault -from errors import * -from Checker import Checker -from HandshakeSettings import HandshakeSettings -from Session import Session -from SessionCache import SessionCache -from SharedKeyDB import SharedKeyDB -from TLSConnection import TLSConnection -from VerifierDB import VerifierDB -from X509 import X509 -from X509CertChain import X509CertChain - -from integration.HTTPTLSConnection import HTTPTLSConnection -from integration.TLSSocketServerMixIn import TLSSocketServerMixIn -from integration.TLSAsyncDispatcherMixIn import TLSAsyncDispatcherMixIn -from integration.POP3_TLS import POP3_TLS -from integration.IMAP4_TLS import IMAP4_TLS -from integration.SMTP_TLS import SMTP_TLS -from integration.XMLRPCTransport import XMLRPCTransport -try: - import twisted - del(twisted) - from integration.TLSTwistedProtocolWrapper import TLSTwistedProtocolWrapper -except ImportError: - pass - -from utils.cryptomath import cryptlibpyLoaded, m2cryptoLoaded, gmpyLoaded, \ - pycryptoLoaded, prngName -from utils.keyfactory import generateRSAKey, parsePEMKey, parseXMLKey, \ - parseAsPublicKey, parsePrivateKey diff --git a/src/lib/tlslite/constants.py b/src/lib/tlslite/constants.py deleted file mode 100755 index 8f2d5590e..000000000 --- a/src/lib/tlslite/constants.py +++ /dev/null @@ -1,225 +0,0 @@ -"""Constants used in various places.""" - -class CertificateType: - x509 = 0 - openpgp = 1 - cryptoID = 2 - -class HandshakeType: - hello_request = 0 - client_hello = 1 - server_hello = 2 - certificate = 11 - server_key_exchange = 12 - certificate_request = 13 - server_hello_done = 14 - certificate_verify = 15 - client_key_exchange = 16 - finished = 20 - -class ContentType: - change_cipher_spec = 20 - alert = 21 - handshake = 22 - application_data = 23 - all = (20,21,22,23) - -class AlertLevel: - warning = 1 - fatal = 2 - -class AlertDescription: - """ - @cvar bad_record_mac: A TLS record failed to decrypt properly. - - If this occurs during a shared-key or SRP handshake it most likely - indicates a bad password. It may also indicate an implementation - error, or some tampering with the data in transit. - - This alert will be signalled by the server if the SRP password is bad. It - may also be signalled by the server if the SRP username is unknown to the - server, but it doesn't wish to reveal that fact. - - This alert will be signalled by the client if the shared-key username is - bad. - - @cvar handshake_failure: A problem occurred while handshaking. - - This typically indicates a lack of common ciphersuites between client and - server, or some other disagreement (about SRP parameters or key sizes, - for example). - - @cvar protocol_version: The other party's SSL/TLS version was unacceptable. - - This indicates that the client and server couldn't agree on which version - of SSL or TLS to use. - - @cvar user_canceled: The handshake is being cancelled for some reason. - - """ - - close_notify = 0 - unexpected_message = 10 - bad_record_mac = 20 - decryption_failed = 21 - record_overflow = 22 - decompression_failure = 30 - handshake_failure = 40 - no_certificate = 41 #SSLv3 - bad_certificate = 42 - unsupported_certificate = 43 - certificate_revoked = 44 - certificate_expired = 45 - certificate_unknown = 46 - illegal_parameter = 47 - unknown_ca = 48 - access_denied = 49 - decode_error = 50 - decrypt_error = 51 - export_restriction = 60 - protocol_version = 70 - insufficient_security = 71 - internal_error = 80 - user_canceled = 90 - no_renegotiation = 100 - unknown_srp_username = 120 - missing_srp_username = 121 - untrusted_srp_parameters = 122 - -class CipherSuite: - TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0x0050 - TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0x0053 - TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0x0056 - - TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0x0051 - TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0x0054 - TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0x0057 - - TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A - TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F - TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 - TLS_RSA_WITH_RC4_128_SHA = 0x0005 - - srpSuites = [] - srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) - srpSuites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA) - srpSuites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA) - def getSrpSuites(ciphers): - suites = [] - for cipher in ciphers: - if cipher == "aes128": - suites.append(CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA) - elif cipher == "aes256": - suites.append(CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA) - elif cipher == "3des": - suites.append(CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) - return suites - getSrpSuites = staticmethod(getSrpSuites) - - srpRsaSuites = [] - srpRsaSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) - srpRsaSuites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) - srpRsaSuites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) - def getSrpRsaSuites(ciphers): - suites = [] - for cipher in ciphers: - if cipher == "aes128": - suites.append(CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) - elif cipher == "aes256": - suites.append(CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) - elif cipher == "3des": - suites.append(CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) - return suites - getSrpRsaSuites = staticmethod(getSrpRsaSuites) - - rsaSuites = [] - rsaSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA) - rsaSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA) - rsaSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA) - rsaSuites.append(TLS_RSA_WITH_RC4_128_SHA) - def getRsaSuites(ciphers): - suites = [] - for cipher in ciphers: - if cipher == "aes128": - suites.append(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA) - elif cipher == "aes256": - suites.append(CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA) - elif cipher == "rc4": - suites.append(CipherSuite.TLS_RSA_WITH_RC4_128_SHA) - elif cipher == "3des": - suites.append(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA) - return suites - getRsaSuites = staticmethod(getRsaSuites) - - tripleDESSuites = [] - tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) - tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) - tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA) - - aes128Suites = [] - aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA) - aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) - aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA) - - aes256Suites = [] - aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA) - aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) - aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA) - - rc4Suites = [] - rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA) - - -class Fault: - badUsername = 101 - badPassword = 102 - badA = 103 - clientSrpFaults = range(101,104) - - badVerifyMessage = 601 - clientCertFaults = range(601,602) - - badPremasterPadding = 501 - shortPremasterSecret = 502 - clientNoAuthFaults = range(501,503) - - badIdentifier = 401 - badSharedKey = 402 - clientSharedKeyFaults = range(401,403) - - badB = 201 - serverFaults = range(201,202) - - badFinished = 300 - badMAC = 301 - badPadding = 302 - genericFaults = range(300,303) - - faultAlerts = {\ - badUsername: (AlertDescription.unknown_srp_username, \ - AlertDescription.bad_record_mac),\ - badPassword: (AlertDescription.bad_record_mac,),\ - badA: (AlertDescription.illegal_parameter,),\ - badIdentifier: (AlertDescription.handshake_failure,),\ - badSharedKey: (AlertDescription.bad_record_mac,),\ - badPremasterPadding: (AlertDescription.bad_record_mac,),\ - shortPremasterSecret: (AlertDescription.bad_record_mac,),\ - badVerifyMessage: (AlertDescription.decrypt_error,),\ - badFinished: (AlertDescription.decrypt_error,),\ - badMAC: (AlertDescription.bad_record_mac,),\ - badPadding: (AlertDescription.bad_record_mac,) - } - - faultNames = {\ - badUsername: "bad username",\ - badPassword: "bad password",\ - badA: "bad A",\ - badIdentifier: "bad identifier",\ - badSharedKey: "bad sharedkey",\ - badPremasterPadding: "bad premaster padding",\ - shortPremasterSecret: "short premaster secret",\ - badVerifyMessage: "bad verify message",\ - badFinished: "bad finished message",\ - badMAC: "bad MAC",\ - badPadding: "bad padding" - } diff --git a/src/lib/tlslite/errors.py b/src/lib/tlslite/errors.py deleted file mode 100755 index c7f7ba81d..000000000 --- a/src/lib/tlslite/errors.py +++ /dev/null @@ -1,149 +0,0 @@ -"""Exception classes. -@sort: TLSError, TLSAbruptCloseError, TLSAlert, TLSLocalAlert, TLSRemoteAlert, -TLSAuthenticationError, TLSNoAuthenticationError, TLSAuthenticationTypeError, -TLSFingerprintError, TLSAuthorizationError, TLSValidationError, TLSFaultError -""" - -from constants import AlertDescription, AlertLevel - -class TLSError(Exception): - """Base class for all TLS Lite exceptions.""" - pass - -class TLSAbruptCloseError(TLSError): - """The socket was closed without a proper TLS shutdown. - - The TLS specification mandates that an alert of some sort - must be sent before the underlying socket is closed. If the socket - is closed without this, it could signify that an attacker is trying - to truncate the connection. It could also signify a misbehaving - TLS implementation, or a random network failure. - """ - pass - -class TLSAlert(TLSError): - """A TLS alert has been signalled.""" - pass - - _descriptionStr = {\ - AlertDescription.close_notify: "close_notify",\ - AlertDescription.unexpected_message: "unexpected_message",\ - AlertDescription.bad_record_mac: "bad_record_mac",\ - AlertDescription.decryption_failed: "decryption_failed",\ - AlertDescription.record_overflow: "record_overflow",\ - AlertDescription.decompression_failure: "decompression_failure",\ - AlertDescription.handshake_failure: "handshake_failure",\ - AlertDescription.no_certificate: "no certificate",\ - AlertDescription.bad_certificate: "bad_certificate",\ - AlertDescription.unsupported_certificate: "unsupported_certificate",\ - AlertDescription.certificate_revoked: "certificate_revoked",\ - AlertDescription.certificate_expired: "certificate_expired",\ - AlertDescription.certificate_unknown: "certificate_unknown",\ - AlertDescription.illegal_parameter: "illegal_parameter",\ - AlertDescription.unknown_ca: "unknown_ca",\ - AlertDescription.access_denied: "access_denied",\ - AlertDescription.decode_error: "decode_error",\ - AlertDescription.decrypt_error: "decrypt_error",\ - AlertDescription.export_restriction: "export_restriction",\ - AlertDescription.protocol_version: "protocol_version",\ - AlertDescription.insufficient_security: "insufficient_security",\ - AlertDescription.internal_error: "internal_error",\ - AlertDescription.user_canceled: "user_canceled",\ - AlertDescription.no_renegotiation: "no_renegotiation",\ - AlertDescription.unknown_srp_username: "unknown_srp_username",\ - AlertDescription.missing_srp_username: "missing_srp_username"} - -class TLSLocalAlert(TLSAlert): - """A TLS alert has been signalled by the local implementation. - - @type description: int - @ivar description: Set to one of the constants in - L{tlslite.constants.AlertDescription} - - @type level: int - @ivar level: Set to one of the constants in - L{tlslite.constants.AlertLevel} - - @type message: str - @ivar message: Description of what went wrong. - """ - def __init__(self, alert, message=None): - self.description = alert.description - self.level = alert.level - self.message = message - - def __str__(self): - alertStr = TLSAlert._descriptionStr.get(self.description) - if alertStr == None: - alertStr = str(self.description) - if self.message: - return alertStr + ": " + self.message - else: - return alertStr - -class TLSRemoteAlert(TLSAlert): - """A TLS alert has been signalled by the remote implementation. - - @type description: int - @ivar description: Set to one of the constants in - L{tlslite.constants.AlertDescription} - - @type level: int - @ivar level: Set to one of the constants in - L{tlslite.constants.AlertLevel} - """ - def __init__(self, alert): - self.description = alert.description - self.level = alert.level - - def __str__(self): - alertStr = TLSAlert._descriptionStr.get(self.description) - if alertStr == None: - alertStr = str(self.description) - return alertStr - -class TLSAuthenticationError(TLSError): - """The handshake succeeded, but the other party's authentication - was inadequate. - - This exception will only be raised when a - L{tlslite.Checker.Checker} has been passed to a handshake function. - The Checker will be invoked once the handshake completes, and if - the Checker objects to how the other party authenticated, a - subclass of this exception will be raised. - """ - pass - -class TLSNoAuthenticationError(TLSAuthenticationError): - """The Checker was expecting the other party to authenticate with a - certificate chain, but this did not occur.""" - pass - -class TLSAuthenticationTypeError(TLSAuthenticationError): - """The Checker was expecting the other party to authenticate with a - different type of certificate chain.""" - pass - -class TLSFingerprintError(TLSAuthenticationError): - """The Checker was expecting the other party to authenticate with a - certificate chain that matches a different fingerprint.""" - pass - -class TLSAuthorizationError(TLSAuthenticationError): - """The Checker was expecting the other party to authenticate with a - certificate chain that has a different authorization.""" - pass - -class TLSValidationError(TLSAuthenticationError): - """The Checker has determined that the other party's certificate - chain is invalid.""" - pass - -class TLSFaultError(TLSError): - """The other party responded incorrectly to an induced fault. - - This exception will only occur during fault testing, when a - TLSConnection's fault variable is set to induce some sort of - faulty behavior, and the other party doesn't respond appropriately. - """ - pass diff --git a/src/lib/tlslite/integration/AsyncStateMachine.py b/src/lib/tlslite/integration/AsyncStateMachine.py deleted file mode 100755 index abed60432..000000000 --- a/src/lib/tlslite/integration/AsyncStateMachine.py +++ /dev/null @@ -1,235 +0,0 @@ -""" -A state machine for using TLS Lite with asynchronous I/O. -""" - -class AsyncStateMachine: - """ - This is an abstract class that's used to integrate TLS Lite with - asyncore and Twisted. - - This class signals wantsReadsEvent() and wantsWriteEvent(). When - the underlying socket has become readable or writeable, the event - should be passed to this class by calling inReadEvent() or - inWriteEvent(). This class will then try to read or write through - the socket, and will update its state appropriately. - - This class will forward higher-level events to its subclass. For - example, when a complete TLS record has been received, - outReadEvent() will be called with the decrypted data. - """ - - def __init__(self): - self._clear() - - def _clear(self): - #These store the various asynchronous operations (i.e. - #generators). Only one of them, at most, is ever active at a - #time. - self.handshaker = None - self.closer = None - self.reader = None - self.writer = None - - #This stores the result from the last call to the - #currently active operation. If 0 it indicates that the - #operation wants to read, if 1 it indicates that the - #operation wants to write. If None, there is no active - #operation. - self.result = None - - def _checkAssert(self, maxActive=1): - #This checks that only one operation, at most, is - #active, and that self.result is set appropriately. - activeOps = 0 - if self.handshaker: - activeOps += 1 - if self.closer: - activeOps += 1 - if self.reader: - activeOps += 1 - if self.writer: - activeOps += 1 - - if self.result == None: - if activeOps != 0: - raise AssertionError() - elif self.result in (0,1): - if activeOps != 1: - raise AssertionError() - else: - raise AssertionError() - if activeOps > maxActive: - raise AssertionError() - - def wantsReadEvent(self): - """If the state machine wants to read. - - If an operation is active, this returns whether or not the - operation wants to read from the socket. If an operation is - not active, this returns None. - - @rtype: bool or None - @return: If the state machine wants to read. - """ - if self.result != None: - return self.result == 0 - return None - - def wantsWriteEvent(self): - """If the state machine wants to write. - - If an operation is active, this returns whether or not the - operation wants to write to the socket. If an operation is - not active, this returns None. - - @rtype: bool or None - @return: If the state machine wants to write. - """ - if self.result != None: - return self.result == 1 - return None - - def outConnectEvent(self): - """Called when a handshake operation completes. - - May be overridden in subclass. - """ - pass - - def outCloseEvent(self): - """Called when a close operation completes. - - May be overridden in subclass. - """ - pass - - def outReadEvent(self, readBuffer): - """Called when a read operation completes. - - May be overridden in subclass.""" - pass - - def outWriteEvent(self): - """Called when a write operation completes. - - May be overridden in subclass.""" - pass - - def inReadEvent(self): - """Tell the state machine it can read from the socket.""" - try: - self._checkAssert() - if self.handshaker: - self._doHandshakeOp() - elif self.closer: - self._doCloseOp() - elif self.reader: - self._doReadOp() - elif self.writer: - self._doWriteOp() - else: - self.reader = self.tlsConnection.readAsync(16384) - self._doReadOp() - except: - self._clear() - raise - - def inWriteEvent(self): - """Tell the state machine it can write to the socket.""" - try: - self._checkAssert() - if self.handshaker: - self._doHandshakeOp() - elif self.closer: - self._doCloseOp() - elif self.reader: - self._doReadOp() - elif self.writer: - self._doWriteOp() - else: - self.outWriteEvent() - except: - self._clear() - raise - - def _doHandshakeOp(self): - try: - self.result = self.handshaker.next() - except StopIteration: - self.handshaker = None - self.result = None - self.outConnectEvent() - - def _doCloseOp(self): - try: - self.result = self.closer.next() - except StopIteration: - self.closer = None - self.result = None - self.outCloseEvent() - - def _doReadOp(self): - self.result = self.reader.next() - if not self.result in (0,1): - readBuffer = self.result - self.reader = None - self.result = None - self.outReadEvent(readBuffer) - - def _doWriteOp(self): - try: - self.result = self.writer.next() - except StopIteration: - self.writer = None - self.result = None - - def setHandshakeOp(self, handshaker): - """Start a handshake operation. - - @type handshaker: generator - @param handshaker: A generator created by using one of the - asynchronous handshake functions (i.e. handshakeServerAsync, or - handshakeClientxxx(..., async=True). - """ - try: - self._checkAssert(0) - self.handshaker = handshaker - self._doHandshakeOp() - except: - self._clear() - raise - - def setServerHandshakeOp(self, **args): - """Start a handshake operation. - - The arguments passed to this function will be forwarded to - L{tlslite.TLSConnection.TLSConnection.handshakeServerAsync}. - """ - handshaker = self.tlsConnection.handshakeServerAsync(**args) - self.setHandshakeOp(handshaker) - - def setCloseOp(self): - """Start a close operation. - """ - try: - self._checkAssert(0) - self.closer = self.tlsConnection.closeAsync() - self._doCloseOp() - except: - self._clear() - raise - - def setWriteOp(self, writeBuffer): - """Start a write operation. - - @type writeBuffer: str - @param writeBuffer: The string to transmit. - """ - try: - self._checkAssert(0) - self.writer = self.tlsConnection.writeAsync(writeBuffer) - self._doWriteOp() - except: - self._clear() - raise - diff --git a/src/lib/tlslite/integration/ClientHelper.py b/src/lib/tlslite/integration/ClientHelper.py deleted file mode 100755 index 6de4ab7a0..000000000 --- a/src/lib/tlslite/integration/ClientHelper.py +++ /dev/null @@ -1,163 +0,0 @@ -""" -A helper class for using TLS Lite with stdlib clients -(httplib, xmlrpclib, imaplib, poplib). -""" - -from Bcfg2.tlslite.Checker import Checker - -class ClientHelper: - """This is a helper class used to integrate TLS Lite with various - TLS clients (e.g. poplib, smtplib, httplib, etc.)""" - - def __init__(self, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings = None): - """ - For client authentication, use one of these argument - combinations: - - username, password (SRP) - - username, sharedKey (shared-key) - - certChain, privateKey (certificate) - - For server authentication, you can either rely on the - implicit mutual authentication performed by SRP or - shared-keys, or you can do certificate-based server - authentication with one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - Certificate-based server authentication is compatible with - SRP or certificate-based client authentication. It is - not compatible with shared-keys. - - The constructor does not perform the TLS handshake itself, but - simply stores these arguments for later. The handshake is - performed only when this class needs to connect with the - server. Then you should be prepared to handle TLS-specific - exceptions. See the client handshake functions in - L{tlslite.TLSConnection.TLSConnection} for details on which - exceptions might be raised. - - @type username: str - @param username: SRP or shared-key username. Requires the - 'password' or 'sharedKey' argument. - - @type password: str - @param password: SRP password for mutual authentication. - Requires the 'username' argument. - - @type sharedKey: str - @param sharedKey: Shared key for mutual authentication. - Requires the 'username' argument. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: Certificate chain for client authentication. - Requires the 'privateKey' argument. Excludes the SRP or - shared-key related arguments. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: Private key for client authentication. - Requires the 'certChain' argument. Excludes the SRP or - shared-key related arguments. - - @type cryptoID: str - @param cryptoID: cryptoID for server authentication. Mutually - exclusive with the 'x509...' arguments. - - @type protocol: str - @param protocol: cryptoID protocol URI for server - authentication. Requires the 'cryptoID' argument. - - @type x509Fingerprint: str - @param x509Fingerprint: Hex-encoded X.509 fingerprint for - server authentication. Mutually exclusive with the 'cryptoID' - and 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed to use this parameter. Mutually exclusive with the - 'cryptoID' and 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - """ - - self.username = None - self.password = None - self.sharedKey = None - self.certChain = None - self.privateKey = None - self.checker = None - - #SRP Authentication - if username and password and not \ - (sharedKey or certChain or privateKey): - self.username = username - self.password = password - - #Shared Key Authentication - elif username and sharedKey and not \ - (password or certChain or privateKey): - self.username = username - self.sharedKey = sharedKey - - #Certificate Chain Authentication - elif certChain and privateKey and not \ - (username or password or sharedKey): - self.certChain = certChain - self.privateKey = privateKey - - #No Authentication - elif not password and not username and not \ - sharedKey and not certChain and not privateKey: - pass - - else: - raise ValueError("Bad parameters") - - #Authenticate the server based on its cryptoID or fingerprint - if sharedKey and (cryptoID or protocol or x509Fingerprint): - raise ValueError("Can't use shared keys with other forms of"\ - "authentication") - - self.checker = Checker(cryptoID, protocol, x509Fingerprint, - x509TrustList, x509CommonName) - self.settings = settings - - self.tlsSession = None - - def _handshake(self, tlsConnection): - if self.username and self.password: - tlsConnection.handshakeClientSRP(username=self.username, - password=self.password, - checker=self.checker, - settings=self.settings, - session=self.tlsSession) - elif self.username and self.sharedKey: - tlsConnection.handshakeClientSharedKey(username=self.username, - sharedKey=self.sharedKey, - settings=self.settings) - else: - tlsConnection.handshakeClientCert(certChain=self.certChain, - privateKey=self.privateKey, - checker=self.checker, - settings=self.settings, - session=self.tlsSession) - self.tlsSession = tlsConnection.session diff --git a/src/lib/tlslite/integration/HTTPTLSConnection.py b/src/lib/tlslite/integration/HTTPTLSConnection.py deleted file mode 100755 index a50c053c7..000000000 --- a/src/lib/tlslite/integration/HTTPTLSConnection.py +++ /dev/null @@ -1,169 +0,0 @@ -"""TLS Lite + httplib.""" - -import socket -import httplib -from Bcfg2.tlslite.TLSConnection import TLSConnection -from Bcfg2.tlslite.integration.ClientHelper import ClientHelper - - -class HTTPBaseTLSConnection(httplib.HTTPConnection): - """This abstract class provides a framework for adding TLS support - to httplib.""" - - default_port = 443 - - def __init__(self, host, port=None, strict=None): - if strict == None: - #Python 2.2 doesn't support strict - httplib.HTTPConnection.__init__(self, host, port) - else: - httplib.HTTPConnection.__init__(self, host, port, strict) - - def connect(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if hasattr(sock, 'settimeout'): - sock.settimeout(90) - sock.connect((self.host, self.port)) - - #Use a TLSConnection to emulate a socket - self.sock = TLSConnection(sock) - - #When httplib closes this, close the socket - self.sock.closeSocket = True - self._handshake(self.sock) - - def _handshake(self, tlsConnection): - """Called to perform some sort of handshake. - - This method must be overridden in a subclass to do some type of - handshake. This method will be called after the socket has - been connected but before any data has been sent. If this - method does not raise an exception, the TLS connection will be - considered valid. - - This method may (or may not) be called every time an HTTP - request is performed, depending on whether the underlying HTTP - connection is persistent. - - @type tlsConnection: L{tlslite.TLSConnection.TLSConnection} - @param tlsConnection: The connection to perform the handshake - on. - """ - raise NotImplementedError() - - -class HTTPTLSConnection(HTTPBaseTLSConnection, ClientHelper): - """This class extends L{HTTPBaseTLSConnection} to support the - common types of handshaking.""" - - def __init__(self, host, port=None, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings = None): - """Create a new HTTPTLSConnection. - - For client authentication, use one of these argument - combinations: - - username, password (SRP) - - username, sharedKey (shared-key) - - certChain, privateKey (certificate) - - For server authentication, you can either rely on the - implicit mutual authentication performed by SRP or - shared-keys, or you can do certificate-based server - authentication with one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - Certificate-based server authentication is compatible with - SRP or certificate-based client authentication. It is - not compatible with shared-keys. - - The constructor does not perform the TLS handshake itself, but - simply stores these arguments for later. The handshake is - performed only when this class needs to connect with the - server. Thus you should be prepared to handle TLS-specific - exceptions when calling methods inherited from - L{httplib.HTTPConnection} such as request(), connect(), and - send(). See the client handshake functions in - L{tlslite.TLSConnection.TLSConnection} for details on which - exceptions might be raised. - - @type host: str - @param host: Server to connect to. - - @type port: int - @param port: Port to connect to. - - @type username: str - @param username: SRP or shared-key username. Requires the - 'password' or 'sharedKey' argument. - - @type password: str - @param password: SRP password for mutual authentication. - Requires the 'username' argument. - - @type sharedKey: str - @param sharedKey: Shared key for mutual authentication. - Requires the 'username' argument. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: Certificate chain for client authentication. - Requires the 'privateKey' argument. Excludes the SRP or - shared-key related arguments. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: Private key for client authentication. - Requires the 'certChain' argument. Excludes the SRP or - shared-key related arguments. - - @type cryptoID: str - @param cryptoID: cryptoID for server authentication. Mutually - exclusive with the 'x509...' arguments. - - @type protocol: str - @param protocol: cryptoID protocol URI for server - authentication. Requires the 'cryptoID' argument. - - @type x509Fingerprint: str - @param x509Fingerprint: Hex-encoded X.509 fingerprint for - server authentication. Mutually exclusive with the 'cryptoID' - and 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed to use this parameter. Mutually exclusive with the - 'cryptoID' and 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - """ - - HTTPBaseTLSConnection.__init__(self, host, port) - - ClientHelper.__init__(self, - username, password, sharedKey, - certChain, privateKey, - cryptoID, protocol, - x509Fingerprint, - x509TrustList, x509CommonName, - settings) - - def _handshake(self, tlsConnection): - ClientHelper._handshake(self, tlsConnection) diff --git a/src/lib/tlslite/integration/IMAP4_TLS.py b/src/lib/tlslite/integration/IMAP4_TLS.py deleted file mode 100755 index 2b005dc7e..000000000 --- a/src/lib/tlslite/integration/IMAP4_TLS.py +++ /dev/null @@ -1,132 +0,0 @@ -"""TLS Lite + imaplib.""" - -import socket -from imaplib import IMAP4 -from Bcfg2.tlslite.TLSConnection import TLSConnection -from Bcfg2.tlslite.integration.ClientHelper import ClientHelper - -# IMAP TLS PORT -IMAP4_TLS_PORT = 993 - -class IMAP4_TLS(IMAP4, ClientHelper): - """This class extends L{imaplib.IMAP4} with TLS support.""" - - def __init__(self, host = '', port = IMAP4_TLS_PORT, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings=None): - """Create a new IMAP4_TLS. - - For client authentication, use one of these argument - combinations: - - username, password (SRP) - - username, sharedKey (shared-key) - - certChain, privateKey (certificate) - - For server authentication, you can either rely on the - implicit mutual authentication performed by SRP or - shared-keys, or you can do certificate-based server - authentication with one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - Certificate-based server authentication is compatible with - SRP or certificate-based client authentication. It is - not compatible with shared-keys. - - The caller should be prepared to handle TLS-specific - exceptions. See the client handshake functions in - L{tlslite.TLSConnection.TLSConnection} for details on which - exceptions might be raised. - - @type host: str - @param host: Server to connect to. - - @type port: int - @param port: Port to connect to. - - @type username: str - @param username: SRP or shared-key username. Requires the - 'password' or 'sharedKey' argument. - - @type password: str - @param password: SRP password for mutual authentication. - Requires the 'username' argument. - - @type sharedKey: str - @param sharedKey: Shared key for mutual authentication. - Requires the 'username' argument. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: Certificate chain for client authentication. - Requires the 'privateKey' argument. Excludes the SRP or - shared-key related arguments. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: Private key for client authentication. - Requires the 'certChain' argument. Excludes the SRP or - shared-key related arguments. - - @type cryptoID: str - @param cryptoID: cryptoID for server authentication. Mutually - exclusive with the 'x509...' arguments. - - @type protocol: str - @param protocol: cryptoID protocol URI for server - authentication. Requires the 'cryptoID' argument. - - @type x509Fingerprint: str - @param x509Fingerprint: Hex-encoded X.509 fingerprint for - server authentication. Mutually exclusive with the 'cryptoID' - and 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed to use this parameter. Mutually exclusive with the - 'cryptoID' and 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - """ - - ClientHelper.__init__(self, - username, password, sharedKey, - certChain, privateKey, - cryptoID, protocol, - x509Fingerprint, - x509TrustList, x509CommonName, - settings) - - IMAP4.__init__(self, host, port) - - - def open(self, host = '', port = IMAP4_TLS_PORT): - """Setup connection to remote server on "host:port". - - This connection will be used by the routines: - read, readline, send, shutdown. - """ - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((host, port)) - self.sock = TLSConnection(self.sock) - self.sock.closeSocket = True - ClientHelper._handshake(self, self.sock) - self.file = self.sock.makefile('rb') diff --git a/src/lib/tlslite/integration/IntegrationHelper.py b/src/lib/tlslite/integration/IntegrationHelper.py deleted file mode 100755 index af5193b48..000000000 --- a/src/lib/tlslite/integration/IntegrationHelper.py +++ /dev/null @@ -1,52 +0,0 @@ - -class IntegrationHelper: - - def __init__(self, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings = None): - - self.username = None - self.password = None - self.sharedKey = None - self.certChain = None - self.privateKey = None - self.checker = None - - #SRP Authentication - if username and password and not \ - (sharedKey or certChain or privateKey): - self.username = username - self.password = password - - #Shared Key Authentication - elif username and sharedKey and not \ - (password or certChain or privateKey): - self.username = username - self.sharedKey = sharedKey - - #Certificate Chain Authentication - elif certChain and privateKey and not \ - (username or password or sharedKey): - self.certChain = certChain - self.privateKey = privateKey - - #No Authentication - elif not password and not username and not \ - sharedKey and not certChain and not privateKey: - pass - - else: - raise ValueError("Bad parameters") - - #Authenticate the server based on its cryptoID or fingerprint - if sharedKey and (cryptoID or protocol or x509Fingerprint): - raise ValueError("Can't use shared keys with other forms of"\ - "authentication") - - self.checker = Checker(cryptoID, protocol, x509Fingerprint, - x509TrustList, x509CommonName) - self.settings = settings \ No newline at end of file diff --git a/src/lib/tlslite/integration/POP3_TLS.py b/src/lib/tlslite/integration/POP3_TLS.py deleted file mode 100755 index 8245a13ca..000000000 --- a/src/lib/tlslite/integration/POP3_TLS.py +++ /dev/null @@ -1,142 +0,0 @@ -"""TLS Lite + poplib.""" - -import socket -from poplib import POP3 -from Bcfg2.tlslite.TLSConnection import TLSConnection -from Bcfg2.tlslite.integration.ClientHelper import ClientHelper - -# POP TLS PORT -POP3_TLS_PORT = 995 - -class POP3_TLS(POP3, ClientHelper): - """This class extends L{poplib.POP3} with TLS support.""" - - def __init__(self, host, port = POP3_TLS_PORT, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings=None): - """Create a new POP3_TLS. - - For client authentication, use one of these argument - combinations: - - username, password (SRP) - - username, sharedKey (shared-key) - - certChain, privateKey (certificate) - - For server authentication, you can either rely on the - implicit mutual authentication performed by SRP or - shared-keys, or you can do certificate-based server - authentication with one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - Certificate-based server authentication is compatible with - SRP or certificate-based client authentication. It is - not compatible with shared-keys. - - The caller should be prepared to handle TLS-specific - exceptions. See the client handshake functions in - L{tlslite.TLSConnection.TLSConnection} for details on which - exceptions might be raised. - - @type host: str - @param host: Server to connect to. - - @type port: int - @param port: Port to connect to. - - @type username: str - @param username: SRP or shared-key username. Requires the - 'password' or 'sharedKey' argument. - - @type password: str - @param password: SRP password for mutual authentication. - Requires the 'username' argument. - - @type sharedKey: str - @param sharedKey: Shared key for mutual authentication. - Requires the 'username' argument. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: Certificate chain for client authentication. - Requires the 'privateKey' argument. Excludes the SRP or - shared-key related arguments. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: Private key for client authentication. - Requires the 'certChain' argument. Excludes the SRP or - shared-key related arguments. - - @type cryptoID: str - @param cryptoID: cryptoID for server authentication. Mutually - exclusive with the 'x509...' arguments. - - @type protocol: str - @param protocol: cryptoID protocol URI for server - authentication. Requires the 'cryptoID' argument. - - @type x509Fingerprint: str - @param x509Fingerprint: Hex-encoded X.509 fingerprint for - server authentication. Mutually exclusive with the 'cryptoID' - and 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed to use this parameter. Mutually exclusive with the - 'cryptoID' and 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - """ - - self.host = host - self.port = port - msg = "getaddrinfo returns an empty list" - self.sock = None - for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self.sock = socket.socket(af, socktype, proto) - self.sock.connect(sa) - except socket.error, msg: - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - - ### New code below (all else copied from poplib) - ClientHelper.__init__(self, - username, password, sharedKey, - certChain, privateKey, - cryptoID, protocol, - x509Fingerprint, - x509TrustList, x509CommonName, - settings) - - self.sock = TLSConnection(self.sock) - self.sock.closeSocket = True - ClientHelper._handshake(self, self.sock) - ### - - self.file = self.sock.makefile('rb') - self._debugging = 0 - self.welcome = self._getresp() diff --git a/src/lib/tlslite/integration/SMTP_TLS.py b/src/lib/tlslite/integration/SMTP_TLS.py deleted file mode 100755 index 203cc0b7f..000000000 --- a/src/lib/tlslite/integration/SMTP_TLS.py +++ /dev/null @@ -1,114 +0,0 @@ -"""TLS Lite + smtplib.""" - -from smtplib import SMTP -from Bcfg2.tlslite.TLSConnection import TLSConnection -from Bcfg2.tlslite.integration.ClientHelper import ClientHelper - -class SMTP_TLS(SMTP): - """This class extends L{smtplib.SMTP} with TLS support.""" - - def starttls(self, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings=None): - """Puts the connection to the SMTP server into TLS mode. - - If the server supports TLS, this will encrypt the rest of the SMTP - session. - - For client authentication, use one of these argument - combinations: - - username, password (SRP) - - username, sharedKey (shared-key) - - certChain, privateKey (certificate) - - For server authentication, you can either rely on the - implicit mutual authentication performed by SRP or - shared-keys, or you can do certificate-based server - authentication with one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - Certificate-based server authentication is compatible with - SRP or certificate-based client authentication. It is - not compatible with shared-keys. - - The caller should be prepared to handle TLS-specific - exceptions. See the client handshake functions in - L{tlslite.TLSConnection.TLSConnection} for details on which - exceptions might be raised. - - @type username: str - @param username: SRP or shared-key username. Requires the - 'password' or 'sharedKey' argument. - - @type password: str - @param password: SRP password for mutual authentication. - Requires the 'username' argument. - - @type sharedKey: str - @param sharedKey: Shared key for mutual authentication. - Requires the 'username' argument. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: Certificate chain for client authentication. - Requires the 'privateKey' argument. Excludes the SRP or - shared-key related arguments. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: Private key for client authentication. - Requires the 'certChain' argument. Excludes the SRP or - shared-key related arguments. - - @type cryptoID: str - @param cryptoID: cryptoID for server authentication. Mutually - exclusive with the 'x509...' arguments. - - @type protocol: str - @param protocol: cryptoID protocol URI for server - authentication. Requires the 'cryptoID' argument. - - @type x509Fingerprint: str - @param x509Fingerprint: Hex-encoded X.509 fingerprint for - server authentication. Mutually exclusive with the 'cryptoID' - and 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed to use this parameter. Mutually exclusive with the - 'cryptoID' and 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - """ - (resp, reply) = self.docmd("STARTTLS") - if resp == 220: - helper = ClientHelper( - username, password, sharedKey, - certChain, privateKey, - cryptoID, protocol, - x509Fingerprint, - x509TrustList, x509CommonName, - settings) - conn = TLSConnection(self.sock) - conn.closeSocket = True - helper._handshake(conn) - self.sock = conn - self.file = conn.makefile('rb') - return (resp, reply) diff --git a/src/lib/tlslite/integration/TLSAsyncDispatcherMixIn.py b/src/lib/tlslite/integration/TLSAsyncDispatcherMixIn.py deleted file mode 100755 index 9201e5cba..000000000 --- a/src/lib/tlslite/integration/TLSAsyncDispatcherMixIn.py +++ /dev/null @@ -1,139 +0,0 @@ -"""TLS Lite + asyncore.""" - - -import asyncore -from Bcfg2.tlslite.TLSConnection import TLSConnection -from AsyncStateMachine import AsyncStateMachine - - -class TLSAsyncDispatcherMixIn(AsyncStateMachine): - """This class can be "mixed in" with an - L{asyncore.dispatcher} to add TLS support. - - This class essentially sits between the dispatcher and the select - loop, intercepting events and only calling the dispatcher when - applicable. - - In the case of handle_read(), a read operation will be activated, - and when it completes, the bytes will be placed in a buffer where - the dispatcher can retrieve them by calling recv(), and the - dispatcher's handle_read() will be called. - - In the case of handle_write(), the dispatcher's handle_write() will - be called, and when it calls send(), a write operation will be - activated. - - To use this class, you must combine it with an asyncore.dispatcher, - and pass in a handshake operation with setServerHandshakeOp(). - - Below is an example of using this class with medusa. This class is - mixed in with http_channel to create http_tls_channel. Note: - 1. the mix-in is listed first in the inheritance list - - 2. the input buffer size must be at least 16K, otherwise the - dispatcher might not read all the bytes from the TLS layer, - leaving some bytes in limbo. - - 3. IE seems to have a problem receiving a whole HTTP response in a - single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't - be displayed on IE. - - Add the following text into 'start_medusa.py', in the 'HTTP Server' - section:: - - from tlslite.api import * - s = open("./serverX509Cert.pem").read() - x509 = X509() - x509.parse(s) - certChain = X509CertChain([x509]) - - s = open("./serverX509Key.pem").read() - privateKey = parsePEMKey(s, private=True) - - class http_tls_channel(TLSAsyncDispatcherMixIn, - http_server.http_channel): - ac_in_buffer_size = 16384 - - def __init__ (self, server, conn, addr): - http_server.http_channel.__init__(self, server, conn, addr) - TLSAsyncDispatcherMixIn.__init__(self, conn) - self.tlsConnection.ignoreAbruptClose = True - self.setServerHandshakeOp(certChain=certChain, - privateKey=privateKey) - - hs.channel_class = http_tls_channel - - If the TLS layer raises an exception, the exception will be caught - in asyncore.dispatcher, which will call close() on this class. The - TLS layer always closes the TLS connection before raising an - exception, so the close operation will complete right away, causing - asyncore.dispatcher.close() to be called, which closes the socket - and removes this instance from the asyncore loop. - - """ - - - def __init__(self, sock=None): - AsyncStateMachine.__init__(self) - - if sock: - self.tlsConnection = TLSConnection(sock) - - #Calculate the sibling I'm being mixed in with. - #This is necessary since we override functions - #like readable(), handle_read(), etc., but we - #also want to call the sibling's versions. - for cl in self.__class__.__bases__: - if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine: - self.siblingClass = cl - break - else: - raise AssertionError() - - def readable(self): - result = self.wantsReadEvent() - if result != None: - return result - return self.siblingClass.readable(self) - - def writable(self): - result = self.wantsWriteEvent() - if result != None: - return result - return self.siblingClass.writable(self) - - def handle_read(self): - self.inReadEvent() - - def handle_write(self): - self.inWriteEvent() - - def outConnectEvent(self): - self.siblingClass.handle_connect(self) - - def outCloseEvent(self): - asyncore.dispatcher.close(self) - - def outReadEvent(self, readBuffer): - self.readBuffer = readBuffer - self.siblingClass.handle_read(self) - - def outWriteEvent(self): - self.siblingClass.handle_write(self) - - def recv(self, bufferSize=16384): - if bufferSize < 16384 or self.readBuffer == None: - raise AssertionError() - returnValue = self.readBuffer - self.readBuffer = None - return returnValue - - def send(self, writeBuffer): - self.setWriteOp(writeBuffer) - return len(writeBuffer) - - def close(self): - if hasattr(self, "tlsConnection"): - self.setCloseOp() - else: - asyncore.dispatcher.close(self) diff --git a/src/lib/tlslite/integration/TLSSocketServerMixIn.py b/src/lib/tlslite/integration/TLSSocketServerMixIn.py deleted file mode 100755 index fe9f303b4..000000000 --- a/src/lib/tlslite/integration/TLSSocketServerMixIn.py +++ /dev/null @@ -1,59 +0,0 @@ -"""TLS Lite + SocketServer.""" - -from Bcfg2.tlslite.TLSConnection import TLSConnection - -class TLSSocketServerMixIn: - """ - This class can be mixed in with any L{SocketServer.TCPServer} to - add TLS support. - - To use this class, define a new class that inherits from it and - some L{SocketServer.TCPServer} (with the mix-in first). Then - implement the handshake() method, doing some sort of server - handshake on the connection argument. If the handshake method - returns True, the RequestHandler will be triggered. Below is a - complete example of a threaded HTTPS server:: - - from SocketServer import * - from BaseHTTPServer import * - from SimpleHTTPServer import * - from tlslite.api import * - - s = open("./serverX509Cert.pem").read() - x509 = X509() - x509.parse(s) - certChain = X509CertChain([x509]) - - s = open("./serverX509Key.pem").read() - privateKey = parsePEMKey(s, private=True) - - sessionCache = SessionCache() - - class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, - HTTPServer): - def handshake(self, tlsConnection): - try: - tlsConnection.handshakeServer(certChain=certChain, - privateKey=privateKey, - sessionCache=sessionCache) - tlsConnection.ignoreAbruptClose = True - return True - except TLSError, error: - print "Handshake failure:", str(error) - return False - - httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler) - httpd.serve_forever() - """ - - - def finish_request(self, sock, client_address): - tlsConnection = TLSConnection(sock) - if self.handshake(tlsConnection) == True: - self.RequestHandlerClass(tlsConnection, client_address, self) - tlsConnection.close() - - #Implement this method to do some form of handshaking. Return True - #if the handshake finishes properly and the request is authorized. - def handshake(self, tlsConnection): - raise NotImplementedError() diff --git a/src/lib/tlslite/integration/TLSTwistedProtocolWrapper.py b/src/lib/tlslite/integration/TLSTwistedProtocolWrapper.py deleted file mode 100755 index b9d2f8529..000000000 --- a/src/lib/tlslite/integration/TLSTwistedProtocolWrapper.py +++ /dev/null @@ -1,196 +0,0 @@ -"""TLS Lite + Twisted.""" - -from twisted.protocols.policies import ProtocolWrapper, WrappingFactory -from twisted.python.failure import Failure - -from AsyncStateMachine import AsyncStateMachine -from Bcfg2.tlslite.TLSConnection import TLSConnection -from Bcfg2.tlslite.errors import * - -import socket -import errno - - -#The TLSConnection is created around a "fake socket" that -#plugs it into the underlying Twisted transport -class _FakeSocket: - def __init__(self, wrapper): - self.wrapper = wrapper - self.data = "" - - def send(self, data): - ProtocolWrapper.write(self.wrapper, data) - return len(data) - - def recv(self, numBytes): - if self.data == "": - raise socket.error, (errno.EWOULDBLOCK, "") - returnData = self.data[:numBytes] - self.data = self.data[numBytes:] - return returnData - -class TLSTwistedProtocolWrapper(ProtocolWrapper, AsyncStateMachine): - """This class can wrap Twisted protocols to add TLS support. - - Below is a complete example of using TLS Lite with a Twisted echo - server. - - There are two server implementations below. Echo is the original - protocol, which is oblivious to TLS. Echo1 subclasses Echo and - negotiates TLS when the client connects. Echo2 subclasses Echo and - negotiates TLS when the client sends "STARTTLS":: - - from twisted.internet.protocol import Protocol, Factory - from twisted.internet import reactor - from twisted.protocols.policies import WrappingFactory - from twisted.protocols.basic import LineReceiver - from twisted.python import log - from twisted.python.failure import Failure - import sys - from tlslite.api import * - - s = open("./serverX509Cert.pem").read() - x509 = X509() - x509.parse(s) - certChain = X509CertChain([x509]) - - s = open("./serverX509Key.pem").read() - privateKey = parsePEMKey(s, private=True) - - verifierDB = VerifierDB("verifierDB") - verifierDB.open() - - class Echo(LineReceiver): - def connectionMade(self): - self.transport.write("Welcome to the echo server!\\r\\n") - - def lineReceived(self, line): - self.transport.write(line + "\\r\\n") - - class Echo1(Echo): - def connectionMade(self): - if not self.transport.tlsStarted: - self.transport.setServerHandshakeOp(certChain=certChain, - privateKey=privateKey, - verifierDB=verifierDB) - else: - Echo.connectionMade(self) - - def connectionLost(self, reason): - pass #Handle any TLS exceptions here - - class Echo2(Echo): - def lineReceived(self, data): - if data == "STARTTLS": - self.transport.setServerHandshakeOp(certChain=certChain, - privateKey=privateKey, - verifierDB=verifierDB) - else: - Echo.lineReceived(self, data) - - def connectionLost(self, reason): - pass #Handle any TLS exceptions here - - factory = Factory() - factory.protocol = Echo1 - #factory.protocol = Echo2 - - wrappingFactory = WrappingFactory(factory) - wrappingFactory.protocol = TLSTwistedProtocolWrapper - - log.startLogging(sys.stdout) - reactor.listenTCP(1079, wrappingFactory) - reactor.run() - - This class works as follows: - - Data comes in and is given to the AsyncStateMachine for handling. - AsyncStateMachine will forward events to this class, and we'll - pass them on to the ProtocolHandler, which will proxy them to the - wrapped protocol. The wrapped protocol may then call back into - this class, and these calls will be proxied into the - AsyncStateMachine. - - The call graph looks like this: - - self.dataReceived - - AsyncStateMachine.inReadEvent - - self.out(Connect|Close|Read)Event - - ProtocolWrapper.(connectionMade|loseConnection|dataReceived) - - self.(loseConnection|write|writeSequence) - - AsyncStateMachine.(setCloseOp|setWriteOp) - """ - - #WARNING: IF YOU COPY-AND-PASTE THE ABOVE CODE, BE SURE TO REMOVE - #THE EXTRA ESCAPING AROUND "\\r\\n" - - def __init__(self, factory, wrappedProtocol): - ProtocolWrapper.__init__(self, factory, wrappedProtocol) - AsyncStateMachine.__init__(self) - self.fakeSocket = _FakeSocket(self) - self.tlsConnection = TLSConnection(self.fakeSocket) - self.tlsStarted = False - self.connectionLostCalled = False - - def connectionMade(self): - try: - ProtocolWrapper.connectionMade(self) - except TLSError, e: - self.connectionLost(Failure(e)) - ProtocolWrapper.loseConnection(self) - - def dataReceived(self, data): - try: - if not self.tlsStarted: - ProtocolWrapper.dataReceived(self, data) - else: - self.fakeSocket.data += data - while self.fakeSocket.data: - AsyncStateMachine.inReadEvent(self) - except TLSError, e: - self.connectionLost(Failure(e)) - ProtocolWrapper.loseConnection(self) - - def connectionLost(self, reason): - if not self.connectionLostCalled: - ProtocolWrapper.connectionLost(self, reason) - self.connectionLostCalled = True - - - def outConnectEvent(self): - ProtocolWrapper.connectionMade(self) - - def outCloseEvent(self): - ProtocolWrapper.loseConnection(self) - - def outReadEvent(self, data): - if data == "": - ProtocolWrapper.loseConnection(self) - else: - ProtocolWrapper.dataReceived(self, data) - - - def setServerHandshakeOp(self, **args): - self.tlsStarted = True - AsyncStateMachine.setServerHandshakeOp(self, **args) - - def loseConnection(self): - if not self.tlsStarted: - ProtocolWrapper.loseConnection(self) - else: - AsyncStateMachine.setCloseOp(self) - - def write(self, data): - if not self.tlsStarted: - ProtocolWrapper.write(self, data) - else: - #Because of the FakeSocket, write operations are guaranteed to - #terminate immediately. - AsyncStateMachine.setWriteOp(self, data) - - def writeSequence(self, seq): - if not self.tlsStarted: - ProtocolWrapper.writeSequence(self, seq) - else: - #Because of the FakeSocket, write operations are guaranteed to - #terminate immediately. - AsyncStateMachine.setWriteOp(self, "".join(seq)) diff --git a/src/lib/tlslite/integration/XMLRPCTransport.py b/src/lib/tlslite/integration/XMLRPCTransport.py deleted file mode 100755 index 61d03428b..000000000 --- a/src/lib/tlslite/integration/XMLRPCTransport.py +++ /dev/null @@ -1,137 +0,0 @@ -"""TLS Lite + xmlrpclib.""" - -import xmlrpclib -import httplib -from Bcfg2.tlslite.integration.HTTPTLSConnection import HTTPTLSConnection -from Bcfg2.tlslite.integration.ClientHelper import ClientHelper - - -class XMLRPCTransport(xmlrpclib.Transport, ClientHelper): - """Handles an HTTPS transaction to an XML-RPC server.""" - - def __init__(self, - username=None, password=None, sharedKey=None, - certChain=None, privateKey=None, - cryptoID=None, protocol=None, - x509Fingerprint=None, - x509TrustList=None, x509CommonName=None, - settings=None): - """Create a new XMLRPCTransport. - - An instance of this class can be passed to L{xmlrpclib.ServerProxy} - to use TLS with XML-RPC calls:: - - from tlslite.api import XMLRPCTransport - from xmlrpclib import ServerProxy - - transport = XMLRPCTransport(user="alice", password="abra123") - server = ServerProxy("https://localhost", transport) - - For client authentication, use one of these argument - combinations: - - username, password (SRP) - - username, sharedKey (shared-key) - - certChain, privateKey (certificate) - - For server authentication, you can either rely on the - implicit mutual authentication performed by SRP or - shared-keys, or you can do certificate-based server - authentication with one of these argument combinations: - - cryptoID[, protocol] (requires cryptoIDlib) - - x509Fingerprint - - x509TrustList[, x509CommonName] (requires cryptlib_py) - - Certificate-based server authentication is compatible with - SRP or certificate-based client authentication. It is - not compatible with shared-keys. - - The constructor does not perform the TLS handshake itself, but - simply stores these arguments for later. The handshake is - performed only when this class needs to connect with the - server. Thus you should be prepared to handle TLS-specific - exceptions when calling methods of L{xmlrpclib.ServerProxy}. See the - client handshake functions in - L{tlslite.TLSConnection.TLSConnection} for details on which - exceptions might be raised. - - @type username: str - @param username: SRP or shared-key username. Requires the - 'password' or 'sharedKey' argument. - - @type password: str - @param password: SRP password for mutual authentication. - Requires the 'username' argument. - - @type sharedKey: str - @param sharedKey: Shared key for mutual authentication. - Requires the 'username' argument. - - @type certChain: L{tlslite.X509CertChain.X509CertChain} or - L{cryptoIDlib.CertChain.CertChain} - @param certChain: Certificate chain for client authentication. - Requires the 'privateKey' argument. Excludes the SRP or - shared-key related arguments. - - @type privateKey: L{tlslite.utils.RSAKey.RSAKey} - @param privateKey: Private key for client authentication. - Requires the 'certChain' argument. Excludes the SRP or - shared-key related arguments. - - @type cryptoID: str - @param cryptoID: cryptoID for server authentication. Mutually - exclusive with the 'x509...' arguments. - - @type protocol: str - @param protocol: cryptoID protocol URI for server - authentication. Requires the 'cryptoID' argument. - - @type x509Fingerprint: str - @param x509Fingerprint: Hex-encoded X.509 fingerprint for - server authentication. Mutually exclusive with the 'cryptoID' - and 'x509TrustList' arguments. - - @type x509TrustList: list of L{tlslite.X509.X509} - @param x509TrustList: A list of trusted root certificates. The - other party must present a certificate chain which extends to - one of these root certificates. The cryptlib_py module must be - installed to use this parameter. Mutually exclusive with the - 'cryptoID' and 'x509Fingerprint' arguments. - - @type x509CommonName: str - @param x509CommonName: The end-entity certificate's 'CN' field - must match this value. For a web server, this is typically a - server name such as 'www.amazon.com'. Mutually exclusive with - the 'cryptoID' and 'x509Fingerprint' arguments. Requires the - 'x509TrustList' argument. - - @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} - @param settings: Various settings which can be used to control - the ciphersuites, certificate types, and SSL/TLS versions - offered by the client. - """ - - ClientHelper.__init__(self, - username, password, sharedKey, - certChain, privateKey, - cryptoID, protocol, - x509Fingerprint, - x509TrustList, x509CommonName, - settings) - self._use_datetime = 0 - - def make_connection(self, host): - # create a HTTPS connection object from a host descriptor - host, extra_headers, x509 = self.get_host_info(host) - http = HTTPTLSConnection(host, None, - self.username, self.password, - self.sharedKey, - self.certChain, self.privateKey, - self.checker.cryptoID, - self.checker.protocol, - self.checker.x509Fingerprint, - self.checker.x509TrustList, - self.checker.x509CommonName, - self.settings) - http2 = httplib.HTTP() - http2._setup(http) - return http2 diff --git a/src/lib/tlslite/integration/__init__.py b/src/lib/tlslite/integration/__init__.py deleted file mode 100755 index 960f4065f..000000000 --- a/src/lib/tlslite/integration/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Classes for integrating TLS Lite with other packages.""" - -__all__ = ["AsyncStateMachine", - "HTTPTLSConnection", - "POP3_TLS", - "IMAP4_TLS", - "SMTP_TLS", - "XMLRPCTransport", - "TLSSocketServerMixIn", - "TLSAsyncDispatcherMixIn", - "TLSTwistedProtocolWrapper"] - -try: - import twisted - del twisted -except ImportError: - del __all__[__all__.index("TLSTwistedProtocolWrapper")] diff --git a/src/lib/tlslite/mathtls.py b/src/lib/tlslite/mathtls.py deleted file mode 100755 index 3b8ede601..000000000 --- a/src/lib/tlslite/mathtls.py +++ /dev/null @@ -1,170 +0,0 @@ -"""Miscellaneous helper functions.""" - -from utils.compat import * -from utils.cryptomath import * - -import hmac -import md5 -import sha - -#1024, 1536, 2048, 3072, 4096, 6144, and 8192 bit groups] -goodGroupParameters = [(2,0xEEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3),\ - (2,0x9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB),\ - (2,0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73),\ - (2,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF),\ - (5,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF),\ - (5,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF),\ - (5,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF)] - -def P_hash(hashModule, secret, seed, length): - bytes = createByteArrayZeros(length) - secret = bytesToString(secret) - seed = bytesToString(seed) - A = seed - index = 0 - while 1: - A = hmac.HMAC(secret, A, hashModule).digest() - output = hmac.HMAC(secret, A+seed, hashModule).digest() - for c in output: - if index >= length: - return bytes - bytes[index] = ord(c) - index += 1 - return bytes - -def PRF(secret, label, seed, length): - #Split the secret into left and right halves - S1 = secret[ : int(math.ceil(len(secret)/2.0))] - S2 = secret[ int(math.floor(len(secret)/2.0)) : ] - - #Run the left half through P_MD5 and the right half through P_SHA1 - p_md5 = P_hash(md5, S1, concatArrays(stringToBytes(label), seed), length) - p_sha1 = P_hash(sha, S2, concatArrays(stringToBytes(label), seed), length) - - #XOR the output values and return the result - for x in range(length): - p_md5[x] ^= p_sha1[x] - return p_md5 - - -def PRF_SSL(secret, seed, length): - secretStr = bytesToString(secret) - seedStr = bytesToString(seed) - bytes = createByteArrayZeros(length) - index = 0 - for x in range(26): - A = chr(ord('A')+x) * (x+1) # 'A', 'BB', 'CCC', etc.. - input = secretStr + sha.sha(A + secretStr + seedStr).digest() - output = md5.md5(input).digest() - for c in output: - if index >= length: - return bytes - bytes[index] = ord(c) - index += 1 - return bytes - -def makeX(salt, username, password): - if len(username)>=256: - raise ValueError("username too long") - if len(salt)>=256: - raise ValueError("salt too long") - return stringToNumber(sha.sha(salt + sha.sha(username + ":" + password)\ - .digest()).digest()) - -#This function is used by VerifierDB.makeVerifier -def makeVerifier(username, password, bits): - bitsIndex = {1024:0, 1536:1, 2048:2, 3072:3, 4096:4, 6144:5, 8192:6}[bits] - g,N = goodGroupParameters[bitsIndex] - salt = bytesToString(getRandomBytes(16)) - x = makeX(salt, username, password) - verifier = powMod(g, x, N) - return N, g, salt, verifier - -def PAD(n, x): - nLength = len(numberToString(n)) - s = numberToString(x) - if len(s) < nLength: - s = ("\0" * (nLength-len(s))) + s - return s - -def makeU(N, A, B): - return stringToNumber(sha.sha(PAD(N, A) + PAD(N, B)).digest()) - -def makeK(N, g): - return stringToNumber(sha.sha(numberToString(N) + PAD(N, g)).digest()) - - -""" -MAC_SSL -Modified from Python HMAC by Trevor -""" - -class MAC_SSL: - """MAC_SSL class. - - This supports the API for Cryptographic Hash Functions (PEP 247). - """ - - def __init__(self, key, msg = None, digestmod = None): - """Create a new MAC_SSL object. - - key: key for the keyed hash object. - msg: Initial input for the hash, if provided. - digestmod: A module supporting PEP 247. Defaults to the md5 module. - """ - if digestmod is None: - import md5 - digestmod = md5 - - if key == None: #TREVNEW - for faster copying - return #TREVNEW - - self.digestmod = digestmod - self.outer = digestmod.new() - self.inner = digestmod.new() - self.digest_size = digestmod.digest_size - - ipad = "\x36" * 40 - opad = "\x5C" * 40 - - self.inner.update(key) - self.inner.update(ipad) - self.outer.update(key) - self.outer.update(opad) - if msg is not None: - self.update(msg) - - - def update(self, msg): - """Update this hashing object with the string msg. - """ - self.inner.update(msg) - - def copy(self): - """Return a separate copy of this hashing object. - - An update to this copy won't affect the original object. - """ - other = MAC_SSL(None) #TREVNEW - for faster copying - other.digest_size = self.digest_size #TREVNEW - other.digestmod = self.digestmod - other.inner = self.inner.copy() - other.outer = self.outer.copy() - return other - - def digest(self): - """Return the hash value of this hashing object. - - This returns a string containing 8-bit data. The object is - not altered in any way by this function; you can continue - updating the object after calling this function. - """ - h = self.outer.copy() - h.update(self.inner.digest()) - return h.digest() - - def hexdigest(self): - """Like digest(), but returns a string of hexadecimal digits instead. - """ - return "".join([hex(ord(x))[2:].zfill(2) - for x in tuple(self.digest())]) diff --git a/src/lib/tlslite/messages.py b/src/lib/tlslite/messages.py deleted file mode 100755 index afccc793a..000000000 --- a/src/lib/tlslite/messages.py +++ /dev/null @@ -1,561 +0,0 @@ -"""Classes representing TLS messages.""" - -from utils.compat import * -from utils.cryptomath import * -from errors import * -from utils.codec import * -from constants import * -from X509 import X509 -from X509CertChain import X509CertChain - -import sha -import md5 - -class RecordHeader3: - def __init__(self): - self.type = 0 - self.version = (0,0) - self.length = 0 - self.ssl2 = False - - def create(self, version, type, length): - self.type = type - self.version = version - self.length = length - return self - - def write(self): - w = Writer(5) - w.add(self.type, 1) - w.add(self.version[0], 1) - w.add(self.version[1], 1) - w.add(self.length, 2) - return w.bytes - - def parse(self, p): - self.type = p.get(1) - self.version = (p.get(1), p.get(1)) - self.length = p.get(2) - self.ssl2 = False - return self - -class RecordHeader2: - def __init__(self): - self.type = 0 - self.version = (0,0) - self.length = 0 - self.ssl2 = True - - def parse(self, p): - if p.get(1)!=128: - raise SyntaxError() - self.type = ContentType.handshake - self.version = (2,0) - #We don't support 2-byte-length-headers; could be a problem - self.length = p.get(1) - return self - - -class Msg: - def preWrite(self, trial): - if trial: - w = Writer() - else: - length = self.write(True) - w = Writer(length) - return w - - def postWrite(self, w, trial): - if trial: - return w.index - else: - return w.bytes - -class Alert(Msg): - def __init__(self): - self.contentType = ContentType.alert - self.level = 0 - self.description = 0 - - def create(self, description, level=AlertLevel.fatal): - self.level = level - self.description = description - return self - - def parse(self, p): - p.setLengthCheck(2) - self.level = p.get(1) - self.description = p.get(1) - p.stopLengthCheck() - return self - - def write(self): - w = Writer(2) - w.add(self.level, 1) - w.add(self.description, 1) - return w.bytes - - -class HandshakeMsg(Msg): - def preWrite(self, handshakeType, trial): - if trial: - w = Writer() - w.add(handshakeType, 1) - w.add(0, 3) - else: - length = self.write(True) - w = Writer(length) - w.add(handshakeType, 1) - w.add(length-4, 3) - return w - - -class ClientHello(HandshakeMsg): - def __init__(self, ssl2=False): - self.contentType = ContentType.handshake - self.ssl2 = ssl2 - self.client_version = (0,0) - self.random = createByteArrayZeros(32) - self.session_id = createByteArraySequence([]) - self.cipher_suites = [] # a list of 16-bit values - self.certificate_types = [CertificateType.x509] - self.compression_methods = [] # a list of 8-bit values - self.srp_username = None # a string - - def create(self, version, random, session_id, cipher_suites, - certificate_types=None, srp_username=None): - self.client_version = version - self.random = random - self.session_id = session_id - self.cipher_suites = cipher_suites - self.certificate_types = certificate_types - self.compression_methods = [0] - self.srp_username = srp_username - return self - - def parse(self, p): - if self.ssl2: - self.client_version = (p.get(1), p.get(1)) - cipherSpecsLength = p.get(2) - sessionIDLength = p.get(2) - randomLength = p.get(2) - self.cipher_suites = p.getFixList(3, int(cipherSpecsLength/3)) - self.session_id = p.getFixBytes(sessionIDLength) - self.random = p.getFixBytes(randomLength) - if len(self.random) < 32: - zeroBytes = 32-len(self.random) - self.random = createByteArrayZeros(zeroBytes) + self.random - self.compression_methods = [0]#Fake this value - - #We're not doing a stopLengthCheck() for SSLv2, oh well.. - else: - p.startLengthCheck(3) - self.client_version = (p.get(1), p.get(1)) - self.random = p.getFixBytes(32) - self.session_id = p.getVarBytes(1) - self.cipher_suites = p.getVarList(2, 2) - self.compression_methods = p.getVarList(1, 1) - if not p.atLengthCheck(): - totalExtLength = p.get(2) - soFar = 0 - while soFar != totalExtLength: - extType = p.get(2) - extLength = p.get(2) - if extType == 6: - self.srp_username = bytesToString(p.getVarBytes(1)) - elif extType == 7: - self.certificate_types = p.getVarList(1, 1) - else: - p.getFixBytes(extLength) - soFar += 4 + extLength - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.client_hello, trial) - w.add(self.client_version[0], 1) - w.add(self.client_version[1], 1) - w.addFixSeq(self.random, 1) - w.addVarSeq(self.session_id, 1, 1) - w.addVarSeq(self.cipher_suites, 2, 2) - w.addVarSeq(self.compression_methods, 1, 1) - - extLength = 0 - if self.certificate_types and self.certificate_types != \ - [CertificateType.x509]: - extLength += 5 + len(self.certificate_types) - if self.srp_username: - extLength += 5 + len(self.srp_username) - if extLength > 0: - w.add(extLength, 2) - - if self.certificate_types and self.certificate_types != \ - [CertificateType.x509]: - w.add(7, 2) - w.add(len(self.certificate_types)+1, 2) - w.addVarSeq(self.certificate_types, 1, 1) - if self.srp_username: - w.add(6, 2) - w.add(len(self.srp_username)+1, 2) - w.addVarSeq(stringToBytes(self.srp_username), 1, 1) - - return HandshakeMsg.postWrite(self, w, trial) - - -class ServerHello(HandshakeMsg): - def __init__(self): - self.contentType = ContentType.handshake - self.server_version = (0,0) - self.random = createByteArrayZeros(32) - self.session_id = createByteArraySequence([]) - self.cipher_suite = 0 - self.certificate_type = CertificateType.x509 - self.compression_method = 0 - - def create(self, version, random, session_id, cipher_suite, - certificate_type): - self.server_version = version - self.random = random - self.session_id = session_id - self.cipher_suite = cipher_suite - self.certificate_type = certificate_type - self.compression_method = 0 - return self - - def parse(self, p): - p.startLengthCheck(3) - self.server_version = (p.get(1), p.get(1)) - self.random = p.getFixBytes(32) - self.session_id = p.getVarBytes(1) - self.cipher_suite = p.get(2) - self.compression_method = p.get(1) - if not p.atLengthCheck(): - totalExtLength = p.get(2) - soFar = 0 - while soFar != totalExtLength: - extType = p.get(2) - extLength = p.get(2) - if extType == 7: - self.certificate_type = p.get(1) - else: - p.getFixBytes(extLength) - soFar += 4 + extLength - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.server_hello, trial) - w.add(self.server_version[0], 1) - w.add(self.server_version[1], 1) - w.addFixSeq(self.random, 1) - w.addVarSeq(self.session_id, 1, 1) - w.add(self.cipher_suite, 2) - w.add(self.compression_method, 1) - - extLength = 0 - if self.certificate_type and self.certificate_type != \ - CertificateType.x509: - extLength += 5 - - if extLength != 0: - w.add(extLength, 2) - - if self.certificate_type and self.certificate_type != \ - CertificateType.x509: - w.add(7, 2) - w.add(1, 2) - w.add(self.certificate_type, 1) - - return HandshakeMsg.postWrite(self, w, trial) - -class Certificate(HandshakeMsg): - def __init__(self, certificateType): - self.certificateType = certificateType - self.contentType = ContentType.handshake - self.certChain = None - - def create(self, certChain): - self.certChain = certChain - return self - - def parse(self, p): - p.startLengthCheck(3) - if self.certificateType == CertificateType.x509: - chainLength = p.get(3) - index = 0 - certificate_list = [] - while index != chainLength: - certBytes = p.getVarBytes(3) - x509 = X509() - x509.parseBinary(certBytes) - certificate_list.append(x509) - index += len(certBytes)+3 - if certificate_list: - self.certChain = X509CertChain(certificate_list) - elif self.certificateType == CertificateType.cryptoID: - s = bytesToString(p.getVarBytes(2)) - if s: - try: - import cryptoIDlib.CertChain - except ImportError: - raise SyntaxError(\ - "cryptoID cert chain received, cryptoIDlib not present") - self.certChain = cryptoIDlib.CertChain.CertChain().parse(s) - else: - raise AssertionError() - - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.certificate, trial) - if self.certificateType == CertificateType.x509: - chainLength = 0 - if self.certChain: - certificate_list = self.certChain.x509List - else: - certificate_list = [] - #determine length - for cert in certificate_list: - bytes = cert.writeBytes() - chainLength += len(bytes)+3 - #add bytes - w.add(chainLength, 3) - for cert in certificate_list: - bytes = cert.writeBytes() - w.addVarSeq(bytes, 1, 3) - elif self.certificateType == CertificateType.cryptoID: - if self.certChain: - bytes = stringToBytes(self.certChain.write()) - else: - bytes = createByteArraySequence([]) - w.addVarSeq(bytes, 1, 2) - else: - raise AssertionError() - return HandshakeMsg.postWrite(self, w, trial) - -class CertificateRequest(HandshakeMsg): - def __init__(self): - self.contentType = ContentType.handshake - self.certificate_types = [] - #treat as opaque bytes for now - self.certificate_authorities = createByteArraySequence([]) - - def create(self, certificate_types, certificate_authorities): - self.certificate_types = certificate_types - self.certificate_authorities = certificate_authorities - return self - - def parse(self, p): - p.startLengthCheck(3) - self.certificate_types = p.getVarList(1, 1) - self.certificate_authorities = p.getVarBytes(2) - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.certificate_request, - trial) - w.addVarSeq(self.certificate_types, 1, 1) - w.addVarSeq(self.certificate_authorities, 1, 2) - return HandshakeMsg.postWrite(self, w, trial) - -class ServerKeyExchange(HandshakeMsg): - def __init__(self, cipherSuite): - self.cipherSuite = cipherSuite - self.contentType = ContentType.handshake - self.srp_N = 0L - self.srp_g = 0L - self.srp_s = createByteArraySequence([]) - self.srp_B = 0L - self.signature = createByteArraySequence([]) - - def createSRP(self, srp_N, srp_g, srp_s, srp_B): - self.srp_N = srp_N - self.srp_g = srp_g - self.srp_s = srp_s - self.srp_B = srp_B - return self - - def parse(self, p): - p.startLengthCheck(3) - self.srp_N = bytesToNumber(p.getVarBytes(2)) - self.srp_g = bytesToNumber(p.getVarBytes(2)) - self.srp_s = p.getVarBytes(1) - self.srp_B = bytesToNumber(p.getVarBytes(2)) - if self.cipherSuite in CipherSuite.srpRsaSuites: - self.signature = p.getVarBytes(2) - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.server_key_exchange, - trial) - w.addVarSeq(numberToBytes(self.srp_N), 1, 2) - w.addVarSeq(numberToBytes(self.srp_g), 1, 2) - w.addVarSeq(self.srp_s, 1, 1) - w.addVarSeq(numberToBytes(self.srp_B), 1, 2) - if self.cipherSuite in CipherSuite.srpRsaSuites: - w.addVarSeq(self.signature, 1, 2) - return HandshakeMsg.postWrite(self, w, trial) - - def hash(self, clientRandom, serverRandom): - oldCipherSuite = self.cipherSuite - self.cipherSuite = None - try: - bytes = clientRandom + serverRandom + self.write()[4:] - s = bytesToString(bytes) - return stringToBytes(md5.md5(s).digest() + sha.sha(s).digest()) - finally: - self.cipherSuite = oldCipherSuite - -class ServerHelloDone(HandshakeMsg): - def __init__(self): - self.contentType = ContentType.handshake - - def create(self): - return self - - def parse(self, p): - p.startLengthCheck(3) - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.server_hello_done, trial) - return HandshakeMsg.postWrite(self, w, trial) - -class ClientKeyExchange(HandshakeMsg): - def __init__(self, cipherSuite, version=None): - self.cipherSuite = cipherSuite - self.version = version - self.contentType = ContentType.handshake - self.srp_A = 0 - self.encryptedPreMasterSecret = createByteArraySequence([]) - - def createSRP(self, srp_A): - self.srp_A = srp_A - return self - - def createRSA(self, encryptedPreMasterSecret): - self.encryptedPreMasterSecret = encryptedPreMasterSecret - return self - - def parse(self, p): - p.startLengthCheck(3) - if self.cipherSuite in CipherSuite.srpSuites + \ - CipherSuite.srpRsaSuites: - self.srp_A = bytesToNumber(p.getVarBytes(2)) - elif self.cipherSuite in CipherSuite.rsaSuites: - if self.version in ((3,1), (3,2)): - self.encryptedPreMasterSecret = p.getVarBytes(2) - elif self.version == (3,0): - self.encryptedPreMasterSecret = \ - p.getFixBytes(len(p.bytes)-p.index) - else: - raise AssertionError() - else: - raise AssertionError() - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.client_key_exchange, - trial) - if self.cipherSuite in CipherSuite.srpSuites + \ - CipherSuite.srpRsaSuites: - w.addVarSeq(numberToBytes(self.srp_A), 1, 2) - elif self.cipherSuite in CipherSuite.rsaSuites: - if self.version in ((3,1), (3,2)): - w.addVarSeq(self.encryptedPreMasterSecret, 1, 2) - elif self.version == (3,0): - w.addFixSeq(self.encryptedPreMasterSecret, 1) - else: - raise AssertionError() - else: - raise AssertionError() - return HandshakeMsg.postWrite(self, w, trial) - -class CertificateVerify(HandshakeMsg): - def __init__(self): - self.contentType = ContentType.handshake - self.signature = createByteArraySequence([]) - - def create(self, signature): - self.signature = signature - return self - - def parse(self, p): - p.startLengthCheck(3) - self.signature = p.getVarBytes(2) - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.certificate_verify, - trial) - w.addVarSeq(self.signature, 1, 2) - return HandshakeMsg.postWrite(self, w, trial) - -class ChangeCipherSpec(Msg): - def __init__(self): - self.contentType = ContentType.change_cipher_spec - self.type = 1 - - def create(self): - self.type = 1 - return self - - def parse(self, p): - p.setLengthCheck(1) - self.type = p.get(1) - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = Msg.preWrite(self, trial) - w.add(self.type,1) - return Msg.postWrite(self, w, trial) - - -class Finished(HandshakeMsg): - def __init__(self, version): - self.contentType = ContentType.handshake - self.version = version - self.verify_data = createByteArraySequence([]) - - def create(self, verify_data): - self.verify_data = verify_data - return self - - def parse(self, p): - p.startLengthCheck(3) - if self.version == (3,0): - self.verify_data = p.getFixBytes(36) - elif self.version in ((3,1), (3,2)): - self.verify_data = p.getFixBytes(12) - else: - raise AssertionError() - p.stopLengthCheck() - return self - - def write(self, trial=False): - w = HandshakeMsg.preWrite(self, HandshakeType.finished, trial) - w.addFixSeq(self.verify_data, 1) - return HandshakeMsg.postWrite(self, w, trial) - -class ApplicationData(Msg): - def __init__(self): - self.contentType = ContentType.application_data - self.bytes = createByteArraySequence([]) - - def create(self, bytes): - self.bytes = bytes - return self - - def parse(self, p): - self.bytes = p.bytes - return self - - def write(self): - return self.bytes \ No newline at end of file diff --git a/src/lib/tlslite/utils/AES.py b/src/lib/tlslite/utils/AES.py deleted file mode 100755 index 8413f4c10..000000000 --- a/src/lib/tlslite/utils/AES.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Abstract class for AES.""" - -class AES: - def __init__(self, key, mode, IV, implementation): - if len(key) not in (16, 24, 32): - raise AssertionError() - if mode != 2: - raise AssertionError() - if len(IV) != 16: - raise AssertionError() - self.isBlockCipher = True - self.block_size = 16 - self.implementation = implementation - if len(key)==16: - self.name = "aes128" - elif len(key)==24: - self.name = "aes192" - elif len(key)==32: - self.name = "aes256" - else: - raise AssertionError() - - #CBC-Mode encryption, returns ciphertext - #WARNING: *MAY* modify the input as well - def encrypt(self, plaintext): - assert(len(plaintext) % 16 == 0) - - #CBC-Mode decryption, returns plaintext - #WARNING: *MAY* modify the input as well - def decrypt(self, ciphertext): - assert(len(ciphertext) % 16 == 0) \ No newline at end of file diff --git a/src/lib/tlslite/utils/ASN1Parser.py b/src/lib/tlslite/utils/ASN1Parser.py deleted file mode 100755 index 16b50f29c..000000000 --- a/src/lib/tlslite/utils/ASN1Parser.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Class for parsing ASN.1""" -from compat import * -from codec import * - -#Takes a byte array which has a DER TLV field at its head -class ASN1Parser: - def __init__(self, bytes): - p = Parser(bytes) - p.get(1) #skip Type - - #Get Length - self.length = self._getASN1Length(p) - - #Get Value - self.value = p.getFixBytes(self.length) - - #Assuming this is a sequence... - def getChild(self, which): - p = Parser(self.value) - for x in range(which+1): - markIndex = p.index - p.get(1) #skip Type - length = self._getASN1Length(p) - p.getFixBytes(length) - return ASN1Parser(p.bytes[markIndex : p.index]) - - #Decode the ASN.1 DER length field - def _getASN1Length(self, p): - firstLength = p.get(1) - if firstLength<=127: - return firstLength - else: - lengthLength = firstLength & 0x7F - return p.get(lengthLength) diff --git a/src/lib/tlslite/utils/Cryptlib_AES.py b/src/lib/tlslite/utils/Cryptlib_AES.py deleted file mode 100755 index 9e101fc62..000000000 --- a/src/lib/tlslite/utils/Cryptlib_AES.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Cryptlib AES implementation.""" - -from cryptomath import * -from AES import * - -if cryptlibpyLoaded: - - def new(key, mode, IV): - return Cryptlib_AES(key, mode, IV) - - class Cryptlib_AES(AES): - - def __init__(self, key, mode, IV): - AES.__init__(self, key, mode, IV, "cryptlib") - self.context = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, cryptlib_py.CRYPT_ALGO_AES) - cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_MODE, cryptlib_py.CRYPT_MODE_CBC) - cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_KEYSIZE, len(key)) - cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_KEY, key) - cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_IV, IV) - - def __del__(self): - cryptlib_py.cryptDestroyContext(self.context) - - def encrypt(self, plaintext): - AES.encrypt(self, plaintext) - bytes = stringToBytes(plaintext) - cryptlib_py.cryptEncrypt(self.context, bytes) - return bytesToString(bytes) - - def decrypt(self, ciphertext): - AES.decrypt(self, ciphertext) - bytes = stringToBytes(ciphertext) - cryptlib_py.cryptDecrypt(self.context, bytes) - return bytesToString(bytes) diff --git a/src/lib/tlslite/utils/Cryptlib_RC4.py b/src/lib/tlslite/utils/Cryptlib_RC4.py deleted file mode 100755 index 7c6d087b8..000000000 --- a/src/lib/tlslite/utils/Cryptlib_RC4.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Cryptlib RC4 implementation.""" - -from cryptomath import * -from RC4 import RC4 - -if cryptlibpyLoaded: - - def new(key): - return Cryptlib_RC4(key) - - class Cryptlib_RC4(RC4): - - def __init__(self, key): - RC4.__init__(self, key, "cryptlib") - self.context = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, cryptlib_py.CRYPT_ALGO_RC4) - cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_KEYSIZE, len(key)) - cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_KEY, key) - - def __del__(self): - cryptlib_py.cryptDestroyContext(self.context) - - def encrypt(self, plaintext): - bytes = stringToBytes(plaintext) - cryptlib_py.cryptEncrypt(self.context, bytes) - return bytesToString(bytes) - - def decrypt(self, ciphertext): - return self.encrypt(ciphertext) \ No newline at end of file diff --git a/src/lib/tlslite/utils/Cryptlib_TripleDES.py b/src/lib/tlslite/utils/Cryptlib_TripleDES.py deleted file mode 100755 index a4f8155a0..000000000 --- a/src/lib/tlslite/utils/Cryptlib_TripleDES.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Cryptlib 3DES implementation.""" - -from cryptomath import * - -from TripleDES import * - -if cryptlibpyLoaded: - - def new(key, mode, IV): - return Cryptlib_TripleDES(key, mode, IV) - - class Cryptlib_TripleDES(TripleDES): - - def __init__(self, key, mode, IV): - TripleDES.__init__(self, key, mode, IV, "cryptlib") - self.context = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, cryptlib_py.CRYPT_ALGO_3DES) - cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_MODE, cryptlib_py.CRYPT_MODE_CBC) - cryptlib_py.cryptSetAttribute(self.context, cryptlib_py.CRYPT_CTXINFO_KEYSIZE, len(key)) - cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_KEY, key) - cryptlib_py.cryptSetAttributeString(self.context, cryptlib_py.CRYPT_CTXINFO_IV, IV) - - def __del__(self): - cryptlib_py.cryptDestroyContext(self.context) - - def encrypt(self, plaintext): - TripleDES.encrypt(self, plaintext) - bytes = stringToBytes(plaintext) - cryptlib_py.cryptEncrypt(self.context, bytes) - return bytesToString(bytes) - - def decrypt(self, ciphertext): - TripleDES.decrypt(self, ciphertext) - bytes = stringToBytes(ciphertext) - cryptlib_py.cryptDecrypt(self.context, bytes) - return bytesToString(bytes) \ No newline at end of file diff --git a/src/lib/tlslite/utils/OpenSSL_AES.py b/src/lib/tlslite/utils/OpenSSL_AES.py deleted file mode 100755 index e60679bf5..000000000 --- a/src/lib/tlslite/utils/OpenSSL_AES.py +++ /dev/null @@ -1,49 +0,0 @@ -"""OpenSSL/M2Crypto AES implementation.""" - -from cryptomath import * -from AES import * - -if m2cryptoLoaded: - - def new(key, mode, IV): - return OpenSSL_AES(key, mode, IV) - - class OpenSSL_AES(AES): - - def __init__(self, key, mode, IV): - AES.__init__(self, key, mode, IV, "openssl") - self.key = key - self.IV = IV - - def _createContext(self, encrypt): - context = m2.cipher_ctx_new() - if len(self.key)==16: - cipherType = m2.aes_128_cbc() - if len(self.key)==24: - cipherType = m2.aes_192_cbc() - if len(self.key)==32: - cipherType = m2.aes_256_cbc() - m2.cipher_init(context, cipherType, self.key, self.IV, encrypt) - return context - - def encrypt(self, plaintext): - AES.encrypt(self, plaintext) - context = self._createContext(1) - ciphertext = m2.cipher_update(context, plaintext) - m2.cipher_ctx_free(context) - self.IV = ciphertext[-self.block_size:] - return ciphertext - - def decrypt(self, ciphertext): - AES.decrypt(self, ciphertext) - context = self._createContext(0) - #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in. - #To work around this, we append sixteen zeros to the string, below: - plaintext = m2.cipher_update(context, ciphertext+('\0'*16)) - - #If this bug is ever fixed, then plaintext will end up having a garbage - #plaintext block on the end. That's okay - the below code will discard it. - plaintext = plaintext[:len(ciphertext)] - m2.cipher_ctx_free(context) - self.IV = ciphertext[-self.block_size:] - return plaintext diff --git a/src/lib/tlslite/utils/OpenSSL_RC4.py b/src/lib/tlslite/utils/OpenSSL_RC4.py deleted file mode 100755 index ac433aad7..000000000 --- a/src/lib/tlslite/utils/OpenSSL_RC4.py +++ /dev/null @@ -1,25 +0,0 @@ -"""OpenSSL/M2Crypto RC4 implementation.""" - -from cryptomath import * -from RC4 import RC4 - -if m2cryptoLoaded: - - def new(key): - return OpenSSL_RC4(key) - - class OpenSSL_RC4(RC4): - - def __init__(self, key): - RC4.__init__(self, key, "openssl") - self.rc4 = m2.rc4_new() - m2.rc4_set_key(self.rc4, key) - - def __del__(self): - m2.rc4_free(self.rc4) - - def encrypt(self, plaintext): - return m2.rc4_update(self.rc4, plaintext) - - def decrypt(self, ciphertext): - return self.encrypt(ciphertext) diff --git a/src/lib/tlslite/utils/OpenSSL_RSAKey.py b/src/lib/tlslite/utils/OpenSSL_RSAKey.py deleted file mode 100755 index fe1a3cd74..000000000 --- a/src/lib/tlslite/utils/OpenSSL_RSAKey.py +++ /dev/null @@ -1,148 +0,0 @@ -"""OpenSSL/M2Crypto RSA implementation.""" - -from cryptomath import * - -from RSAKey import * -from Python_RSAKey import Python_RSAKey - -#copied from M2Crypto.util.py, so when we load the local copy of m2 -#we can still use it -def password_callback(v, prompt1='Enter private key passphrase:', - prompt2='Verify passphrase:'): - from getpass import getpass - while 1: - try: - p1=getpass(prompt1) - if v: - p2=getpass(prompt2) - if p1==p2: - break - else: - break - except KeyboardInterrupt: - return None - return p1 - - -if m2cryptoLoaded: - class OpenSSL_RSAKey(RSAKey): - def __init__(self, n=0, e=0): - self.rsa = None - self._hasPrivateKey = False - if (n and not e) or (e and not n): - raise AssertionError() - if n and e: - self.rsa = m2.rsa_new() - m2.rsa_set_n(self.rsa, numberToMPI(n)) - m2.rsa_set_e(self.rsa, numberToMPI(e)) - - def __del__(self): - if self.rsa: - m2.rsa_free(self.rsa) - - def __getattr__(self, name): - if name == 'e': - if not self.rsa: - return 0 - return mpiToNumber(m2.rsa_get_e(self.rsa)) - elif name == 'n': - if not self.rsa: - return 0 - return mpiToNumber(m2.rsa_get_n(self.rsa)) - else: - raise AttributeError - - def hasPrivateKey(self): - return self._hasPrivateKey - - def hash(self): - return Python_RSAKey(self.n, self.e).hash() - - def _rawPrivateKeyOp(self, m): - s = numberToString(m) - byteLength = numBytes(self.n) - if len(s)== byteLength: - pass - elif len(s) == byteLength-1: - s = '\0' + s - else: - raise AssertionError() - c = stringToNumber(m2.rsa_private_encrypt(self.rsa, s, - m2.no_padding)) - return c - - def _rawPublicKeyOp(self, c): - s = numberToString(c) - byteLength = numBytes(self.n) - if len(s)== byteLength: - pass - elif len(s) == byteLength-1: - s = '\0' + s - else: - raise AssertionError() - m = stringToNumber(m2.rsa_public_decrypt(self.rsa, s, - m2.no_padding)) - return m - - def acceptsPassword(self): return True - - def write(self, password=None): - bio = m2.bio_new(m2.bio_s_mem()) - if self._hasPrivateKey: - if password: - def f(v): return password - m2.rsa_write_key(self.rsa, bio, m2.des_ede_cbc(), f) - else: - def f(): pass - m2.rsa_write_key_no_cipher(self.rsa, bio, f) - else: - if password: - raise AssertionError() - m2.rsa_write_pub_key(self.rsa, bio) - s = m2.bio_read(bio, m2.bio_ctrl_pending(bio)) - m2.bio_free(bio) - return s - - def writeXMLPublicKey(self, indent=''): - return Python_RSAKey(self.n, self.e).write(indent) - - def generate(bits): - key = OpenSSL_RSAKey() - def f():pass - key.rsa = m2.rsa_generate_key(bits, 3, f) - key._hasPrivateKey = True - return key - generate = staticmethod(generate) - - def parse(s, passwordCallback=None): - if s.startswith("-----BEGIN "): - if passwordCallback==None: - callback = password_callback - else: - def f(v, prompt1=None, prompt2=None): - return passwordCallback() - callback = f - bio = m2.bio_new(m2.bio_s_mem()) - try: - m2.bio_write(bio, s) - key = OpenSSL_RSAKey() - if s.startswith("-----BEGIN RSA PRIVATE KEY-----"): - def f():pass - key.rsa = m2.rsa_read_key(bio, callback) - if key.rsa == None: - raise SyntaxError() - key._hasPrivateKey = True - elif s.startswith("-----BEGIN PUBLIC KEY-----"): - key.rsa = m2.rsa_read_pub_key(bio) - if key.rsa == None: - raise SyntaxError() - key._hasPrivateKey = False - else: - raise SyntaxError() - return key - finally: - m2.bio_free(bio) - else: - raise SyntaxError() - - parse = staticmethod(parse) diff --git a/src/lib/tlslite/utils/OpenSSL_TripleDES.py b/src/lib/tlslite/utils/OpenSSL_TripleDES.py deleted file mode 100755 index f5ba16565..000000000 --- a/src/lib/tlslite/utils/OpenSSL_TripleDES.py +++ /dev/null @@ -1,44 +0,0 @@ -"""OpenSSL/M2Crypto 3DES implementation.""" - -from cryptomath import * -from TripleDES import * - -if m2cryptoLoaded: - - def new(key, mode, IV): - return OpenSSL_TripleDES(key, mode, IV) - - class OpenSSL_TripleDES(TripleDES): - - def __init__(self, key, mode, IV): - TripleDES.__init__(self, key, mode, IV, "openssl") - self.key = key - self.IV = IV - - def _createContext(self, encrypt): - context = m2.cipher_ctx_new() - cipherType = m2.des_ede3_cbc() - m2.cipher_init(context, cipherType, self.key, self.IV, encrypt) - return context - - def encrypt(self, plaintext): - TripleDES.encrypt(self, plaintext) - context = self._createContext(1) - ciphertext = m2.cipher_update(context, plaintext) - m2.cipher_ctx_free(context) - self.IV = ciphertext[-self.block_size:] - return ciphertext - - def decrypt(self, ciphertext): - TripleDES.decrypt(self, ciphertext) - context = self._createContext(0) - #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in. - #To work around this, we append sixteen zeros to the string, below: - plaintext = m2.cipher_update(context, ciphertext+('\0'*16)) - - #If this bug is ever fixed, then plaintext will end up having a garbage - #plaintext block on the end. That's okay - the below code will ignore it. - plaintext = plaintext[:len(ciphertext)] - m2.cipher_ctx_free(context) - self.IV = ciphertext[-self.block_size:] - return plaintext \ No newline at end of file diff --git a/src/lib/tlslite/utils/PyCrypto_AES.py b/src/lib/tlslite/utils/PyCrypto_AES.py deleted file mode 100755 index e38b19d6f..000000000 --- a/src/lib/tlslite/utils/PyCrypto_AES.py +++ /dev/null @@ -1,22 +0,0 @@ -"""PyCrypto AES implementation.""" - -from cryptomath import * -from AES import * - -if pycryptoLoaded: - import Crypto.Cipher.AES - - def new(key, mode, IV): - return PyCrypto_AES(key, mode, IV) - - class PyCrypto_AES(AES): - - def __init__(self, key, mode, IV): - AES.__init__(self, key, mode, IV, "pycrypto") - self.context = Crypto.Cipher.AES.new(key, mode, IV) - - def encrypt(self, plaintext): - return self.context.encrypt(plaintext) - - def decrypt(self, ciphertext): - return self.context.decrypt(ciphertext) \ No newline at end of file diff --git a/src/lib/tlslite/utils/PyCrypto_RC4.py b/src/lib/tlslite/utils/PyCrypto_RC4.py deleted file mode 100755 index 6c6d86afd..000000000 --- a/src/lib/tlslite/utils/PyCrypto_RC4.py +++ /dev/null @@ -1,22 +0,0 @@ -"""PyCrypto RC4 implementation.""" - -from cryptomath import * -from RC4 import * - -if pycryptoLoaded: - import Crypto.Cipher.ARC4 - - def new(key): - return PyCrypto_RC4(key) - - class PyCrypto_RC4(RC4): - - def __init__(self, key): - RC4.__init__(self, key, "pycrypto") - self.context = Crypto.Cipher.ARC4.new(key) - - def encrypt(self, plaintext): - return self.context.encrypt(plaintext) - - def decrypt(self, ciphertext): - return self.context.decrypt(ciphertext) \ No newline at end of file diff --git a/src/lib/tlslite/utils/PyCrypto_RSAKey.py b/src/lib/tlslite/utils/PyCrypto_RSAKey.py deleted file mode 100755 index 48b5cef03..000000000 --- a/src/lib/tlslite/utils/PyCrypto_RSAKey.py +++ /dev/null @@ -1,61 +0,0 @@ -"""PyCrypto RSA implementation.""" - -from cryptomath import * - -from RSAKey import * -from Python_RSAKey import Python_RSAKey - -if pycryptoLoaded: - - from Crypto.PublicKey import RSA - - class PyCrypto_RSAKey(RSAKey): - def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0): - if not d: - self.rsa = RSA.construct( (n, e) ) - else: - self.rsa = RSA.construct( (n, e, d, p, q) ) - - def __getattr__(self, name): - return getattr(self.rsa, name) - - def hasPrivateKey(self): - return self.rsa.has_private() - - def hash(self): - return Python_RSAKey(self.n, self.e).hash() - - def _rawPrivateKeyOp(self, m): - s = numberToString(m) - byteLength = numBytes(self.n) - if len(s)== byteLength: - pass - elif len(s) == byteLength-1: - s = '\0' + s - else: - raise AssertionError() - c = stringToNumber(self.rsa.decrypt((s,))) - return c - - def _rawPublicKeyOp(self, c): - s = numberToString(c) - byteLength = numBytes(self.n) - if len(s)== byteLength: - pass - elif len(s) == byteLength-1: - s = '\0' + s - else: - raise AssertionError() - m = stringToNumber(self.rsa.encrypt(s, None)[0]) - return m - - def writeXMLPublicKey(self, indent=''): - return Python_RSAKey(self.n, self.e).write(indent) - - def generate(bits): - key = PyCrypto_RSAKey() - def f(numBytes): - return bytesToString(getRandomBytes(numBytes)) - key.rsa = RSA.generate(bits, f) - return key - generate = staticmethod(generate) diff --git a/src/lib/tlslite/utils/PyCrypto_TripleDES.py b/src/lib/tlslite/utils/PyCrypto_TripleDES.py deleted file mode 100755 index 8c22bb80a..000000000 --- a/src/lib/tlslite/utils/PyCrypto_TripleDES.py +++ /dev/null @@ -1,22 +0,0 @@ -"""PyCrypto 3DES implementation.""" - -from cryptomath import * -from TripleDES import * - -if pycryptoLoaded: - import Crypto.Cipher.DES3 - - def new(key, mode, IV): - return PyCrypto_TripleDES(key, mode, IV) - - class PyCrypto_TripleDES(TripleDES): - - def __init__(self, key, mode, IV): - TripleDES.__init__(self, key, mode, IV, "pycrypto") - self.context = Crypto.Cipher.DES3.new(key, mode, IV) - - def encrypt(self, plaintext): - return self.context.encrypt(plaintext) - - def decrypt(self, ciphertext): - return self.context.decrypt(ciphertext) \ No newline at end of file diff --git a/src/lib/tlslite/utils/Python_AES.py b/src/lib/tlslite/utils/Python_AES.py deleted file mode 100755 index 657152f89..000000000 --- a/src/lib/tlslite/utils/Python_AES.py +++ /dev/null @@ -1,68 +0,0 @@ -"""Pure-Python AES implementation.""" - -from cryptomath import * - -from AES import * -from rijndael import rijndael - -def new(key, mode, IV): - return Python_AES(key, mode, IV) - -class Python_AES(AES): - def __init__(self, key, mode, IV): - AES.__init__(self, key, mode, IV, "python") - self.rijndael = rijndael(key, 16) - self.IV = IV - - def encrypt(self, plaintext): - AES.encrypt(self, plaintext) - - plaintextBytes = stringToBytes(plaintext) - chainBytes = stringToBytes(self.IV) - - #CBC Mode: For each block... - for x in range(len(plaintextBytes)/16): - - #XOR with the chaining block - blockBytes = plaintextBytes[x*16 : (x*16)+16] - for y in range(16): - blockBytes[y] ^= chainBytes[y] - blockString = bytesToString(blockBytes) - - #Encrypt it - encryptedBytes = stringToBytes(self.rijndael.encrypt(blockString)) - - #Overwrite the input with the output - for y in range(16): - plaintextBytes[(x*16)+y] = encryptedBytes[y] - - #Set the next chaining block - chainBytes = encryptedBytes - - self.IV = bytesToString(chainBytes) - return bytesToString(plaintextBytes) - - def decrypt(self, ciphertext): - AES.decrypt(self, ciphertext) - - ciphertextBytes = stringToBytes(ciphertext) - chainBytes = stringToBytes(self.IV) - - #CBC Mode: For each block... - for x in range(len(ciphertextBytes)/16): - - #Decrypt it - blockBytes = ciphertextBytes[x*16 : (x*16)+16] - blockString = bytesToString(blockBytes) - decryptedBytes = stringToBytes(self.rijndael.decrypt(blockString)) - - #XOR with the chaining block and overwrite the input with output - for y in range(16): - decryptedBytes[y] ^= chainBytes[y] - ciphertextBytes[(x*16)+y] = decryptedBytes[y] - - #Set the next chaining block - chainBytes = blockBytes - - self.IV = bytesToString(chainBytes) - return bytesToString(ciphertextBytes) diff --git a/src/lib/tlslite/utils/Python_RC4.py b/src/lib/tlslite/utils/Python_RC4.py deleted file mode 100755 index 56ce5fb2f..000000000 --- a/src/lib/tlslite/utils/Python_RC4.py +++ /dev/null @@ -1,39 +0,0 @@ -"""Pure-Python RC4 implementation.""" - -from RC4 import RC4 -from cryptomath import * - -def new(key): - return Python_RC4(key) - -class Python_RC4(RC4): - def __init__(self, key): - RC4.__init__(self, key, "python") - keyBytes = stringToBytes(key) - S = [i for i in range(256)] - j = 0 - for i in range(256): - j = (j + S[i] + keyBytes[i % len(keyBytes)]) % 256 - S[i], S[j] = S[j], S[i] - - self.S = S - self.i = 0 - self.j = 0 - - def encrypt(self, plaintext): - plaintextBytes = stringToBytes(plaintext) - S = self.S - i = self.i - j = self.j - for x in range(len(plaintextBytes)): - i = (i + 1) % 256 - j = (j + S[i]) % 256 - S[i], S[j] = S[j], S[i] - t = (S[i] + S[j]) % 256 - plaintextBytes[x] ^= S[t] - self.i = i - self.j = j - return bytesToString(plaintextBytes) - - def decrypt(self, ciphertext): - return self.encrypt(ciphertext) diff --git a/src/lib/tlslite/utils/Python_RSAKey.py b/src/lib/tlslite/utils/Python_RSAKey.py deleted file mode 100755 index 2c469b572..000000000 --- a/src/lib/tlslite/utils/Python_RSAKey.py +++ /dev/null @@ -1,209 +0,0 @@ -"""Pure-Python RSA implementation.""" - -from cryptomath import * -import xmltools -from ASN1Parser import ASN1Parser -from RSAKey import * - -class Python_RSAKey(RSAKey): - def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0): - if (n and not e) or (e and not n): - raise AssertionError() - self.n = n - self.e = e - self.d = d - self.p = p - self.q = q - self.dP = dP - self.dQ = dQ - self.qInv = qInv - self.blinder = 0 - self.unblinder = 0 - - def hasPrivateKey(self): - return self.d != 0 - - def hash(self): - s = self.writeXMLPublicKey('\t\t') - return hashAndBase64(s.strip()) - - def _rawPrivateKeyOp(self, m): - #Create blinding values, on the first pass: - if not self.blinder: - self.unblinder = getRandomNumber(2, self.n) - self.blinder = powMod(invMod(self.unblinder, self.n), self.e, - self.n) - - #Blind the input - m = (m * self.blinder) % self.n - - #Perform the RSA operation - c = self._rawPrivateKeyOpHelper(m) - - #Unblind the output - c = (c * self.unblinder) % self.n - - #Update blinding values - self.blinder = (self.blinder * self.blinder) % self.n - self.unblinder = (self.unblinder * self.unblinder) % self.n - - #Return the output - return c - - - def _rawPrivateKeyOpHelper(self, m): - #Non-CRT version - #c = powMod(m, self.d, self.n) - - #CRT version (~3x faster) - s1 = powMod(m, self.dP, self.p) - s2 = powMod(m, self.dQ, self.q) - h = ((s1 - s2) * self.qInv) % self.p - c = s2 + self.q * h - return c - - def _rawPublicKeyOp(self, c): - m = powMod(c, self.e, self.n) - return m - - def acceptsPassword(self): return False - - def write(self, indent=''): - if self.d: - s = indent+'\n' - else: - s = indent+'\n' - s += indent+'\t%s\n' % numberToBase64(self.n) - s += indent+'\t%s\n' % numberToBase64(self.e) - if self.d: - s += indent+'\t%s\n' % numberToBase64(self.d) - s += indent+'\t

%s

\n' % numberToBase64(self.p) - s += indent+'\t%s\n' % numberToBase64(self.q) - s += indent+'\t%s\n' % numberToBase64(self.dP) - s += indent+'\t%s\n' % numberToBase64(self.dQ) - s += indent+'\t%s\n' % numberToBase64(self.qInv) - s += indent+'
' - else: - s += indent+'' - #Only add \n if part of a larger structure - if indent != '': - s += '\n' - return s - - def writeXMLPublicKey(self, indent=''): - return Python_RSAKey(self.n, self.e).write(indent) - - def generate(bits): - key = Python_RSAKey() - p = getRandomPrime(bits/2, False) - q = getRandomPrime(bits/2, False) - t = lcm(p-1, q-1) - key.n = p * q - key.e = 3L #Needed to be long, for Java - key.d = invMod(key.e, t) - key.p = p - key.q = q - key.dP = key.d % (p-1) - key.dQ = key.d % (q-1) - key.qInv = invMod(q, p) - return key - generate = staticmethod(generate) - - def parsePEM(s, passwordCallback=None): - """Parse a string containing a or , or - PEM-encoded key.""" - - start = s.find("-----BEGIN PRIVATE KEY-----") - if start != -1: - end = s.find("-----END PRIVATE KEY-----") - if end == -1: - raise SyntaxError("Missing PEM Postfix") - s = s[start+len("-----BEGIN PRIVATE KEY -----") : end] - bytes = base64ToBytes(s) - return Python_RSAKey._parsePKCS8(bytes) - else: - start = s.find("-----BEGIN RSA PRIVATE KEY-----") - if start != -1: - end = s.find("-----END RSA PRIVATE KEY-----") - if end == -1: - raise SyntaxError("Missing PEM Postfix") - s = s[start+len("-----BEGIN RSA PRIVATE KEY -----") : end] - bytes = base64ToBytes(s) - return Python_RSAKey._parseSSLeay(bytes) - raise SyntaxError("Missing PEM Prefix") - parsePEM = staticmethod(parsePEM) - - def parseXML(s): - element = xmltools.parseAndStripWhitespace(s) - return Python_RSAKey._parseXML(element) - parseXML = staticmethod(parseXML) - - def _parsePKCS8(bytes): - p = ASN1Parser(bytes) - - version = p.getChild(0).value[0] - if version != 0: - raise SyntaxError("Unrecognized PKCS8 version") - - rsaOID = p.getChild(1).value - if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]: - raise SyntaxError("Unrecognized AlgorithmIdentifier") - - #Get the privateKey - privateKeyP = p.getChild(2) - - #Adjust for OCTET STRING encapsulation - privateKeyP = ASN1Parser(privateKeyP.value) - - return Python_RSAKey._parseASN1PrivateKey(privateKeyP) - _parsePKCS8 = staticmethod(_parsePKCS8) - - def _parseSSLeay(bytes): - privateKeyP = ASN1Parser(bytes) - return Python_RSAKey._parseASN1PrivateKey(privateKeyP) - _parseSSLeay = staticmethod(_parseSSLeay) - - def _parseASN1PrivateKey(privateKeyP): - version = privateKeyP.getChild(0).value[0] - if version != 0: - raise SyntaxError("Unrecognized RSAPrivateKey version") - n = bytesToNumber(privateKeyP.getChild(1).value) - e = bytesToNumber(privateKeyP.getChild(2).value) - d = bytesToNumber(privateKeyP.getChild(3).value) - p = bytesToNumber(privateKeyP.getChild(4).value) - q = bytesToNumber(privateKeyP.getChild(5).value) - dP = bytesToNumber(privateKeyP.getChild(6).value) - dQ = bytesToNumber(privateKeyP.getChild(7).value) - qInv = bytesToNumber(privateKeyP.getChild(8).value) - return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv) - _parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey) - - def _parseXML(element): - try: - xmltools.checkName(element, "privateKey") - except SyntaxError: - xmltools.checkName(element, "publicKey") - - #Parse attributes - xmltools.getReqAttribute(element, "xmlns", "http://trevp.net/rsa\Z") - xmltools.checkNoMoreAttributes(element) - - #Parse public values ( and ) - n = base64ToNumber(xmltools.getText(xmltools.getChild(element, 0, "n"), xmltools.base64RegEx)) - e = base64ToNumber(xmltools.getText(xmltools.getChild(element, 1, "e"), xmltools.base64RegEx)) - d = 0 - p = 0 - q = 0 - dP = 0 - dQ = 0 - qInv = 0 - #Parse private values, if present - if element.childNodes.length>=3: - d = base64ToNumber(xmltools.getText(xmltools.getChild(element, 2, "d"), xmltools.base64RegEx)) - p = base64ToNumber(xmltools.getText(xmltools.getChild(element, 3, "p"), xmltools.base64RegEx)) - q = base64ToNumber(xmltools.getText(xmltools.getChild(element, 4, "q"), xmltools.base64RegEx)) - dP = base64ToNumber(xmltools.getText(xmltools.getChild(element, 5, "dP"), xmltools.base64RegEx)) - dQ = base64ToNumber(xmltools.getText(xmltools.getChild(element, 6, "dQ"), xmltools.base64RegEx)) - qInv = base64ToNumber(xmltools.getText(xmltools.getLastChild(element, 7, "qInv"), xmltools.base64RegEx)) - return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv) - _parseXML = staticmethod(_parseXML) diff --git a/src/lib/tlslite/utils/RC4.py b/src/lib/tlslite/utils/RC4.py deleted file mode 100755 index 550692327..000000000 --- a/src/lib/tlslite/utils/RC4.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Abstract class for RC4.""" - -from compat import * #For False - -class RC4: - def __init__(self, keyBytes, implementation): - if len(keyBytes) < 16 or len(keyBytes) > 256: - raise ValueError() - self.isBlockCipher = False - self.name = "rc4" - self.implementation = implementation - - def encrypt(self, plaintext): - raise NotImplementedError() - - def decrypt(self, ciphertext): - raise NotImplementedError() \ No newline at end of file diff --git a/src/lib/tlslite/utils/RSAKey.py b/src/lib/tlslite/utils/RSAKey.py deleted file mode 100755 index 37c292df5..000000000 --- a/src/lib/tlslite/utils/RSAKey.py +++ /dev/null @@ -1,264 +0,0 @@ -"""Abstract class for RSA.""" - -from cryptomath import * - - -class RSAKey: - """This is an abstract base class for RSA keys. - - Particular implementations of RSA keys, such as - L{OpenSSL_RSAKey.OpenSSL_RSAKey}, - L{Python_RSAKey.Python_RSAKey}, and - L{PyCrypto_RSAKey.PyCrypto_RSAKey}, - inherit from this. - - To create or parse an RSA key, don't use one of these classes - directly. Instead, use the factory functions in - L{tlslite.utils.keyfactory}. - """ - - def __init__(self, n=0, e=0): - """Create a new RSA key. - - If n and e are passed in, the new key will be initialized. - - @type n: int - @param n: RSA modulus. - - @type e: int - @param e: RSA public exponent. - """ - raise NotImplementedError() - - def __len__(self): - """Return the length of this key in bits. - - @rtype: int - """ - return numBits(self.n) - - def hasPrivateKey(self): - """Return whether or not this key has a private component. - - @rtype: bool - """ - raise NotImplementedError() - - def hash(self): - """Return the cryptoID value corresponding to this - key. - - @rtype: str - """ - raise NotImplementedError() - - def getSigningAlgorithm(self): - """Return the cryptoID sigAlgo value corresponding to this key. - - @rtype: str - """ - return "pkcs1-sha1" - - def hashAndSign(self, bytes): - """Hash and sign the passed-in bytes. - - This requires the key to have a private component. It performs - a PKCS1-SHA1 signature on the passed-in data. - - @type bytes: str or L{array.array} of unsigned bytes - @param bytes: The value which will be hashed and signed. - - @rtype: L{array.array} of unsigned bytes. - @return: A PKCS1-SHA1 signature on the passed-in data. - """ - if not isinstance(bytes, type("")): - bytes = bytesToString(bytes) - hashBytes = stringToBytes(sha.sha(bytes).digest()) - prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) - sigBytes = self.sign(prefixedHashBytes) - return sigBytes - - def hashAndVerify(self, sigBytes, bytes): - """Hash and verify the passed-in bytes with the signature. - - This verifies a PKCS1-SHA1 signature on the passed-in data. - - @type sigBytes: L{array.array} of unsigned bytes - @param sigBytes: A PKCS1-SHA1 signature. - - @type bytes: str or L{array.array} of unsigned bytes - @param bytes: The value which will be hashed and verified. - - @rtype: bool - @return: Whether the signature matches the passed-in data. - """ - if not isinstance(bytes, type("")): - bytes = bytesToString(bytes) - hashBytes = stringToBytes(sha.sha(bytes).digest()) - prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) - return self.verify(sigBytes, prefixedHashBytes) - - def sign(self, bytes): - """Sign the passed-in bytes. - - This requires the key to have a private component. It performs - a PKCS1 signature on the passed-in data. - - @type bytes: L{array.array} of unsigned bytes - @param bytes: The value which will be signed. - - @rtype: L{array.array} of unsigned bytes. - @return: A PKCS1 signature on the passed-in data. - """ - if not self.hasPrivateKey(): - raise AssertionError() - paddedBytes = self._addPKCS1Padding(bytes, 1) - m = bytesToNumber(paddedBytes) - if m >= self.n: - raise ValueError() - c = self._rawPrivateKeyOp(m) - sigBytes = numberToBytes(c) - return sigBytes - - def verify(self, sigBytes, bytes): - """Verify the passed-in bytes with the signature. - - This verifies a PKCS1 signature on the passed-in data. - - @type sigBytes: L{array.array} of unsigned bytes - @param sigBytes: A PKCS1 signature. - - @type bytes: L{array.array} of unsigned bytes - @param bytes: The value which will be verified. - - @rtype: bool - @return: Whether the signature matches the passed-in data. - """ - paddedBytes = self._addPKCS1Padding(bytes, 1) - c = bytesToNumber(sigBytes) - if c >= self.n: - return False - m = self._rawPublicKeyOp(c) - checkBytes = numberToBytes(m) - return checkBytes == paddedBytes - - def encrypt(self, bytes): - """Encrypt the passed-in bytes. - - This performs PKCS1 encryption of the passed-in data. - - @type bytes: L{array.array} of unsigned bytes - @param bytes: The value which will be encrypted. - - @rtype: L{array.array} of unsigned bytes. - @return: A PKCS1 encryption of the passed-in data. - """ - paddedBytes = self._addPKCS1Padding(bytes, 2) - m = bytesToNumber(paddedBytes) - if m >= self.n: - raise ValueError() - c = self._rawPublicKeyOp(m) - encBytes = numberToBytes(c) - return encBytes - - def decrypt(self, encBytes): - """Decrypt the passed-in bytes. - - This requires the key to have a private component. It performs - PKCS1 decryption of the passed-in data. - - @type encBytes: L{array.array} of unsigned bytes - @param encBytes: The value which will be decrypted. - - @rtype: L{array.array} of unsigned bytes or None. - @return: A PKCS1 decryption of the passed-in data or None if - the data is not properly formatted. - """ - if not self.hasPrivateKey(): - raise AssertionError() - c = bytesToNumber(encBytes) - if c >= self.n: - return None - m = self._rawPrivateKeyOp(c) - decBytes = numberToBytes(m) - if (len(decBytes) != numBytes(self.n)-1): #Check first byte - return None - if decBytes[0] != 2: #Check second byte - return None - for x in range(len(decBytes)-1): #Scan through for zero separator - if decBytes[x]== 0: - break - else: - return None - return decBytes[x+1:] #Return everything after the separator - - def _rawPrivateKeyOp(self, m): - raise NotImplementedError() - - def _rawPublicKeyOp(self, c): - raise NotImplementedError() - - def acceptsPassword(self): - """Return True if the write() method accepts a password for use - in encrypting the private key. - - @rtype: bool - """ - raise NotImplementedError() - - def write(self, password=None): - """Return a string containing the key. - - @rtype: str - @return: A string describing the key, in whichever format (PEM - or XML) is native to the implementation. - """ - raise NotImplementedError() - - def writeXMLPublicKey(self, indent=''): - """Return a string containing the key. - - @rtype: str - @return: A string describing the public key, in XML format. - """ - return Python_RSAKey(self.n, self.e).write(indent) - - def generate(bits): - """Generate a new key with the specified bit length. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - """ - raise NotImplementedError() - generate = staticmethod(generate) - - - # ************************************************************************** - # Helper Functions for RSA Keys - # ************************************************************************** - - def _addPKCS1SHA1Prefix(self, bytes): - prefixBytes = createByteArraySequence(\ - [48,33,48,9,6,5,43,14,3,2,26,5,0,4,20]) - prefixedBytes = prefixBytes + bytes - return prefixedBytes - - def _addPKCS1Padding(self, bytes, blockType): - padLength = (numBytes(self.n) - (len(bytes)+3)) - if blockType == 1: #Signature padding - pad = [0xFF] * padLength - elif blockType == 2: #Encryption padding - pad = createByteArraySequence([]) - while len(pad) < padLength: - padBytes = getRandomBytes(padLength * 2) - pad = [b for b in padBytes if b != 0] - pad = pad[:padLength] - else: - raise AssertionError() - - #NOTE: To be proper, we should add [0,blockType]. However, - #the zero is lost when the returned padding is converted - #to a number, so we don't even bother with it. Also, - #adding it would cause a misalignment in verify() - padding = createByteArraySequence([blockType] + pad + [0]) - paddedBytes = padding + bytes - return paddedBytes diff --git a/src/lib/tlslite/utils/TripleDES.py b/src/lib/tlslite/utils/TripleDES.py deleted file mode 100755 index 2db45888b..000000000 --- a/src/lib/tlslite/utils/TripleDES.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Abstract class for 3DES.""" - -from compat import * #For True - -class TripleDES: - def __init__(self, key, mode, IV, implementation): - if len(key) != 24: - raise ValueError() - if mode != 2: - raise ValueError() - if len(IV) != 8: - raise ValueError() - self.isBlockCipher = True - self.block_size = 8 - self.implementation = implementation - self.name = "3des" - - #CBC-Mode encryption, returns ciphertext - #WARNING: *MAY* modify the input as well - def encrypt(self, plaintext): - assert(len(plaintext) % 8 == 0) - - #CBC-Mode decryption, returns plaintext - #WARNING: *MAY* modify the input as well - def decrypt(self, ciphertext): - assert(len(ciphertext) % 8 == 0) diff --git a/src/lib/tlslite/utils/__init__.py b/src/lib/tlslite/utils/__init__.py deleted file mode 100755 index f63f080fa..000000000 --- a/src/lib/tlslite/utils/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Toolkit for crypto and other stuff.""" - -__all__ = ["AES", - "ASN1Parser", - "cipherfactory", - "codec", - "Cryptlib_AES", - "Cryptlib_RC4", - "Cryptlib_TripleDES", - "cryptomath: cryptomath module", - "dateFuncs", - "hmac", - "JCE_RSAKey", - "compat", - "keyfactory", - "OpenSSL_AES", - "OpenSSL_RC4", - "OpenSSL_RSAKey", - "OpenSSL_TripleDES", - "prngd: prngd module", - "PyCrypto_AES", - "PyCrypto_RC4", - "PyCrypto_RSAKey", - "PyCrypto_TripleDES", - "Python_AES", - "Python_RC4", - "Python_RSAKey", - "RC4", - "rijndael", - "RSAKey", - "TripleDES", - "xmltools"] diff --git a/src/lib/tlslite/utils/cipherfactory.py b/src/lib/tlslite/utils/cipherfactory.py deleted file mode 100755 index ccbb6b5ff..000000000 --- a/src/lib/tlslite/utils/cipherfactory.py +++ /dev/null @@ -1,111 +0,0 @@ -"""Factory functions for symmetric cryptography.""" - -import os - -import Python_AES -import Python_RC4 - -import cryptomath - -tripleDESPresent = False - -if cryptomath.m2cryptoLoaded: - import OpenSSL_AES - import OpenSSL_RC4 - import OpenSSL_TripleDES - tripleDESPresent = True - -if cryptomath.cryptlibpyLoaded: - import Cryptlib_AES - import Cryptlib_RC4 - import Cryptlib_TripleDES - tripleDESPresent = True - -if cryptomath.pycryptoLoaded: - import PyCrypto_AES - import PyCrypto_RC4 - import PyCrypto_TripleDES - tripleDESPresent = True - -# ************************************************************************** -# Factory Functions for AES -# ************************************************************************** - -def createAES(key, IV, implList=None): - """Create a new AES object. - - @type key: str - @param key: A 16, 24, or 32 byte string. - - @type IV: str - @param IV: A 16 byte string - - @rtype: L{tlslite.utils.AES} - @return: An AES object. - """ - if implList == None: - implList = ["cryptlib", "openssl", "pycrypto", "python"] - - for impl in implList: - if impl == "cryptlib" and cryptomath.cryptlibpyLoaded: - return Cryptlib_AES.new(key, 2, IV) - elif impl == "openssl" and cryptomath.m2cryptoLoaded: - return OpenSSL_AES.new(key, 2, IV) - elif impl == "pycrypto" and cryptomath.pycryptoLoaded: - return PyCrypto_AES.new(key, 2, IV) - elif impl == "python": - return Python_AES.new(key, 2, IV) - raise NotImplementedError() - -def createRC4(key, IV, implList=None): - """Create a new RC4 object. - - @type key: str - @param key: A 16 to 32 byte string. - - @type IV: object - @param IV: Ignored, whatever it is. - - @rtype: L{tlslite.utils.RC4} - @return: An RC4 object. - """ - if implList == None: - implList = ["cryptlib", "openssl", "pycrypto", "python"] - - if len(IV) != 0: - raise AssertionError() - for impl in implList: - if impl == "cryptlib" and cryptomath.cryptlibpyLoaded: - return Cryptlib_RC4.new(key) - elif impl == "openssl" and cryptomath.m2cryptoLoaded: - return OpenSSL_RC4.new(key) - elif impl == "pycrypto" and cryptomath.pycryptoLoaded: - return PyCrypto_RC4.new(key) - elif impl == "python": - return Python_RC4.new(key) - raise NotImplementedError() - -#Create a new TripleDES instance -def createTripleDES(key, IV, implList=None): - """Create a new 3DES object. - - @type key: str - @param key: A 24 byte string. - - @type IV: str - @param IV: An 8 byte string - - @rtype: L{tlslite.utils.TripleDES} - @return: A 3DES object. - """ - if implList == None: - implList = ["cryptlib", "openssl", "pycrypto"] - - for impl in implList: - if impl == "cryptlib" and cryptomath.cryptlibpyLoaded: - return Cryptlib_TripleDES.new(key, 2, IV) - elif impl == "openssl" and cryptomath.m2cryptoLoaded: - return OpenSSL_TripleDES.new(key, 2, IV) - elif impl == "pycrypto" and cryptomath.pycryptoLoaded: - return PyCrypto_TripleDES.new(key, 2, IV) - raise NotImplementedError() \ No newline at end of file diff --git a/src/lib/tlslite/utils/codec.py b/src/lib/tlslite/utils/codec.py deleted file mode 100755 index 13022a0b9..000000000 --- a/src/lib/tlslite/utils/codec.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Classes for reading/writing binary data (such as TLS records).""" - -from compat import * - -class Writer: - def __init__(self, length=0): - #If length is zero, then this is just a "trial run" to determine length - self.index = 0 - self.bytes = createByteArrayZeros(length) - - def add(self, x, length): - if self.bytes: - newIndex = self.index+length-1 - while newIndex >= self.index: - self.bytes[newIndex] = x & 0xFF - x >>= 8 - newIndex -= 1 - self.index += length - - def addFixSeq(self, seq, length): - if self.bytes: - for e in seq: - self.add(e, length) - else: - self.index += len(seq)*length - - def addVarSeq(self, seq, length, lengthLength): - if self.bytes: - self.add(len(seq)*length, lengthLength) - for e in seq: - self.add(e, length) - else: - self.index += lengthLength + (len(seq)*length) - - -class Parser: - def __init__(self, bytes): - self.bytes = bytes - self.index = 0 - - def get(self, length): - if self.index + length > len(self.bytes): - raise SyntaxError() - x = 0 - for count in range(length): - x <<= 8 - x |= self.bytes[self.index] - self.index += 1 - return x - - def getFixBytes(self, lengthBytes): - bytes = self.bytes[self.index : self.index+lengthBytes] - self.index += lengthBytes - return bytes - - def getVarBytes(self, lengthLength): - lengthBytes = self.get(lengthLength) - return self.getFixBytes(lengthBytes) - - def getFixList(self, length, lengthList): - l = [0] * lengthList - for x in range(lengthList): - l[x] = self.get(length) - return l - - def getVarList(self, length, lengthLength): - lengthList = self.get(lengthLength) - if lengthList % length != 0: - raise SyntaxError() - lengthList = int(lengthList/length) - l = [0] * lengthList - for x in range(lengthList): - l[x] = self.get(length) - return l - - def startLengthCheck(self, lengthLength): - self.lengthCheck = self.get(lengthLength) - self.indexCheck = self.index - - def setLengthCheck(self, length): - self.lengthCheck = length - self.indexCheck = self.index - - def stopLengthCheck(self): - if (self.index - self.indexCheck) != self.lengthCheck: - raise SyntaxError() - - def atLengthCheck(self): - if (self.index - self.indexCheck) < self.lengthCheck: - return False - elif (self.index - self.indexCheck) == self.lengthCheck: - return True - else: - raise SyntaxError() \ No newline at end of file diff --git a/src/lib/tlslite/utils/compat.py b/src/lib/tlslite/utils/compat.py deleted file mode 100755 index 7d2d9250d..000000000 --- a/src/lib/tlslite/utils/compat.py +++ /dev/null @@ -1,140 +0,0 @@ -"""Miscellaneous functions to mask Python version differences.""" - -import sys -import os - -if sys.version_info < (2,2): - raise AssertionError("Python 2.2 or later required") - -if sys.version_info < (2,3): - - def enumerate(collection): - return zip(range(len(collection)), collection) - - class Set: - def __init__(self, seq=None): - self.values = {} - if seq: - for e in seq: - self.values[e] = None - - def add(self, e): - self.values[e] = None - - def discard(self, e): - if e in self.values.keys(): - del(self.values[e]) - - def union(self, s): - ret = Set() - for e in self.values.keys(): - ret.values[e] = None - for e in s.values.keys(): - ret.values[e] = None - return ret - - def issubset(self, other): - for e in self.values.keys(): - if e not in other.values.keys(): - return False - return True - - def __nonzero__( self): - return len(self.values.keys()) - - def __contains__(self, e): - return e in self.values.keys() - - def __iter__(self): - return iter(set.values.keys()) - - -if os.name != "java": - - import array - def createByteArraySequence(seq): - return array.array('B', seq) - def createByteArrayZeros(howMany): - return array.array('B', [0] * howMany) - def concatArrays(a1, a2): - return a1+a2 - - def bytesToString(bytes): - return bytes.tostring() - def stringToBytes(s): - bytes = createByteArrayZeros(0) - bytes.fromstring(s) - return bytes - - import math - def numBits(n): - if n==0: - return 0 - s = "%x" % n - return ((len(s)-1)*4) + \ - {'0':0, '1':1, '2':2, '3':2, - '4':3, '5':3, '6':3, '7':3, - '8':4, '9':4, 'a':4, 'b':4, - 'c':4, 'd':4, 'e':4, 'f':4, - }[s[0]] - return int(math.floor(math.log(n, 2))+1) - - BaseException = Exception - import sys - import traceback - def formatExceptionTrace(e): - newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) - return newStr - -else: - #Jython 2.1 is missing lots of python 2.3 stuff, - #which we have to emulate here: - #NOTE: JYTHON SUPPORT NO LONGER WORKS, DUE TO USE OF GENERATORS. - #THIS CODE IS LEFT IN SO THAT ONE JYTHON UPDATES TO 2.2, IT HAS A - #CHANCE OF WORKING AGAIN. - - import java - import jarray - - def createByteArraySequence(seq): - if isinstance(seq, type("")): #If it's a string, convert - seq = [ord(c) for c in seq] - return jarray.array(seq, 'h') #use short instead of bytes, cause bytes are signed - def createByteArrayZeros(howMany): - return jarray.zeros(howMany, 'h') #use short instead of bytes, cause bytes are signed - def concatArrays(a1, a2): - l = list(a1)+list(a2) - return createByteArraySequence(l) - - #WAY TOO SLOW - MUST BE REPLACED------------ - def bytesToString(bytes): - return "".join([chr(b) for b in bytes]) - - def stringToBytes(s): - bytes = createByteArrayZeros(len(s)) - for count, c in enumerate(s): - bytes[count] = ord(c) - return bytes - #WAY TOO SLOW - MUST BE REPLACED------------ - - def numBits(n): - if n==0: - return 0 - n= 1L * n; #convert to long, if it isn't already - return n.__tojava__(java.math.BigInteger).bitLength() - - #Adjust the string to an array of bytes - def stringToJavaByteArray(s): - bytes = jarray.zeros(len(s), 'b') - for count, c in enumerate(s): - x = ord(c) - if x >= 128: x -= 256 - bytes[count] = x - return bytes - - BaseException = java.lang.Exception - import sys - import traceback - def formatExceptionTrace(e): - newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) - return newStr \ No newline at end of file diff --git a/src/lib/tlslite/utils/cryptomath.py b/src/lib/tlslite/utils/cryptomath.py deleted file mode 100755 index 9b6f0495f..000000000 --- a/src/lib/tlslite/utils/cryptomath.py +++ /dev/null @@ -1,411 +0,0 @@ -"""cryptomath module - -This module has basic math/crypto code.""" - -import os -import math -import base64 -import binascii -import sha - -from compat import * - - -# ************************************************************************** -# Load Optional Modules -# ************************************************************************** - -# Try to load M2Crypto/OpenSSL -try: - from M2Crypto import m2 - m2cryptoLoaded = True - -except ImportError: - m2cryptoLoaded = False - - -# Try to load cryptlib -try: - import cryptlib_py - try: - cryptlib_py.cryptInit() - except cryptlib_py.CryptException, e: - #If tlslite and cryptoIDlib are both present, - #they might each try to re-initialize this, - #so we're tolerant of that. - if e[0] != cryptlib_py.CRYPT_ERROR_INITED: - raise - cryptlibpyLoaded = True - -except ImportError: - cryptlibpyLoaded = False - -#Try to load GMPY -try: - import gmpy - gmpyLoaded = True -except ImportError: - gmpyLoaded = False - -#Try to load pycrypto -try: - import Crypto.Cipher.AES - pycryptoLoaded = True -except ImportError: - pycryptoLoaded = False - - -# ************************************************************************** -# PRNG Functions -# ************************************************************************** - -# Get os.urandom PRNG -try: - os.urandom(1) - def getRandomBytes(howMany): - return stringToBytes(os.urandom(howMany)) - prngName = "os.urandom" - -except: - # Else get cryptlib PRNG - if cryptlibpyLoaded: - def getRandomBytes(howMany): - randomKey = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED, - cryptlib_py.CRYPT_ALGO_AES) - cryptlib_py.cryptSetAttribute(randomKey, - cryptlib_py.CRYPT_CTXINFO_MODE, - cryptlib_py.CRYPT_MODE_OFB) - cryptlib_py.cryptGenerateKey(randomKey) - bytes = createByteArrayZeros(howMany) - cryptlib_py.cryptEncrypt(randomKey, bytes) - return bytes - prngName = "cryptlib" - - else: - #Else get UNIX /dev/urandom PRNG - try: - devRandomFile = open("/dev/urandom", "rb") - def getRandomBytes(howMany): - return stringToBytes(devRandomFile.read(howMany)) - prngName = "/dev/urandom" - except IOError: - #Else get Win32 CryptoAPI PRNG - try: - import win32prng - def getRandomBytes(howMany): - s = win32prng.getRandomBytes(howMany) - if len(s) != howMany: - raise AssertionError() - return stringToBytes(s) - prngName ="CryptoAPI" - except ImportError: - # Else see if we ahve Pprngd running - try: - def getRandomBytes(howMany): - from prngd import PRNGD - try: - p = PRNGD(sockname="/var/run/egd-pool") - except: - p = PRNGD(sockname="/dev/egd-pool") - return stringToBytes(p.read(howMany)) - prngName = "PRNGD" - except: - #Else no PRNG :-( - def getRandomBytes(howMany): - raise NotImplementedError("No Random Number Generator "\ - "available.") - prngName = "None" - -# ************************************************************************** -# Converter Functions -# ************************************************************************** - -def bytesToNumber(bytes): - total = 0L - multiplier = 1L - for count in range(len(bytes)-1, -1, -1): - byte = bytes[count] - total += multiplier * byte - multiplier *= 256 - return total - -def numberToBytes(n): - howManyBytes = numBytes(n) - bytes = createByteArrayZeros(howManyBytes) - for count in range(howManyBytes-1, -1, -1): - bytes[count] = int(n % 256) - n >>= 8 - return bytes - -def bytesToBase64(bytes): - s = bytesToString(bytes) - return stringToBase64(s) - -def base64ToBytes(s): - s = base64ToString(s) - return stringToBytes(s) - -def numberToBase64(n): - bytes = numberToBytes(n) - return bytesToBase64(bytes) - -def base64ToNumber(s): - bytes = base64ToBytes(s) - return bytesToNumber(bytes) - -def stringToNumber(s): - bytes = stringToBytes(s) - return bytesToNumber(bytes) - -def numberToString(s): - bytes = numberToBytes(s) - return bytesToString(bytes) - -def base64ToString(s): - try: - return base64.decodestring(s) - except binascii.Error, e: - raise SyntaxError(e) - except binascii.Incomplete, e: - raise SyntaxError(e) - -def stringToBase64(s): - return base64.encodestring(s).replace("\n", "") - -def mpiToNumber(mpi): #mpi is an openssl-format bignum string - if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number - raise AssertionError() - bytes = stringToBytes(mpi[4:]) - return bytesToNumber(bytes) - -def numberToMPI(n): - bytes = numberToBytes(n) - ext = 0 - #If the high-order bit is going to be set, - #add an extra byte of zeros - if (numBits(n) & 0x7)==0: - ext = 1 - length = numBytes(n) + ext - bytes = concatArrays(createByteArrayZeros(4+ext), bytes) - bytes[0] = (length >> 24) & 0xFF - bytes[1] = (length >> 16) & 0xFF - bytes[2] = (length >> 8) & 0xFF - bytes[3] = length & 0xFF - return bytesToString(bytes) - - - -# ************************************************************************** -# Misc. Utility Functions -# ************************************************************************** - -def numBytes(n): - if n==0: - return 0 - bits = numBits(n) - return int(math.ceil(bits / 8.0)) - -def hashAndBase64(s): - return stringToBase64(sha.sha(s).digest()) - -def getBase64Nonce(numChars=22): #defaults to an 132 bit nonce - bytes = getRandomBytes(numChars) - bytesStr = "".join([chr(b) for b in bytes]) - return stringToBase64(bytesStr)[:numChars] - - -# ************************************************************************** -# Big Number Math -# ************************************************************************** - -def getRandomNumber(low, high): - if low >= high: - raise AssertionError() - howManyBits = numBits(high) - howManyBytes = numBytes(high) - lastBits = howManyBits % 8 - while 1: - bytes = getRandomBytes(howManyBytes) - if lastBits: - bytes[0] = bytes[0] % (1 << lastBits) - n = bytesToNumber(bytes) - if n >= low and n < high: - return n - -def gcd(a,b): - a, b = max(a,b), min(a,b) - while b: - a, b = b, a % b - return a - -def lcm(a, b): - #This will break when python division changes, but we can't use // cause - #of Jython - return (a * b) / gcd(a, b) - -#Returns inverse of a mod b, zero if none -#Uses Extended Euclidean Algorithm -def invMod(a, b): - c, d = a, b - uc, ud = 1, 0 - while c != 0: - #This will break when python division changes, but we can't use // - #cause of Jython - q = d / c - c, d = d-(q*c), c - uc, ud = ud - (q * uc), uc - if d == 1: - return ud % b - return 0 - - -if gmpyLoaded: - def powMod(base, power, modulus): - base = gmpy.mpz(base) - power = gmpy.mpz(power) - modulus = gmpy.mpz(modulus) - result = pow(base, power, modulus) - return long(result) - -else: - #Copied from Bryan G. Olson's post to comp.lang.python - #Does left-to-right instead of pow()'s right-to-left, - #thus about 30% faster than the python built-in with small bases - def powMod(base, power, modulus): - nBitScan = 5 - - """ Return base**power mod modulus, using multi bit scanning - with nBitScan bits at a time.""" - - #TREV - Added support for negative exponents - negativeResult = False - if (power < 0): - power *= -1 - negativeResult = True - - exp2 = 2**nBitScan - mask = exp2 - 1 - - # Break power into a list of digits of nBitScan bits. - # The list is recursive so easy to read in reverse direction. - nibbles = None - while power: - nibbles = int(power & mask), nibbles - power = power >> nBitScan - - # Make a table of powers of base up to 2**nBitScan - 1 - lowPowers = [1] - for i in xrange(1, exp2): - lowPowers.append((lowPowers[i-1] * base) % modulus) - - # To exponentiate by the first nibble, look it up in the table - nib, nibbles = nibbles - prod = lowPowers[nib] - - # For the rest, square nBitScan times, then multiply by - # base^nibble - while nibbles: - nib, nibbles = nibbles - for i in xrange(nBitScan): - prod = (prod * prod) % modulus - if nib: prod = (prod * lowPowers[nib]) % modulus - - #TREV - Added support for negative exponents - if negativeResult: - prodInv = invMod(prod, modulus) - #Check to make sure the inverse is correct - if (prod * prodInv) % modulus != 1: - raise AssertionError() - return prodInv - return prod - - -#Pre-calculate a sieve of the ~100 primes < 1000: -def makeSieve(n): - sieve = range(n) - for count in range(2, int(math.sqrt(n))): - if sieve[count] == 0: - continue - x = sieve[count] * 2 - while x < len(sieve): - sieve[x] = 0 - x += sieve[count] - sieve = [x for x in sieve[2:] if x] - return sieve - -sieve = makeSieve(1000) - -def isPrime(n, iterations=5, display=False): - #Trial division with sieve - for x in sieve: - if x >= n: return True - if n % x == 0: return False - #Passed trial division, proceed to Rabin-Miller - #Rabin-Miller implemented per Ferguson & Schneier - #Compute s, t for Rabin-Miller - if display: print "*", - s, t = n-1, 0 - while s % 2 == 0: - s, t = s/2, t+1 - #Repeat Rabin-Miller x times - a = 2 #Use 2 as a base for first iteration speedup, per HAC - for count in range(iterations): - v = powMod(a, s, n) - if v==1: - continue - i = 0 - while v != n-1: - if i == t-1: - return False - else: - v, i = powMod(v, 2, n), i+1 - a = getRandomNumber(2, n) - return True - -def getRandomPrime(bits, display=False): - if bits < 10: - raise AssertionError() - #The 1.5 ensures the 2 MSBs are set - #Thus, when used for p,q in RSA, n will have its MSB set - # - #Since 30 is lcm(2,3,5), we'll set our test numbers to - #29 % 30 and keep them there - low = (2L ** (bits-1)) * 3/2 - high = 2L ** bits - 30 - p = getRandomNumber(low, high) - p += 29 - (p % 30) - while 1: - if display: print ".", - p += 30 - if p >= high: - p = getRandomNumber(low, high) - p += 29 - (p % 30) - if isPrime(p, display=display): - return p - -#Unused at the moment... -def getRandomSafePrime(bits, display=False): - if bits < 10: - raise AssertionError() - #The 1.5 ensures the 2 MSBs are set - #Thus, when used for p,q in RSA, n will have its MSB set - # - #Since 30 is lcm(2,3,5), we'll set our test numbers to - #29 % 30 and keep them there - low = (2 ** (bits-2)) * 3/2 - high = (2 ** (bits-1)) - 30 - q = getRandomNumber(low, high) - q += 29 - (q % 30) - while 1: - if display: print ".", - q += 30 - if (q >= high): - q = getRandomNumber(low, high) - q += 29 - (q % 30) - #Ideas from Tom Wu's SRP code - #Do trial division on p and q before Rabin-Miller - if isPrime(q, 0, display=display): - p = (2 * q) + 1 - if isPrime(p, display=display): - if isPrime(q, display=display): - return p diff --git a/src/lib/tlslite/utils/dateFuncs.py b/src/lib/tlslite/utils/dateFuncs.py deleted file mode 100755 index 38812ebf8..000000000 --- a/src/lib/tlslite/utils/dateFuncs.py +++ /dev/null @@ -1,75 +0,0 @@ - -import os - -#Functions for manipulating datetime objects -#CCYY-MM-DDThh:mm:ssZ -def parseDateClass(s): - year, month, day = s.split("-") - day, tail = day[:2], day[2:] - hour, minute, second = tail[1:].split(":") - second = second[:2] - year, month, day = int(year), int(month), int(day) - hour, minute, second = int(hour), int(minute), int(second) - return createDateClass(year, month, day, hour, minute, second) - - -if os.name != "java": - from datetime import datetime, timedelta - - #Helper functions for working with a date/time class - def createDateClass(year, month, day, hour, minute, second): - return datetime(year, month, day, hour, minute, second) - - def printDateClass(d): - #Split off fractional seconds, append 'Z' - return d.isoformat().split(".")[0]+"Z" - - def getNow(): - return datetime.utcnow() - - def getHoursFromNow(hours): - return datetime.utcnow() + timedelta(hours=hours) - - def getMinutesFromNow(minutes): - return datetime.utcnow() + timedelta(minutes=minutes) - - def isDateClassExpired(d): - return d < datetime.utcnow() - - def isDateClassBefore(d1, d2): - return d1 < d2 - -else: - #Jython 2.1 is missing lots of python 2.3 stuff, - #which we have to emulate here: - import java - import jarray - - def createDateClass(year, month, day, hour, minute, second): - c = java.util.Calendar.getInstance() - c.setTimeZone(java.util.TimeZone.getTimeZone("UTC")) - c.set(year, month-1, day, hour, minute, second) - return c - - def printDateClass(d): - return "%04d-%02d-%02dT%02d:%02d:%02dZ" % \ - (d.get(d.YEAR), d.get(d.MONTH)+1, d.get(d.DATE), \ - d.get(d.HOUR_OF_DAY), d.get(d.MINUTE), d.get(d.SECOND)) - - def getNow(): - c = java.util.Calendar.getInstance() - c.setTimeZone(java.util.TimeZone.getTimeZone("UTC")) - c.get(c.HOUR) #force refresh? - return c - - def getHoursFromNow(hours): - d = getNow() - d.add(d.HOUR, hours) - return d - - def isDateClassExpired(d): - n = getNow() - return d.before(n) - - def isDateClassBefore(d1, d2): - return d1.before(d2) diff --git a/src/lib/tlslite/utils/entropy.c b/src/lib/tlslite/utils/entropy.c deleted file mode 100755 index c627794d2..000000000 --- a/src/lib/tlslite/utils/entropy.c +++ /dev/null @@ -1,173 +0,0 @@ - -#include "Python.h" - - -#ifdef MS_WINDOWS - -/* The following #define is not needed on VC6 with the Platform SDK, and it -may not be needed on VC7, I'm not sure. I don't think it hurts anything.*/ -#define _WIN32_WINNT 0x0400 - -#include - - -typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\ - LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\ - DWORD dwFlags ); -typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\ - BYTE *pbBuffer ); -typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv,\ - DWORD dwFlags); - - -static PyObject* entropy(PyObject *self, PyObject *args) -{ - int howMany = 0; - HINSTANCE hAdvAPI32 = NULL; - CRYPTACQUIRECONTEXTA pCryptAcquireContextA = NULL; - CRYPTGENRANDOM pCryptGenRandom = NULL; - CRYPTRELEASECONTEXT pCryptReleaseContext = NULL; - HCRYPTPROV hCryptProv = 0; - unsigned char* bytes = NULL; - PyObject* returnVal = NULL; - - - /* Read arguments */ - if (!PyArg_ParseTuple(args, "i", &howMany)) - return(NULL); - - /* Obtain handle to the DLL containing CryptoAPI - This should not fail */ - if( (hAdvAPI32 = GetModuleHandle("advapi32.dll")) == NULL) { - PyErr_Format(PyExc_SystemError, - "Advapi32.dll not found"); - return NULL; - } - - /* Obtain pointers to the CryptoAPI functions - This will fail on some early version of Win95 */ - pCryptAcquireContextA = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32,\ - "CryptAcquireContextA"); - pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32,\ - "CryptGenRandom"); - pCryptReleaseContext = (CRYPTRELEASECONTEXT) GetProcAddress(hAdvAPI32,\ - "CryptReleaseContext"); - if (pCryptAcquireContextA == NULL || pCryptGenRandom == NULL || - pCryptReleaseContext == NULL) { - PyErr_Format(PyExc_NotImplementedError, - "CryptoAPI not available on this version of Windows"); - return NULL; - } - - /* Allocate bytes */ - if ((bytes = (unsigned char*)PyMem_Malloc(howMany)) == NULL) - return PyErr_NoMemory(); - - - /* Acquire context */ - if(!pCryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - PyErr_Format(PyExc_SystemError, - "CryptAcquireContext failed, error %d", GetLastError()); - PyMem_Free(bytes); - return NULL; - } - - /* Get random data */ - if(!pCryptGenRandom(hCryptProv, howMany, bytes)) { - PyErr_Format(PyExc_SystemError, - "CryptGenRandom failed, error %d", GetLastError()); - PyMem_Free(bytes); - CryptReleaseContext(hCryptProv, 0); - return NULL; - } - - /* Build return value */ - returnVal = Py_BuildValue("s#", bytes, howMany); - PyMem_Free(bytes); - - /* Release context */ - if (!pCryptReleaseContext(hCryptProv, 0)) { - PyErr_Format(PyExc_SystemError, - "CryptReleaseContext failed, error %d", GetLastError()); - return NULL; - } - - return returnVal; -} - -#elif defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL_H) - -#include -#include - -static PyObject* entropy(PyObject *self, PyObject *args) -{ - int howMany; - int fd; - unsigned char* bytes = NULL; - PyObject* returnVal = NULL; - - - /* Read arguments */ - if (!PyArg_ParseTuple(args, "i", &howMany)) - return(NULL); - - /* Allocate bytes */ - if ((bytes = (unsigned char*)PyMem_Malloc(howMany)) == NULL) - return PyErr_NoMemory(); - - /* Open device */ - if ((fd = open("/dev/urandom", O_RDONLY, 0)) == -1) { - PyErr_Format(PyExc_NotImplementedError, - "No entropy source found"); - PyMem_Free(bytes); - return NULL; - } - - /* Get random data */ - if (read(fd, bytes, howMany) < howMany) { - PyErr_Format(PyExc_SystemError, - "Reading from /dev/urandom failed"); - PyMem_Free(bytes); - close(fd); - return NULL; - } - - /* Build return value */ - returnVal = Py_BuildValue("s#", bytes, howMany); - PyMem_Free(bytes); - - /* Close device */ - close(fd); - - return returnVal; -} - -#else - -static PyObject* entropy(PyObject *self, PyObject *args) -{ - PyErr_Format(PyExc_NotImplementedError, - "Function not supported"); - return NULL; -} - -#endif - - - -/* List of functions exported by this module */ - -static struct PyMethodDef entropy_functions[] = { - {"entropy", (PyCFunction)entropy, METH_VARARGS, "Return a string of random bytes produced by a platform-specific\nentropy source."}, - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -PyMODINIT_FUNC initentropy(void) -{ - Py_InitModule("entropy", entropy_functions); -} \ No newline at end of file diff --git a/src/lib/tlslite/utils/hmac.py b/src/lib/tlslite/utils/hmac.py deleted file mode 100755 index fe8feec21..000000000 --- a/src/lib/tlslite/utils/hmac.py +++ /dev/null @@ -1,104 +0,0 @@ -"""HMAC (Keyed-Hashing for Message Authentication) Python module. - -Implements the HMAC algorithm as described by RFC 2104. - -(This file is modified from the standard library version to do faster -copying) -""" - -def _strxor(s1, s2): - """Utility method. XOR the two strings s1 and s2 (must have same length). - """ - return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2)) - -# The size of the digests returned by HMAC depends on the underlying -# hashing module used. -digest_size = None - -class HMAC: - """RFC2104 HMAC class. - - This supports the API for Cryptographic Hash Functions (PEP 247). - """ - - def __init__(self, key, msg = None, digestmod = None): - """Create a new HMAC object. - - key: key for the keyed hash object. - msg: Initial input for the hash, if provided. - digestmod: A module supporting PEP 247. Defaults to the md5 module. - """ - if digestmod is None: - import md5 - digestmod = md5 - - if key == None: #TREVNEW - for faster copying - return #TREVNEW - - self.digestmod = digestmod - self.outer = digestmod.new() - self.inner = digestmod.new() - self.digest_size = digestmod.digest_size - - blocksize = 64 - ipad = "\x36" * blocksize - opad = "\x5C" * blocksize - - if len(key) > blocksize: - key = digestmod.new(key).digest() - - key = key + chr(0) * (blocksize - len(key)) - self.outer.update(_strxor(key, opad)) - self.inner.update(_strxor(key, ipad)) - if msg is not None: - self.update(msg) - -## def clear(self): -## raise NotImplementedError, "clear() method not available in HMAC." - - def update(self, msg): - """Update this hashing object with the string msg. - """ - self.inner.update(msg) - - def copy(self): - """Return a separate copy of this hashing object. - - An update to this copy won't affect the original object. - """ - other = HMAC(None) #TREVNEW - for faster copying - other.digest_size = self.digest_size #TREVNEW - other.digestmod = self.digestmod - other.inner = self.inner.copy() - other.outer = self.outer.copy() - return other - - def digest(self): - """Return the hash value of this hashing object. - - This returns a string containing 8-bit data. The object is - not altered in any way by this function; you can continue - updating the object after calling this function. - """ - h = self.outer.copy() - h.update(self.inner.digest()) - return h.digest() - - def hexdigest(self): - """Like digest(), but returns a string of hexadecimal digits instead. - """ - return "".join([hex(ord(x))[2:].zfill(2) - for x in tuple(self.digest())]) - -def new(key, msg = None, digestmod = None): - """Create a new hashing object and return it. - - key: The starting key for the hash. - msg: if available, will immediately be hashed into the object's starting - state. - - You can now feed arbitrary strings into the object using its update() - method, and can ask for the hash value at any time by calling its digest() - method. - """ - return HMAC(key, msg, digestmod) diff --git a/src/lib/tlslite/utils/jython_compat.py b/src/lib/tlslite/utils/jython_compat.py deleted file mode 100755 index 1245183a9..000000000 --- a/src/lib/tlslite/utils/jython_compat.py +++ /dev/null @@ -1,195 +0,0 @@ -"""Miscellaneous functions to mask Python/Jython differences.""" - -import os -import sha - -if os.name != "java": - BaseException = Exception - - from sets import Set - import array - import math - - def createByteArraySequence(seq): - return array.array('B', seq) - def createByteArrayZeros(howMany): - return array.array('B', [0] * howMany) - def concatArrays(a1, a2): - return a1+a2 - - def bytesToString(bytes): - return bytes.tostring() - - def stringToBytes(s): - bytes = createByteArrayZeros(0) - bytes.fromstring(s) - return bytes - - def numBits(n): - if n==0: - return 0 - return int(math.floor(math.log(n, 2))+1) - - class CertChainBase: pass - class SelfTestBase: pass - class ReportFuncBase: pass - - #Helper functions for working with sets (from Python 2.3) - def iterSet(set): - return iter(set) - - def getListFromSet(set): - return list(set) - - #Factory function for getting a SHA1 object - def getSHA1(s): - return sha.sha(s) - - import sys - import traceback - - def formatExceptionTrace(e): - newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) - return newStr - -else: - #Jython 2.1 is missing lots of python 2.3 stuff, - #which we have to emulate here: - import java - import jarray - - BaseException = java.lang.Exception - - def createByteArraySequence(seq): - if isinstance(seq, type("")): #If it's a string, convert - seq = [ord(c) for c in seq] - return jarray.array(seq, 'h') #use short instead of bytes, cause bytes are signed - def createByteArrayZeros(howMany): - return jarray.zeros(howMany, 'h') #use short instead of bytes, cause bytes are signed - def concatArrays(a1, a2): - l = list(a1)+list(a2) - return createByteArraySequence(l) - - #WAY TOO SLOW - MUST BE REPLACED------------ - def bytesToString(bytes): - return "".join([chr(b) for b in bytes]) - - def stringToBytes(s): - bytes = createByteArrayZeros(len(s)) - for count, c in enumerate(s): - bytes[count] = ord(c) - return bytes - #WAY TOO SLOW - MUST BE REPLACED------------ - - def numBits(n): - if n==0: - return 0 - n= 1L * n; #convert to long, if it isn't already - return n.__tojava__(java.math.BigInteger).bitLength() - - #This properly creates static methods for Jython - class staticmethod: - def __init__(self, anycallable): self.__call__ = anycallable - - #Properties are not supported for Jython - class property: - def __init__(self, anycallable): pass - - #True and False have to be specially defined - False = 0 - True = 1 - - class StopIteration(Exception): pass - - def enumerate(collection): - return zip(range(len(collection)), collection) - - class Set: - def __init__(self, seq=None): - self.values = {} - if seq: - for e in seq: - self.values[e] = None - - def add(self, e): - self.values[e] = None - - def discard(self, e): - if e in self.values.keys(): - del(self.values[e]) - - def union(self, s): - ret = Set() - for e in self.values.keys(): - ret.values[e] = None - for e in s.values.keys(): - ret.values[e] = None - return ret - - def issubset(self, other): - for e in self.values.keys(): - if e not in other.values.keys(): - return False - return True - - def __nonzero__( self): - return len(self.values.keys()) - - def __contains__(self, e): - return e in self.values.keys() - - def iterSet(set): - return set.values.keys() - - def getListFromSet(set): - return set.values.keys() - - """ - class JCE_SHA1: - def __init__(self, s=None): - self.md = java.security.MessageDigest.getInstance("SHA1") - if s: - self.update(s) - - def update(self, s): - self.md.update(s) - - def copy(self): - sha1 = JCE_SHA1() - sha1.md = self.md.clone() - return sha1 - - def digest(self): - digest = self.md.digest() - bytes = jarray.zeros(20, 'h') - for count in xrange(20): - x = digest[count] - if x < 0: x += 256 - bytes[count] = x - return bytes - """ - - #Factory function for getting a SHA1 object - #The JCE_SHA1 class is way too slow... - #the sha.sha object we use instead is broken in the jython 2.1 - #release, and needs to be patched - def getSHA1(s): - #return JCE_SHA1(s) - return sha.sha(s) - - - #Adjust the string to an array of bytes - def stringToJavaByteArray(s): - bytes = jarray.zeros(len(s), 'b') - for count, c in enumerate(s): - x = ord(c) - if x >= 128: x -= 256 - bytes[count] = x - return bytes - - import sys - import traceback - - def formatExceptionTrace(e): - newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) - return newStr diff --git a/src/lib/tlslite/utils/keyfactory.py b/src/lib/tlslite/utils/keyfactory.py deleted file mode 100755 index 5005af7f5..000000000 --- a/src/lib/tlslite/utils/keyfactory.py +++ /dev/null @@ -1,243 +0,0 @@ -"""Factory functions for asymmetric cryptography. -@sort: generateRSAKey, parseXMLKey, parsePEMKey, parseAsPublicKey, -parseAsPrivateKey -""" - -from compat import * - -from RSAKey import RSAKey -from Python_RSAKey import Python_RSAKey -import cryptomath - -if cryptomath.m2cryptoLoaded: - from OpenSSL_RSAKey import OpenSSL_RSAKey - -if cryptomath.pycryptoLoaded: - from PyCrypto_RSAKey import PyCrypto_RSAKey - -# ************************************************************************** -# Factory Functions for RSA Keys -# ************************************************************************** - -def generateRSAKey(bits, implementations=["openssl", "python"]): - """Generate an RSA key with the specified bit length. - - @type bits: int - @param bits: Desired bit length of the new key's modulus. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - @return: A new RSA private key. - """ - for implementation in implementations: - if implementation == "openssl" and cryptomath.m2cryptoLoaded: - return OpenSSL_RSAKey.generate(bits) - elif implementation == "python": - return Python_RSAKey.generate(bits) - raise ValueError("No acceptable implementations") - -def parseXMLKey(s, private=False, public=False, implementations=["python"]): - """Parse an XML-format key. - - The XML format used here is specific to tlslite and cryptoIDlib. The - format can store the public component of a key, or the public and - private components. For example:: - - - 4a5yzB8oGNlHo866CAspAC47M4Fvx58zwK8pou... - Aw== - - - - 4a5yzB8oGNlHo866CAspAC47M4Fvx58zwK8pou... - Aw== - JZ0TIgUxWXmL8KJ0VqyG1V0J3ern9pqIoB0xmy... -

5PreIj6z6ldIGL1V4+1C36dQFHNCQHJvW52GXc... - /E/wDit8YXPCxx126zTq2ilQ3IcW54NJYyNjiZ... - mKc+wX8inDowEH45Qp4slRo1YveBgExKPROu6... - qDVKtBz9lk0shL5PR3ickXDgkwS576zbl2ztB... - j6E8EA7dNsTImaXexAmLA1DoeArsYeFAInr... - - - @type s: str - @param s: A string containing an XML public or private key. - - @type private: bool - @param private: If True, a L{SyntaxError} will be raised if the private - key component is not present. - - @type public: bool - @param public: If True, the private key component (if present) will be - discarded, so this function will always return a public key. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - @return: An RSA key. - - @raise SyntaxError: If the key is not properly formatted. - """ - for implementation in implementations: - if implementation == "python": - key = Python_RSAKey.parseXML(s) - break - else: - raise ValueError("No acceptable implementations") - - return _parseKeyHelper(key, private, public) - -#Parse as an OpenSSL or Python key -def parsePEMKey(s, private=False, public=False, passwordCallback=None, - implementations=["openssl", "python"]): - """Parse a PEM-format key. - - The PEM format is used by OpenSSL and other tools. The - format is typically used to store both the public and private - components of a key. For example:: - - -----BEGIN RSA PRIVATE KEY----- - MIICXQIBAAKBgQDYscuoMzsGmW0pAYsmyHltxB2TdwHS0dImfjCMfaSDkfLdZY5+ - dOWORVns9etWnr194mSGA1F0Pls/VJW8+cX9+3vtJV8zSdANPYUoQf0TP7VlJxkH - dSRkUbEoz5bAAs/+970uos7n7iXQIni+3erUTdYEk2iWnMBjTljfgbK/dQIDAQAB - AoGAJHoJZk75aKr7DSQNYIHuruOMdv5ZeDuJvKERWxTrVJqE32/xBKh42/IgqRrc - esBN9ZregRCd7YtxoL+EVUNWaJNVx2mNmezEznrc9zhcYUrgeaVdFO2yBF1889zO - gCOVwrO8uDgeyj6IKa25H6c1N13ih/o7ZzEgWbGG+ylU1yECQQDv4ZSJ4EjSh/Fl - aHdz3wbBa/HKGTjC8iRy476Cyg2Fm8MZUe9Yy3udOrb5ZnS2MTpIXt5AF3h2TfYV - VoFXIorjAkEA50FcJmzT8sNMrPaV8vn+9W2Lu4U7C+K/O2g1iXMaZms5PC5zV5aV - CKXZWUX1fq2RaOzlbQrpgiolhXpeh8FjxwJBAOFHzSQfSsTNfttp3KUpU0LbiVvv - i+spVSnA0O4rq79KpVNmK44Mq67hsW1P11QzrzTAQ6GVaUBRv0YS061td1kCQHnP - wtN2tboFR6lABkJDjxoGRvlSt4SOPr7zKGgrWjeiuTZLHXSAnCY+/hr5L9Q3ZwXG - 6x6iBdgLjVIe4BZQNtcCQQDXGv/gWinCNTN3MPWfTW/RGzuMYVmyBFais0/VrgdH - h1dLpztmpQqfyH/zrBXQ9qL/zR4ojS6XYneO/U18WpEe - -----END RSA PRIVATE KEY----- - - To generate a key like this with OpenSSL, run:: - - openssl genrsa 2048 > key.pem - - This format also supports password-encrypted private keys. TLS - Lite can only handle password-encrypted private keys when OpenSSL - and M2Crypto are installed. In this case, passwordCallback will be - invoked to query the user for the password. - - @type s: str - @param s: A string containing a PEM-encoded public or private key. - - @type private: bool - @param private: If True, a L{SyntaxError} will be raised if the - private key component is not present. - - @type public: bool - @param public: If True, the private key component (if present) will - be discarded, so this function will always return a public key. - - @type passwordCallback: callable - @param passwordCallback: This function will be called, with no - arguments, if the PEM-encoded private key is password-encrypted. - The callback should return the password string. If the password is - incorrect, SyntaxError will be raised. If no callback is passed - and the key is password-encrypted, a prompt will be displayed at - the console. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - @return: An RSA key. - - @raise SyntaxError: If the key is not properly formatted. - """ - for implementation in implementations: - if implementation == "openssl" and cryptomath.m2cryptoLoaded: - key = OpenSSL_RSAKey.parse(s, passwordCallback) - break - elif implementation == "python": - key = Python_RSAKey.parsePEM(s) - break - else: - raise ValueError("No acceptable implementations") - - return _parseKeyHelper(key, private, public) - - -def _parseKeyHelper(key, private, public): - if private: - if not key.hasPrivateKey(): - raise SyntaxError("Not a private key!") - - if public: - return _createPublicKey(key) - - if private: - if hasattr(key, "d"): - return _createPrivateKey(key) - else: - return key - - return key - -def parseAsPublicKey(s): - """Parse an XML or PEM-formatted public key. - - @type s: str - @param s: A string containing an XML or PEM-encoded public or private key. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - @return: An RSA public key. - - @raise SyntaxError: If the key is not properly formatted. - """ - try: - return parsePEMKey(s, public=True) - except: - return parseXMLKey(s, public=True) - -def parsePrivateKey(s): - """Parse an XML or PEM-formatted private key. - - @type s: str - @param s: A string containing an XML or PEM-encoded private key. - - @rtype: L{tlslite.utils.RSAKey.RSAKey} - @return: An RSA private key. - - @raise SyntaxError: If the key is not properly formatted. - """ - try: - return parsePEMKey(s, private=True) - except: - return parseXMLKey(s, private=True) - -def _createPublicKey(key): - """ - Create a new public key. Discard any private component, - and return the most efficient key possible. - """ - if not isinstance(key, RSAKey): - raise AssertionError() - return _createPublicRSAKey(key.n, key.e) - -def _createPrivateKey(key): - """ - Create a new private key. Return the most efficient key possible. - """ - if not isinstance(key, RSAKey): - raise AssertionError() - if not key.hasPrivateKey(): - raise AssertionError() - return _createPrivateRSAKey(key.n, key.e, key.d, key.p, key.q, key.dP, - key.dQ, key.qInv) - -def _createPublicRSAKey(n, e, implementations = ["openssl", "pycrypto", - "python"]): - for implementation in implementations: - if implementation == "openssl" and cryptomath.m2cryptoLoaded: - return OpenSSL_RSAKey(n, e) - elif implementation == "pycrypto" and cryptomath.pycryptoLoaded: - return PyCrypto_RSAKey(n, e) - elif implementation == "python": - return Python_RSAKey(n, e) - raise ValueError("No acceptable implementations") - -def _createPrivateRSAKey(n, e, d, p, q, dP, dQ, qInv, - implementations = ["pycrypto", "python"]): - for implementation in implementations: - if implementation == "pycrypto" and cryptomath.pycryptoLoaded: - return PyCrypto_RSAKey(n, e, d, p, q, dP, dQ, qInv) - elif implementation == "python": - return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv) - raise ValueError("No acceptable implementations") diff --git a/src/lib/tlslite/utils/prngd.py b/src/lib/tlslite/utils/prngd.py deleted file mode 100644 index c86b7046a..000000000 --- a/src/lib/tlslite/utils/prngd.py +++ /dev/null @@ -1,62 +0,0 @@ -"""prngd module - -This module interfaces with PRNGD - Pseudo Random Number Generator -Daemon for platforms without /dev/random or /dev/urandom. - -It is based on code from Stuart D. Gathman stuart at bmsi.com and is -Public Domain. The original code is available from -http://mail.python.org/pipermail/python-list/2002-November/170737.html""" - -import socket -from struct import unpack,pack - -class PRNGD: - "Provide access to the Portable Random Number Generator Daemon" - - def __init__(self,sockname="/var/run/egd-pool"): - self.randfile = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM) - self.randfile.connect(sockname) - - def _readall(self,n): - s = self.randfile.recv(n) - while len(s) < n: - s = s + self.randfile.recv(n - len(s)) - return s - - def get(self): - "Return number of available bytes of entropy." - self.randfile.sendall('\x00') - return unpack(">i",self._readall(4))[0] - - def read(self,cnt): - "Return available entropy, up to cnt bytes." - if cnt > 255: cnt = 255 - self.randfile.sendall(pack("BB",0x01,cnt)) - buf = self._readall(1) - assert len(buf) == 1 - count = unpack("B",buf)[0] - buf = self._readall(count) - assert len(buf) == count, "didn't get all the entropy" - return buf - - def readall(self,cnt): - "Return all entropy bytes requested" - if cnt < 256: - self.randfile.sendall(pack("BB",0x02,cnt)) - return self._readall(cnt) - buf = readall(self,255) - cnt -= len(buf) - while cnt > 255: - buf += readall(self,255) - cnt -= len(buf) - return buf + readall(self,cnt) - - def getpid(self): - "Return the process id string of the prngd" - self.randfile.sendall('\x04') - buf = self._readall(1) - assert len(buf) == 1 - count = unpack("B",buf)[0] - buf = self._readall(count) - assert len(buf) == count, "didn't get whole PID string" - return buf diff --git a/src/lib/tlslite/utils/rijndael.py b/src/lib/tlslite/utils/rijndael.py deleted file mode 100755 index cb2f54734..000000000 --- a/src/lib/tlslite/utils/rijndael.py +++ /dev/null @@ -1,392 +0,0 @@ -""" -A pure python (slow) implementation of rijndael with a decent interface - -To include - - -from rijndael import rijndael - -To do a key setup - - -r = rijndael(key, block_size = 16) - -key must be a string of length 16, 24, or 32 -blocksize must be 16, 24, or 32. Default is 16 - -To use - - -ciphertext = r.encrypt(plaintext) -plaintext = r.decrypt(ciphertext) - -If any strings are of the wrong length a ValueError is thrown -""" - -# ported from the Java reference code by Bram Cohen, bram@gawth.com, April 2001 -# this code is public domain, unless someone makes -# an intellectual property claim against the reference -# code, in which case it can be made public domain by -# deleting all the comments and renaming all the variables - -import copy -import string - - - -#----------------------- -#TREV - ADDED BECAUSE THERE'S WARNINGS ABOUT INT OVERFLOW BEHAVIOR CHANGING IN -#2.4..... -import os -if os.name != "java": - import exceptions - if hasattr(exceptions, "FutureWarning"): - import warnings - warnings.filterwarnings("ignore", category=FutureWarning, append=1) -#----------------------- - - - -shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]], - [[0, 0], [1, 5], [2, 4], [3, 3]], - [[0, 0], [1, 7], [3, 5], [4, 4]]] - -# [keysize][block_size] -num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}} - -A = [[1, 1, 1, 1, 1, 0, 0, 0], - [0, 1, 1, 1, 1, 1, 0, 0], - [0, 0, 1, 1, 1, 1, 1, 0], - [0, 0, 0, 1, 1, 1, 1, 1], - [1, 0, 0, 0, 1, 1, 1, 1], - [1, 1, 0, 0, 0, 1, 1, 1], - [1, 1, 1, 0, 0, 0, 1, 1], - [1, 1, 1, 1, 0, 0, 0, 1]] - -# produce log and alog tables, needed for multiplying in the -# field GF(2^m) (generator = 3) -alog = [1] -for i in xrange(255): - j = (alog[-1] << 1) ^ alog[-1] - if j & 0x100 != 0: - j ^= 0x11B - alog.append(j) - -log = [0] * 256 -for i in xrange(1, 255): - log[alog[i]] = i - -# multiply two elements of GF(2^m) -def mul(a, b): - if a == 0 or b == 0: - return 0 - return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255] - -# substitution box based on F^{-1}(x) -box = [[0] * 8 for i in xrange(256)] -box[1][7] = 1 -for i in xrange(2, 256): - j = alog[255 - log[i]] - for t in xrange(8): - box[i][t] = (j >> (7 - t)) & 0x01 - -B = [0, 1, 1, 0, 0, 0, 1, 1] - -# affine transform: box[i] <- B + A*box[i] -cox = [[0] * 8 for i in xrange(256)] -for i in xrange(256): - for t in xrange(8): - cox[i][t] = B[t] - for j in xrange(8): - cox[i][t] ^= A[t][j] * box[i][j] - -# S-boxes and inverse S-boxes -S = [0] * 256 -Si = [0] * 256 -for i in xrange(256): - S[i] = cox[i][0] << 7 - for t in xrange(1, 8): - S[i] ^= cox[i][t] << (7-t) - Si[S[i] & 0xFF] = i - -# T-boxes -G = [[2, 1, 1, 3], - [3, 2, 1, 1], - [1, 3, 2, 1], - [1, 1, 3, 2]] - -AA = [[0] * 8 for i in xrange(4)] - -for i in xrange(4): - for j in xrange(4): - AA[i][j] = G[i][j] - AA[i][i+4] = 1 - -for i in xrange(4): - pivot = AA[i][i] - if pivot == 0: - t = i + 1 - while AA[t][i] == 0 and t < 4: - t += 1 - assert t != 4, 'G matrix must be invertible' - for j in xrange(8): - AA[i][j], AA[t][j] = AA[t][j], AA[i][j] - pivot = AA[i][i] - for j in xrange(8): - if AA[i][j] != 0: - AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255] - for t in xrange(4): - if i != t: - for j in xrange(i+1, 8): - AA[t][j] ^= mul(AA[i][j], AA[t][i]) - AA[t][i] = 0 - -iG = [[0] * 4 for i in xrange(4)] - -for i in xrange(4): - for j in xrange(4): - iG[i][j] = AA[i][j + 4] - -def mul4(a, bs): - if a == 0: - return 0 - r = 0 - for b in bs: - r <<= 8 - if b != 0: - r = r | mul(a, b) - return r - -T1 = [] -T2 = [] -T3 = [] -T4 = [] -T5 = [] -T6 = [] -T7 = [] -T8 = [] -U1 = [] -U2 = [] -U3 = [] -U4 = [] - -for t in xrange(256): - s = S[t] - T1.append(mul4(s, G[0])) - T2.append(mul4(s, G[1])) - T3.append(mul4(s, G[2])) - T4.append(mul4(s, G[3])) - - s = Si[t] - T5.append(mul4(s, iG[0])) - T6.append(mul4(s, iG[1])) - T7.append(mul4(s, iG[2])) - T8.append(mul4(s, iG[3])) - - U1.append(mul4(t, iG[0])) - U2.append(mul4(t, iG[1])) - U3.append(mul4(t, iG[2])) - U4.append(mul4(t, iG[3])) - -# round constants -rcon = [1] -r = 1 -for t in xrange(1, 30): - r = mul(2, r) - rcon.append(r) - -del A -del AA -del pivot -del B -del G -del box -del log -del alog -del i -del j -del r -del s -del t -del mul -del mul4 -del cox -del iG - -class rijndael: - def __init__(self, key, block_size = 16): - if block_size != 16 and block_size != 24 and block_size != 32: - raise ValueError('Invalid block size: ' + str(block_size)) - if len(key) != 16 and len(key) != 24 and len(key) != 32: - raise ValueError('Invalid key size: ' + str(len(key))) - self.block_size = block_size - - ROUNDS = num_rounds[len(key)][block_size] - BC = block_size / 4 - # encryption round keys - Ke = [[0] * BC for i in xrange(ROUNDS + 1)] - # decryption round keys - Kd = [[0] * BC for i in xrange(ROUNDS + 1)] - ROUND_KEY_COUNT = (ROUNDS + 1) * BC - KC = len(key) / 4 - - # copy user material bytes into temporary ints - tk = [] - for i in xrange(0, KC): - tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) | - (ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3])) - - # copy values into round key arrays - t = 0 - j = 0 - while j < KC and t < ROUND_KEY_COUNT: - Ke[t / BC][t % BC] = tk[j] - Kd[ROUNDS - (t / BC)][t % BC] = tk[j] - j += 1 - t += 1 - tt = 0 - rconpointer = 0 - while t < ROUND_KEY_COUNT: - # extrapolate using phi (the round key evolution function) - tt = tk[KC - 1] - tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \ - (S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \ - (S[ tt & 0xFF] & 0xFF) << 8 ^ \ - (S[(tt >> 24) & 0xFF] & 0xFF) ^ \ - (rcon[rconpointer] & 0xFF) << 24 - rconpointer += 1 - if KC != 8: - for i in xrange(1, KC): - tk[i] ^= tk[i-1] - else: - for i in xrange(1, KC / 2): - tk[i] ^= tk[i-1] - tt = tk[KC / 2 - 1] - tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF) ^ \ - (S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \ - (S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \ - (S[(tt >> 24) & 0xFF] & 0xFF) << 24 - for i in xrange(KC / 2 + 1, KC): - tk[i] ^= tk[i-1] - # copy values into round key arrays - j = 0 - while j < KC and t < ROUND_KEY_COUNT: - Ke[t / BC][t % BC] = tk[j] - Kd[ROUNDS - (t / BC)][t % BC] = tk[j] - j += 1 - t += 1 - # inverse MixColumn where needed - for r in xrange(1, ROUNDS): - for j in xrange(BC): - tt = Kd[r][j] - Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \ - U2[(tt >> 16) & 0xFF] ^ \ - U3[(tt >> 8) & 0xFF] ^ \ - U4[ tt & 0xFF] - self.Ke = Ke - self.Kd = Kd - - def encrypt(self, plaintext): - if len(plaintext) != self.block_size: - raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext))) - Ke = self.Ke - - BC = self.block_size / 4 - ROUNDS = len(Ke) - 1 - if BC == 4: - SC = 0 - elif BC == 6: - SC = 1 - else: - SC = 2 - s1 = shifts[SC][1][0] - s2 = shifts[SC][2][0] - s3 = shifts[SC][3][0] - a = [0] * BC - # temporary work array - t = [] - # plaintext to ints + key - for i in xrange(BC): - t.append((ord(plaintext[i * 4 ]) << 24 | - ord(plaintext[i * 4 + 1]) << 16 | - ord(plaintext[i * 4 + 2]) << 8 | - ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i]) - # apply round transforms - for r in xrange(1, ROUNDS): - for i in xrange(BC): - a[i] = (T1[(t[ i ] >> 24) & 0xFF] ^ - T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^ - T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^ - T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i] - t = copy.copy(a) - # last round is special - result = [] - for i in xrange(BC): - tt = Ke[ROUNDS][i] - result.append((S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF) - result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF) - result.append((S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF) - result.append((S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF) - return string.join(map(chr, result), '') - - def decrypt(self, ciphertext): - if len(ciphertext) != self.block_size: - raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext))) - Kd = self.Kd - - BC = self.block_size / 4 - ROUNDS = len(Kd) - 1 - if BC == 4: - SC = 0 - elif BC == 6: - SC = 1 - else: - SC = 2 - s1 = shifts[SC][1][1] - s2 = shifts[SC][2][1] - s3 = shifts[SC][3][1] - a = [0] * BC - # temporary work array - t = [0] * BC - # ciphertext to ints + key - for i in xrange(BC): - t[i] = (ord(ciphertext[i * 4 ]) << 24 | - ord(ciphertext[i * 4 + 1]) << 16 | - ord(ciphertext[i * 4 + 2]) << 8 | - ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i] - # apply round transforms - for r in xrange(1, ROUNDS): - for i in xrange(BC): - a[i] = (T5[(t[ i ] >> 24) & 0xFF] ^ - T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^ - T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^ - T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i] - t = copy.copy(a) - # last round is special - result = [] - for i in xrange(BC): - tt = Kd[ROUNDS][i] - result.append((Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF) - result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF) - result.append((Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF) - result.append((Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF) - return string.join(map(chr, result), '') - -def encrypt(key, block): - return rijndael(key, len(block)).encrypt(block) - -def decrypt(key, block): - return rijndael(key, len(block)).decrypt(block) - -def test(): - def t(kl, bl): - b = 'b' * bl - r = rijndael('a' * kl, bl) - assert r.decrypt(r.encrypt(b)) == b - t(16, 16) - t(16, 24) - t(16, 32) - t(24, 16) - t(24, 24) - t(24, 32) - t(32, 16) - t(32, 24) - t(32, 32) - diff --git a/src/lib/tlslite/utils/win32prng.c b/src/lib/tlslite/utils/win32prng.c deleted file mode 100755 index de08b3b3b..000000000 --- a/src/lib/tlslite/utils/win32prng.c +++ /dev/null @@ -1,63 +0,0 @@ - -#include "Python.h" -#define _WIN32_WINNT 0x0400 /* Needed for CryptoAPI on some systems */ -#include - - -static PyObject* getRandomBytes(PyObject *self, PyObject *args) -{ - int howMany; - HCRYPTPROV hCryptProv; - unsigned char* bytes = NULL; - PyObject* returnVal = NULL; - - - /* Read Arguments */ - if (!PyArg_ParseTuple(args, "i", &howMany)) - return(NULL); - - /* Get Context */ - if(CryptAcquireContext( - &hCryptProv, - NULL, - NULL, - PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT) == 0) - return Py_BuildValue("s#", NULL, 0); - - - /* Allocate bytes */ - bytes = malloc(howMany); - - - /* Get random data */ - if(CryptGenRandom( - hCryptProv, - howMany, - bytes) == 0) - returnVal = Py_BuildValue("s#", NULL, 0); - else - returnVal = Py_BuildValue("s#", bytes, howMany); - - free(bytes); - CryptReleaseContext(hCryptProv, 0); - - return returnVal; -} - - - -/* List of functions exported by this module */ - -static struct PyMethodDef win32prng_functions[] = { - {"getRandomBytes", (PyCFunction)getRandomBytes, METH_VARARGS}, - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -DL_EXPORT(void) initwin32prng(void) -{ - Py_InitModule("win32prng", win32prng_functions); -} diff --git a/src/lib/tlslite/utils/xmltools.py b/src/lib/tlslite/utils/xmltools.py deleted file mode 100755 index 06f2e4307..000000000 --- a/src/lib/tlslite/utils/xmltools.py +++ /dev/null @@ -1,201 +0,0 @@ -"""Helper functions for XML. - -This module has misc. helper functions for working with XML DOM nodes.""" - -import re -from compat import * - -import os -if os.name != "java": - from xml.dom import minidom - from xml.sax import saxutils - - def parseDocument(s): - return minidom.parseString(s) -else: - from javax.xml.parsers import * - import java - - builder = DocumentBuilderFactory.newInstance().newDocumentBuilder() - - def parseDocument(s): - stream = java.io.ByteArrayInputStream(java.lang.String(s).getBytes()) - return builder.parse(stream) - -def parseAndStripWhitespace(s): - try: - element = parseDocument(s).documentElement - except BaseException, e: - raise SyntaxError(str(e)) - stripWhitespace(element) - return element - -#Goes through a DOM tree and removes whitespace besides child elements, -#as long as this whitespace is correctly tab-ified -def stripWhitespace(element, tab=0): - element.normalize() - - lastSpacer = "\n" + ("\t"*tab) - spacer = lastSpacer + "\t" - - #Zero children aren't allowed (i.e. ) - #This makes writing output simpler, and matches Canonical XML - if element.childNodes.length==0: #DON'T DO len(element.childNodes) - doesn't work in Jython - raise SyntaxError("Empty XML elements not allowed") - - #If there's a single child, it must be text context - if element.childNodes.length==1: - if element.firstChild.nodeType == element.firstChild.TEXT_NODE: - #If it's an empty element, remove - if element.firstChild.data == lastSpacer: - element.removeChild(element.firstChild) - return - #If not text content, give an error - elif element.firstChild.nodeType == element.firstChild.ELEMENT_NODE: - raise SyntaxError("Bad whitespace under '%s'" % element.tagName) - else: - raise SyntaxError("Unexpected node type in XML document") - - #Otherwise there's multiple child element - child = element.firstChild - while child: - if child.nodeType == child.ELEMENT_NODE: - stripWhitespace(child, tab+1) - child = child.nextSibling - elif child.nodeType == child.TEXT_NODE: - if child == element.lastChild: - if child.data != lastSpacer: - raise SyntaxError("Bad whitespace under '%s'" % element.tagName) - elif child.data != spacer: - raise SyntaxError("Bad whitespace under '%s'" % element.tagName) - next = child.nextSibling - element.removeChild(child) - child = next - else: - raise SyntaxError("Unexpected node type in XML document") - - -def checkName(element, name): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Missing element: '%s'" % name) - - if name == None: - return - - if element.tagName != name: - raise SyntaxError("Wrong element name: should be '%s', is '%s'" % (name, element.tagName)) - -def getChild(element, index, name=None): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Wrong node type in getChild()") - - child = element.childNodes.item(index) - if child == None: - raise SyntaxError("Missing child: '%s'" % name) - checkName(child, name) - return child - -def getChildIter(element, index): - class ChildIter: - def __init__(self, element, index): - self.element = element - self.index = index - - def next(self): - if self.index < len(self.element.childNodes): - retVal = self.element.childNodes.item(self.index) - self.index += 1 - else: - retVal = None - return retVal - - def checkEnd(self): - if self.index != len(self.element.childNodes): - raise SyntaxError("Too many elements under: '%s'" % self.element.tagName) - return ChildIter(element, index) - -def getChildOrNone(element, index): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Wrong node type in getChild()") - child = element.childNodes.item(index) - return child - -def getLastChild(element, index, name=None): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Wrong node type in getLastChild()") - - child = element.childNodes.item(index) - if child == None: - raise SyntaxError("Missing child: '%s'" % name) - if child != element.lastChild: - raise SyntaxError("Too many elements under: '%s'" % element.tagName) - checkName(child, name) - return child - -#Regular expressions for syntax-checking attribute and element content -nsRegEx = "http://trevp.net/cryptoID\Z" -cryptoIDRegEx = "([a-km-z3-9]{5}\.){3}[a-km-z3-9]{5}\Z" -urlRegEx = "http(s)?://.{1,100}\Z" -sha1Base64RegEx = "[A-Za-z0-9+/]{27}=\Z" -base64RegEx = "[A-Za-z0-9+/]+={0,4}\Z" -certsListRegEx = "(0)?(1)?(2)?(3)?(4)?(5)?(6)?(7)?(8)?(9)?\Z" -keyRegEx = "[A-Z]\Z" -keysListRegEx = "(A)?(B)?(C)?(D)?(E)?(F)?(G)?(H)?(I)?(J)?(K)?(L)?(M)?(N)?(O)?(P)?(Q)?(R)?(S)?(T)?(U)?(V)?(W)?(X)?(Y)?(Z)?\Z" -dateTimeRegEx = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\Z" -shortStringRegEx = ".{1,100}\Z" -exprRegEx = "[a-zA-Z0-9 ,()]{1,200}\Z" -notAfterDeltaRegEx = "0|([1-9][0-9]{0,8})\Z" #A number from 0 to (1 billion)-1 -booleanRegEx = "(true)|(false)" - -def getReqAttribute(element, attrName, regEx=""): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Wrong node type in getReqAttribute()") - - value = element.getAttribute(attrName) - if not value: - raise SyntaxError("Missing Attribute: " + attrName) - if not re.match(regEx, value): - raise SyntaxError("Bad Attribute Value for '%s': '%s' " % (attrName, value)) - element.removeAttribute(attrName) - return str(value) #de-unicode it; this is needed for bsddb, for example - -def getAttribute(element, attrName, regEx=""): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Wrong node type in getAttribute()") - - value = element.getAttribute(attrName) - if value: - if not re.match(regEx, value): - raise SyntaxError("Bad Attribute Value for '%s': '%s' " % (attrName, value)) - element.removeAttribute(attrName) - return str(value) #de-unicode it; this is needed for bsddb, for example - -def checkNoMoreAttributes(element): - if element.nodeType != element.ELEMENT_NODE: - raise SyntaxError("Wrong node type in checkNoMoreAttributes()") - - if element.attributes.length!=0: - raise SyntaxError("Extra attributes on '%s'" % element.tagName) - -def getText(element, regEx=""): - textNode = element.firstChild - if textNode == None: - raise SyntaxError("Empty element '%s'" % element.tagName) - if textNode.nodeType != textNode.TEXT_NODE: - raise SyntaxError("Non-text node: '%s'" % element.tagName) - if not re.match(regEx, textNode.data): - raise SyntaxError("Bad Text Value for '%s': '%s' " % (element.tagName, textNode.data)) - return str(textNode.data) #de-unicode it; this is needed for bsddb, for example - -#Function for adding tabs to a string -def indent(s, steps, ch="\t"): - tabs = ch*steps - if s[-1] != "\n": - s = tabs + s.replace("\n", "\n"+tabs) - else: - s = tabs + s.replace("\n", "\n"+tabs) - s = s[ : -len(tabs)] - return s - -def escape(s): - return saxutils.escape(s) -- cgit v1.2.3-1-g7c22