| OLD | NEW |
| 1 # Authors: | 1 # Authors: |
| 2 # Trevor Perrin | 2 # Trevor Perrin |
| 3 # Google - handling CertificateRequest.certificate_types | 3 # Google - handling CertificateRequest.certificate_types |
| 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support | 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support |
| 5 # Dimitris Moraitis - Anon ciphersuites | 5 # Dimitris Moraitis - Anon ciphersuites |
| 6 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 | 6 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 |
| 7 # | 7 # |
| 8 # See the LICENSE file for legal information regarding use of this file. | 8 # See the LICENSE file for legal information regarding use of this file. |
| 9 | 9 |
| 10 """Classes representing TLS messages.""" | 10 """Classes representing TLS messages.""" |
| 11 | 11 |
| 12 from .utils.compat import * | 12 from .utils.compat import * |
| 13 from .utils.cryptomath import * | 13 from .utils.cryptomath import * |
| 14 from .errors import * | 14 from .errors import * |
| 15 from .utils.codec import * | 15 from .utils.codec import * |
| 16 from .constants import * | 16 from .constants import * |
| 17 from .x509 import X509 | 17 from .x509 import X509 |
| 18 from .x509certchain import X509CertChain | 18 from .x509certchain import X509CertChain |
| 19 from .utils.tackwrapper import * | 19 from .utils.tackwrapper import * |
| 20 | 20 |
| 21 def parse_next_protos(b): |
| 22 protos = [] |
| 23 while True: |
| 24 if len(b) == 0: |
| 25 break |
| 26 l = b[0] |
| 27 b = b[1:] |
| 28 if len(b) < l: |
| 29 raise BadNextProtos(len(b)) |
| 30 protos.append(b[:l]) |
| 31 b = b[l:] |
| 32 return protos |
| 33 |
| 34 def next_protos_encoded(protocol_list): |
| 35 b = bytearray() |
| 36 for e in protocol_list: |
| 37 if len(e) > 255 or len(e) == 0: |
| 38 raise BadNextProtos(len(e)) |
| 39 b += bytearray( [len(e)] ) + bytearray(e) |
| 40 return b |
| 41 |
| 21 class RecordHeader3(object): | 42 class RecordHeader3(object): |
| 22 def __init__(self): | 43 def __init__(self): |
| 23 self.type = 0 | 44 self.type = 0 |
| 24 self.version = (0,0) | 45 self.version = (0,0) |
| 25 self.length = 0 | 46 self.length = 0 |
| 26 self.ssl2 = False | 47 self.ssl2 = False |
| 27 | 48 |
| 28 def create(self, version, type, length): | 49 def create(self, version, type, length): |
| 29 self.type = type | 50 self.type = type |
| 30 self.version = version | 51 self.version = version |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 HandshakeMsg.__init__(self, HandshakeType.client_hello) | 125 HandshakeMsg.__init__(self, HandshakeType.client_hello) |
| 105 self.ssl2 = ssl2 | 126 self.ssl2 = ssl2 |
| 106 self.client_version = (0,0) | 127 self.client_version = (0,0) |
| 107 self.random = bytearray(32) | 128 self.random = bytearray(32) |
| 108 self.session_id = bytearray(0) | 129 self.session_id = bytearray(0) |
| 109 self.cipher_suites = [] # a list of 16-bit values | 130 self.cipher_suites = [] # a list of 16-bit values |
| 110 self.certificate_types = [CertificateType.x509] | 131 self.certificate_types = [CertificateType.x509] |
| 111 self.compression_methods = [] # a list of 8-bit values | 132 self.compression_methods = [] # a list of 8-bit values |
| 112 self.srp_username = None # a string | 133 self.srp_username = None # a string |
| 113 self.tack = False | 134 self.tack = False |
| 135 self.alpn_protos_advertised = None |
| 114 self.supports_npn = False | 136 self.supports_npn = False |
| 115 self.server_name = bytearray(0) | 137 self.server_name = bytearray(0) |
| 116 self.channel_id = False | 138 self.channel_id = False |
| 117 self.extended_master_secret = False | 139 self.extended_master_secret = False |
| 118 self.tb_client_params = [] | 140 self.tb_client_params = [] |
| 119 self.support_signed_cert_timestamps = False | 141 self.support_signed_cert_timestamps = False |
| 120 self.status_request = False | 142 self.status_request = False |
| 121 | 143 |
| 122 def create(self, version, random, session_id, cipher_suites, | 144 def create(self, version, random, session_id, cipher_suites, |
| 123 certificate_types=None, srpUsername=None, | 145 certificate_types=None, srpUsername=None, |
| 124 tack=False, supports_npn=False, serverName=None): | 146 tack=False, alpn_protos_advertised=None, |
| 147 supports_npn=False, serverName=None): |
| 125 self.client_version = version | 148 self.client_version = version |
| 126 self.random = random | 149 self.random = random |
| 127 self.session_id = session_id | 150 self.session_id = session_id |
| 128 self.cipher_suites = cipher_suites | 151 self.cipher_suites = cipher_suites |
| 129 self.certificate_types = certificate_types | 152 self.certificate_types = certificate_types |
| 130 self.compression_methods = [0] | 153 self.compression_methods = [0] |
| 131 if srpUsername: | 154 if srpUsername: |
| 132 self.srp_username = bytearray(srpUsername, "utf-8") | 155 self.srp_username = bytearray(srpUsername, "utf-8") |
| 133 self.tack = tack | 156 self.tack = tack |
| 157 self.alpn_protos_advertised = alpn_protos_advertised |
| 134 self.supports_npn = supports_npn | 158 self.supports_npn = supports_npn |
| 135 if serverName: | 159 if serverName: |
| 136 self.server_name = bytearray(serverName, "utf-8") | 160 self.server_name = bytearray(serverName, "utf-8") |
| 137 return self | 161 return self |
| 138 | 162 |
| 139 def parse(self, p): | 163 def parse(self, p): |
| 140 if self.ssl2: | 164 if self.ssl2: |
| 141 self.client_version = (p.get(1), p.get(1)) | 165 self.client_version = (p.get(1), p.get(1)) |
| 142 cipherSpecsLength = p.get(2) | 166 cipherSpecsLength = p.get(2) |
| 143 sessionIDLength = p.get(2) | 167 sessionIDLength = p.get(2) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 164 while soFar != totalExtLength: | 188 while soFar != totalExtLength: |
| 165 extType = p.get(2) | 189 extType = p.get(2) |
| 166 extLength = p.get(2) | 190 extLength = p.get(2) |
| 167 index1 = p.index | 191 index1 = p.index |
| 168 if extType == ExtensionType.srp: | 192 if extType == ExtensionType.srp: |
| 169 self.srp_username = p.getVarBytes(1) | 193 self.srp_username = p.getVarBytes(1) |
| 170 elif extType == ExtensionType.cert_type: | 194 elif extType == ExtensionType.cert_type: |
| 171 self.certificate_types = p.getVarList(1, 1) | 195 self.certificate_types = p.getVarList(1, 1) |
| 172 elif extType == ExtensionType.tack: | 196 elif extType == ExtensionType.tack: |
| 173 self.tack = True | 197 self.tack = True |
| 198 elif extType == ExtensionType.alpn: |
| 199 structLength = p.get(2) |
| 200 if structLength + 2 != extLength: |
| 201 raise SyntaxError() |
| 202 self.alpn_protos_advertised = parse_next_protos(p.getFix
Bytes(structLength)) |
| 174 elif extType == ExtensionType.supports_npn: | 203 elif extType == ExtensionType.supports_npn: |
| 175 self.supports_npn = True | 204 self.supports_npn = True |
| 176 elif extType == ExtensionType.server_name: | 205 elif extType == ExtensionType.server_name: |
| 177 serverNameListBytes = p.getFixBytes(extLength) | 206 serverNameListBytes = p.getFixBytes(extLength) |
| 178 p2 = Parser(serverNameListBytes) | 207 p2 = Parser(serverNameListBytes) |
| 179 p2.startLengthCheck(2) | 208 p2.startLengthCheck(2) |
| 180 while 1: | 209 while 1: |
| 181 if p2.atLengthCheck(): | 210 if p2.atLengthCheck(): |
| 182 break # no host_name, oh well | 211 break # no host_name, oh well |
| 183 name_type = p2.get(1) | 212 name_type = p2.get(1) |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 w2 = Writer() # For Extensions | 265 w2 = Writer() # For Extensions |
| 237 if self.certificate_types and self.certificate_types != \ | 266 if self.certificate_types and self.certificate_types != \ |
| 238 [CertificateType.x509]: | 267 [CertificateType.x509]: |
| 239 w2.add(ExtensionType.cert_type, 2) | 268 w2.add(ExtensionType.cert_type, 2) |
| 240 w2.add(len(self.certificate_types)+1, 2) | 269 w2.add(len(self.certificate_types)+1, 2) |
| 241 w2.addVarSeq(self.certificate_types, 1, 1) | 270 w2.addVarSeq(self.certificate_types, 1, 1) |
| 242 if self.srp_username: | 271 if self.srp_username: |
| 243 w2.add(ExtensionType.srp, 2) | 272 w2.add(ExtensionType.srp, 2) |
| 244 w2.add(len(self.srp_username)+1, 2) | 273 w2.add(len(self.srp_username)+1, 2) |
| 245 w2.addVarSeq(self.srp_username, 1, 1) | 274 w2.addVarSeq(self.srp_username, 1, 1) |
| 275 if self.alpn_protos_advertised is not None: |
| 276 encoded_alpn_protos_advertised = next_protos_encoded(self.alpn_proto
s_advertised) |
| 277 w2.add(ExtensionType.alpn, 2) |
| 278 w2.add(len(encoded_alpn_protos_advertised) + 2, 2) |
| 279 w2.add(len(encoded_alpn_protos_advertised), 2) |
| 280 w2.addFixSeq(encoded_alpn_protos_advertised, 1) |
| 246 if self.supports_npn: | 281 if self.supports_npn: |
| 247 w2.add(ExtensionType.supports_npn, 2) | 282 w2.add(ExtensionType.supports_npn, 2) |
| 248 w2.add(0, 2) | 283 w2.add(0, 2) |
| 249 if self.server_name: | 284 if self.server_name: |
| 250 w2.add(ExtensionType.server_name, 2) | 285 w2.add(ExtensionType.server_name, 2) |
| 251 w2.add(len(self.server_name)+5, 2) | 286 w2.add(len(self.server_name)+5, 2) |
| 252 w2.add(len(self.server_name)+3, 2) | 287 w2.add(len(self.server_name)+3, 2) |
| 253 w2.add(NameType.host_name, 1) | 288 w2.add(NameType.host_name, 1) |
| 254 w2.addVarSeq(self.server_name, 1, 2) | 289 w2.addVarSeq(self.server_name, 1, 2) |
| 255 if self.tack: | 290 if self.tack: |
| 256 w2.add(ExtensionType.tack, 2) | 291 w2.add(ExtensionType.tack, 2) |
| 257 w2.add(0, 2) | 292 w2.add(0, 2) |
| 258 if len(w2.bytes): | 293 if len(w2.bytes): |
| 259 w.add(len(w2.bytes), 2) | 294 w.add(len(w2.bytes), 2) |
| 260 w.bytes += w2.bytes | 295 w.bytes += w2.bytes |
| 261 return self.postWrite(w) | 296 return self.postWrite(w) |
| 262 | 297 |
| 263 class BadNextProtos(Exception): | 298 class BadNextProtos(Exception): |
| 264 def __init__(self, l): | 299 def __init__(self, l): |
| 265 self.length = l | 300 self.length = l |
| 266 | 301 |
| 267 def __str__(self): | 302 def __str__(self): |
| 268 return 'Cannot encode a list of next protocols because it contains an el
ement with invalid length %d. Element lengths must be 0 < x < 256' % self.length | 303 return 'Cannot encode a list of next protocols because it contains an el
ement with invalid length %d. Element lengths must be 0 < x < 256' % self.length |
| 269 | 304 |
| 305 class InvalidALPNResponse(Exception): |
| 306 def __init__(self, l): |
| 307 self.length = l |
| 308 |
| 309 def __str__(self): |
| 310 return 'ALPN server response protocol list has invalid length %d. It mu
st be of length one.' % self.length |
| 311 |
| 270 class ServerHello(HandshakeMsg): | 312 class ServerHello(HandshakeMsg): |
| 271 def __init__(self): | 313 def __init__(self): |
| 272 HandshakeMsg.__init__(self, HandshakeType.server_hello) | 314 HandshakeMsg.__init__(self, HandshakeType.server_hello) |
| 273 self.server_version = (0,0) | 315 self.server_version = (0,0) |
| 274 self.random = bytearray(32) | 316 self.random = bytearray(32) |
| 275 self.session_id = bytearray(0) | 317 self.session_id = bytearray(0) |
| 276 self.cipher_suite = 0 | 318 self.cipher_suite = 0 |
| 277 self.certificate_type = CertificateType.x509 | 319 self.certificate_type = CertificateType.x509 |
| 278 self.compression_method = 0 | 320 self.compression_method = 0 |
| 279 self.tackExt = None | 321 self.tackExt = None |
| 322 self.alpn_proto_selected = None |
| 280 self.next_protos_advertised = None | 323 self.next_protos_advertised = None |
| 281 self.next_protos = None | 324 self.next_protos = None |
| 282 self.channel_id = False | 325 self.channel_id = False |
| 283 self.extended_master_secret = False | 326 self.extended_master_secret = False |
| 284 self.tb_params = None | 327 self.tb_params = None |
| 285 self.signed_cert_timestamps = None | 328 self.signed_cert_timestamps = None |
| 286 self.status_request = False | 329 self.status_request = False |
| 287 | 330 |
| 288 def create(self, version, random, session_id, cipher_suite, | 331 def create(self, version, random, session_id, cipher_suite, |
| 289 certificate_type, tackExt, next_protos_advertised): | 332 certificate_type, tackExt, alpn_proto_selected, |
| 333 next_protos_advertised): |
| 290 self.server_version = version | 334 self.server_version = version |
| 291 self.random = random | 335 self.random = random |
| 292 self.session_id = session_id | 336 self.session_id = session_id |
| 293 self.cipher_suite = cipher_suite | 337 self.cipher_suite = cipher_suite |
| 294 self.certificate_type = certificate_type | 338 self.certificate_type = certificate_type |
| 295 self.compression_method = 0 | 339 self.compression_method = 0 |
| 296 self.tackExt = tackExt | 340 self.tackExt = tackExt |
| 341 self.alpn_proto_selected = alpn_proto_selected |
| 297 self.next_protos_advertised = next_protos_advertised | 342 self.next_protos_advertised = next_protos_advertised |
| 298 return self | 343 return self |
| 299 | 344 |
| 300 def parse(self, p): | 345 def parse(self, p): |
| 301 p.startLengthCheck(3) | 346 p.startLengthCheck(3) |
| 302 self.server_version = (p.get(1), p.get(1)) | 347 self.server_version = (p.get(1), p.get(1)) |
| 303 self.random = p.getFixBytes(32) | 348 self.random = p.getFixBytes(32) |
| 304 self.session_id = p.getVarBytes(1) | 349 self.session_id = p.getVarBytes(1) |
| 305 self.cipher_suite = p.get(2) | 350 self.cipher_suite = p.get(2) |
| 306 self.compression_method = p.get(1) | 351 self.compression_method = p.get(1) |
| 307 if not p.atLengthCheck(): | 352 if not p.atLengthCheck(): |
| 308 totalExtLength = p.get(2) | 353 totalExtLength = p.get(2) |
| 309 soFar = 0 | 354 soFar = 0 |
| 310 while soFar != totalExtLength: | 355 while soFar != totalExtLength: |
| 311 extType = p.get(2) | 356 extType = p.get(2) |
| 312 extLength = p.get(2) | 357 extLength = p.get(2) |
| 313 if extType == ExtensionType.cert_type: | 358 if extType == ExtensionType.cert_type: |
| 314 if extLength != 1: | 359 if extLength != 1: |
| 315 raise SyntaxError() | 360 raise SyntaxError() |
| 316 self.certificate_type = p.get(1) | 361 self.certificate_type = p.get(1) |
| 317 elif extType == ExtensionType.tack and tackpyLoaded: | 362 elif extType == ExtensionType.tack and tackpyLoaded: |
| 318 self.tackExt = TackExtension(p.getFixBytes(extLength)) | 363 self.tackExt = TackExtension(p.getFixBytes(extLength)) |
| 364 elif extType == ExtensionType.alpn: |
| 365 structLength = p.get(2) |
| 366 if structLength + 2 != extLength: |
| 367 raise SyntaxError() |
| 368 alpn_protos = parse_next_protos(p.getFixBytes(structLength)) |
| 369 if len(alpn_protos) != 1: |
| 370 raise InvalidALPNResponse(len(alpn_protos)); |
| 371 self.alpn_proto_selected = alpn_protos[0] |
| 319 elif extType == ExtensionType.supports_npn: | 372 elif extType == ExtensionType.supports_npn: |
| 320 self.next_protos = self.__parse_next_protos(p.getFixBytes(ex
tLength)) | 373 self.next_protos = parse_next_protos(p.getFixBytes(extLength
)) |
| 321 else: | 374 else: |
| 322 p.getFixBytes(extLength) | 375 p.getFixBytes(extLength) |
| 323 soFar += 4 + extLength | 376 soFar += 4 + extLength |
| 324 p.stopLengthCheck() | 377 p.stopLengthCheck() |
| 325 return self | 378 return self |
| 326 | 379 |
| 327 def __parse_next_protos(self, b): | |
| 328 protos = [] | |
| 329 while True: | |
| 330 if len(b) == 0: | |
| 331 break | |
| 332 l = b[0] | |
| 333 b = b[1:] | |
| 334 if len(b) < l: | |
| 335 raise BadNextProtos(len(b)) | |
| 336 protos.append(b[:l]) | |
| 337 b = b[l:] | |
| 338 return protos | |
| 339 | |
| 340 def __next_protos_encoded(self): | |
| 341 b = bytearray() | |
| 342 for e in self.next_protos_advertised: | |
| 343 if len(e) > 255 or len(e) == 0: | |
| 344 raise BadNextProtos(len(e)) | |
| 345 b += bytearray( [len(e)] ) + bytearray(e) | |
| 346 return b | |
| 347 | |
| 348 def write(self): | 380 def write(self): |
| 349 w = Writer() | 381 w = Writer() |
| 350 w.add(self.server_version[0], 1) | 382 w.add(self.server_version[0], 1) |
| 351 w.add(self.server_version[1], 1) | 383 w.add(self.server_version[1], 1) |
| 352 w.addFixSeq(self.random, 1) | 384 w.addFixSeq(self.random, 1) |
| 353 w.addVarSeq(self.session_id, 1, 1) | 385 w.addVarSeq(self.session_id, 1, 1) |
| 354 w.add(self.cipher_suite, 2) | 386 w.add(self.cipher_suite, 2) |
| 355 w.add(self.compression_method, 1) | 387 w.add(self.compression_method, 1) |
| 356 | 388 |
| 357 w2 = Writer() # For Extensions | 389 w2 = Writer() # For Extensions |
| 358 if self.certificate_type and self.certificate_type != \ | 390 if self.certificate_type and self.certificate_type != \ |
| 359 CertificateType.x509: | 391 CertificateType.x509: |
| 360 w2.add(ExtensionType.cert_type, 2) | 392 w2.add(ExtensionType.cert_type, 2) |
| 361 w2.add(1, 2) | 393 w2.add(1, 2) |
| 362 w2.add(self.certificate_type, 1) | 394 w2.add(self.certificate_type, 1) |
| 363 if self.tackExt: | 395 if self.tackExt: |
| 364 b = self.tackExt.serialize() | 396 b = self.tackExt.serialize() |
| 365 w2.add(ExtensionType.tack, 2) | 397 w2.add(ExtensionType.tack, 2) |
| 366 w2.add(len(b), 2) | 398 w2.add(len(b), 2) |
| 367 w2.bytes += b | 399 w2.bytes += b |
| 400 if self.alpn_proto_selected is not None: |
| 401 alpn_protos_single_element_list = [self.alpn_proto_selected] |
| 402 encoded_alpn_protos_advertised = next_protos_encoded(alpn_protos_sin
gle_element_list) |
| 403 w2.add(ExtensionType.alpn, 2) |
| 404 w2.add(len(encoded_alpn_protos_advertised) + 2, 2) |
| 405 w2.add(len(encoded_alpn_protos_advertised), 2) |
| 406 w2.addFixSeq(encoded_alpn_protos_advertised, 1) |
| 368 if self.next_protos_advertised is not None: | 407 if self.next_protos_advertised is not None: |
| 369 encoded_next_protos_advertised = self.__next_protos_encoded() | 408 encoded_next_protos_advertised = next_protos_encoded(self.next_proto
s_advertised) |
| 370 w2.add(ExtensionType.supports_npn, 2) | 409 w2.add(ExtensionType.supports_npn, 2) |
| 371 w2.add(len(encoded_next_protos_advertised), 2) | 410 w2.add(len(encoded_next_protos_advertised), 2) |
| 372 w2.addFixSeq(encoded_next_protos_advertised, 1) | 411 w2.addFixSeq(encoded_next_protos_advertised, 1) |
| 373 if self.channel_id: | 412 if self.channel_id: |
| 374 w2.add(ExtensionType.channel_id, 2) | 413 w2.add(ExtensionType.channel_id, 2) |
| 375 w2.add(0, 2) | 414 w2.add(0, 2) |
| 376 if self.extended_master_secret: | 415 if self.extended_master_secret: |
| 377 w2.add(ExtensionType.extended_master_secret, 2) | 416 w2.add(ExtensionType.extended_master_secret, 2) |
| 378 w2.add(0, 2) | 417 w2.add(0, 2) |
| 379 if self.tb_params: | 418 if self.tb_params: |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 newMsg = ApplicationData().create(self.bytes[:1]) | 864 newMsg = ApplicationData().create(self.bytes[:1]) |
| 826 self.bytes = self.bytes[1:] | 865 self.bytes = self.bytes[1:] |
| 827 return newMsg | 866 return newMsg |
| 828 | 867 |
| 829 def parse(self, p): | 868 def parse(self, p): |
| 830 self.bytes = p.bytes | 869 self.bytes = p.bytes |
| 831 return self | 870 return self |
| 832 | 871 |
| 833 def write(self): | 872 def write(self): |
| 834 return self.bytes | 873 return self.bytes |
| OLD | NEW |