1 /**
2 * SSL3-MAC
3 * 
4 * Copyright:
5 * (C) 1999-2004 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.mac.ssl3_mac;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_SSL3_MAC):
15 
16 import botan.hash.hash;
17 import botan.mac.mac;
18 import botan.utils.mem_ops;
19 import std.algorithm : fill;
20 
21 /**
22 * A MAC only used in SSLv3. Do not use elsewhere! Use HMAC instead.
23 */
24 final class SSL3MAC : MessageAuthenticationCode, SymmetricAlgorithm
25 {
26 public:
27     /*
28     * Return the name of this type
29     */
30     override @property string name() const
31     {
32         return "SSL3-MAC(" ~ m_hash.name ~ ")";
33     }
34 
35     override @property size_t outputLength() const { return m_hash.outputLength; }
36 
37     /*
38     * Return a clone of this object
39     */
40     override MessageAuthenticationCode clone() const
41     {
42         return new SSL3MAC(m_hash.clone());
43     }
44 
45 
46     /*
47     * Clear memory of sensitive data
48     */
49     void clear()
50     {
51         m_hash.clear();
52         zap(m_ikey);
53         zap(m_okey);
54     }
55 
56     KeyLengthSpecification keySpec() const
57     {
58         return KeyLengthSpecification(m_hash.outputLength);
59     }
60 
61     /**
62     * Params:
63     *  hash = the underlying hash to use
64     */
65     this(HashFunction hash)
66     {
67         m_hash = hash;
68         if (m_hash.hashBlockSize == 0)
69             throw new InvalidArgument("SSL3-MAC cannot be used with " ~ m_hash.name);
70     }
71 protected:
72     /*
73     * Update a SSL3-MAC Calculation
74     */
75     override void addData(const(ubyte)* input, size_t length)
76     {
77         m_hash.update(input, length);
78     }
79 
80     /*
81     * Finalize a SSL3-MAC Calculation
82     */
83     override void finalResult(ubyte* mac)
84     {
85         m_hash.flushInto(mac);
86         m_hash.update(m_okey);
87         m_hash.update(mac, outputLength());
88         m_hash.flushInto(mac);
89         m_hash.update(m_ikey);
90     }
91 
92     /*
93     * SSL3-MAC Key Schedule
94     */
95     override void keySchedule(const(ubyte)* key, size_t length)
96     {
97         m_hash.clear();
98         
99         // Quirk to deal with specification bug
100         const size_t inner_hash_length = (m_hash.name == "SHA-160") ? 60 : m_hash.hashBlockSize;
101         
102         m_ikey.resize(inner_hash_length);
103         m_okey.resize(inner_hash_length);
104         
105         fill(m_ikey.ptr[0 .. m_ikey.length], cast(ubyte) 0x36);
106         fill(m_okey.ptr[0 .. m_ikey.length], cast(ubyte) 0x5C);
107         
108         copyMem(m_ikey.ptr, key, length);
109         copyMem(m_okey.ptr, key, length);
110         
111         m_hash.update(m_ikey);
112     }
113 
114     Unique!HashFunction m_hash;
115     SecureVector!ubyte m_ikey, m_okey;
116 }