1 ## This file is part of Scapy 2 ## Copyright (C) 2017 Maxence Tury 3 ## This program is published under a GPLv2 license 4 5 """ 6 Stateless HKDF for TLS 1.3. 7 """ 8 9 import struct 10 11 from scapy.config import conf 12 from scapy.layers.tls.crypto.pkcs1 import _get_hash 13 14 if conf.crypto_valid: 15 from cryptography.hazmat.backends import default_backend 16 from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand 17 from cryptography.hazmat.primitives.hashes import Hash 18 from cryptography.hazmat.primitives.hmac import HMAC 19 20 21 class TLS13_HKDF(object): 22 def __init__(self, hash_name="sha256"): 23 self.hash = _get_hash(hash_name) 24 25 def extract(self, salt, ikm): 26 h = self.hash 27 hkdf = HKDF(h, h.digest_size, salt, None, default_backend()) 28 if ikm is None: 29 ikm = b"\x00" * h.digest_size 30 return hkdf._extract(ikm) 31 32 def expand(self, prk, info, L): 33 h = self.hash 34 hkdf = HKDFExpand(h, L, info, default_backend()) 35 return hkdf.derive(prk) 36 37 def expand_label(self, secret, label, hash_value, length): 38 hkdf_label = struct.pack("!H", length) 39 hkdf_label += struct.pack("B", 9 + len(label)) 40 hkdf_label += b"TLS 1.3, " 41 hkdf_label += label 42 hkdf_label += struct.pack("B", len(hash_value)) 43 hkdf_label += hash_value 44 return self.expand(secret, hkdf_label, length) 45 46 def derive_secret(self, secret, label, messages): 47 h = Hash(self.hash, backend=default_backend()) 48 h.update(messages) 49 hash_messages = h.finalize() 50 hash_len = self.hash.digest_size 51 return self.expand_label(secret, label, hash_messages, hash_len) 52 53 def compute_verify_data(self, basekey, handshake_context): 54 hash_len = self.hash.digest_size 55 finished_key = self.expand_label(basekey, b"finished", b"", hash_len) 56 57 h = Hash(self.hash, backend=default_backend()) 58 h.update(handshake_context) 59 hash_value = h.finalize() 60 61 hm = HMAC(finished_key, self.hash, default_backend()) 62 hm.update(hash_value) 63 return hm.finalize() 64 65