Browse Source

[trac781] tabs/spaces, and a bit of exception handling

Jelte Jansen 14 years ago
parent
commit
253d063204
3 changed files with 275 additions and 197 deletions
  1. 64 49
      src/lib/crypto/crypto.cc
  2. 41 0
      src/lib/crypto/crypto.h
  3. 170 148
      src/lib/crypto/tests/crypto_unittests.cc

+ 64 - 49
src/lib/crypto/crypto.cc

@@ -35,15 +35,16 @@ using namespace isc::dns;
 
 namespace {
 HashFunction* getHash(const Name& hash_name) {
-	if (hash_name == TSIGKey::HMACMD5_NAME()) {
-		return get_hash("MD5");
-	} else if (hash_name == TSIGKey::HMACSHA1_NAME()) {
-		return get_hash("SHA-1");
-	} else if (hash_name == TSIGKey::HMACSHA256_NAME()) {
-		return get_hash("SHA-256");
-	} else {
-		isc_throw(isc::InvalidParameter, "Unknown Hash type");
-	}
+    if (hash_name == TSIGKey::HMACMD5_NAME()) {
+        return get_hash("MD5");
+    } else if (hash_name == TSIGKey::HMACSHA1_NAME()) {
+        return get_hash("SHA-1");
+    } else if (hash_name == TSIGKey::HMACSHA256_NAME()) {
+        return get_hash("SHA-256");
+    } else {
+        isc_throw(isc::crypto::UnsupportedAlgorithm,
+                  "Unknown Hash type " + hash_name.toText());
+    }
 }
 
     // Library needs to have been inited during the entire program
@@ -65,8 +66,12 @@ signHMAC(const OutputBuffer& data, TSIGKey key,
     HMAC::HMAC hmac(hash);
 
     // Take the 'secret' from the key
-    hmac.set_key(static_cast<const byte*>(key.getSecret()),
-                 key.getSecretLength());
+    try {
+        hmac.set_key(static_cast<const byte*>(key.getSecret()),
+                    key.getSecretLength());
+    } catch (Invalid_Key_Length ikl) {
+        isc_throw(BadKey, ikl.what());
+    }
 
     // update the data from whatever we get (probably as a buffer)
     hmac.update(static_cast<const byte*>(data.getData()),
@@ -85,7 +90,11 @@ verifyHMAC(const OutputBuffer& data, TSIGKey key,
 {
     HashFunction* hash = getHash(key.getAlgorithmName());
     HMAC::HMAC hmac(hash);
-    hmac.set_key(static_cast<const byte*>(key.getSecret()), key.getSecretLength());
+    try {
+        hmac.set_key(static_cast<const byte*>(key.getSecret()), key.getSecretLength());
+    } catch (Invalid_Key_Length ikl) {
+        isc_throw(BadKey, ikl.what());
+    }
     hmac.update(static_cast<const byte*>(data.getData()), data.getLength());
 
     return hmac.verify_mac(static_cast<const byte*>(result.getData()), result.getLength());
@@ -93,47 +102,53 @@ verifyHMAC(const OutputBuffer& data, TSIGKey key,
 
 isc::dns::TSIGKey
 TSIGKeyFromString(const std::string& str) {
-	size_t pos = str.find(':');
-	if (pos == 0 || pos == str.npos) {
-		// error, TODO: raise
-		isc_throw(InvalidParameter, "Invalid TSIG key string");
-	}
-	Name key_name(str.substr(0, pos));
-	
-	Name algo_name("hmac-md5.sig-alg.reg.int");
-	
-	// optional algorithm part
-	size_t pos2 = str.find(':', pos+1);
-	if (pos2 != str.npos) {
-		if (pos2 == pos + 1) {
-			isc_throw(InvalidParameter, "Invalid TSIG key string");
-		}
-		algo_name = Name(str.substr(pos2+1));
-	} else {
-		pos2 = str.size() - pos;
-	}
-	
-	std::string secret_str = str.substr(pos + 1, pos2 - pos - 1);
-
-	vector<uint8_t> secret;
-	decodeBase64(secret_str, secret);
-	unsigned char secret_b[secret.size()];
-	for (size_t i=0; i < secret.size(); ++i) {
-		secret_b[i] = secret[i];
-	}
-	return isc::dns::TSIGKey(key_name, algo_name, secret_b, secret.size());
+    size_t pos = str.find(':');
+    if (pos == 0 || pos == str.npos) {
+        // error
+        isc_throw(InvalidParameter, "Invalid TSIG key string");
+    }
+    try {
+        Name key_name(str.substr(0, pos));
+        Name algo_name("hmac-md5.sig-alg.reg.int");
+
+        // optional algorithm part
+        size_t pos2 = str.find(':', pos+1);
+        if (pos2 != str.npos) {
+            if (pos2 == pos + 1) {
+                isc_throw(InvalidParameter, "Invalid TSIG key string");
+            }
+            algo_name = Name(str.substr(pos2+1));
+        } else {
+            pos2 = str.size() - pos;
+        }
+
+        std::string secret_str = str.substr(pos + 1, pos2 - pos - 1);
+    
+        vector<uint8_t> secret;
+        decodeBase64(secret_str, secret);
+        unsigned char secret_b[secret.size()];
+        for (size_t i=0; i < secret.size(); ++i) {
+            secret_b[i] = secret[i];
+        }
+
+        return isc::dns::TSIGKey(key_name, algo_name, secret_b, secret.size());
+    } catch (Exception e) {
+        // 'reduce' the several types of exceptions name parsing and
+        // Base64 decoding can throw to just the InvalidParameter
+        isc_throw(InvalidParameter, e.what());
+    }
 }
 
 std::string
 TSIGKeyToString(const isc::dns::TSIGKey& key) {
-	const uint8_t* secret_b = static_cast<const uint8_t*>(key.getSecret());
-	vector<uint8_t> secret_v;
-	for (size_t i=0; i < key.getSecretLength(); ++i) {
-		secret_v.push_back(secret_b[i]);
-	}
-	std::string secret_str = encodeBase64(secret_v);
-	
-	return key.getKeyName().toText() + ":" + secret_str + ":" + key.getAlgorithmName().toText();
+    const uint8_t* secret_b = static_cast<const uint8_t*>(key.getSecret());
+    vector<uint8_t> secret_v;
+    for (size_t i=0; i < key.getSecretLength(); ++i) {
+        secret_v.push_back(secret_b[i]);
+    }
+    std::string secret_str = encodeBase64(secret_v);
+    
+    return key.getKeyName().toText() + ":" + secret_str + ":" + key.getAlgorithmName().toText();
 }
 
 

+ 41 - 0
src/lib/crypto/crypto.h

@@ -28,6 +28,7 @@
 #include <string>
 #include <dns/buffer.h>
 #include <dns/tsigkey.h>
+#include <exceptions/exceptions.h>
 
 #ifndef _ISC_CRYPTO_H
 #define _ISC_CRYPTO_H
@@ -35,10 +36,50 @@
 namespace isc {
 namespace crypto {
 
+class CryptoError : public Exception {
+public:
+    CryptoError(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+class UnsupportedAlgorithm : public CryptoError {
+public:
+    UnsupportedAlgorithm(const char* file, size_t line, const char* what) :
+        CryptoError(file, line, what) {}
+};
+
+// The underlying library could not handle this key
+class BadKey : public CryptoError {
+public:
+    BadKey(const char* file, size_t line, const char* what) :
+        CryptoError(file, line, what) {}
+};
+
+/// \brief Create an HMAC signature for the given data
+///
+/// Raises an UnsupportedAlgorithm if we do not support the given
+/// algorithm. Raises a BadKey exception if the underlying library
+/// cannot handle the given TSIGKey (for instance if it has a bad
+/// length).
+///
+/// \param data The data to sign
+/// \param key The TSIGKey to sign with
+/// \param result The signature will be written to the end of this buffer
 void signHMAC(const isc::dns::OutputBuffer& data,
               isc::dns::TSIGKey key,
               isc::dns::OutputBuffer& result);
 
+/// \brief Verify an HMAC signature for the given data
+///
+/// Raises an UnsupportedAlgorithm if we do not support the given
+/// algorithm. Raises a BadKey exception if the underlying library
+/// cannot handle the given TSIGKey (for instance if it has a bad
+/// length).
+///
+/// \param data The data to verify
+/// \param key The TSIGKey to verify with
+/// \param mac The signature to verify
+/// \return True if the signature verifies, false if not
 bool verifyHMAC(const isc::dns::OutputBuffer& data,
                 isc::dns::TSIGKey key,
                 const isc::dns::OutputBuffer& mac);

+ 170 - 148
src/lib/crypto/tests/crypto_unittests.cc

@@ -18,175 +18,197 @@
 #include <crypto/crypto.h>
 #include <crypto/crypto_botan.h>
 #include <dns/buffer.h>
+#include <dns/name.h>
 #include <exceptions/exceptions.h>
 
 using namespace isc::dns;
 using namespace isc::crypto;
 
 namespace {
-	void checkBuffer(const OutputBuffer& buf, uint8_t *data, size_t len) {
-		ASSERT_EQ(buf.getLength(), len);
-		const uint8_t* buf_d = static_cast<const uint8_t*>(buf.getData());
-		for (size_t i = 0; i < len; ++i) {
-			//std::cout << "[XX] I: " << i << ", buf: " << buf_d[i] << ", dat: " << data[i] << std::endl;
-			ASSERT_EQ(buf_d[i], data[i]);
-		}
-	}
-	
-	void doHMACTest(std::string data, std::string key_str,
-	                uint8_t* expected_hmac, size_t hmac_len) {
-	    OutputBuffer data_buf(data.size());
-	    data_buf.writeData(data.c_str(), data.size());
-	    OutputBuffer hmac_sig(1);
-	    
-	    TSIGKey key = TSIGKeyFromString(key_str);
-	    
-	    signHMAC(data_buf, key, hmac_sig);
-	    checkBuffer(hmac_sig, expected_hmac, hmac_len);
-	}
+    void checkBuffer(const OutputBuffer& buf, uint8_t *data, size_t len) {
+        ASSERT_EQ(buf.getLength(), len);
+        const uint8_t* buf_d = static_cast<const uint8_t*>(buf.getData());
+        for (size_t i = 0; i < len; ++i) {
+            //std::cout << "[XX] I: " << i << ", buf: " << buf_d[i] << ", dat: " << data[i] << std::endl;
+            ASSERT_EQ(buf_d[i], data[i]);
+        }
+    }
+    
+    void doHMACTest(std::string data, std::string key_str,
+                    uint8_t* expected_hmac, size_t hmac_len) {
+        OutputBuffer data_buf(data.size());
+        data_buf.writeData(data.c_str(), data.size());
+        OutputBuffer hmac_sig(1);
+        
+        TSIGKey key = TSIGKeyFromString(key_str);
+        
+        signHMAC(data_buf, key, hmac_sig);
+        checkBuffer(hmac_sig, expected_hmac, hmac_len);
+    }
 }
 
+//
 // Test values taken from RFC 2202
+//
 TEST(CryptoTest, HMAC_MD5_RFC2202_SIGN) {
-	// 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b = CwsLCwsLCwsLCwsLCwsLCw==
+    // 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b = CwsLCwsLCwsLCwsLCwsLCw==
     uint8_t hmac_expected[] = { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38,
                                 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8,
                                 0x15, 0x8b, 0xfc, 0x9d };
-	doHMACTest("Hi There",
-	           "test.example:CwsLCwsLCwsLCwsLCwsLCw==:hmac-md5.sig-alg.reg.int",
-	           hmac_expected, 16);
-	uint8_t hmac_expected2[] = { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0,
-	                             0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31,
-	                             0x0a, 0x5d, 0xb7, 0x38 };
-	doHMACTest("what do ya want for nothing?",
-	           "test.example:SmVmZQ==:hmac-md5.sig-alg.reg.int",
-	           hmac_expected2, 16);
-
-	std::string data3;
-	for (int i = 0; i < 50; ++i) {
-		data3.push_back(0xdd);
-	}
-	uint8_t hmac_expected3[] = { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14,
-	                             0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33,
-	                             0xf0, 0xe8, 0xb3, 0xf6};
-	doHMACTest(data3,
-	           "test.example:qqqqqqqqqqqqqqqqqqqqqg==:hmac-md5.sig-alg.reg.int",
-	           hmac_expected3, 16);
-
-	std::string data4;
-	for (int i = 0; i < 50; ++i) {
-		data4.push_back(0xcd);
-	}
-	uint8_t hmac_expected4[] = { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a,
-	                             0x3a, 0xea, 0x3a, 0x75, 0x16, 0x47,
-	                             0x46, 0xff, 0xaa, 0x79 };
-	doHMACTest(data4,
-	           "test.example:AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGQ==:hmac-md5.sig-alg.reg.int",
-	           hmac_expected4, 16);
-
-	uint8_t hmac_expected5[] = { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e,
-	                             0xdc, 0x00, 0xf9, 0xba, 0xb9, 0x95,
-	                             0x69, 0x0e, 0xfd, 0x4c };
-	doHMACTest("Test With Truncation",
-	           "test.example:DAwMDAwMDAwMDAwMDAwMDA==:hmac-md5.sig-alg.reg.int",
-	           hmac_expected5, 16);
-	           
-	uint8_t hmac_expected6[] = { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7,
-	                             0xbf, 0x8f, 0x0b, 0x62, 0xe6, 0xce,
-	                             0x61, 0xb9, 0xd0, 0xcd };
-	doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
-	           "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-md5.sig-alg.reg.int",
-	           hmac_expected6, 16);
-
-	uint8_t hmac_expected7[] = { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd,
-	                             0xa0, 0xee, 0x1f, 0xb1, 0xf5, 0x62,
-	                             0xdb, 0x3a, 0xa5, 0x3e };
-	doHMACTest("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
-	           "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-md5.sig-alg.reg.int",
-	           hmac_expected7, 16);
+    doHMACTest("Hi There",
+               "test.example:CwsLCwsLCwsLCwsLCwsLCw==:hmac-md5.sig-alg.reg.int",
+               hmac_expected, 16);
+    uint8_t hmac_expected2[] = { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0,
+                                 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31,
+                                 0x0a, 0x5d, 0xb7, 0x38 };
+    doHMACTest("what do ya want for nothing?",
+               "test.example:SmVmZQ==:hmac-md5.sig-alg.reg.int",
+               hmac_expected2, 16);
+
+    std::string data3;
+    for (int i = 0; i < 50; ++i) {
+        data3.push_back(0xdd);
+    }
+    uint8_t hmac_expected3[] = { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14,
+                                 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33,
+                                 0xf0, 0xe8, 0xb3, 0xf6};
+    doHMACTest(data3,
+               "test.example:qqqqqqqqqqqqqqqqqqqqqg==:hmac-md5.sig-alg.reg.int",
+               hmac_expected3, 16);
+
+    std::string data4;
+    for (int i = 0; i < 50; ++i) {
+        data4.push_back(0xcd);
+    }
+    uint8_t hmac_expected4[] = { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a,
+                                 0x3a, 0xea, 0x3a, 0x75, 0x16, 0x47,
+                                 0x46, 0xff, 0xaa, 0x79 };
+    doHMACTest(data4,
+               "test.example:AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGQ==:hmac-md5.sig-alg.reg.int",
+               hmac_expected4, 16);
+
+    uint8_t hmac_expected5[] = { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e,
+                                 0xdc, 0x00, 0xf9, 0xba, 0xb9, 0x95,
+                                 0x69, 0x0e, 0xfd, 0x4c };
+    doHMACTest("Test With Truncation",
+               "test.example:DAwMDAwMDAwMDAwMDAwMDA==:hmac-md5.sig-alg.reg.int",
+               hmac_expected5, 16);
+               
+    uint8_t hmac_expected6[] = { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7,
+                                 0xbf, 0x8f, 0x0b, 0x62, 0xe6, 0xce,
+                                 0x61, 0xb9, 0xd0, 0xcd };
+    doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
+               "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-md5.sig-alg.reg.int",
+               hmac_expected6, 16);
+
+    uint8_t hmac_expected7[] = { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd,
+                                 0xa0, 0xee, 0x1f, 0xb1, 0xf5, 0x62,
+                                 0xdb, 0x3a, 0xa5, 0x3e };
+    doHMACTest("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+               "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-md5.sig-alg.reg.int",
+               hmac_expected7, 16);
 
 }
 
+//
+// Test values taken from RFC 2202
+//
 TEST(CryptoTest, HMAC_SHA1_RFC2202_SIGN) {
     uint8_t hmac_expected[] = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05,
                                 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6,
                                 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46,
                                 0xbe, 0x00 };
-	doHMACTest("Hi There",
-	           "test.example:CwsLCwsLCwsLCwsLCwsLCwsLCws=:hmac-sha1",
-	           hmac_expected, 20);
-
-	uint8_t hmac_expected2[] = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb,
-	                             0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5,
-	                             0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a,
-	                             0x7c, 0x79 };
-	doHMACTest("what do ya want for nothing?",
-	           "test.example:SmVmZQ==:hmac-sha1",
-	           hmac_expected2, 20);
-
-	std::string data3;
-	for (int i = 0; i < 50; ++i) {
-		data3.push_back(0xdd);
-	}
-	uint8_t hmac_expected3[] = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac,
-	                             0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4,
-	                             0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1,
-	                             0x75, 0xd3 };
-	doHMACTest(data3,
-	           "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-sha1",
-	           hmac_expected3, 20);
-
-	std::string data4;
-	for (int i = 0; i < 50; ++i) {
-		data4.push_back(0xcd);
-	}
-	uint8_t hmac_expected4[] = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62,
-	                             0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9,
-	                             0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72,
-	                             0x35, 0xda };
-	doHMACTest(data4,
-	           "test.example:AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGQ==:hmac-sha1",
-	           hmac_expected4, 20);
-
-	uint8_t hmac_expected5[] = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55,
-	                             0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1,
-	                             0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a,
-	                             0x5a, 0x04 };
-	doHMACTest("Test With Truncation",
-	           "test.example:DAwMDAwMDAwMDAwMDAwMDAwMDAw=:hmac-sha1",
-	           hmac_expected5, 20);
-	           
-	uint8_t hmac_expected6[] = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72,
-	                             0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37,
-	                             0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40,
-	                             0x21, 0x12 };
-	doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
-	           "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-sha1",
-	           hmac_expected6, 20);
-
-	uint8_t hmac_expected7[] = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23,
-	                             0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7,
-	                             0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff,
-	                             0x1a, 0x91 };
-	doHMACTest("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
-	           "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-sha1",
-	           hmac_expected7, 20);
+    doHMACTest("Hi There",
+               "test.example:CwsLCwsLCwsLCwsLCwsLCwsLCws=:hmac-sha1",
+               hmac_expected, 20);
+
+    uint8_t hmac_expected2[] = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb,
+                                 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5,
+                                 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a,
+                                 0x7c, 0x79 };
+    doHMACTest("what do ya want for nothing?",
+               "test.example:SmVmZQ==:hmac-sha1",
+               hmac_expected2, 20);
+
+    std::string data3;
+    for (int i = 0; i < 50; ++i) {
+        data3.push_back(0xdd);
+    }
+    uint8_t hmac_expected3[] = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac,
+                                 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4,
+                                 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1,
+                                 0x75, 0xd3 };
+    doHMACTest(data3,
+               "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-sha1",
+               hmac_expected3, 20);
+
+    std::string data4;
+    for (int i = 0; i < 50; ++i) {
+        data4.push_back(0xcd);
+    }
+    uint8_t hmac_expected4[] = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62,
+                                 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9,
+                                 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72,
+                                 0x35, 0xda };
+    doHMACTest(data4,
+               "test.example:AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGQ==:hmac-sha1",
+               hmac_expected4, 20);
+
+    uint8_t hmac_expected5[] = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55,
+                                 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1,
+                                 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a,
+                                 0x5a, 0x04 };
+    doHMACTest("Test With Truncation",
+               "test.example:DAwMDAwMDAwMDAwMDAwMDAwMDAw=:hmac-sha1",
+               hmac_expected5, 20);
+               
+    uint8_t hmac_expected6[] = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72,
+                                 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37,
+                                 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40,
+                                 0x21, 0x12 };
+    doHMACTest("Test Using Larger Than Block-Size Key - Hash Key First",
+               "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-sha1",
+               hmac_expected6, 20);
+
+    uint8_t hmac_expected7[] = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23,
+                                 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7,
+                                 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff,
+                                 0x1a, 0x91 };
+    doHMACTest("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+               "test.example:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=:hmac-sha1",
+               hmac_expected7, 20);
 }
 
-TEST(CryptoText, TSIGKeyFromString) {
-	TSIGKey k1 = TSIGKeyFromString("test.example:MSG6Ng==:hmac-md5.sig-alg.reg.int");
-	TSIGKey k2 = TSIGKeyFromString("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.");
-	TSIGKey k3 = TSIGKeyFromString("test.example:MSG6Ng==");
-	
-	EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
-	          TSIGKeyToString(k1));
-	EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
-	          TSIGKeyToString(k2));
-	EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
-	          TSIGKeyToString(k3));
-
-	EXPECT_THROW(TSIGKeyFromString(""), isc::InvalidParameter);
-	EXPECT_THROW(TSIGKeyFromString("::"), isc::InvalidParameter);
-	EXPECT_THROW(TSIGKeyFromString("test.example.::"), isc::InvalidParameter);
-	EXPECT_THROW(TSIGKeyFromString("test.example.:MSG6Ng==:unknown"), isc::InvalidParameter);
+TEST(CryptoTest, BadKey) {
+    TSIGKey bad_key = TSIGKey(Name("test.example."), Name("hmac-sha1."),
+                              NULL, 0);
+
+    OutputBuffer data_buf(0);
+    OutputBuffer hmac_sig(1);
+    
+    EXPECT_THROW(signHMAC(data_buf, bad_key, hmac_sig), BadKey);
+    EXPECT_THROW(verifyHMAC(data_buf, bad_key, hmac_sig), BadKey);
+}
+
+TEST(CryptoTest, TSIGKeyFromToString) {
+    TSIGKey k1 = TSIGKeyFromString("test.example:MSG6Ng==:hmac-md5.sig-alg.reg.int");
+    TSIGKey k2 = TSIGKeyFromString("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.");
+    TSIGKey k3 = TSIGKeyFromString("test.example:MSG6Ng==");
+    TSIGKey k4 = TSIGKey(Name("test.example."), Name("hmac-sha1."), NULL, 0);
+    
+    EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+              TSIGKeyToString(k1));
+    EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+              TSIGKeyToString(k2));
+    EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+              TSIGKeyToString(k3));
+    EXPECT_EQ("test.example.::hmac-sha1.", TSIGKeyToString(k4));
+
+    EXPECT_THROW(TSIGKeyFromString(""), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKeyFromString("::"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKeyFromString("..:aa:"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKeyFromString("test.example:xxxx:"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKeyFromString("test.example.::"), isc::InvalidParameter);
+    EXPECT_THROW(TSIGKeyFromString("test.example.:MSG6Ng==:unknown"), isc::InvalidParameter);
+
 }