Unit tests for forbidden RSA key usage
This CL adds unit tests to verify that the following forbidden uses of an RSA private key do not work: - ForbidPrepAndSign -- A cast cert key cannot sign a license request. - ForbidUseAsDRMCert -- A cast cert cannot be used with the DRM cert's padding scheme and it cannot be used to derive keys from a session key. - *ForbidRSASignatureForDRMKey* -- A DRM cert key cannot be used with GenerateRSASignature. - *OEMCertForbidGenerateRSASignature* -- An OEM cert key cannot be used with GenerateRSASignature. Bug: 251875110 Change-Id: Ic2b23e3fd279e878c190a8294078a8d092126a29
This commit is contained in:
committed by
Robert Shih
parent
343324e97c
commit
8f3ee84c1b
@@ -1201,6 +1201,8 @@ OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
|||||||
* @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
|
* @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
|
||||||
* @retval OEMCrypto_ERROR_SESSION_LOST_STATE
|
* @retval OEMCrypto_ERROR_SESSION_LOST_STATE
|
||||||
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_KEY if the session's private key is not a
|
||||||
|
* DRM key.
|
||||||
*
|
*
|
||||||
* @buffer_size
|
* @buffer_size
|
||||||
* OEMCrypto shall support message sizes as described in the section
|
* OEMCrypto shall support message sizes as described in the section
|
||||||
|
|||||||
@@ -11,16 +11,32 @@ using ::testing::Range;
|
|||||||
|
|
||||||
namespace wvoec {
|
namespace wvoec {
|
||||||
|
|
||||||
// The alternate padding is only required for cast receivers, but if a device
|
/** If a device can load a private key with the alternate padding schemes, it
|
||||||
// does load an alternate certificate, it should NOT use it for generating
|
* should support signing with the alternate scheme. */
|
||||||
// a license request signature.
|
|
||||||
TEST_F(OEMCryptoLoadsCertificateAlternates, TestSignaturePKCS1) {
|
TEST_F(OEMCryptoLoadsCertificateAlternates, TestSignaturePKCS1) {
|
||||||
// TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for
|
// Try to load an RSA key with alternative padding schemes. This signing
|
||||||
// provisioning 4. Disabled here temporarily.
|
// scheme is used by cast receivers.
|
||||||
if (!global_features.loads_certificate ||
|
LoadCastCertificateKey(false);
|
||||||
global_features.provisioning_method == OEMCrypto_BootCertificateChain) {
|
// If the device is a cast receiver, then this scheme is required.
|
||||||
GTEST_SKIP() << "Test for non Prov 4.0 devices only.";
|
if (global_features.cast_receiver) {
|
||||||
|
ASSERT_TRUE(key_loaded_);
|
||||||
|
// A signature with a valid size should succeed.
|
||||||
|
TestSignature(kSign_PKCS1_Block1, 83);
|
||||||
|
TestSignature(kSign_PKCS1_Block1, 50);
|
||||||
}
|
}
|
||||||
|
// If the key loaded with no error, then we will verify that it is not used
|
||||||
|
// for forbidden padding schemes. This should be tested for both devices that
|
||||||
|
// are cast receivers and devices that are not.
|
||||||
|
if (key_loaded_) {
|
||||||
|
// A signature with padding that is too big should fail.
|
||||||
|
DisallowForbiddenPaddingDRMKey(kSign_PKCS1_Block1, 84); // too big.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The alternate padding is only required for cast receivers, but if a device
|
||||||
|
* does load an alternate certificate, it should NOT be used to as a DRM cert
|
||||||
|
* key. */
|
||||||
|
TEST_F(OEMCryptoLoadsCertificateAlternates, ForbidUseAsDRMCert) {
|
||||||
// Try to load an RSA key with alternative padding schemes. This signing
|
// Try to load an RSA key with alternative padding schemes. This signing
|
||||||
// scheme is used by cast receivers.
|
// scheme is used by cast receivers.
|
||||||
LoadCastCertificateKey(false);
|
LoadCastCertificateKey(false);
|
||||||
@@ -34,13 +50,39 @@ TEST_F(OEMCryptoLoadsCertificateAlternates, TestSignaturePKCS1) {
|
|||||||
// The other padding scheme should fail.
|
// The other padding scheme should fail.
|
||||||
DisallowForbiddenPaddingDRMKey(kSign_RSASSA_PSS, 83);
|
DisallowForbiddenPaddingDRMKey(kSign_RSASSA_PSS, 83);
|
||||||
DisallowDeriveKeys();
|
DisallowDeriveKeys();
|
||||||
if (global_features.cast_receiver) {
|
|
||||||
// A signature with a valid size should succeed.
|
|
||||||
TestSignature(kSign_PKCS1_Block1, 83);
|
|
||||||
TestSignature(kSign_PKCS1_Block1, 50);
|
|
||||||
}
|
}
|
||||||
// A signature with padding that is too big should fail.
|
}
|
||||||
DisallowForbiddenPaddingDRMKey(kSign_PKCS1_Block1, 84); // too big.
|
|
||||||
|
/** A Cast receiver certificate private key cannot be used with the function
|
||||||
|
* PrepAndSignLicenseRequest.
|
||||||
|
*/
|
||||||
|
TEST_F(OEMCryptoLoadsCertificateAlternates, ForbidPrepAndSign) {
|
||||||
|
// Try to load an RSA key with alternative padding schemes. This signing
|
||||||
|
// scheme is used by cast receivers.
|
||||||
|
LoadCastCertificateKey(false);
|
||||||
|
// If the device is a cast receiver, then this scheme is required.
|
||||||
|
if (global_features.cast_receiver) {
|
||||||
|
ASSERT_TRUE(key_loaded_);
|
||||||
|
}
|
||||||
|
// If the key loaded with no error, then we will verify that it is not used
|
||||||
|
// for forbidden padding schemes.
|
||||||
|
if (key_loaded_) {
|
||||||
|
Session s;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_));
|
||||||
|
s.GenerateNonce();
|
||||||
|
|
||||||
|
size_t core_message_length = 100;
|
||||||
|
std::vector<uint8_t> message(128, 0);
|
||||||
|
std::vector<uint8_t> signature(256, 0);
|
||||||
|
size_t signature_length = signature.size();
|
||||||
|
|
||||||
|
OEMCryptoResult result = OEMCrypto_PrepAndSignLicenseRequest(
|
||||||
|
s.session_id(), message.data(), message.size(), &core_message_length,
|
||||||
|
signature.data(), &signature_length);
|
||||||
|
ASSERT_EQ(OEMCrypto_ERROR_INVALID_KEY, result);
|
||||||
|
const vector<uint8_t> zero(signature.size(), 0);
|
||||||
|
ASSERT_EQ(signature, zero); // Signature should not have been computed.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,36 +119,24 @@ TEST_F(OEMCryptoProv30Test, OEMCertValid) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert(kVerify)); // Load and verify.
|
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert(kVerify)); // Load and verify.
|
||||||
}
|
}
|
||||||
|
|
||||||
// This verifies that the OEM Certificate cannot be used for other RSA padding
|
/** This verifies that the OEM Certificate cannot be used with
|
||||||
// schemes. Those schemes should only be used by cast receiver certificates.
|
* GenerateRSASignature.
|
||||||
TEST_F(OEMCryptoProv30Test, OEMCertForbiddenPaddingScheme) {
|
*/
|
||||||
|
TEST_F(OEMCryptoProv30Test, OEMCertForbidGenerateRSASignature1) {
|
||||||
Session s;
|
Session s;
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert());
|
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert());
|
||||||
OEMCryptoResult sts;
|
DisallowForbiddenPadding(s.session_id(), kSign_PKCS1_Block1, 80);
|
||||||
// Sign a Message
|
}
|
||||||
vector<uint8_t> data(500);
|
|
||||||
GetRandBytes(data.data(), data.size());
|
|
||||||
size_t signature_length = 0;
|
|
||||||
// We need a size one vector to pass as a pointer.
|
|
||||||
vector<uint8_t> signature(1, 0);
|
|
||||||
vector<uint8_t> zero(1, 0);
|
|
||||||
|
|
||||||
sts = OEMCrypto_GenerateRSASignature(s.session_id(), data.data(), data.size(),
|
/** This verifies that the OEM Certificate cannot be used with
|
||||||
signature.data(), &signature_length,
|
* GenerateRSASignature.
|
||||||
kSign_PKCS1_Block1);
|
*/
|
||||||
if (OEMCrypto_ERROR_SHORT_BUFFER == sts) {
|
TEST_F(OEMCryptoProv30Test, OEMCertForbidGenerateRSASignature2) {
|
||||||
// The OEMCrypto could complain about buffer length first, so let's
|
Session s;
|
||||||
// resize and check if it's writing to the signature again.
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
signature.resize(signature_length, 0);
|
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert());
|
||||||
zero.resize(signature_length, 0);
|
DisallowForbiddenPadding(s.session_id(), kSign_RSASSA_PSS, 80);
|
||||||
sts = OEMCrypto_GenerateRSASignature(s.session_id(), data.data(),
|
|
||||||
data.size(), signature.data(),
|
|
||||||
&signature_length, kSign_PKCS1_Block1);
|
|
||||||
}
|
|
||||||
EXPECT_NE(OEMCrypto_SUCCESS, sts)
|
|
||||||
<< "OEM Cert Signed with forbidden kSign_PKCS1_Block1.";
|
|
||||||
ASSERT_EQ(zero, signature); // signature should not be computed.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calling OEMCrypto_GetOEMPublicCertificate should not change the session's
|
// Calling OEMCrypto_GetOEMPublicCertificate should not change the session's
|
||||||
@@ -186,6 +174,46 @@ TEST_F(OEMCryptoProv30Test, GetCertOnlyAPI16) {
|
|||||||
ASSERT_EQ(OEMCrypto_SUCCESS, license_messages.LoadResponse());
|
ASSERT_EQ(OEMCrypto_SUCCESS, license_messages.LoadResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** This verifies that the OEM Certificate cannot be used with
|
||||||
|
* GenerateRSASignature.
|
||||||
|
*/
|
||||||
|
TEST_F(OEMCryptoProv40Test, OEMCertForbidGenerateRSASignature1) {
|
||||||
|
// Create an OEM Cert and save it for later.
|
||||||
|
Session s1;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s1.open());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CreateProv4OEMKey(&s1));
|
||||||
|
ASSERT_EQ(s1.IsPublicKeySet(), true);
|
||||||
|
s1.close();
|
||||||
|
Session s2;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s2.open());
|
||||||
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
|
OEMCrypto_InstallOemPrivateKey(
|
||||||
|
s2.session_id(), oem_key_type_,
|
||||||
|
reinterpret_cast<const uint8_t*>(wrapped_oem_key_.data()),
|
||||||
|
wrapped_oem_key_.size()));
|
||||||
|
DisallowForbiddenPadding(s2.session_id(), kSign_PKCS1_Block1, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This verifies that the OEM Certificate cannot be used with
|
||||||
|
* GenerateRSASignature.
|
||||||
|
*/
|
||||||
|
TEST_F(OEMCryptoProv40Test, OEMCertForbidGenerateRSASignature2) {
|
||||||
|
// Create an OEM Cert and save it for later.
|
||||||
|
Session s1;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s1.open());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CreateProv4OEMKey(&s1));
|
||||||
|
ASSERT_EQ(s1.IsPublicKeySet(), true);
|
||||||
|
s1.close();
|
||||||
|
Session s2;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(s2.open());
|
||||||
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
|
OEMCrypto_InstallOemPrivateKey(
|
||||||
|
s2.session_id(), oem_key_type_,
|
||||||
|
reinterpret_cast<const uint8_t*>(wrapped_oem_key_.data()),
|
||||||
|
wrapped_oem_key_.size()));
|
||||||
|
DisallowForbiddenPadding(s2.session_id(), kSign_RSASSA_PSS, 80);
|
||||||
|
}
|
||||||
|
|
||||||
// This verifies that the device really does claim to have BCC.
|
// This verifies that the device really does claim to have BCC.
|
||||||
// It should be filtered out for devices that have a keybox or factory OEM
|
// It should be filtered out for devices that have a keybox or factory OEM
|
||||||
// cert.
|
// cert.
|
||||||
@@ -654,6 +682,16 @@ TEST_P(OEMCryptoProv40CastTest, ProvisionCastWorks) {
|
|||||||
INSTANTIATE_TEST_SUITE_P(Prov4CastProvisioningBasic, OEMCryptoProv40CastTest,
|
INSTANTIATE_TEST_SUITE_P(Prov4CastProvisioningBasic, OEMCryptoProv40CastTest,
|
||||||
testing::Values(true, false));
|
testing::Values(true, false));
|
||||||
|
|
||||||
|
// Verify that you cannot use GenerateRSASignature with a normal DRM Cert.
|
||||||
|
// that function needs a cast cert.
|
||||||
|
TEST_F(OEMCryptoLoadsCertificate, ForbidRSASignatureForDRMKey1) {
|
||||||
|
DisallowForbiddenPadding(session_.session_id(), kSign_RSASSA_PSS, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(OEMCryptoLoadsCertificate, ForbidRSASignatureForDRMKey2) {
|
||||||
|
DisallowForbiddenPadding(session_.session_id(), kSign_PKCS1_Block1, 80);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(OEMCryptoLoadsCertificate, PrepAndSignLicenseRequestCounterAPI18) {
|
TEST_F(OEMCryptoLoadsCertificate, PrepAndSignLicenseRequestCounterAPI18) {
|
||||||
// TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for
|
// TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for
|
||||||
// provisioning 4. Disabled here temporarily.
|
// provisioning 4. Disabled here temporarily.
|
||||||
|
|||||||
@@ -812,6 +812,7 @@ TEST_F(OEMCryptoLoadsCertificateAlternates,
|
|||||||
sts = OEMCrypto_GenerateRSASignature(s.session_id(), message_buffer.data(),
|
sts = OEMCrypto_GenerateRSASignature(s.session_id(), message_buffer.data(),
|
||||||
message_buffer.size(), nullptr,
|
message_buffer.size(), nullptr,
|
||||||
&signature_length, kSign_PKCS1_Block1);
|
&signature_length, kSign_PKCS1_Block1);
|
||||||
|
if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) return;
|
||||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||||
ASSERT_NE(static_cast<size_t>(0), signature_length);
|
ASSERT_NE(static_cast<size_t>(0), signature_length);
|
||||||
vector<uint8_t> signature(signature_length);
|
vector<uint8_t> signature(signature_length);
|
||||||
|
|||||||
Reference in New Issue
Block a user