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""" 7HMAC classes. 8""" 9 10from __future__ import absolute_import 11import hmac 12 13from scapy.layers.tls.crypto.hash import _tls_hash_algs 14import scapy.modules.six as six 15from 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 24class _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 47class HMACError(Exception): 48 """ 49 Raised when HMAC verification fails. 50 """ 51 pass 52 53class _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 80class 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 90class Hmac_MD5(_GenericHMAC): 91 pass 92 93class Hmac_SHA(_GenericHMAC): 94 pass 95 96class Hmac_SHA224(_GenericHMAC): 97 pass 98 99class Hmac_SHA256(_GenericHMAC): 100 pass 101 102class Hmac_SHA384(_GenericHMAC): 103 pass 104 105class Hmac_SHA512(_GenericHMAC): 106 pass 107 108