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