Improve RSA performance in Level 3 OEMCrypto
Merge from widevine repo of http://go/wvgerrit/14668 This CL modifies the multiplication routine to avoid memory cache misses. This shows a 10-20% speed improvment in license requests on an x86. Level 3 library version: level3/arm/libwvlevel3.a Level3 Library Jun 15 2015 14:09:24 level3/x86/libwvlevel3.a Level3 Library Jun 15 2015 14:09:10 bug: 18252910 Change-Id: I4429324374de46d1d710d5fcac80f7ed363c696c
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,7 @@
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -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<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
|
||||
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
vector<uint8_t> encryptionIv =
|
||||
wvcdm::a2b_hex("719dbcb253b2ec702bb8c1b1bc2f3bc6");
|
||||
const size_t max_length = 250*1000;
|
||||
vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<size_t>(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<uint8_t> enc_session_key;
|
||||
s.PreparePublicKey();
|
||||
ASSERT_TRUE(s.GenerateRSASessionKey(&enc_session_key));
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> 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
|
||||
|
||||
Reference in New Issue
Block a user