clean up clienthello parsing
This commit is contained in:
parent
2cfc1b1b40
commit
9c6b3eb58a
|
@ -8,3 +8,7 @@ jsbeautifier, git checkout 25/03/12, MIT license
|
|||
|
||||
wbxml
|
||||
- https://github.com/davidpshaw/PyWBXMLDecoder
|
||||
|
||||
tls, BSD license
|
||||
- https://github.com/mhils/tls/tree/extension-parsing
|
||||
- limited to required files.
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from construct import Array, Bytes, Struct, UBInt16, UBInt32, UBInt8, PascalString, Embed, \
|
||||
TunnelAdapter, GreedyRange, Switch
|
||||
from construct import (Array, Bytes, Struct, UBInt16, UBInt32, UBInt8, PascalString, Embed, TunnelAdapter, GreedyRange,
|
||||
Switch, OptionalGreedyRange)
|
||||
|
||||
from .utils import UBInt24
|
||||
|
||||
|
@ -113,7 +113,7 @@ Extension = Struct(
|
|||
|
||||
extensions = TunnelAdapter(
|
||||
PascalString("extensions", length_field=UBInt16("extensions_length")),
|
||||
GreedyRange(Extension)
|
||||
OptionalGreedyRange(Extension)
|
||||
)
|
||||
|
||||
ClientHello = Struct(
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from characteristic import attributes
|
||||
|
||||
from . import _constructs
|
||||
|
||||
|
||||
class AlertLevel(Enum):
|
||||
WARNING = 1
|
||||
FATAL = 2
|
||||
|
||||
|
||||
class AlertDescription(Enum):
|
||||
CLOSE_NOTIFY = 0
|
||||
UNEXPECTED_MESSAGE = 10
|
||||
BAD_RECORD_MAC = 20
|
||||
DECRYPTION_FAILED_RESERVED = 21
|
||||
RECORD_OVERFLOW = 22
|
||||
DECOMPRESSION_FAILURE = 30
|
||||
HANDSHAKE_FAILURE = 40
|
||||
NO_CERTIFICATE_RESERVED = 41
|
||||
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_RESERVED = 60
|
||||
PROTOCOL_VERSION = 70
|
||||
INSUFFICIENT_SECURITY = 71
|
||||
INTERNAL_ERROR = 80
|
||||
USER_CANCELED = 90
|
||||
NO_RENEGOTIATION = 100
|
||||
UNSUPPORTED_EXTENSION = 110
|
||||
|
||||
|
||||
@attributes(['level', 'description'])
|
||||
class Alert(object):
|
||||
"""
|
||||
An object representing an Alert message.
|
||||
"""
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse an ``Alert`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: Alert object.
|
||||
"""
|
||||
construct = _constructs.Alert.parse(bytes)
|
||||
return cls(
|
||||
level=AlertLevel(construct.level),
|
||||
description=AlertDescription(construct.description)
|
||||
)
|
|
@ -1,343 +0,0 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from .exceptions import UnsupportedCipherException
|
||||
|
||||
|
||||
class CipherSuites(Enum):
|
||||
TLS_NULL_WITH_NULL_NULL = 0x0000
|
||||
TLS_RSA_WITH_NULL_MD5 = 0x0001
|
||||
TLS_RSA_WITH_NULL_SHA = 0x0002
|
||||
TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003
|
||||
TLS_RSA_WITH_RC4_128_MD5 = 0x0004
|
||||
TLS_RSA_WITH_RC4_128_SHA = 0x0005
|
||||
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006
|
||||
TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007
|
||||
TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008
|
||||
TLS_RSA_WITH_DES_CBC_SHA = 0x0009
|
||||
TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A
|
||||
TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B
|
||||
TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C
|
||||
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D
|
||||
TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E
|
||||
TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F
|
||||
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010
|
||||
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011
|
||||
TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012
|
||||
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013
|
||||
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014
|
||||
TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015
|
||||
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016
|
||||
TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017
|
||||
TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018
|
||||
TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019
|
||||
TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A
|
||||
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B
|
||||
TLS_KRB5_WITH_DES_CBC_SHA = 0x001E
|
||||
TLS_KRB5_WITH_3DES_EDE_CBC_SHA = 0x001F
|
||||
TLS_KRB5_WITH_RC4_128_SHA = 0x0020
|
||||
TLS_KRB5_WITH_IDEA_CBC_SHA = 0x0021
|
||||
TLS_KRB5_WITH_DES_CBC_MD5 = 0x0022
|
||||
TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = 0x0023
|
||||
TLS_KRB5_WITH_RC4_128_MD5 = 0x0024
|
||||
TLS_KRB5_WITH_IDEA_CBC_MD5 = 0x0025
|
||||
TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = 0x0026
|
||||
TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = 0x0027
|
||||
TLS_KRB5_EXPORT_WITH_RC4_40_SHA = 0x0028
|
||||
TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = 0x0029
|
||||
TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = 0x002A
|
||||
TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = 0x002B
|
||||
TLS_PSK_WITH_NULL_SHA = 0x002C
|
||||
TLS_DHE_PSK_WITH_NULL_SHA = 0x002D
|
||||
TLS_RSA_PSK_WITH_NULL_SHA = 0x002E
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F
|
||||
TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030
|
||||
TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
|
||||
TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
|
||||
TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036
|
||||
TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
|
||||
TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A
|
||||
TLS_RSA_WITH_NULL_SHA256 = 0x003B
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D
|
||||
TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E
|
||||
TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040
|
||||
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041
|
||||
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042
|
||||
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043
|
||||
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045
|
||||
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
|
||||
TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068
|
||||
TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
|
||||
TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C
|
||||
TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D
|
||||
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084
|
||||
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085
|
||||
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086
|
||||
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088
|
||||
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089
|
||||
TLS_PSK_WITH_RC4_128_SHA = 0x008A
|
||||
TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B
|
||||
TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C
|
||||
TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D
|
||||
TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E
|
||||
TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F
|
||||
TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090
|
||||
TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091
|
||||
TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092
|
||||
TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093
|
||||
TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094
|
||||
TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095
|
||||
TLS_RSA_WITH_SEED_CBC_SHA = 0x0096
|
||||
TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097
|
||||
TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098
|
||||
TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099
|
||||
TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A
|
||||
TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
|
||||
TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D
|
||||
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
|
||||
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F
|
||||
TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0
|
||||
TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1
|
||||
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2
|
||||
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3
|
||||
TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4
|
||||
TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5
|
||||
TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6
|
||||
TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7
|
||||
TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8
|
||||
TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9
|
||||
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA
|
||||
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB
|
||||
TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC
|
||||
TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD
|
||||
TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE
|
||||
TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF
|
||||
TLS_PSK_WITH_NULL_SHA256 = 0x00B0
|
||||
TLS_PSK_WITH_NULL_SHA384 = 0x00B1
|
||||
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2
|
||||
TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3
|
||||
TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4
|
||||
TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5
|
||||
TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6
|
||||
TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7
|
||||
TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8
|
||||
TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9
|
||||
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA
|
||||
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB
|
||||
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC
|
||||
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE
|
||||
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF
|
||||
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0
|
||||
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1
|
||||
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2
|
||||
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4
|
||||
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5
|
||||
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF
|
||||
TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001
|
||||
TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002
|
||||
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003
|
||||
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004
|
||||
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005
|
||||
TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006
|
||||
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007
|
||||
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A
|
||||
TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B
|
||||
TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C
|
||||
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D
|
||||
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E
|
||||
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F
|
||||
TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010
|
||||
TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014
|
||||
TLS_ECDH_anon_WITH_NULL_SHA = 0xC015
|
||||
TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016
|
||||
TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017
|
||||
TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018
|
||||
TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019
|
||||
TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A
|
||||
TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B
|
||||
TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C
|
||||
TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D
|
||||
TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E
|
||||
TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F
|
||||
TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020
|
||||
TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021
|
||||
TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024
|
||||
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025
|
||||
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028
|
||||
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029
|
||||
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C
|
||||
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D
|
||||
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030
|
||||
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031
|
||||
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032
|
||||
TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033
|
||||
TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034
|
||||
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035
|
||||
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036
|
||||
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037
|
||||
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038
|
||||
TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039
|
||||
TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A
|
||||
TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B
|
||||
TLS_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC03C
|
||||
TLS_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC03D
|
||||
TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC03E
|
||||
TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC03F
|
||||
TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC040
|
||||
TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC041
|
||||
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC042
|
||||
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC043
|
||||
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC044
|
||||
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC045
|
||||
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 = 0xC046
|
||||
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 = 0xC047
|
||||
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC048
|
||||
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC049
|
||||
TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC04A
|
||||
TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC04B
|
||||
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04C
|
||||
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04D
|
||||
TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04E
|
||||
TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04F
|
||||
TLS_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC050
|
||||
TLS_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC051
|
||||
TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC052
|
||||
TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC053
|
||||
TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC054
|
||||
TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC055
|
||||
TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC056
|
||||
TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC057
|
||||
TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC058
|
||||
TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC059
|
||||
TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 = 0xC05A
|
||||
TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 = 0xC05B
|
||||
TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05C
|
||||
TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05D
|
||||
TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05E
|
||||
TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05F
|
||||
TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC060
|
||||
TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC061
|
||||
TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC062
|
||||
TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC063
|
||||
TLS_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC064
|
||||
TLS_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC065
|
||||
TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC066
|
||||
TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC067
|
||||
TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC068
|
||||
TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC069
|
||||
TLS_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06A
|
||||
TLS_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06B
|
||||
TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06C
|
||||
TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06D
|
||||
TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06E
|
||||
TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06F
|
||||
TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC070
|
||||
TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC071
|
||||
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072
|
||||
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073
|
||||
TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074
|
||||
TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075
|
||||
TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076
|
||||
TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077
|
||||
TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078
|
||||
TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079
|
||||
TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A
|
||||
TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D
|
||||
TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E
|
||||
TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F
|
||||
TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080
|
||||
TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081
|
||||
TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082
|
||||
TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083
|
||||
TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084
|
||||
TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085
|
||||
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086
|
||||
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087
|
||||
TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088
|
||||
TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089
|
||||
TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A
|
||||
TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B
|
||||
TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C
|
||||
TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D
|
||||
TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E
|
||||
TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F
|
||||
TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090
|
||||
TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091
|
||||
TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092
|
||||
TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093
|
||||
TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094
|
||||
TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095
|
||||
TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096
|
||||
TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097
|
||||
TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098
|
||||
TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099
|
||||
TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A
|
||||
TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B
|
||||
TLS_RSA_WITH_AES_128_CCM = 0xC09C
|
||||
TLS_RSA_WITH_AES_256_CCM = 0xC09D
|
||||
TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E
|
||||
TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F
|
||||
TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0
|
||||
TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1
|
||||
TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2
|
||||
TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3
|
||||
TLS_PSK_WITH_AES_128_CCM = 0xC0A4
|
||||
TLS_PSK_WITH_AES_256_CCM = 0xC0A5
|
||||
TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6
|
||||
TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7
|
||||
TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8
|
||||
TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9
|
||||
TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA
|
||||
TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xC0AC
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CCM = 0xC0AD
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xC0AF
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13
|
||||
|
||||
|
||||
def select_preferred_ciphersuite(client_supported, server_supported):
|
||||
for i in server_supported:
|
||||
assert isinstance(i, CipherSuites)
|
||||
if i in client_supported:
|
||||
return i
|
||||
|
||||
raise UnsupportedCipherException(
|
||||
"Client supported ciphersuites are not supported on the server."
|
||||
)
|
|
@ -1,2 +0,0 @@
|
|||
class UnsupportedCipherException(Exception):
|
||||
pass
|
|
@ -1,178 +0,0 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from characteristic import attributes
|
||||
|
||||
from construct import Container
|
||||
|
||||
from six import BytesIO
|
||||
|
||||
from . import _constructs
|
||||
|
||||
|
||||
@attributes(['major', 'minor'])
|
||||
class ProtocolVersion(object):
|
||||
"""
|
||||
An object representing a ProtocolVersion struct.
|
||||
"""
|
||||
|
||||
|
||||
@attributes(['gmt_unix_time', 'random_bytes'])
|
||||
class Random(object):
|
||||
"""
|
||||
An object representing a Random struct.
|
||||
"""
|
||||
|
||||
|
||||
@attributes(['type', 'data'])
|
||||
class Extension(object):
|
||||
"""
|
||||
An object representing an Extension struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.Extension.build(Container(
|
||||
type=self.type.value, length=len(self.data), data=self.data))
|
||||
|
||||
|
||||
@attributes(['client_version', 'random', 'session_id', 'cipher_suites',
|
||||
'compression_methods', 'extensions'])
|
||||
class ClientHello(object):
|
||||
"""
|
||||
An object representing a ClientHello message.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.ClientHello.build(
|
||||
Container(
|
||||
version=Container(major=self.client_version.major,
|
||||
minor=self.client_version.minor),
|
||||
random=Container(
|
||||
gmt_unix_time=self.random.gmt_unix_time,
|
||||
random_bytes=self.random.random_bytes
|
||||
),
|
||||
session_id=Container(length=len(self.session_id),
|
||||
session_id=self.session_id),
|
||||
cipher_suites=Container(length=len(self.cipher_suites) * 2,
|
||||
cipher_suites=self.cipher_suites),
|
||||
compression_methods=Container(
|
||||
length=len(self.compression_methods),
|
||||
compression_methods=self.compression_methods
|
||||
),
|
||||
extensions_length=sum([2 + 2 + len(ext.data)
|
||||
for ext in self.extensions]),
|
||||
extensions_bytes=b''.join(
|
||||
[ext.as_bytes() for ext in self.extensions]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``ClientHello`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: ClientHello object.
|
||||
"""
|
||||
construct = _constructs.ClientHello.parse(bytes)
|
||||
# XXX Is there a better way in Construct to parse an array of
|
||||
# variable-length structs?
|
||||
extensions = []
|
||||
extensions_io = BytesIO(construct.extensions_bytes)
|
||||
while extensions_io.tell() < construct.extensions_length:
|
||||
extension_construct = _constructs.Extension.parse_stream(
|
||||
extensions_io)
|
||||
extensions.append(
|
||||
Extension(type=ExtensionType(extension_construct.type),
|
||||
data=extension_construct.data))
|
||||
return ClientHello(
|
||||
client_version=ProtocolVersion(
|
||||
major=construct.version.major,
|
||||
minor=construct.version.minor,
|
||||
),
|
||||
random=Random(
|
||||
gmt_unix_time=construct.random.gmt_unix_time,
|
||||
random_bytes=construct.random.random_bytes,
|
||||
),
|
||||
session_id=construct.session_id.session_id,
|
||||
# TODO: cipher suites should be enums
|
||||
cipher_suites=construct.cipher_suites.cipher_suites,
|
||||
compression_methods=(
|
||||
construct.compression_methods.compression_methods
|
||||
),
|
||||
extensions=extensions,
|
||||
)
|
||||
|
||||
|
||||
class ExtensionType(Enum):
|
||||
SIGNATURE_ALGORITHMS = 13
|
||||
# XXX: See http://tools.ietf.org/html/rfc5246#ref-TLSEXT
|
||||
|
||||
|
||||
@attributes(['server_version', 'random', 'session_id', 'cipher_suite',
|
||||
'compression_method', 'extensions'])
|
||||
class ServerHello(object):
|
||||
"""
|
||||
An object representing a ServerHello message.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.ServerHello.build(
|
||||
Container(
|
||||
version=Container(major=self.server_version.major,
|
||||
minor=self.server_version.minor),
|
||||
random=Container(
|
||||
gmt_unix_time=self.random.gmt_unix_time,
|
||||
random_bytes=self.random.random_bytes
|
||||
),
|
||||
session_id=Container(length=len(self.session_id),
|
||||
session_id=self.session_id),
|
||||
cipher_suite=self.cipher_suite,
|
||||
compression_method=self.compression_method.value,
|
||||
extensions_length=sum([2 + 2 + len(ext.data)
|
||||
for ext in self.extensions]),
|
||||
extensions_bytes=b''.join(
|
||||
[ext.as_bytes() for ext in self.extensions]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``ServerHello`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: ServerHello object.
|
||||
"""
|
||||
construct = _constructs.ServerHello.parse(bytes)
|
||||
# XXX: Find a better way to parse extensions
|
||||
extensions = []
|
||||
extensions_io = BytesIO(construct.extensions_bytes)
|
||||
while extensions_io.tell() < construct.extensions_length:
|
||||
extension_construct = _constructs.Extension.parse_stream(
|
||||
extensions_io)
|
||||
extensions.append(
|
||||
Extension(type=ExtensionType(extension_construct.type),
|
||||
data=extension_construct.data))
|
||||
return ServerHello(
|
||||
server_version=ProtocolVersion(
|
||||
major=construct.version.major,
|
||||
minor=construct.version.minor,
|
||||
),
|
||||
random=Random(
|
||||
gmt_unix_time=construct.random.gmt_unix_time,
|
||||
random_bytes=construct.random.random_bytes,
|
||||
),
|
||||
session_id=construct.session_id.session_id,
|
||||
cipher_suite=construct.cipher_suite,
|
||||
compression_method=CompressionMethod(construct.compression_method),
|
||||
extensions=extensions,
|
||||
)
|
||||
|
||||
|
||||
class CompressionMethod(Enum):
|
||||
NULL = 0
|
|
@ -1,313 +0,0 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from characteristic import attributes
|
||||
|
||||
from construct import Container
|
||||
|
||||
from six import BytesIO
|
||||
|
||||
from . import _constructs
|
||||
|
||||
from .hello_message import (
|
||||
ClientHello, ProtocolVersion, ServerHello
|
||||
)
|
||||
|
||||
|
||||
class ClientCertificateType(Enum):
|
||||
RSA_SIGN = 1
|
||||
DSS_SIGN = 2
|
||||
RSA_FIXED_DH = 3
|
||||
DSS_FIXED_DH = 4
|
||||
RSA_EPHEMERAL_DH_RESERVED = 5
|
||||
DSS_EPHEMERAL_DH_RESERVED = 6
|
||||
FORTEZZA_DMS_RESERVED = 20
|
||||
|
||||
|
||||
class HashAlgorithm(Enum):
|
||||
NONE = 0
|
||||
MD5 = 1
|
||||
SHA1 = 2
|
||||
SHA224 = 3
|
||||
SHA256 = 4
|
||||
SHA384 = 5
|
||||
SHA512 = 6
|
||||
|
||||
|
||||
class SignatureAlgorithm(Enum):
|
||||
ANONYMOUS = 0
|
||||
RSA = 1
|
||||
DSA = 2
|
||||
ECDSA = 3
|
||||
|
||||
|
||||
class HandshakeType(Enum):
|
||||
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 HelloRequest(object):
|
||||
"""
|
||||
An object representing a HelloRequest struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return b''
|
||||
|
||||
|
||||
class ServerHelloDone(object):
|
||||
"""
|
||||
An object representing a ServerHelloDone struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return b''
|
||||
|
||||
|
||||
@attributes(['certificate_types', 'supported_signature_algorithms',
|
||||
'certificate_authorities'])
|
||||
class CertificateRequest(object):
|
||||
"""
|
||||
An object representing a CertificateRequest struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.CertificateRequest.build(Container(
|
||||
certificate_types=Container(
|
||||
length=len(self.certificate_types),
|
||||
certificate_types=[cert_type.value
|
||||
for cert_type in self.certificate_types]
|
||||
),
|
||||
supported_signature_algorithms=Container(
|
||||
supported_signature_algorithms_length=2 * len(
|
||||
self.supported_signature_algorithms
|
||||
),
|
||||
algorithms=[Container(
|
||||
hash=algorithm.hash.value,
|
||||
signature=algorithm.signature.value,
|
||||
)
|
||||
for algorithm in self.supported_signature_algorithms
|
||||
]
|
||||
),
|
||||
certificate_authorities=Container(
|
||||
length=len(self.certificate_authorities),
|
||||
certificate_authorities=self.certificate_authorities
|
||||
)
|
||||
))
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``CertificateRequest`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: CertificateRequest object.
|
||||
"""
|
||||
construct = _constructs.CertificateRequest.parse(bytes)
|
||||
return cls(
|
||||
certificate_types=[
|
||||
ClientCertificateType(cert_type)
|
||||
for cert_type in construct.certificate_types.certificate_types
|
||||
],
|
||||
supported_signature_algorithms=[
|
||||
SignatureAndHashAlgorithm(
|
||||
hash=HashAlgorithm(algorithm.hash),
|
||||
signature=SignatureAlgorithm(algorithm.signature),
|
||||
)
|
||||
for algorithm in (
|
||||
construct.supported_signature_algorithms.algorithms
|
||||
)
|
||||
],
|
||||
certificate_authorities=(
|
||||
construct.certificate_authorities.certificate_authorities
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@attributes(['hash', 'signature'])
|
||||
class SignatureAndHashAlgorithm(object):
|
||||
"""
|
||||
An object representing a SignatureAndHashAlgorithm struct.
|
||||
"""
|
||||
|
||||
|
||||
@attributes(['dh_p', 'dh_g', 'dh_Ys'])
|
||||
class ServerDHParams(object):
|
||||
"""
|
||||
An object representing a ServerDHParams struct.
|
||||
"""
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``ServerDHParams`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: ServerDHParams object.
|
||||
"""
|
||||
construct = _constructs.ServerDHParams.parse(bytes)
|
||||
return cls(
|
||||
dh_p=construct.dh_p,
|
||||
dh_g=construct.dh_g,
|
||||
dh_Ys=construct.dh_Ys
|
||||
)
|
||||
|
||||
|
||||
@attributes(['client_version', 'random'])
|
||||
class PreMasterSecret(object):
|
||||
"""
|
||||
An object representing a PreMasterSecret struct.
|
||||
"""
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``PreMasterSecret`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: CertificateRequest object.
|
||||
"""
|
||||
construct = _constructs.PreMasterSecret.parse(bytes)
|
||||
return cls(
|
||||
client_version=ProtocolVersion(
|
||||
major=construct.version.major,
|
||||
minor=construct.version.minor,
|
||||
),
|
||||
random=construct.random_bytes,
|
||||
)
|
||||
|
||||
|
||||
@attributes(['asn1_cert'])
|
||||
class ASN1Cert(object):
|
||||
"""
|
||||
An object representing ASN.1 Certificate
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.ASN1Cert.build(Container(
|
||||
length=len(self.asn1_cert),
|
||||
asn1_cert=self.asn1_cert
|
||||
))
|
||||
|
||||
|
||||
@attributes(['certificate_list'])
|
||||
class Certificate(object):
|
||||
"""
|
||||
An object representing a Certificate struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.Certificate.build(Container(
|
||||
certificates_length=sum([4 + len(asn1cert.asn1_cert)
|
||||
for asn1cert in self.certificate_list]),
|
||||
certificates_bytes=b''.join(
|
||||
[asn1cert.as_bytes() for asn1cert in self.certificate_list]
|
||||
)
|
||||
|
||||
))
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``Certificate`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: Certificate object.
|
||||
"""
|
||||
construct = _constructs.Certificate.parse(bytes)
|
||||
# XXX: Find a better way to parse an array of variable-length objects
|
||||
certificates = []
|
||||
certificates_io = BytesIO(construct.certificates_bytes)
|
||||
|
||||
while certificates_io.tell() < construct.certificates_length:
|
||||
certificate_construct = _constructs.ASN1Cert.parse_stream(
|
||||
certificates_io
|
||||
)
|
||||
certificates.append(
|
||||
ASN1Cert(asn1_cert=certificate_construct.asn1_cert)
|
||||
)
|
||||
return cls(
|
||||
certificate_list=certificates
|
||||
)
|
||||
|
||||
|
||||
@attributes(['verify_data'])
|
||||
class Finished(object):
|
||||
def as_bytes(self):
|
||||
return self.verify_data
|
||||
|
||||
|
||||
@attributes(['msg_type', 'length', 'body'])
|
||||
class Handshake(object):
|
||||
"""
|
||||
An object representing a Handshake struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
if self.msg_type in [
|
||||
HandshakeType.SERVER_HELLO, HandshakeType.CLIENT_HELLO,
|
||||
HandshakeType.CERTIFICATE, HandshakeType.CERTIFICATE_REQUEST,
|
||||
HandshakeType.HELLO_REQUEST, HandshakeType.SERVER_HELLO_DONE,
|
||||
HandshakeType.FINISHED
|
||||
]:
|
||||
_body_as_bytes = self.body.as_bytes()
|
||||
else:
|
||||
_body_as_bytes = b''
|
||||
return _constructs.Handshake.build(
|
||||
Container(
|
||||
msg_type=self.msg_type.value,
|
||||
length=self.length,
|
||||
body=_body_as_bytes
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``Handshake`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: Handshake object.
|
||||
"""
|
||||
construct = _constructs.Handshake.parse(bytes)
|
||||
return cls(
|
||||
msg_type=HandshakeType(construct.msg_type),
|
||||
length=construct.length,
|
||||
body=cls._get_handshake_message(
|
||||
HandshakeType(construct.msg_type), construct.body
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _get_handshake_message(msg_type, body):
|
||||
_handshake_message_parser = {
|
||||
HandshakeType.CLIENT_HELLO: ClientHello.from_bytes,
|
||||
HandshakeType.SERVER_HELLO: ServerHello.from_bytes,
|
||||
HandshakeType.CERTIFICATE: Certificate.from_bytes,
|
||||
# 12: parse_server_key_exchange,
|
||||
HandshakeType.CERTIFICATE_REQUEST: CertificateRequest.from_bytes,
|
||||
# 15: parse_certificate_verify,
|
||||
# 16: parse_client_key_exchange,
|
||||
}
|
||||
|
||||
try:
|
||||
if msg_type == HandshakeType.HELLO_REQUEST:
|
||||
return HelloRequest()
|
||||
elif msg_type == HandshakeType.SERVER_HELLO_DONE:
|
||||
return ServerHelloDone()
|
||||
elif msg_type == HandshakeType.FINISHED:
|
||||
return Finished(verify_data=body)
|
||||
elif msg_type in [HandshakeType.SERVER_KEY_EXCHANGE,
|
||||
HandshakeType.CERTIFICATE_VERIFY,
|
||||
HandshakeType.CLIENT_KEY_EXCHANGE,
|
||||
]:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
return _handshake_message_parser[msg_type](body)
|
||||
except NotImplementedError:
|
||||
return None # TODO
|
|
@ -1,110 +0,0 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from characteristic import attributes
|
||||
|
||||
from construct import Container
|
||||
|
||||
from . import _constructs
|
||||
|
||||
|
||||
@attributes(['major', 'minor'])
|
||||
class ProtocolVersion(object):
|
||||
"""
|
||||
An object representing a ProtocolVersion struct.
|
||||
"""
|
||||
|
||||
|
||||
@attributes(['type', 'version', 'fragment'])
|
||||
class TLSPlaintext(object):
|
||||
"""
|
||||
An object representing a TLSPlaintext struct.
|
||||
"""
|
||||
def as_bytes(self):
|
||||
return _constructs.TLSPlaintext.build(
|
||||
Container(
|
||||
type=self.type.value,
|
||||
version=Container(major=self.version.major,
|
||||
minor=self.version.minor),
|
||||
length=len(self.fragment),
|
||||
fragment=self.fragment
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``TLSPlaintext`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: TLSPlaintext object.
|
||||
"""
|
||||
construct = _constructs.TLSPlaintext.parse(bytes)
|
||||
return cls(
|
||||
type=ContentType(construct.type),
|
||||
version=ProtocolVersion(
|
||||
major=construct.version.major,
|
||||
minor=construct.version.minor
|
||||
),
|
||||
fragment=construct.fragment
|
||||
)
|
||||
|
||||
|
||||
@attributes(['type', 'version', 'fragment'])
|
||||
class TLSCompressed(object):
|
||||
"""
|
||||
An object representing a TLSCompressed struct.
|
||||
"""
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``TLSCompressed`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: TLSCompressed object.
|
||||
"""
|
||||
construct = _constructs.TLSCompressed.parse(bytes)
|
||||
return cls(
|
||||
type=ContentType(construct.type),
|
||||
version=ProtocolVersion(
|
||||
major=construct.version.major,
|
||||
minor=construct.version.minor
|
||||
),
|
||||
fragment=construct.fragment
|
||||
)
|
||||
|
||||
|
||||
@attributes(['type', 'version', 'fragment'])
|
||||
class TLSCiphertext(object):
|
||||
"""
|
||||
An object representing a TLSCiphertext struct.
|
||||
"""
|
||||
@classmethod
|
||||
def from_bytes(cls, bytes):
|
||||
"""
|
||||
Parse a ``TLSCiphertext`` struct.
|
||||
|
||||
:param bytes: the bytes representing the input.
|
||||
:return: TLSCiphertext object.
|
||||
"""
|
||||
construct = _constructs.TLSCiphertext.parse(bytes)
|
||||
return cls(
|
||||
type=ContentType(construct.type),
|
||||
version=ProtocolVersion(
|
||||
major=construct.version.major,
|
||||
minor=construct.version.minor
|
||||
),
|
||||
fragment=construct.fragment
|
||||
)
|
||||
|
||||
|
||||
class ContentType(Enum):
|
||||
CHANGE_CIPHER_SPEC = 20
|
||||
ALERT = 21
|
||||
HANDSHAKE = 22
|
||||
APPLICATION_DATA = 23
|
|
@ -24,29 +24,3 @@ class _UBInt24(construct.Adapter):
|
|||
|
||||
def UBInt24(name): # noqa
|
||||
return _UBInt24(construct.Bytes(name, 3))
|
||||
|
||||
|
||||
def LengthPrefixedArray(subcon, length_field=construct.UBInt8("length")):
|
||||
"""
|
||||
An array prefixed by a byte length field.
|
||||
|
||||
In contrast to construct.macros.PrefixedArray,
|
||||
the length field signifies the number of bytes, not the number of elements.
|
||||
"""
|
||||
subcon_with_pos = construct.Struct(
|
||||
subcon.name,
|
||||
construct.Embed(subcon),
|
||||
construct.Anchor("__current_pos")
|
||||
)
|
||||
|
||||
return construct.Embed(
|
||||
construct.Struct(
|
||||
"",
|
||||
length_field,
|
||||
construct.Anchor("__start_pos"),
|
||||
construct.RepeatUntil(
|
||||
lambda obj, ctx: obj.__current_pos == ctx.__start_pos + getattr(ctx, length_field.name),
|
||||
subcon_with_pos
|
||||
),
|
||||
)
|
||||
)
|
|
@ -61,7 +61,12 @@ class TlsLayer(Layer):
|
|||
layer()
|
||||
|
||||
def _get_client_hello(self):
|
||||
# Read all records that contain the initial Client Hello message.
|
||||
"""
|
||||
Peek into the socket and read all records that contain the initial client hello message.
|
||||
|
||||
Returns:
|
||||
The raw handshake packet bytes, without TLS record header(s).
|
||||
"""
|
||||
client_hello = ""
|
||||
client_hello_size = 1
|
||||
offset = 0
|
||||
|
@ -75,10 +80,15 @@ class TlsLayer(Layer):
|
|||
return client_hello
|
||||
|
||||
def _parse_client_hello(self):
|
||||
"""
|
||||
Peek into the connection, read the initial client hello and parse it to obtain ALPN values.
|
||||
"""
|
||||
raw_client_hello = self._get_client_hello()[4:] # exclude handshake header.
|
||||
try:
|
||||
client_hello = ClientHello.parse(self._get_client_hello()[4:])
|
||||
client_hello = ClientHello.parse(raw_client_hello)
|
||||
except ConstructError as e:
|
||||
self.log("Cannot parse Client Hello: %s" % repr(e), "error")
|
||||
self.log("Raw Client Hello:\r\n:%s" % raw_client_hello.encode("hex"), "debug")
|
||||
return
|
||||
|
||||
for extension in client_hello.extensions:
|
||||
|
|
Loading…
Reference in New Issue