summaryrefslogtreecommitdiffstats
path: root/src/lib/tlslite/HandshakeSettings.py
blob: c7c3223e515f1e6d6c01a968f25ed58c1fa38597 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
"""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