@@ -15,60 +15,93 @@ class TransformDirection(Enum):
1515 Decrypt = 1
1616
1717class SrtpMasterKeys :
18- MASTER_KEY_SIZE = 30
18+ MASTER_KEY_SIZE = 16
19+ MASTER_SALT_SIZE = 14
1920 DUMMY_KEY = (
2021 b'\x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0A \x0B \x0C \x0D \x0E \x0F '
2122 b'\x10 \x11 \x12 \x13 '
2223 )
2324
24- def __init__ (self , master_key : bytes ):
25+ def __init__ (self , master_key : bytes , master_salt : bytes ):
2526 assert len (master_key ) == SrtpMasterKeys .MASTER_KEY_SIZE
26- self .key1_buf = master_key [:0x10 ]
27- self .key1_len = len (self .key1_buf )
28- self .key1_counter = 0
27+ assert len (master_salt ) == SrtpMasterKeys .MASTER_SALT_SIZE
2928
30- self .key2_buf = master_key [0x10 :]
31- self .key2_len = len (self .key2_buf )
32- self .key2_counter = 0
29+ self ._master_key = master_key
30+ self ._master_key_id = 0
31+
32+ self ._master_salt = master_salt
33+ self ._master_salt_id = 0
3334
3435 @classmethod
35- def from_base64 (cls , master_key_b64 : str ):
36- return cls (base64 .b64decode (master_key_b64 ))
36+ def from_base64 (cls , master_bytes_b64 : str ):
37+ decoded = base64 .b64decode (master_bytes_b64 )
38+ return cls (
39+ decoded [:SrtpMasterKeys .MASTER_KEY_SIZE ],
40+ decoded [SrtpMasterKeys .MASTER_KEY_SIZE :]
41+ )
3742
3843 @classmethod
3944 def null_keys (cls ):
40- return cls (SrtpMasterKeys .MASTER_KEY_SIZE * b'\x00 ' )
45+ return cls (
46+ SrtpMasterKeys .MASTER_KEY_SIZE * b'\x00 ' ,
47+ SrtpMasterKeys .MASTER_SALT_SIZE * b'\x00 ' ,
48+ )
4149
4250 @classmethod
4351 def dummy_keys (cls ):
44- dummy_key = SrtpMasterKeys .DUMMY_KEY [:0x10 ] + SrtpMasterKeys .DUMMY_KEY [:0x0E ]
45- return cls (dummy_key )
52+ return cls (
53+ SrtpMasterKeys .DUMMY_KEY [:SrtpMasterKeys .MASTER_KEY_SIZE ],
54+ SrtpMasterKeys .DUMMY_KEY [:SrtpMasterKeys .MASTER_SALT_SIZE ]
55+ )
56+
57+ @property
58+ def master_key (self ) -> bytes :
59+ return self ._master_key
4660
47- @dataclass
48- class SrtpSessionKey :
49- buf : bytes
50- len : int
51- tag : bytes
61+ @property
62+ def master_key_id (self ) -> int :
63+ return self ._master_key_id
5264
53- def __init__ (self , key : bytes ):
54- self .buf = key
55- self .len = len (key )
56- self .tag = 1
65+ @property
66+ def master_salt (self ) -> bytes :
67+ return self ._master_salt
68+
69+ @property
70+ def master_salt_id (self ) -> int :
71+ return self ._master_salt_id
5772
5873class SrtpSessionKeys :
59- def __init__ (self , session_keys : List [SrtpSessionKey ]):
60- assert len (session_keys ) == 3
61- self .session_key_1 = session_keys [0 ]
62- self .session_key_2 = session_keys [1 ]
63- self .session_key_3 = session_keys [2 ]
74+ SRTP_CRYPT = 0
75+ SRTP_AUTH = 1
76+ SRTP_SALT = 2
77+ # Max count of keys
78+ SRTP_SESSION_KEYS_MAX = 3
79+
80+ def __init__ (self , crypt_key : bytes , auth_key : bytes , salt_key : bytes ):
81+ self ._crypt_key = crypt_key
82+ self ._auth_key = auth_key
83+ self ._salt_key = salt_key
6484
85+ @classmethod
86+ def from_list (cls , session_keys : List [bytes ]):
87+ assert len (session_keys ) == SrtpSessionKeys .SRTP_SESSION_KEYS_MAX
88+ return cls (
89+ session_keys [SrtpSessionKeys .SRTP_CRYPT ],
90+ session_keys [SrtpSessionKeys .SRTP_AUTH ],
91+ session_keys [SrtpSessionKeys .SRTP_SALT ]
92+ )
93+
6594 @property
66- def aes_gcm_key (self ) -> bytes :
67- return self .session_key_1 . buf
95+ def crypt_key (self ) -> bytes :
96+ return self ._crypt_key
6897
6998 @property
70- def nonce_key (self ) -> bytes :
71- return self .session_key_3 .buf
99+ def auth_key (self ) -> bytes :
100+ return self ._auth_key
101+
102+ @property
103+ def salt_key (self ) -> bytes :
104+ return self ._salt_key
72105
73106class SrtpContext :
74107 _backend = default_backend ()
@@ -79,27 +112,27 @@ def __init__(self, master_keys: SrtpMasterKeys):
79112 """
80113 self .master_keys = master_keys
81114 self .session_keys = SrtpContext ._derive_session_keys (
82- self .master_keys .key1_buf , self .master_keys .key2_buf
115+ self .master_keys .master_key , self .master_keys .master_salt
83116 )
84117
85118 # Set-up GCM crypto instances
86- self .decryptor_ctx = SrtpContext ._init_gcm_cryptor (self .session_keys .aes_gcm_key )
87- self .decryptor_ctx = SrtpContext ._init_gcm_cryptor (self .session_keys .aes_gcm_key )
119+ self .decryptor_ctx = SrtpContext ._init_gcm_cryptor (self .session_keys .crypt_key )
120+ self .decryptor_ctx = SrtpContext ._init_gcm_cryptor (self .session_keys .crypt_key )
88121
89122 @classmethod
90- def from_base64 (cls , master_key_b64 : str ):
123+ def from_base64 (cls , master_bytes_b64 : str ):
91124 return cls (
92- SrtpMasterKeys .from_base64 (master_key_b64 )
125+ SrtpMasterKeys .from_base64 (master_bytes_b64 )
93126 )
94127
95128 @classmethod
96- def from_bytes (cls , master_key : bytes ):
129+ def from_bytes (cls , master_key : bytes , master_salt : bytes ):
97130 return cls (
98- SrtpMasterKeys (master_key )
131+ SrtpMasterKeys (master_key , master_salt )
99132 )
100133
101134 @staticmethod
102- def _derive_single_key (input_key : bytes , bitmask : int = 0 ) -> bytes :
135+ def _derive_single_key (input_key : bytes , key_index : int = 0 ) -> bytes :
103136 keysize = len (input_key )
104137 keyout = bytearray (b'\x00 ' * 16 )
105138
@@ -111,10 +144,10 @@ def _derive_single_key(input_key: bytes, bitmask: int = 0) -> bytes:
111144 if keysize != 1 :
112145 keyout [12 ] = input_key [keysize - 2 ]
113146 if keysize >= 3 :
114- key_index = 0
147+ pos = 0
115148 for _ in range (2 , keysize ):
116- keyout [key_index + 11 ] = input_key [key_index + keysize - 3 ]
117- key_index = key_index - 1
149+ keyout [pos + 11 ] = input_key [pos + keysize - 3 ]
150+ pos -= 1
118151
119152 if keysize <= 13 :
120153 null_count = 14 - keysize
@@ -124,10 +157,10 @@ def _derive_single_key(input_key: bytes, bitmask: int = 0) -> bytes:
124157 for index in range (14 , 16 ):
125158 keyout [index ] = 0
126159
127- if bitmask :
160+ if key_index :
128161 len_before_xor = len (keyout )
129162 value_to_xor = struct .unpack_from ('<I' , keyout , 4 )[0 ]
130- value_to_xor ^= bitmask
163+ value_to_xor ^= ( key_index * 0x1000000 )
131164 keyout = keyout [:4 ] + struct .pack ('<I' , value_to_xor ) + keyout [8 :]
132165 assert len (keyout ) == len_before_xor
133166 return keyout
@@ -146,20 +179,16 @@ def _crypt_ctr_oneshot(key: bytes, iv: bytes, plaintext: bytes, max_bytes: Optio
146179 return cipher_out
147180
148181 @staticmethod
149- def _derive_session_keys (key1 : bytes , key2 : bytes ) -> SrtpSessionKeys :
150- session1 = SrtpContext ._derive_single_key (key2 )
151- session2 = SrtpContext ._derive_single_key (key2 , 0x1000000 )
152- session3 = SrtpContext ._derive_single_key (key2 , 0x2000000 )
182+ def _derive_session_keys (master_key : bytes , master_salt : bytes ) -> SrtpSessionKeys :
183+ tmp1 = SrtpContext ._derive_single_key (master_salt , SrtpSessionKeys . SRTP_CRYPT )
184+ tmp2 = SrtpContext ._derive_single_key (master_salt , SrtpSessionKeys . SRTP_AUTH )
185+ tmp3 = SrtpContext ._derive_single_key (master_salt , SrtpSessionKeys . SRTP_SALT )
153186
154- session1 = SrtpContext ._crypt_ctr_oneshot (key1 , session1 , b'\x00 ' * 16 )
155- session2 = SrtpContext ._crypt_ctr_oneshot (key1 , session2 , b'\x00 ' * 16 )
156- session3 = SrtpContext ._crypt_ctr_oneshot (key1 , session3 , b'\x00 ' * 16 , max_bytes = 14 )
187+ crypt_key = SrtpContext ._crypt_ctr_oneshot (master_key , tmp1 , b'\x00 ' * 16 )
188+ auth_key = SrtpContext ._crypt_ctr_oneshot (master_key , tmp2 , b'\x00 ' * 16 )
189+ salt_key = SrtpContext ._crypt_ctr_oneshot (master_key , tmp3 , b'\x00 ' * 16 , max_bytes = 14 )
157190
158- return SrtpSessionKeys ([
159- SrtpSessionKey (session1 ),
160- SrtpSessionKey (session2 ),
161- SrtpSessionKey (session3 )
162- ])
191+ return SrtpSessionKeys (crypt_key , auth_key , salt_key )
163192
164193 @staticmethod
165194 def _init_gcm_cryptor (key : bytes ) -> AESGCM :
@@ -175,11 +204,11 @@ def _encrypt(ctx: AESGCM, nonce: bytes, data: bytes, aad: bytes) -> bytes:
175204
176205 def _get_transformed_nonce (self , transform_direction : TransformDirection ) -> bytes :
177206 # Skip first 2 bytes of Nonce key
178- nonce = bytearray (self .session_keys .nonce_key [2 :])
207+ nonce = bytearray (self .session_keys .salt_key [2 :])
179208 # TODO: Implement transform logic
180209 # FIXME: Just tranforming the Nonce to a known value for
181210 # our single test packet
182- nonce [- 1 ] = nonce [ - 1 ] + 1
211+ nonce [- 1 ] += 1
183212
184213 return nonce
185214
0 commit comments