Home | History | Annotate | Download | only in crypto
      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