From 2ca704e5c04bc8368ae1972d2a86ab54e5da3ada Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Thu, 6 Nov 2014 15:02:19 -0800 Subject: [PATCH] Adjust PreventNonceFlood tests The OEMCrypto library should prevent too many nonces from occuring in a row. Previously, we tested that GenerateNonce generated an error if there were too many nonce requests. This CL makes it possible for OEMCrypto to delay the return from GenerateNonce if there are too many requests. This is an equally valid solution to the nonce flood attack. This is a unit test change only. No production code is affected. This is a merge from the widevine repository of: https://widevine-internal-review.googlesource.com/#/c/11604/ bug: 17630253 Change-Id: Ie97f712d70230cd8e7ea7089da0aa18039673bb4 --- .../oemcrypto/test/oemcrypto_test.cpp | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index b53243e2..c246ea54 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -899,6 +899,7 @@ class Session { public: Session() : open_(false), + session_id_(0), mac_key_server_(wvcdm::MAC_KEY_SIZE), mac_key_client_(wvcdm::MAC_KEY_SIZE), enc_key_(wvcdm::KEY_SIZE), @@ -1766,36 +1767,88 @@ TEST_F(OEMCryptoClientTest, PreventNonceFlood) { s.open(); int error_counter = 0; uint32_t nonce; - // More than 20 nonces should generate an error. + time_t test_start = time(NULL); + // More than 20 nonces per second should generate an error. // To allow for some slop, we actually test for more than 40. for (int i = 0; i < 60; i++) { s.GenerateNonce(&nonce, &error_counter); } - ASSERT_LE(20, error_counter); + time_t test_end = time(NULL); + // Either there should be a two second delay, or there should have been + // at least 20 errors. + if (20 > error_counter) { + EXPECT_LE(2, test_end - test_start); + } else { + EXPECT_LE(20, error_counter); + } error_counter = 0; sleep(2); // After a pause, we should be able to regenerate nonces. s.GenerateNonce(&nonce, &error_counter); - ASSERT_EQ(0, error_counter); + EXPECT_EQ(0, error_counter); } // Prevent a nonce flood even if each nonce is in a different session. TEST_F(OEMCryptoClientTest, PreventNonceFlood2) { int error_counter = 0; uint32_t nonce; - // More than 20 nonces should generate an error. + time_t test_start = time(NULL); + // More than 20 nonces per second should generate an error. // To allow for some slop, we actually test for more than 40. for (int i = 0; i < 60; i++) { Session s; s.open(); + EXPECT_TRUE(s.isOpen()); s.GenerateNonce(&nonce, &error_counter); } - ASSERT_LE(20, error_counter); + time_t test_end = time(NULL); + // Either there should be a two second delay, or there should have been + // at least 20 errors. + if (20 > error_counter) { + EXPECT_LE(2, test_end - test_start); + } else { + EXPECT_LE(20, error_counter); + } error_counter = 0; sleep(2); // After a pause, we should be able to regenerate nonces. Session s; s.open(); s.GenerateNonce(&nonce, &error_counter); - ASSERT_EQ(0, error_counter); + EXPECT_EQ(0, error_counter); +} + +// Prevent a nonce flood even if some nonces are in a different session. This +// is different from the test above because there are several session open at +// the same time. We want to make sure you can't get a flood of nonces by +// opening a flood of sessions. +TEST_F(OEMCryptoClientTest, PreventNonceFlood3) { + int error_counter = 0; + uint32_t nonce; + time_t test_start = time(NULL); + // More than 20 nonces per second should generate an error. + // To allow for some slop, we actually test for more than 40. + Session s[6]; + for (int i = 0; i < 6; i++) { + s[i].open(); + EXPECT_TRUE(s[i].isOpen()); + for (int j = 0; j < 10; j++) { + s[i].GenerateNonce(&nonce, &error_counter); + } + } + time_t test_end = time(NULL); + // Either there should be a two second delay, or there should have been + // at least 20 errors. + if (20 > error_counter) { + EXPECT_LE(2, test_end - test_start); + } else { + EXPECT_LE(20, error_counter); + } + error_counter = 0; + sleep(2); // After a pause, we should be able to regenerate nonces. + Session s7; + s7.open(); + EXPECT_TRUE(s7.isOpen()); + s7.GenerateNonce(&nonce, &error_counter); + EXPECT_EQ(0, error_counter); } TEST_F(OEMCryptoClientTest, GenerateDerivedKeys) {