Debugging Keymaster Key Characteristics Verification in OP-TEE

The test PerInstance/SigningOperationsTest.RsaGetKeyCharacteristicsRequiresCorrectAppIdAppData/0_default is failing with multiple assertion errors. The test expects specific behavior when retrieving key characteristics with incorrect application IDs and application data, but the actual implementation returns unexpected results.

Key failures include:

  • The function returns OK instead of the expected INVALID_KEY_BLOB error
  • The key characteristics contain 11 hardware-enforced and 1 software-enforced parameters when empty parameters are expected

Test Code Implementation

The test verifies that GetCharacteristics properly validates client identity and application data. The implementation checks four scenarios:

  1. Call with valid parameters (should succeed)
  2. Call with empty client ID (should fail with INVALID_KEY_BLOB)
  3. Call with empty application data (should fail with INVALID_KEY_BLOB)
  4. Call with both empty client ID and application data (should fail with INVALID_KEY_BLOB)

Serialization-Deserialization Mismatch

Investigation reveals a mismatch between the client-side serialization and Trusted Application (TA) deserialization processes:

Client-Side Serialization

The client first serializes a keymaster_key_blob_t structure, followed by an AuthorizationSet:

uint8_t* GetKeyCharacteristicsRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
    buf = serialize_key_blob(key_blob, buf, end);
    return additional_params.Serialize(buf, end);
}

TA-Side Deserialization

The TA deserializes the request in a different order, first extracting the key blob, then client ID, and finally application data:

in += TA_deserialize_key_blob_akms(in, in_end, &key_blob, &res);
if (res != KM_ERROR_OK)
    goto exit;
in += TA_deserialize_blob_akms(in, in_end, &client_id, false, &res, false);
if (res != KM_ERROR_OK)
    goto exit;
in += TA_deserialize_blob_akms(in, in_end, &app_data, false, &res, false);
if (res != KM_ERROR_OK)
    goto exit;

Permission Check Logic Issue

After fixing the serialization-deserialization mismatch, another issue was found in the permission checking logic. The TEE_MemCompare function returns:

  • 0 if buffers are identical
  • A positive value if the first differing byte is higher in buffer1
  • A negative value if the first differing byte is higher in buffer2

The original implementation incorrectly handled the comparison result:

client_id_same = TEE_MemCompare(client_id.data,
        params->params[i].key_param.blob.data,
        client_id.data_length);

The client_id_same variable was declared as a boolean but was assigned the integer result of TEE_MemCompare, leading to incorrect logic flow.

Corrected Implementation

The fix properly converts the comparison result to a boolean value and adjusts the condition checks:

client_id_same = (TEE_MemCompare(client_id.data,
        params->params[i].key_param.blob.data,
        client_id.data_length) == 0);

app_data_same = (TEE_MemCompare(app_data.data,
        params->params[i].key_param.blob.data,
        app_data.data_length) == 0);

if ((app_data_checked && !app_data_same) ||
       (client_id_checked && !client_id_same)) {
    EMSG("Invalid client id or app data!");
    return KM_ERROR_INVALID_KEY_BLOB;
}

Test Results

After implementing both fixes, the test now passes successfully, confirming that the key characteristics verification properly handles invalid application IDs and application data.

Tags: OP-TEE keymaster TEE Security cryptography

Posted on Tue, 16 Jun 2026 17:30:47 +0000 by basdog22