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)
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)
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))
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 CipherSuites = List(size_t=Uint16, elem_t=CipherSuite)
from type import Uint8, Uint16, List, Enum import structmeta as meta from protocol_types import HandshakeType class ProtocolVersion(Enum): elem_t = Uint16 SSL3 = Uint16(0x0300) TLS10 = Uint16(0x0301) TLS11 = Uint16(0x0302) TLS12 = Uint16(0x0303) TLS13 = Uint16(0x0304) ProtocolVersions = List(size_t=Uint8, elem_t=ProtocolVersion) @meta.struct class SupportedVersions(meta.StructMeta): versions: meta.Select('Handshake.msg_type', cases={ HandshakeType.client_hello: ProtocolVersions, HandshakeType.server_hello: ProtocolVersion, }) # ------------------------------------------------------------------------------ if __name__ == '__main__': from protocol_handshake import Handshake import unittest
# 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) # Reserved Code Points #ffdhe_private_use = Uint16(0x01FC)..Uint16(0x01FF) #ecdhe_private_use = Uint16(0xFE00)..Uint16(0xFEFF) #obsolete_RESERVED = Uint16(0xFF01)..Uint16(0xFF02) NamedGroups = List(size_t=Uint16, elem_t=NamedGroup) @meta.struct class NamedGroupList(meta.StructMeta): named_group_list: NamedGroups if __name__ == '__main__': import unittest class TestUnit(unittest.TestCase): def test_namedgrouplist(self): ngl = NamedGroupList(named_group_list=NamedGroups([
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) # Reserved Code Points #private_use = Uint16(0xFE00)..Uint16(0xFFFF) SignatureSchemes = List(size_t=Uint16, elem_t=SignatureScheme) @meta.struct class SignatureSchemeList(meta.StructMeta): supported_signature_algorithms: SignatureSchemes
from protocol_ext_signature import SignatureScheme # --- Certificate -------------------------------------------------------------- class CertificateType(Enum): elem_t = Uint8 X509 = Uint8(0) RawPublicKey = Uint8(2) @meta.struct class CertificateEntry(meta.StructMeta): cert_data: OpaqueUint24 extensions: Extensions CertificateEntrys = List(size_t=Uint24, elem_t=CertificateEntry) @meta.struct class Certificate(meta.StructMeta): certificate_request_context: OpaqueUint8 certificate_list: CertificateEntrys @meta.struct class CertificateVerify(meta.StructMeta): algorithm: SignatureScheme signature: OpaqueUint16 # --- Finished ----------------------------------------------------------------- class Hash: length = None
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, }) Extensions = List(size_t=Uint16, elem_t=Extension) # ------------------------------------------------------------------------------ # Server Parameters @meta.struct class EncryptedExtensions(meta.StructMeta): extensions: Extensions # ------------------------------------------------------------------------------ if __name__ == '__main__': from protocol_ext_supportedgroups import NamedGroups, NamedGroup
from type import Uint16, OpaqueUint16, List import structmeta as meta from protocol_types import HandshakeType from protocol_ext_supportedgroups import NamedGroup @meta.struct class KeyShareEntry(meta.StructMeta): group: NamedGroup key_exchange: OpaqueUint16 KeyShareEntrys = List(size_t=Uint16, elem_t=KeyShareEntry) @meta.struct class KeyShareHello(meta.StructMeta): shares: meta.Select('Handshake.msg_type', cases={ HandshakeType.client_hello: KeyShareEntrys, HandshakeType.server_hello: KeyShareEntry, }) # ------------------------------------------------------------------------------ if __name__ == '__main__': import unittest class TestUnit(unittest.TestCase): def test_keyshare_clienthello(self):