aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/mac
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-01-10 03:41:59 +0000
committerlloyd <[email protected]>2014-01-10 03:41:59 +0000
commit6894dca64c04936d07048c0e8cbf7e25858548c3 (patch)
tree5d572bfde9fe667dab14e3f04b5285a85d8acd95 /src/lib/mac
parent9efa3be92442afb3d0b69890a36c7f122df18eda (diff)
Move lib into src
Diffstat (limited to 'src/lib/mac')
-rw-r--r--src/lib/mac/cbc_mac/cbc_mac.cpp105
-rw-r--r--src/lib/mac/cbc_mac/cbc_mac.h49
-rw-r--r--src/lib/mac/cbc_mac/info.txt5
-rw-r--r--src/lib/mac/cmac/cmac.cpp156
-rw-r--r--src/lib/mac/cmac/cmac.h63
-rw-r--r--src/lib/mac/cmac/info.txt5
-rw-r--r--src/lib/mac/hmac/hmac.cpp97
-rw-r--r--src/lib/mac/hmac/hmac.h53
-rw-r--r--src/lib/mac/hmac/info.txt5
-rw-r--r--src/lib/mac/info.txt3
-rw-r--r--src/lib/mac/mac.cpp26
-rw-r--r--src/lib/mac/mac.h46
-rw-r--r--src/lib/mac/ssl3mac/info.txt5
-rw-r--r--src/lib/mac/ssl3mac/ssl3_mac.cpp90
-rw-r--r--src/lib/mac/ssl3mac/ssl3_mac.h49
-rw-r--r--src/lib/mac/x919_mac/info.txt5
-rw-r--r--src/lib/mac/x919_mac/x919_mac.cpp103
-rw-r--r--src/lib/mac/x919_mac/x919_mac.h54
18 files changed, 919 insertions, 0 deletions
diff --git a/src/lib/mac/cbc_mac/cbc_mac.cpp b/src/lib/mac/cbc_mac/cbc_mac.cpp
new file mode 100644
index 000000000..118570e72
--- /dev/null
+++ b/src/lib/mac/cbc_mac/cbc_mac.cpp
@@ -0,0 +1,105 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cbc_mac.h>
+#include <botan/internal/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Update an CBC-MAC Calculation
+*/
+void CBC_MAC::add_data(const byte input[], size_t length)
+ {
+ size_t xored = std::min(output_length() - position, length);
+ xor_buf(&state[position], input, xored);
+ position += xored;
+
+ if(position < output_length())
+ return;
+
+ e->encrypt(state);
+ input += xored;
+ length -= xored;
+ while(length >= output_length())
+ {
+ xor_buf(state, input, output_length());
+ e->encrypt(state);
+ input += output_length();
+ length -= output_length();
+ }
+
+ xor_buf(state, input, length);
+ position = length;
+ }
+
+/*
+* Finalize an CBC-MAC Calculation
+*/
+void CBC_MAC::final_result(byte mac[])
+ {
+ if(position)
+ e->encrypt(state);
+
+ copy_mem(mac, &state[0], state.size());
+ zeroise(state);
+ position = 0;
+ }
+
+/*
+* CBC-MAC Key Schedule
+*/
+void CBC_MAC::key_schedule(const byte key[], size_t length)
+ {
+ e->set_key(key, length);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void CBC_MAC::clear()
+ {
+ e->clear();
+ zeroise(state);
+ position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CBC_MAC::name() const
+ {
+ return "CBC-MAC(" + e->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* CBC_MAC::clone() const
+ {
+ return new CBC_MAC(e->clone());
+ }
+
+/*
+* CBC-MAC Constructor
+*/
+CBC_MAC::CBC_MAC(BlockCipher* e_in) :
+ e(e_in), state(e->block_size())
+ {
+ position = 0;
+ }
+
+/*
+* CBC-MAC Destructor
+*/
+CBC_MAC::~CBC_MAC()
+ {
+ delete e;
+ }
+
+}
diff --git a/src/lib/mac/cbc_mac/cbc_mac.h b/src/lib/mac/cbc_mac/cbc_mac.h
new file mode 100644
index 000000000..be25718d9
--- /dev/null
+++ b/src/lib/mac/cbc_mac/cbc_mac.h
@@ -0,0 +1,49 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CBC_MAC_H__
+#define BOTAN_CBC_MAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* CBC-MAC
+*/
+class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode
+ {
+ public:
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+ size_t output_length() const { return e->block_size(); }
+ void clear();
+
+ Key_Length_Specification key_spec() const
+ {
+ return e->key_spec();
+ }
+
+ /**
+ * @param cipher the underlying block cipher to use
+ */
+ CBC_MAC(BlockCipher* cipher);
+ ~CBC_MAC();
+ private:
+ void add_data(const byte[], size_t);
+ void final_result(byte[]);
+ void key_schedule(const byte[], size_t);
+
+ BlockCipher* e;
+ secure_vector<byte> state;
+ size_t position;
+ };
+
+}
+
+#endif
diff --git a/src/lib/mac/cbc_mac/info.txt b/src/lib/mac/cbc_mac/info.txt
new file mode 100644
index 000000000..cb017e2a1
--- /dev/null
+++ b/src/lib/mac/cbc_mac/info.txt
@@ -0,0 +1,5 @@
+define CBC_MAC 20131128
+
+<requires>
+block
+</requires>
diff --git a/src/lib/mac/cmac/cmac.cpp b/src/lib/mac/cmac/cmac.cpp
new file mode 100644
index 000000000..00120cf14
--- /dev/null
+++ b/src/lib/mac/cmac/cmac.cpp
@@ -0,0 +1,156 @@
+/*
+* CMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cmac.h>
+#include <botan/internal/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Perform CMAC's multiplication in GF(2^n)
+*/
+secure_vector<byte> CMAC::poly_double(const secure_vector<byte>& in,
+ byte polynomial)
+ {
+ const byte poly_xor = (in[0] & 0x80) ? polynomial : 0;
+
+ secure_vector<byte> out = in;
+
+ byte carry = 0;
+ for(size_t i = out.size(); i != 0; --i)
+ {
+ byte temp = out[i-1];
+ out[i-1] = (temp << 1) | carry;
+ carry = (temp >> 7);
+ }
+
+ out[out.size()-1] ^= poly_xor;
+
+ return out;
+ }
+
+/*
+* Update an CMAC Calculation
+*/
+void CMAC::add_data(const byte input[], size_t length)
+ {
+ buffer_insert(buffer, position, input, length);
+ if(position + length > output_length())
+ {
+ xor_buf(state, buffer, output_length());
+ e->encrypt(state);
+ input += (output_length() - position);
+ length -= (output_length() - position);
+ while(length > output_length())
+ {
+ xor_buf(state, input, output_length());
+ e->encrypt(state);
+ input += output_length();
+ length -= output_length();
+ }
+ copy_mem(&buffer[0], input, length);
+ position = 0;
+ }
+ position += length;
+ }
+
+/*
+* Finalize an CMAC Calculation
+*/
+void CMAC::final_result(byte mac[])
+ {
+ xor_buf(state, buffer, position);
+
+ if(position == output_length())
+ {
+ xor_buf(state, B, output_length());
+ }
+ else
+ {
+ state[position] ^= 0x80;
+ xor_buf(state, P, output_length());
+ }
+
+ e->encrypt(state);
+
+ for(size_t i = 0; i != output_length(); ++i)
+ mac[i] = state[i];
+
+ zeroise(state);
+ zeroise(buffer);
+ position = 0;
+ }
+
+/*
+* CMAC Key Schedule
+*/
+void CMAC::key_schedule(const byte key[], size_t length)
+ {
+ clear();
+ e->set_key(key, length);
+ e->encrypt(B);
+ B = poly_double(B, polynomial);
+ P = poly_double(B, polynomial);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void CMAC::clear()
+ {
+ e->clear();
+ zeroise(state);
+ zeroise(buffer);
+ zeroise(B);
+ zeroise(P);
+ position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CMAC::name() const
+ {
+ return "CMAC(" + e->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* CMAC::clone() const
+ {
+ return new CMAC(e->clone());
+ }
+
+/*
+* CMAC Constructor
+*/
+CMAC::CMAC(BlockCipher* e_in) : e(e_in)
+ {
+ if(e->block_size() == 16)
+ polynomial = 0x87;
+ else if(e->block_size() == 8)
+ polynomial = 0x1B;
+ else
+ throw Invalid_Argument("CMAC cannot use the cipher " + e->name());
+
+ state.resize(output_length());
+ buffer.resize(output_length());
+ B.resize(output_length());
+ P.resize(output_length());
+ position = 0;
+ }
+
+/*
+* CMAC Destructor
+*/
+CMAC::~CMAC()
+ {
+ delete e;
+ }
+
+}
diff --git a/src/lib/mac/cmac/cmac.h b/src/lib/mac/cmac/cmac.h
new file mode 100644
index 000000000..c1b75cfa5
--- /dev/null
+++ b/src/lib/mac/cmac/cmac.h
@@ -0,0 +1,63 @@
+/*
+* CMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CMAC_H__
+#define BOTAN_CMAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* CMAC, also known as OMAC1
+*/
+class BOTAN_DLL CMAC : public MessageAuthenticationCode
+ {
+ public:
+ std::string name() const;
+ size_t output_length() const { return e->block_size(); }
+ MessageAuthenticationCode* clone() const;
+
+ void clear();
+
+ Key_Length_Specification key_spec() const
+ {
+ return e->key_spec();
+ }
+
+ /**
+ * CMAC's polynomial doubling operation
+ * @param in the input
+ * @param polynomial the byte value of the polynomial
+ */
+ static secure_vector<byte> poly_double(const secure_vector<byte>& in,
+ byte polynomial);
+
+ /**
+ * @param cipher the underlying block cipher to use
+ */
+ CMAC(BlockCipher* cipher);
+
+ CMAC(const CMAC&) = delete;
+ CMAC& operator=(const CMAC&) = delete;
+
+ ~CMAC();
+ private:
+ void add_data(const byte[], size_t);
+ void final_result(byte[]);
+ void key_schedule(const byte[], size_t);
+
+ BlockCipher* e;
+ secure_vector<byte> buffer, state, B, P;
+ size_t position;
+ byte polynomial;
+ };
+
+}
+
+#endif
diff --git a/src/lib/mac/cmac/info.txt b/src/lib/mac/cmac/info.txt
new file mode 100644
index 000000000..d2dc6f68d
--- /dev/null
+++ b/src/lib/mac/cmac/info.txt
@@ -0,0 +1,5 @@
+define CMAC 20131128
+
+<requires>
+block
+</requires>
diff --git a/src/lib/mac/hmac/hmac.cpp b/src/lib/mac/hmac/hmac.cpp
new file mode 100644
index 000000000..9e9a643db
--- /dev/null
+++ b/src/lib/mac/hmac/hmac.cpp
@@ -0,0 +1,97 @@
+/*
+* HMAC
+* (C) 1999-2007 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hmac.h>
+#include <botan/internal/xor_buf.h>
+
+namespace Botan {
+
+/*
+* Update a HMAC Calculation
+*/
+void HMAC::add_data(const byte input[], size_t length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Finalize a HMAC Calculation
+*/
+void HMAC::final_result(byte mac[])
+ {
+ hash->final(mac);
+ hash->update(o_key);
+ hash->update(mac, output_length());
+ hash->final(mac);
+ hash->update(i_key);
+ }
+
+/*
+* HMAC Key Schedule
+*/
+void HMAC::key_schedule(const byte key[], size_t length)
+ {
+ hash->clear();
+
+ i_key.resize(hash->hash_block_size());
+ o_key.resize(hash->hash_block_size());
+
+ std::fill(i_key.begin(), i_key.end(), 0x36);
+ std::fill(o_key.begin(), o_key.end(), 0x5C);
+
+ if(length > hash->hash_block_size())
+ {
+ secure_vector<byte> hmac_key = hash->process(key, length);
+ xor_buf(i_key, hmac_key, hmac_key.size());
+ xor_buf(o_key, hmac_key, hmac_key.size());
+ }
+ else
+ {
+ xor_buf(i_key, key, length);
+ xor_buf(o_key, key, length);
+ }
+
+ hash->update(i_key);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void HMAC::clear()
+ {
+ hash->clear();
+ zap(i_key);
+ zap(o_key);
+ }
+
+/*
+* Return the name of this type
+*/
+std::string HMAC::name() const
+ {
+ return "HMAC(" + hash->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* HMAC::clone() const
+ {
+ return new HMAC(hash->clone());
+ }
+
+/*
+* HMAC Constructor
+*/
+HMAC::HMAC(HashFunction* hash_in) : hash(hash_in)
+ {
+ if(hash->hash_block_size() == 0)
+ throw Invalid_Argument("HMAC cannot be used with " + hash->name());
+ }
+
+}
diff --git a/src/lib/mac/hmac/hmac.h b/src/lib/mac/hmac/hmac.h
new file mode 100644
index 000000000..39a084874
--- /dev/null
+++ b/src/lib/mac/hmac/hmac.h
@@ -0,0 +1,53 @@
+/*
+* HMAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HMAC_H__
+#define BOTAN_HMAC_H__
+
+#include <botan/mac.h>
+#include <botan/hash.h>
+
+namespace Botan {
+
+/**
+* HMAC
+*/
+class BOTAN_DLL HMAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear();
+ std::string name() const;
+ MessageAuthenticationCode* clone() const;
+
+ size_t output_length() const { return hash->output_length(); }
+
+ Key_Length_Specification key_spec() const
+ {
+ return Key_Length_Specification(0, 512);
+ }
+
+ /**
+ * @param hash the hash to use for HMACing
+ */
+ HMAC(HashFunction* hash);
+
+ HMAC(const HMAC&) = delete;
+ HMAC& operator=(const HMAC&) = delete;
+
+ ~HMAC() { delete hash; }
+ private:
+ void add_data(const byte[], size_t);
+ void final_result(byte[]);
+ void key_schedule(const byte[], size_t);
+
+ HashFunction* hash;
+ secure_vector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/src/lib/mac/hmac/info.txt b/src/lib/mac/hmac/info.txt
new file mode 100644
index 000000000..7bc8b27f8
--- /dev/null
+++ b/src/lib/mac/hmac/info.txt
@@ -0,0 +1,5 @@
+define HMAC 20131128
+
+<requires>
+hash
+</requires>
diff --git a/src/lib/mac/info.txt b/src/lib/mac/info.txt
new file mode 100644
index 000000000..d991577f7
--- /dev/null
+++ b/src/lib/mac/info.txt
@@ -0,0 +1,3 @@
+<requires>
+algo_base
+</requires>
diff --git a/src/lib/mac/mac.cpp b/src/lib/mac/mac.cpp
new file mode 100644
index 000000000..094aa1b4a
--- /dev/null
+++ b/src/lib/mac/mac.cpp
@@ -0,0 +1,26 @@
+/*
+* Message Authentication Code base class
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/mac.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+/*
+* Default (deterministic) MAC verification operation
+*/
+bool MessageAuthenticationCode::verify_mac(const byte mac[], size_t length)
+ {
+ secure_vector<byte> our_mac = final();
+
+ if(our_mac.size() != length)
+ return false;
+
+ return same_mem(&our_mac[0], &mac[0], length);
+ }
+
+}
diff --git a/src/lib/mac/mac.h b/src/lib/mac/mac.h
new file mode 100644
index 000000000..d42092908
--- /dev/null
+++ b/src/lib/mac/mac.h
@@ -0,0 +1,46 @@
+/*
+* Base class for message authentiction codes
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_MESSAGE_AUTH_CODE_BASE_H__
+#define BOTAN_MESSAGE_AUTH_CODE_BASE_H__
+
+#include <botan/buf_comp.h>
+#include <botan/sym_algo.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents Message Authentication Code (MAC) objects.
+*/
+class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation,
+ public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * Verify a MAC.
+ * @param in the MAC to verify as a byte array
+ * @param length the length of param in
+ * @return true if the MAC is valid, false otherwise
+ */
+ virtual bool verify_mac(const byte in[], size_t length);
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual MessageAuthenticationCode* clone() const = 0;
+
+ /**
+ * Get the name of this algorithm.
+ * @return name of this algorithm
+ */
+ virtual std::string name() const = 0;
+ };
+
+}
+
+#endif
diff --git a/src/lib/mac/ssl3mac/info.txt b/src/lib/mac/ssl3mac/info.txt
new file mode 100644
index 000000000..5e69b0ae8
--- /dev/null
+++ b/src/lib/mac/ssl3mac/info.txt
@@ -0,0 +1,5 @@
+define SSL3_MAC 20131128
+
+<requires>
+hash
+</requires>
diff --git a/src/lib/mac/ssl3mac/ssl3_mac.cpp b/src/lib/mac/ssl3mac/ssl3_mac.cpp
new file mode 100644
index 000000000..64f3103ef
--- /dev/null
+++ b/src/lib/mac/ssl3mac/ssl3_mac.cpp
@@ -0,0 +1,90 @@
+/*
+* SSL3-MAC
+* (C) 1999-2004 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ssl3_mac.h>
+
+namespace Botan {
+
+/*
+* Update a SSL3-MAC Calculation
+*/
+void SSL3_MAC::add_data(const byte input[], size_t length)
+ {
+ hash->update(input, length);
+ }
+
+/*
+* Finalize a SSL3-MAC Calculation
+*/
+void SSL3_MAC::final_result(byte mac[])
+ {
+ hash->final(mac);
+ hash->update(o_key);
+ hash->update(mac, output_length());
+ hash->final(mac);
+ hash->update(i_key);
+ }
+
+/*
+* SSL3-MAC Key Schedule
+*/
+void SSL3_MAC::key_schedule(const byte key[], size_t length)
+ {
+ hash->clear();
+
+ // Quirk to deal with specification bug
+ const size_t inner_hash_length =
+ (hash->name() == "SHA-160") ? 60 : hash->hash_block_size();
+
+ i_key.resize(inner_hash_length);
+ o_key.resize(inner_hash_length);
+
+ std::fill(i_key.begin(), i_key.end(), 0x36);
+ std::fill(o_key.begin(), o_key.end(), 0x5C);
+
+ copy_mem(&i_key[0], key, length);
+ copy_mem(&o_key[0], key, length);
+
+ hash->update(i_key);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SSL3_MAC::clear()
+ {
+ hash->clear();
+ zap(i_key);
+ zap(o_key);
+ }
+
+/*
+* Return the name of this type
+*/
+std::string SSL3_MAC::name() const
+ {
+ return "SSL3-MAC(" + hash->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* SSL3_MAC::clone() const
+ {
+ return new SSL3_MAC(hash->clone());
+ }
+
+/*
+* SSL3-MAC Constructor
+*/
+SSL3_MAC::SSL3_MAC(HashFunction* hash_in) : hash(hash_in)
+ {
+ if(hash->hash_block_size() == 0)
+ throw Invalid_Argument("SSL3-MAC cannot be used with " + hash->name());
+ }
+
+}
diff --git a/src/lib/mac/ssl3mac/ssl3_mac.h b/src/lib/mac/ssl3mac/ssl3_mac.h
new file mode 100644
index 000000000..d23ac023c
--- /dev/null
+++ b/src/lib/mac/ssl3mac/ssl3_mac.h
@@ -0,0 +1,49 @@
+/*
+* SSL3-MAC
+* (C) 1999-2004 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SSL3_MAC_H__
+#define BOTAN_SSL3_MAC_H__
+
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+namespace Botan {
+
+/**
+* A MAC only used in SSLv3. Do not use elsewhere! Use HMAC instead.
+*/
+class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode
+ {
+ public:
+ std::string name() const;
+ size_t output_length() const { return hash->output_length(); }
+ MessageAuthenticationCode* clone() const;
+
+ void clear();
+
+ Key_Length_Specification key_spec() const
+ {
+ return Key_Length_Specification(hash->output_length());
+ }
+
+ /**
+ * @param hash the underlying hash to use
+ */
+ SSL3_MAC(HashFunction* hash);
+ ~SSL3_MAC() { delete hash; }
+ private:
+ void add_data(const byte[], size_t);
+ void final_result(byte[]);
+ void key_schedule(const byte[], size_t);
+
+ HashFunction* hash;
+ secure_vector<byte> i_key, o_key;
+ };
+
+}
+
+#endif
diff --git a/src/lib/mac/x919_mac/info.txt b/src/lib/mac/x919_mac/info.txt
new file mode 100644
index 000000000..63bf40790
--- /dev/null
+++ b/src/lib/mac/x919_mac/info.txt
@@ -0,0 +1,5 @@
+define ANSI_X919_MAC 20131128
+
+<requires>
+block
+</requires>
diff --git a/src/lib/mac/x919_mac/x919_mac.cpp b/src/lib/mac/x919_mac/x919_mac.cpp
new file mode 100644
index 000000000..faf6138ef
--- /dev/null
+++ b/src/lib/mac/x919_mac/x919_mac.cpp
@@ -0,0 +1,103 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x919_mac.h>
+#include <botan/internal/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* Update an ANSI X9.19 MAC Calculation
+*/
+void ANSI_X919_MAC::add_data(const byte input[], size_t length)
+ {
+ size_t xored = std::min(8 - position, length);
+ xor_buf(&state[position], input, xored);
+ position += xored;
+
+ if(position < 8) return;
+
+ e->encrypt(state);
+ input += xored;
+ length -= xored;
+ while(length >= 8)
+ {
+ xor_buf(state, input, 8);
+ e->encrypt(state);
+ input += 8;
+ length -= 8;
+ }
+
+ xor_buf(state, input, length);
+ position = length;
+ }
+
+/*
+* Finalize an ANSI X9.19 MAC Calculation
+*/
+void ANSI_X919_MAC::final_result(byte mac[])
+ {
+ if(position)
+ e->encrypt(state);
+ d->decrypt(&state[0], mac);
+ e->encrypt(mac);
+ zeroise(state);
+ position = 0;
+ }
+
+/*
+* ANSI X9.19 MAC Key Schedule
+*/
+void ANSI_X919_MAC::key_schedule(const byte key[], size_t length)
+ {
+ e->set_key(key, 8);
+ if(length == 8) d->set_key(key, 8);
+ else d->set_key(key + 8, 8);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void ANSI_X919_MAC::clear()
+ {
+ e->clear();
+ d->clear();
+ zeroise(state);
+ position = 0;
+ }
+
+std::string ANSI_X919_MAC::name() const
+ {
+ return "X9.19-MAC";
+ }
+
+MessageAuthenticationCode* ANSI_X919_MAC::clone() const
+ {
+ return new ANSI_X919_MAC(e->clone());
+ }
+
+/*
+* ANSI X9.19 MAC Constructor
+*/
+ANSI_X919_MAC::ANSI_X919_MAC(BlockCipher* e_in) :
+ e(e_in), d(e->clone()), state(e->block_size()), position(0)
+ {
+ if(e->name() != "DES")
+ throw Invalid_Argument("ANSI X9.19 MAC only supports DES");
+ }
+
+/*
+* ANSI X9.19 MAC Destructor
+le*/
+ANSI_X919_MAC::~ANSI_X919_MAC()
+ {
+ delete e;
+ delete d;
+ }
+
+}
diff --git a/src/lib/mac/x919_mac/x919_mac.h b/src/lib/mac/x919_mac/x919_mac.h
new file mode 100644
index 000000000..b7b7d685e
--- /dev/null
+++ b/src/lib/mac/x919_mac/x919_mac.h
@@ -0,0 +1,54 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X919_MAC_H__
+#define BOTAN_ANSI_X919_MAC_H__
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* DES/3DES-based MAC from ANSI X9.19
+*/
+class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode
+ {
+ public:
+ void clear();
+ std::string name() const;
+ size_t output_length() const { return e->block_size(); }
+ MessageAuthenticationCode* clone() const;
+
+ Key_Length_Specification key_spec() const
+ {
+ return Key_Length_Specification(8, 16, 8);
+ }
+
+ /**
+ * @param cipher the underlying block cipher to use
+ */
+ ANSI_X919_MAC(BlockCipher* cipher);
+
+ ANSI_X919_MAC(const ANSI_X919_MAC&) = delete;
+ ANSI_X919_MAC& operator=(const ANSI_X919_MAC&) = delete;
+
+ ~ANSI_X919_MAC();
+ private:
+ void add_data(const byte[], size_t);
+ void final_result(byte[]);
+ void key_schedule(const byte[], size_t);
+
+ BlockCipher* e;
+ BlockCipher* d;
+ secure_vector<byte> state;
+ size_t position;
+ };
+
+}
+
+#endif