Skip to content

Commit a81a9ba

Browse files
committed
Crypto: Use session key derivation from pysrtp
1 parent 4d868b9 commit a81a9ba

1 file changed

Lines changed: 22 additions & 39 deletions

File tree

xcloud/protocol/srtp_crypto.py

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -145,46 +145,29 @@ def _crypt_ctr_oneshot(key: bytes, iv: bytes, plaintext: bytes, max_bytes: Optio
145145
return cipher_out
146146

147147
@staticmethod
148-
def _derive_single_key(
149-
master_key: bytes,
150-
master_salt: bytes,
151-
key_index: Optional[int] = 0,
152-
max_bytes: Optional[int] = 16
153-
) -> bytes:
154-
keysize = len(master_salt)
155-
keyout = bytearray(b'\x00' * 16)
156-
157-
if keysize >= 14:
158-
keysize = 14
159-
160-
if keysize:
161-
keyout[13] = master_salt[keysize - 1]
162-
if keysize != 1:
163-
keyout[12] = master_salt[keysize - 2]
164-
if keysize >= 3:
165-
pos = 0
166-
for _ in range(2, keysize):
167-
keyout[pos + 11] = master_salt[pos + keysize - 3]
168-
pos -= 1
169-
170-
if keysize <= 13:
171-
null_count = 14 - keysize
172-
for i in range(0, null_count):
173-
keyout[i] = 0
174-
175-
for index in range(14, 16):
176-
keyout[index] = 0
148+
def _derive_single_key(master_key, master_salt, key_index: int = 0, max_bytes: int = 16, pkt_i=0, key_derivation_rate=0):
149+
import binascii
150+
'''SRTP key derivation, https://tools.ietf.org/html/rfc3711#section-4.3'''
151+
152+
def bytes_to_int(b):
153+
return int.from_bytes(b, byteorder='big')
154+
155+
def int_to_bytes(i, n_bytes):
156+
return i.to_bytes(n_bytes, byteorder='big')
157+
158+
assert len(master_key) == 128 // 8
159+
assert len(master_salt) == 112 // 8
160+
salt = bytes_to_int(master_salt)
161+
162+
DIV = lambda x, y: 0 if y == 0 else x // y
163+
prng = lambda iv: SrtpContext._crypt_ctr_oneshot(
164+
master_key, int_to_bytes(iv, 16), b'\x00' * 16, max_bytes=max_bytes
165+
)
166+
r = DIV(pkt_i, key_derivation_rate) # pkt_i is always 48 bits
167+
derive_key_from_label = lambda label: prng(
168+
(salt ^ ((label << 48) + r)) << 16)
177169

178-
if key_index:
179-
len_before_xor = len(keyout)
180-
value_to_xor = struct.unpack_from('<I', keyout, 4)[0]
181-
value_to_xor ^= (key_index * 0x1000000)
182-
keyout = keyout[:4] + struct.pack('<I', value_to_xor) + keyout[8:]
183-
assert len(keyout) == len_before_xor
184-
185-
# Encrypt the key
186-
keyout = SrtpContext._crypt_ctr_oneshot(master_key, keyout, b'\x00' * 16, max_bytes=max_bytes)
187-
return keyout
170+
return derive_key_from_label(key_index)
188171

189172
@staticmethod
190173
def _derive_session_keys(master_key: bytes, master_salt: bytes) -> SrtpSessionKeys:

0 commit comments

Comments
 (0)