Home | History | Annotate | Download | only in crypto
      1 ## This file is part of Scapy
      2 ## Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
      3 ##                     2015, 2016 Maxence Tury
      4 ## This program is published under a GPLv2 license
      5 
      6 """
      7 HMAC classes.
      8 """
      9 
     10 from __future__ import absolute_import
     11 import hmac
     12 
     13 from scapy.layers.tls.crypto.hash import _tls_hash_algs
     14 import scapy.modules.six as six
     15 from scapy.compat import *
     16 
     17 _SSLv3_PAD1_MD5  = b"\x36"*48
     18 _SSLv3_PAD1_SHA1 = b"\x36"*40
     19 _SSLv3_PAD2_MD5  = b"\x5c"*48
     20 _SSLv3_PAD2_SHA1 = b"\x5c"*40
     21 
     22 _tls_hmac_algs = {}
     23 
     24 class _GenericHMACMetaclass(type):
     25     """
     26     HMAC classes are automatically registered through this metaclass.
     27     Furthermore, their name attribute is extracted from their class name.
     28 
     29     Note that, when used with TLS, the HMAC key length equates the output of
     30     the associated hash function (see RFC 5246, appendix C).
     31     Also, we do not need to instantiate the associated hash function.
     32     """
     33     def __new__(cls, hmac_name, bases, dct):
     34         hash_name = hmac_name[5:]               # remove leading "Hmac_"
     35         if hmac_name != "_GenericHMAC":
     36             dct["name"] = "HMAC-%s" % hash_name
     37             dct["hash_alg"] = _tls_hash_algs[hash_name]
     38             dct["hmac_len"] = _tls_hash_algs[hash_name].hash_len
     39             dct["key_len"] = dct["hmac_len"]
     40         the_class = super(_GenericHMACMetaclass, cls).__new__(cls, hmac_name,
     41                                                               bases, dct)
     42         if hmac_name != "_GenericHMAC":
     43             _tls_hmac_algs[dct["name"]] = the_class
     44         return the_class
     45 
     46 
     47 class HMACError(Exception):
     48     """
     49     Raised when HMAC verification fails.
     50     """
     51     pass
     52 
     53 class _GenericHMAC(six.with_metaclass(_GenericHMACMetaclass, object)):
     54     def __init__(self, key=None):
     55         self.key = key
     56 
     57     def digest(self, tbd):
     58         if self.key is None:
     59             raise HMACError
     60         return hmac.new(raw(self.key), raw(tbd), self.hash_alg.hash_cls).digest()
     61 
     62     def digest_sslv3(self, tbd):
     63         if self.key is None:
     64             raise HMACError
     65 
     66         h = self.hash_alg()
     67         if h.name == "SHA":
     68             pad1 = _SSLv3_PAD1_SHA1
     69             pad2 = _SSLv3_PAD2_SHA1
     70         elif h.name == "MD5":
     71             pad1 = _SSLv3_PAD1_MD5
     72             pad2 = _SSLv3_PAD2_MD5
     73         else:
     74             raise HMACError("Provided hash does not work with SSLv3.")
     75 
     76         return h.digest(self.key + pad2 +
     77                         h.digest(self.key + pad1 + tbd))
     78 
     79 
     80 class Hmac_NULL(_GenericHMAC):
     81     hmac_len = 0
     82     key_len = 0
     83 
     84     def digest(self, tbd):
     85         return b""
     86 
     87     def digest_sslv3(self, tbd):
     88         return b""
     89 
     90 class Hmac_MD5(_GenericHMAC):
     91     pass
     92 
     93 class Hmac_SHA(_GenericHMAC):
     94     pass
     95 
     96 class Hmac_SHA224(_GenericHMAC):
     97     pass
     98 
     99 class Hmac_SHA256(_GenericHMAC):
    100     pass
    101 
    102 class Hmac_SHA384(_GenericHMAC):
    103     pass
    104 
    105 class Hmac_SHA512(_GenericHMAC):
    106     pass
    107 
    108