Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60275359 authored by David Zeuthen's avatar David Zeuthen
Browse files

Identity Credential: Restrict AccessControlProfile identifiers to 32.

In order to implement Identity Credential on resource-restricted
secure hardware, we need to limit the number of possible
AccessControlProfile in a credential. A limit of 32 means that such
hardware only need to devote four bytes of RAM for a bitmask with
information about which profiles are authorized.

Document this, add new VTS test, and update the default
implementation.

Bug: 155100967
Test: atest android.security.identity.cts
Test: atest VtsHalIdentityTargetTest
Merged-In: Ia4f2ee0013b330561df744e0595f298a0d156122
Change-Id: I2dd672447bedfa9407bf1044e6261af26fd137f9
parent d2115c98
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -140,7 +140,8 @@ interface IWritableIdentityCredential {
     * with STATUS_INVALID_DATA.
     *
     * @param id a numeric identifier that must be unique within the context of a Credential and may
     *     be used to reference the profile. If this is not satisfied the call fails with
     *     be used to reference the profile. This id must be non-negative and less than 32 (allowing
     *     for a total of 32 profiles). If this is not satisfied the call fails with
     *     STATUS_INVALID_DATA.
     *
     * @param readerCertificate if non-empty, specifies a single X.509 certificate (not a chain of
+6 −0
Original line number Diff line number Diff line
@@ -143,6 +143,12 @@ ndk::ScopedAStatus WritableIdentityCredential::addAccessControlProfile(
    }
    accessControlProfileIds_.insert(id);

    if (id < 0 || id >= 32) {
        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                IIdentityCredentialStore::STATUS_INVALID_DATA,
                "Access Control Profile id must be non-negative and less than 32"));
    }

    // Spec requires if |userAuthenticationRequired| is false, then |timeoutMillis| must also
    // be zero.
    if (!userAuthenticationRequired && timeoutMillis != 0) {
+34 −0
Original line number Diff line number Diff line
@@ -641,6 +641,40 @@ TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
    EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
}

TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
    sp<IWritableIdentityCredential> writableCredential;
    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));

    const vector<int32_t> entryCounts = {1};
    Status result = writableCredential->startPersonalization(1, entryCounts);
    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                               << endl;

    SecureAccessControlProfile profile;

    // This should fail because the id is >= 32
    result = writableCredential->addAccessControlProfile(32,     // id
                                                         {},     // readerCertificate
                                                         false,  // userAuthenticationRequired
                                                         0,      // timeoutMillis
                                                         42,     // secureUserId
                                                         &profile);
    ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
    ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
    ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());

    // This should fail because the id is < 0
    result = writableCredential->addAccessControlProfile(-1,     // id
                                                         {},     // readerCertificate
                                                         false,  // userAuthenticationRequired
                                                         0,      // timeoutMillis
                                                         42,     // secureUserId
                                                         &profile);
    ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
    ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
    ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
}

INSTANTIATE_TEST_SUITE_P(
        Identity, IdentityCredentialTests,
        testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),