diff --git a/libwvdrmengine/level3/arm/libwvlevel3.a b/libwvdrmengine/level3/arm/libwvlevel3.a index ffa38071..645dd864 100644 Binary files a/libwvdrmengine/level3/arm/libwvlevel3.a and b/libwvdrmengine/level3/arm/libwvlevel3.a differ diff --git a/libwvdrmengine/level3/x86/libwvlevel3.a b/libwvdrmengine/level3/x86/libwvlevel3.a index 72767f46..e67efd00 100644 Binary files a/libwvdrmengine/level3/x86/libwvlevel3.a and b/libwvdrmengine/level3/x86/libwvlevel3.a differ diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 42d1a369..00397692 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -677,6 +678,11 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) { if (!usage_table) FilterOut(&filter, "*UsageTable*"); if (derive_key_method == NO_METHOD) FilterOut(&filter, "*SessionTest*"); if (api_version < 10) FilterOut(&filter, "*API10*"); + // Performance tests take a long time. Filter them out if they are not + // specifically requested. + if (filter.find("Performance") == std::string::npos) { + FilterOut(&filter, "*Performance*"); + } return filter; } @@ -2443,6 +2449,75 @@ TEST_F(OEMCryptoSessionTests, Decrypt) { s.TestDecryptCTR(); } +TEST_F(OEMCryptoSessionTests, DecryptPerformance) { + OEMCryptoResult sts; + Session s; + s.open(); + s.GenerateTestSessionKeys(); + const time_t TestDuration = 5; + s.FillSimpleMessage(600, 0, 0); + s.EncryptAndSign(); + s.LoadTestKeys(); + vector keyId = wvcdm::a2b_hex("000000000000000000000000"); + sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + vector encryptionIv = + wvcdm::a2b_hex("719dbcb253b2ec702bb8c1b1bc2f3bc6"); + const size_t max_length = 250*1000; + vector input(max_length); + printf("Size of input is %zd\n", input.size()); + for(unsigned int i=0; i < max_length; i++) input[i] = i % 256; + vector output(max_length); + OEMCrypto_DestBufferDesc destBuffer; + destBuffer.type = OEMCrypto_BufferType_Clear; + destBuffer.buffer.clear.address = &output[0]; + + const char* level = OEMCrypto_SecurityLevel(); + const int n = 10; + double x[n], y[n]; + double xsum = 0.0; + double ysum = 0.0; + double xysum = 0.0; + double xsqsum = 0.0; + printf("PERF:head, security, bytes, bytes/frame, time(ms)/frame, bandwidth\n"); + + for(int i=0; i < n; i++) { + size_t length = 1000 + i*1000; + destBuffer.buffer.clear.max_length = length; + time_t test_start = time(NULL); + time_t test_end = time(NULL); + int count = 0; + size_t total = 0; + do { + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_DecryptCTR( + s.session_id(), &input[0], length, true, + &encryptionIv[0], 0, &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample)); + count++; + total += length; + test_end = time(NULL); + } while(test_end - test_start < TestDuration); + x[i] = length; + y[i] = 1000*(test_end-test_start)/((double)count); + xsum += x[i]; + ysum += y[i]; + xysum += x[i]*y[i]; + xsqsum += x[i]*x[i]; + printf("PERF:stat, %s, %12zd, %12g, %12g, %12g\n", level, total, + x[i], y[i], + ((double)total)/((double)(test_end-test_start)) + ); + } + double b = (n*xysum - xsum*ysum) / (n*xsqsum - xsum*xsum); + double a = (ysum - b*xsum)/n; + printf("PERF-FIT, security=%s fit time(ms)/frame = %g + %g * buffer_size\n", + level, a, b); + for(int i=0; i < n; i++) { + printf("PERF-FIT, %12g, %12g, %12g\n", x[i], y[i], a + b*x[i]); + } +} + TEST_F(OEMCryptoSessionTests, DecryptZeroDuration) { OEMCryptoResult sts; Session s; @@ -3003,6 +3078,116 @@ class OEMCryptoUsesCertificate : public OEMCryptoLoadsCertificate { Session session_; }; +// Test performance +TEST_F( OEMCryptoLoadsCertificate, RSAPerformance) { + OEMCryptoResult sts; + sleep(2); // Make sure are not nonce limited. + const uint32_t TestDuration = 5000; // milliseconds. + struct timeval start_time, end_time; + gettimeofday(&start_time, NULL); + gettimeofday(&end_time, NULL); + double mtime = 0; + long count = 0; + for(int i=0; i< 15; i++) { // Only 20 nonce available. + vector wrapped_key; + CreateWrappedRSAKey(&wrapped_key, kSign_RSASSA_PSS, true); + count++; + gettimeofday(&end_time, NULL); + long seconds = end_time.tv_sec - start_time.tv_sec; + long useconds = end_time.tv_usec - start_time.tv_usec; + mtime = seconds * 1e3 + useconds * 1e-3; + } + double provision_time = mtime / count; + + std::vector wrapped_rsa_key; + Session session; + CreateWrappedRSAKey(&wrapped_rsa_key, kSign_RSASSA_PSS, true); + gettimeofday(&start_time, NULL); + gettimeofday(&end_time, NULL); + mtime = 0; + count = 0; + do { + Session s; + s.open(); + sts = OEMCrypto_LoadDeviceRSAKey(s.session_id(), &wrapped_rsa_key[0], + wrapped_rsa_key.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + const size_t size = 50; + vector licenseRequest(size); + OEMCrypto_GetRandom(&licenseRequest[0], licenseRequest.size()); + size_t signature_length = 0; + sts = OEMCrypto_GenerateRSASignature(s.session_id(), &licenseRequest[0], + licenseRequest.size(), NULL, + &signature_length, kSign_RSASSA_PSS); + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); + ASSERT_NE(static_cast(0), signature_length); + uint8_t* signature = new uint8_t[signature_length]; + sts = OEMCrypto_GenerateRSASignature(s.session_id(), &licenseRequest[0], + licenseRequest.size(), signature, + &signature_length, kSign_RSASSA_PSS); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + count++; + gettimeofday(&end_time, NULL); + long seconds = end_time.tv_sec - start_time.tv_sec; + long useconds = end_time.tv_usec - start_time.tv_usec; + mtime = seconds * 1e3 + useconds * 1e-3; + } while(mtime < TestDuration); + double license_request_time = mtime / count; + + Session s; + s.open(); + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_LoadDeviceRSAKey(s.session_id(), &wrapped_rsa_key[0], + wrapped_rsa_key.size())); + vector enc_session_key; + s.PreparePublicKey(); + ASSERT_TRUE(s.GenerateRSASessionKey(&enc_session_key)); + vector mac_context; + vector enc_context; + s.FillDefaultContext(&mac_context, &enc_context); + gettimeofday(&start_time, NULL); + gettimeofday(&end_time, NULL); + mtime = 0; + count = 0; + + enc_session_key = wvcdm::a2b_hex( + "7789c619aa3b9fa3c0a53f57a4abc6" + "02157c8aa57e3c6fb450b0bea22667fb" + "0c3200f9d9d618e397837c720dc2dadf" + "486f33590744b2a4e54ca134ae7dbf74" + "434c2fcf6b525f3e132262f05ea3b3c1" + "198595c0e52b573335b2e8a3debd0d0d" + "d0306f8fcdde4e76476be71342957251" + "e1688c9ca6c1c34ed056d3b989394160" + "cf6937e5ce4d39cc73d11a2e93da21a2" + "fa019d246c852fe960095b32f120c3c2" + "7085f7b64aac344a68d607c0768676ce" + "d4c5b2d057f7601921b453a451e1dea0" + "843ebfef628d9af2784d68e86b730476" + "e136dfe19989de4be30a4e7878efcde5" + "ad2b1254f80c0c5dd3cf111b56572217" + "b9f58fc1dacbf74b59d354a1e62cfa0e" + "bf"); + do { + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_DeriveKeysFromSessionKey( + s.session_id(), &enc_session_key[0], enc_session_key.size(), + &mac_context[0], mac_context.size(), &enc_context[0], + enc_context.size())); + count++; + gettimeofday(&end_time, NULL); + long seconds = end_time.tv_sec - start_time.tv_sec; + long useconds = end_time.tv_usec - start_time.tv_usec; + mtime = seconds * 1e3 + useconds * 1e-3; + } while(mtime < TestDuration); + double derive_keys_time = mtime / count; + + const char* level = OEMCrypto_SecurityLevel(); + printf("PERF:head, security, provision (ms), lic req(ms), derive keys(ms)\n"); + printf("PERF:stat, %s, %8.3f, %8.3f, %8.3f\n", level, provision_time, + license_request_time, derive_keys_time); +} + TEST_F(OEMCryptoUsesCertificate, RSASignature) { OEMCryptoResult sts; // Sign a Message