Example #1
0
class ProtocolVersion(Enum):
    elem_t = Uint16

    SSL3  = Uint16(0x0300)
    TLS10 = Uint16(0x0301)
    TLS11 = Uint16(0x0302)
    TLS12 = Uint16(0x0303)
    TLS13 = Uint16(0x0304)
Example #2
0
class TLSCiphertext(meta.StructMeta):
    opaque_type: ContentType = ContentType.application_data
    legacy_record_version: ProtocolVersion = ProtocolVersion(0x0303)
    length: Uint16 = lambda self: Uint16(len(bytes(self.encrypted_record)))
    encrypted_record: OpaqueLength

    def decrypt(self, cipher_instance):
        encrypted_record = self.encrypted_record.get_raw_bytes()
        aad = bytes.fromhex('170303') + bytes(Uint16(len(encrypted_record)))
        plaindata = cipher_instance.decrypt_and_verify(encrypted_record, aad)
        plaindata, content_type = TLSInnerPlaintext.split_pad(plaindata)
        # print(hexdump(bytes(plaindata)))
        if content_type == ContentType.application_data:
            return self._decrypt_app_data(plaindata, content_type)

        return TLSPlaintext(type=content_type,
                            fragment=OpaqueLength(bytes(plaindata)))

    # Application Data を受信したとき
    def _decrypt_app_data(self, plaindata, content_type):
        # NewSessionTicketを受け取った場合
        if plaindata[:2] == bytes(HandshakeType.new_session_ticket) + b'\x00':
            return TLSPlaintext(type=content_type,
                                fragment=OpaqueLength(bytes(plaindata)))
        # それ以外は通信データ
        else:
            return TLSPlaintext(type=content_type,
                                length=len(plaindata),
                                fragment=OpaqueLength(bytes(plaindata)))
Example #3
0
        def test_structmeta_keep_rest_bytes(self):
            import io

            OpaqueUint8 = Opaque(size_t=Uint8)
            ListUint8OpaqueUint8 = List(size_t=Uint8,
                                        elem_t=Opaque(size_t=Uint8))

            @struct
            class Sample1(StructMeta):
                fieldA: Uint16
                fieldB: OpaqueUint8
                fieldC: ListUint8OpaqueUint8

            s = Sample1(fieldA=Uint16(0x1),
                        fieldB=OpaqueUint8(b'\xff'),
                        fieldC=ListUint8OpaqueUint8(
                            [OpaqueUint8(b'\xaa'),
                             OpaqueUint8(b'\xbb')]))

            deadbeef = bytes.fromhex('deadbeef')
            fs = io.BytesIO(bytes(s) + deadbeef)

            s2 = Sample1.from_fs(fs)

            rest = fs.read()
            self.assertEqual(rest, deadbeef)
Example #4
0
        def test_structmeta(self):

            OpaqueUint8 = Opaque(size_t=Uint8)
            ListUint8OpaqueUint8 = List(size_t=Uint8,
                                        elem_t=Opaque(size_t=Uint8))

            @struct
            class Sample1(StructMeta):
                fieldA: Uint16
                fieldB: OpaqueUint8
                fieldC: ListUint8OpaqueUint8

            s = Sample1(fieldA=Uint16(0x1),
                        fieldB=OpaqueUint8(b'\xff'),
                        fieldC=ListUint8OpaqueUint8(
                            [OpaqueUint8(b'\xaa'),
                             OpaqueUint8(b'\xbb')]))

            self.assertTrue(hasattr(s, 'fieldA'))
            self.assertTrue(isinstance(s.fieldA, Uint16))
            self.assertTrue(hasattr(s, 'fieldB'))
            self.assertTrue(isinstance(s.fieldB, OpaqueUint8))
            self.assertTrue(hasattr(s, 'fieldC'))
            self.assertTrue(isinstance(s.fieldC, ListUint8OpaqueUint8))

            self.assertEqual(bytes(s), b'\x00\x01\x01\xff\x04\x01\xaa\x01\xbb')
            self.assertEqual(Sample1.from_bytes(bytes(s)), s)
Example #5
0
        def test_structmeta_multiple_parents(self):
            @struct
            class Sample1(StructMeta):
                child_field: Select('Sample3.parent_fieldA',
                                    cases={
                                        Uint8(0xaa): Uint8,
                                        Uint8(0xbb): Uint16,
                                    })

            @struct
            class Sample2(StructMeta):
                parent_fieldB: Uint8
                fragment: Sample1

            @struct
            class Sample3(StructMeta):
                parent_fieldA: Uint8
                fragment: Sample2

            s = Sample3(parent_fieldA=Uint8(0xbb),
                        fragment=Sample2(
                            parent_fieldB=Uint8(0x12),
                            fragment=Sample1(child_field=Uint16(0x0101))))
            s_byte = bytes.fromhex('bb 12 0101')

            self.assertEqual(bytes(s), s_byte)
            self.assertEqual(Sample3.from_bytes(bytes(s)), s)
Example #6
0
        def test_structmeta_parent(self):
            @struct
            class Sample1(StructMeta):
                child_field: Select('Sample2.parent_field',
                                    cases={
                                        Uint8(0xaa): Uint8,
                                        Uint8(0xbb): Uint16,
                                    })

            @struct
            class Sample2(StructMeta):
                parent_field: Uint8
                fragment: Sample1

            s1 = Sample2(parent_field=Uint8(0xaa),
                         fragment=Sample1(child_field=Uint8(0xff)))
            s1_byte = bytes.fromhex('aa ff')
            s2 = Sample2(parent_field=Uint8(0xbb),
                         fragment=Sample1(child_field=Uint16(0xffff)))
            s2_byte = bytes.fromhex('bb ffff')

            self.assertEqual(bytes(s1), s1_byte)
            self.assertEqual(bytes(s2), s2_byte)
            self.assertEqual(Sample2.from_bytes(bytes(s1)), s1)
            self.assertEqual(Sample2.from_bytes(bytes(s2)), s2)
Example #7
0
 def encrypt(self, cipher_instance):
     msg_pad = TLSInnerPlaintext.append_pad(self)
     tag_size = cipher_instance.__class__.tag_size
     aad = bytes.fromhex('170303') + bytes(
         Uint16(len(bytes(msg_pad)) + tag_size))
     encrypted_record = cipher_instance.encrypt_and_tag(msg_pad, aad)
     return TLSCiphertext(
         encrypted_record=OpaqueLength(bytes(encrypted_record)))
class NamedGroup(Enum):
    elem_t = Uint16

    # Elliptic Curve Groups (ECDHE)
    #obsolete_RESERVED = Uint16(0x0001)..Uint16(0x0016)
    secp256r1 = Uint16(0x0017)
    secp384r1 = Uint16(0x0018)
    secp521r1 = Uint16(0x0019)
    #obsolete_RESERVED = Uint16(0x001A)..Uint16(0x001C)
    x25519 = Uint16(0x001D)
    x448 = Uint16(0x001E)

    # Finite Field Groups (DHE)
    # https://tools.ietf.org/html/rfc7919#appendix-A
    ffdhe2048 = Uint16(0x0100)
    ffdhe3072 = Uint16(0x0101)
    ffdhe4096 = Uint16(0x0102)
    ffdhe6144 = Uint16(0x0103)
    ffdhe8192 = Uint16(0x0104)
Example #9
0
        def test_structmeta_recursive(self):
            @struct
            class Sample1(StructMeta):
                fieldC: Uint16
                fieldD: Uint16

            @struct
            class Sample2(StructMeta):
                fieldA: Uint16
                fieldB: Sample1

            s = Sample2(fieldA=Uint16(0xaaaa),
                        fieldB=Sample1(fieldC=Uint16(0xbbbb),
                                       fieldD=Uint16(0xcccc)))

            self.assertTrue(isinstance(s.fieldB, Sample1))
            self.assertTrue(isinstance(s.fieldB.fieldC, Uint16))

            self.assertEqual(bytes(s), b'\xaa\xaa\xbb\xbb\xcc\xcc')
            self.assertEqual(Sample2.from_bytes(bytes(s)), s)
Example #10
0
    def decrypt(self, cipher_instance):
        encrypted_record = self.encrypted_record.get_raw_bytes()
        aad = bytes.fromhex('170303') + bytes(Uint16(len(encrypted_record)))
        plaindata = cipher_instance.decrypt_and_verify(encrypted_record, aad)
        plaindata, content_type = TLSInnerPlaintext.split_pad(plaindata)
        # print(hexdump(bytes(plaindata)))
        if content_type == ContentType.application_data:
            return self._decrypt_app_data(plaindata, content_type)

        return TLSPlaintext(type=content_type,
                            fragment=OpaqueLength(bytes(plaindata)))
Example #11
0
class CipherSuite(Enum):
    elem_t = Uint16

    TLS_AES_128_GCM_SHA256 = Uint16(0x1301)
    TLS_AES_256_GCM_SHA384 = Uint16(0x1302)
    TLS_CHACHA20_POLY1305_SHA256 = Uint16(0x1303)
    TLS_AES_128_CCM_SHA256 = Uint16(0x1304)
    TLS_AES_128_CCM_8_SHA256 = Uint16(0x1305)
    TLS_EMPTY_RENEGOTIATION_INFO_SCSV = Uint16(0x00FF)

    @classmethod
    def get_cipher_class(cls, cipher_suite):
        ciphercuite2class = {
            CipherSuite.TLS_AES_128_GCM_SHA256: None,
            CipherSuite.TLS_AES_256_GCM_SHA384: None,
            CipherSuite.TLS_CHACHA20_POLY1305_SHA256: Chacha20Poly1305,
            CipherSuite.TLS_AES_128_CCM_SHA256: None,
            CipherSuite.TLS_AES_128_CCM_8_SHA256: None,
        }
        return ciphercuite2class.get(cipher_suite)

    @classmethod
    def get_hash_name(cls, cipher_suite):
        if cipher_suite == CipherSuite.TLS_AES_256_GCM_SHA384:
            return 'sha384'
        else:
            return 'sha256'

    @classmethod
    def get_hash_size(cls, cipher_suite):
        if cipher_suite == CipherSuite.TLS_AES_256_GCM_SHA384:
            return 48
        else:
            return 32
Example #12
0
class Extension(meta.StructMeta):
    extension_type: ExtensionType
    length: Uint16 = lambda self: Uint16(len(bytes(self.extension_data)))
    extension_data: meta.Select('extension_type',
                                cases={
                                    ExtensionType.supported_versions:
                                    SupportedVersions,
                                    ExtensionType.supported_groups:
                                    NamedGroupList,
                                    ExtensionType.key_share: KeyShareHello,
                                    ExtensionType.signature_algorithms:
                                    SignatureSchemeList,
                                    meta.Otherwise: OpaqueLength,
                                })
Example #13
0
        def test_structmeta_has_parent_ref(self):
            @struct
            class Sample1(StructMeta):
                child_field: Select('Sample3.parent_fieldA',
                                    cases={
                                        Uint8(0xaa): Uint8,
                                        Uint8(0xbb): Uint16,
                                    })

            @struct
            class Sample2(StructMeta):
                parent_fieldB: Uint8
                fragment: Sample1

            Sample2s = List(size_t=Uint8, elem_t=Sample2)

            @struct
            class Sample3(StructMeta):
                parent_fieldA: Uint8
                fragment: Sample2s

            s = Sample3(parent_fieldA=Uint8(0xbb),
                        fragment=Sample2s([
                            Sample2(
                                parent_fieldB=Uint8(0x12),
                                fragment=Sample1(child_field=Uint16(0x0101)))
                        ]))

            # コンストラクタで構造体を構築した場合
            target = s.fragment.get_array()[0].fragment  # 最下の子インスタンス
            self.assertTrue(isinstance(target, Sample1))
            self.assertTrue(isinstance(target.parent, Sample2))
            self.assertTrue(isinstance(target.parent.parent, Sample3))

            # バイト列から構造体を構築した場合
            s2 = Sample3.from_bytes(bytes(s))
            target = s.fragment.get_array()[0].fragment  # 最下の子インスタンス
            self.assertTrue(isinstance(target, Sample1))
            self.assertTrue(isinstance(target.parent, Sample2))
            self.assertTrue(isinstance(target.parent.parent, Sample3))
Example #14
0
        def test_structmeta_select(self):
            @struct
            class Sample1(StructMeta):
                field: Uint16

            @struct
            class Sample2(StructMeta):
                type: Uint8
                fragment: Select('type',
                                 cases={
                                     Uint8(0xaa): Opaque(0),
                                     Uint8(0xbb): Sample1,
                                 })

            s1 = Sample2(type=Uint8(0xaa), fragment=Opaque(0)(b''))
            self.assertEqual(bytes(s1), bytes.fromhex('aa'))
            self.assertEqual(Sample2.from_bytes(bytes(s1)), s1)

            s2 = Sample2(type=Uint8(0xbb),
                         fragment=Sample1(field=Uint16(0x1212)))
            self.assertEqual(bytes(s2), bytes.fromhex('bb 1212'))
            self.assertEqual(Sample2.from_bytes(bytes(s2)), s2)
Example #15
0
class TLSPlaintext(meta.StructMeta):
    type: ContentType
    legacy_record_version: ProtocolVersion = ProtocolVersion(0x0303)
    length: Uint16 = lambda self: Uint16(len(bytes(self.fragment)))
    fragment: OpaqueLength

    @classmethod
    def create(self, content_type, *messages):
        assert isinstance(content_type, ContentType)
        messages_byte = b''.join(bytes(msg) for msg in messages)
        return TLSPlaintext(type=content_type,
                            fragment=OpaqueLength(messages_byte))

    def encrypt(self, cipher_instance):
        msg_pad = TLSInnerPlaintext.append_pad(self)
        tag_size = cipher_instance.__class__.tag_size
        aad = bytes.fromhex('170303') + bytes(
            Uint16(len(bytes(msg_pad)) + tag_size))
        encrypted_record = cipher_instance.encrypt_and_tag(msg_pad, aad)
        return TLSCiphertext(
            encrypted_record=OpaqueLength(bytes(encrypted_record)))

    def get_messages(self):
        contenttype2class = {
            ContentType.handshake: Handshake,
            ContentType.change_cipher_spec: OpaqueLength,
            ContentType.alert: Alert,
        }
        elem_t = contenttype2class.get(self.type)

        # 複数のHandshakeメッセージは結合して一つのTLSPlaintextで送ることができる
        # https://tools.ietf.org/html/rfc8446#section-5.1
        messages = []
        stream_len = len(self.fragment.get_raw_bytes())
        stream = io.BytesIO(self.fragment.get_raw_bytes())
        while stream.tell() < stream_len:
            messages.append(elem_t.from_fs(stream))
        return messages
Example #16
0
def HKDF_expand_label(secret, label, hash_value, length,
                      hash_name='sha256') -> bytearray:
    # HKDF-Expand-Label (https://tools.ietf.org/html/rfc8446#section-7.1)
    #
    #     HKDF-Expand-Label(Secret, Label, Context, Length) =
    #         HKDF-Expand(Secret, HkdfLabel, Length)
    #
    #     Where HkdfLabel is specified as:
    #
    #     struct {
    #         uint16 length = Length;
    #         opaque label<7..255> = "tls13 " + Label;
    #         opaque context<0..255> = Context;
    #     } HkdfLabel;
    #
    hkdf_label = b''
    hkdf_label += bytes(Uint16(length))
    hkdf_label += bytes(OpaqueUint8(b'tls13 ' + label))
    hkdf_label += bytes(OpaqueUint8(hash_value))
    # print('- [-] hkdf_label:', hkdf_label.hex())

    out = HKDF_expand(secret, hkdf_label, length, hash_name)
    # print('- [-] out:', out.hex())
    return out
Example #17
0
class SignatureScheme(Enum):
    elem_t = Uint16

    # RSASSA-PKCS1-v1_5 algorithms
    rsa_pkcs1_sha256 = Uint16(0x0401)
    rsa_pkcs1_sha384 = Uint16(0x0501)
    rsa_pkcs1_sha512 = Uint16(0x0601)

    # ECDSA algorithms
    ecdsa_secp256r1_sha256 = Uint16(0x0403)
    ecdsa_secp384r1_sha384 = Uint16(0x0503)
    ecdsa_secp512r1_sha512 = Uint16(0x0603)

    # RSASSA-PSS algorithms with public key OID rsaEncryption
    rsa_pss_rsae_sha256 = Uint16(0x0804)
    rsa_pss_rsae_sha384 = Uint16(0x0805)
    rsa_pss_rsae_sha512 = Uint16(0x0806)

    # EdDSA algorithms
    ed25519 = Uint16(0x0807)
    ed448 = Uint16(0x0808)

    # RSASSA-PSS algorithms with public key OID RSASSA-PSS
    rsa_pss_pss_sha256 = Uint16(0x0809)
    rsa_pss_pss_sha384 = Uint16(0x080a)
    rsa_pss_pss_sha512 = Uint16(0x080b)

    # Legacy algorithms
    rsa_pkcs1_sha1 = Uint16(0x0201)
    ecdsa_sha1 = Uint16(0x0203)
Example #18
0
class ExtensionType(EnumUnknown):
    elem_t = Uint16

    server_name = Uint16(0)
    max_fragment_length = Uint16(1)
    status_request = Uint16(5)
    supported_groups = Uint16(10)
    signature_algorithms = Uint16(13)
    use_srtp = Uint16(14)
    heartbeat = Uint16(15)
    application_layer_protocol_negotiation = Uint16(16)
    signed_certificate_timestamp = Uint16(18)
    client_certificate_type = Uint16(19)
    server_certificate_type = Uint16(20)
    padding = Uint16(21)
    #RESERVED = Uint16(40)
    pre_shared_key = Uint16(41)
    early_data = Uint16(42)
    supported_versions = Uint16(43)
    cookie = Uint16(44)
    psk_key_exchange_modes = Uint16(45)
    #RESERVED = Uint16(46)
    certificate_authorities = Uint16(47)
    oid_filters = Uint16(48)
    post_handshake_auth = Uint16(49)
    signature_algorithms_cert = Uint16(50)
    key_share = Uint16(51)