]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[sedhcpv6] fixed multiple verify in HMAC
authorFrancis Dupont <fdupont@isc.org>
Mon, 8 Jun 2015 10:55:18 +0000 (12:55 +0200)
committerFrancis Dupont <fdupont@isc.org>
Mon, 8 Jun 2015 10:55:18 +0000 (12:55 +0200)
src/lib/cryptolink/botan_hmac.cc
src/lib/cryptolink/openssl_hmac.cc
src/lib/cryptolink/tests/hmac_unittests.cc

index 14539c97e736a16a2f38b8f09764a50c1e7e5a45..ce90e9ff3a07f04ff72ea7cb8d54521938710b92 100644 (file)
@@ -48,11 +48,11 @@ public:
         try {
             hash = Botan::get_hash(btn::getHashAlgorithmName(hash_algorithm));
         } catch (const Botan::Algorithm_Not_Found&) {
-            isc_throw(isc::cryptolink::UnsupportedAlgorithm,
+            isc_throw(UnsupportedAlgorithm,
                       "Unknown hash algorithm: " <<
                       static_cast<int>(hash_algorithm));
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
 
         hmac_.reset(new Botan::HMAC(hash));
@@ -88,7 +88,7 @@ public:
         } catch (const Botan::Invalid_Key_Length& ikl) {
             isc_throw(BadKey, ikl.what());
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -123,7 +123,7 @@ public:
         try {
             hmac_->update(static_cast<const Botan::byte*>(data), len);
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -139,7 +139,7 @@ public:
             }
             result.writeData(b_result.begin(), len);
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -155,7 +155,7 @@ public:
             }
             std::memcpy(result, b_result.begin(), output_size);
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -171,7 +171,7 @@ public:
                 return (std::vector<uint8_t>(b_result.begin(), &b_result[len]));
             }
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -184,7 +184,6 @@ public:
         /// which causes it to fail for truncated signatures, so we do
         /// the check ourselves
         try {
-            Botan::SecureVector<Botan::byte> our_mac = hmac_->final();
             size_t size = getOutputLength();
             if (len < 10 || len < size / 2) {
                 return (false);
@@ -192,11 +191,14 @@ public:
             if (len > size) {
                 len = size;
             }
-            return (Botan::same_mem(&our_mac[0],
+            if (digest_.empty()) {
+                digest_ = hmac_->final();
+            }
+            return (Botan::same_mem(&digest_[0],
                                     static_cast<const unsigned char*>(sig),
                                     len));
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -206,6 +208,9 @@ private:
 
     /// @brief The protected pointer to the Botan HMAC object
     boost::scoped_ptr<Botan::HMAC> hmac_;
+
+    /// @brief The digest cache for multiple verify
+    Botan::SecureVector<Botan::byte> digest_;
 };
 
 HMAC::HMAC(const void* secret, size_t secret_length,
index ed1a618177abe66c13672079df64e47cb3ba4905..baf7fa66e970da18480c4ff5043c6ef8dbfd3edc 100644 (file)
@@ -76,7 +76,7 @@ public:
     size_t getOutputLength() const {
         int size = HMAC_size(md_.get());
         if (size < 0) {
-            isc_throw(isc::cryptolink::LibraryError, "EVP_MD_CTX_size");
+            isc_throw(LibraryError, "HMAC_size");
         }
         return (static_cast<size_t>(size));
     }
@@ -131,12 +131,23 @@ public:
     ///
     /// See @ref isc::cryptolink::HMAC::verify() for details.
     bool verify(const void* sig, size_t len) {
+        // Check the length
         size_t size = getOutputLength();
         if (len < 10 || len < size / 2) {
             return (false);
         }
+        // Get the digest from a copy of the context
+        HMAC_CTX tmp;
+        HMAC_CTX_init(&tmp);
+        if (!HMAC_CTX_copy(&tmp, md_.get())) {
+            isc_throw(LibraryError, "HMAC_CTX_copy");
+        }
         ossl::SecBuf<unsigned char> digest(size);
-        HMAC_Final(md_.get(), &digest[0], NULL);
+        if (!HMAC_Final(&tmp, &digest[0], NULL)) {
+            HMAC_CTX_cleanup(&tmp);
+            isc_throw(LibraryError, "HMAC_Final");
+        }
+        HMAC_CTX_cleanup(&tmp);
         if (len > size) {
             len = size;
         }
index f148dca59e3d960cb74a5dcf78c60d4e0ee60006..6e2af12d746adbee8dbbe5887507428e5ede3f73 100644 (file)
@@ -133,6 +133,13 @@ namespace {
         hmac_sig.writeUint8At(~hmac_sig[0], 0);
         EXPECT_FALSE(hmac_verify->verify(hmac_sig.getData(),
                                          hmac_sig.getLength()));
+
+        // Restore the sig by flipping the first octet, and check
+        // whether verification succeeds then
+        hmac_sig.writeUint8At(~hmac_sig[0], 0);
+        EXPECT_TRUE(hmac_verify->verify(hmac_sig.getData(),
+                                        hmac_sig.getLength()));
+
     }
 
     /// @brief Sign and verify with vector representation of signature
@@ -197,6 +204,9 @@ namespace {
         sig[0] = ~sig[0];
         EXPECT_FALSE(hmac_verify->verify(sig, hmac_len));
 
+        sig[0] = ~sig[0];
+        EXPECT_TRUE(hmac_verify->verify(sig, hmac_len));
+
         delete[] sig;
     }