Re-registers a factory-provisioned key into Android Keystore2 at boot time

Below is a mock C++ code snippet for a custom KeyMint or Keymaster HAL implementation that re-registers a factory-provisioned key into Android Keystore2 at boot time.

This is useful when:

  • A key was pre-provisioned at the factory into QSFS/SPU
  • Its Android-side metadata was deleted (e.g., /data/misc/keystore/)
  • You want to rebind it to an alias and make it available again to apps

🛠️ 🔧 Mock HAL Code: Re-register Pre-Provisioned Key

📁 File: KeymasterDevice.cpp
📦 Layer: Android KeyMint HAL or vendor Keymaster HAL
⚙️ Context: Called during boot or HAL initialize() function

cppCopyEdit#include <keymaster/key_blob.h>
#include <keymaster/key_store.h>
#include <keymaster/logger.h>
#include <keymint_support/authorization_set.h>

// Assumes existence of device-specific SPU API
#include "provisioned_key_loader.h"  // Your internal OEM API

namespace vendor {
namespace mycompany {
namespace keymaster {

bool reRegisterFactoryProvisionedKey(const std::string& alias) {
    LOG_I("🔁 Re-registering factory key: %s", alias.c_str());

    // 1. Load the key from secure storage (QSFS/SPU)
    SecureKeyBlob spu_blob;
    if (!loadKeyFromSpu("provisioned_key_id_001", &spu_blob)) {
        LOG_E("❌ Failed to load key from SPU");
        return false;
    }

    // 2. Define key characteristics (match what was provisioned)
    AuthorizationSet auths;
    auths.push_back(TAG_ALGORITHM, Algorithm::RSA);
    auths.push_back(TAG_PURPOSE, KeyPurpose::SIGN | KeyPurpose::VERIFY);
    auths.push_back(TAG_KEY_SIZE, 2048);
    auths.push_back(TAG_ORIGIN, KeyOrigin::PROVISIONED);
    auths.push_back(TAG_ROLLBACK_RESISTANT);
    auths.push_back(TAG_NO_AUTH_REQUIRED);
    auths.push_back(TAG_ALIAS, alias);  // Set target alias for Keystore

    // 3. Wrap into Android-compatible KeyBlob
    KeyBlob wrapped_blob;
    if (!wrapKey(spu_blob, auths, &wrapped_blob)) {
        LOG_E("❌ Key wrapping failed");
        return false;
    }

    // 4. Register with Keystore2 (via service or internal DB)
    if (!registerKeyWithKeystore2(alias, wrapped_blob, auths)) {
        LOG_E("❌ Failed to register alias with Keystore2");
        return false;
    }

    LOG_I("✅ Key '%s' successfully re-registered", alias.c_str());
    return true;
}

}  // namespace keymaster
}  // namespace mycompany
}  // namespace vendor

🧠 Key Components Explained

StepWhat It Does
loadKeyFromSpu()Vendor-specific function to load a key from QSFS/SPU based on internal ID
AuthorizationSetDefines the key’s capabilities and constraints
wrapKey()Prepares a KeyBlob structure (optional signing or encryption)
registerKeyWithKeystore2()Inserts alias and blob into Keystore2’s key table (e.g., /data/misc/keystore2/) or via HAL callback

📦 Optional: Use Keystore2 Binder Interface to Register

If your HAL is separate from Keystore2 service, use Android’s binder service to push the key:

cppCopyEditsp<IKeystoreService> ks = getKeystoreService();
ks->importKey(
    /* alias */ "shared_key",
    /* blob  */ wrapped_blob,
    /* metadata */ auths,
    /* uid  */ AID_SYSTEM
);

✅ What This Achieves

✅ Outcome✅ Benefit
Rebinds factory key → usable aliasAvoids complete key regeneration
Recovers deleted metadataEnables post-reset secure boot logic
Centralizes key reuse policyEnables sharing across system components (attestation, secure logging, etc.)

flowchart of the re-registration flow (HAL → TEE → Keystore2)

Here’s a mock init.rc trigger that automatically runs a key re-registration routine during early device boot, typically used in OEM firmware or custom AOSP builds.

This integrates your C++ re-registration logic (from the HAL) into the Android boot process via init.rc.


📦 📁 File: init.keyrestore.rc

rcCopyEdit# init.keyrestore.rc

on early-boot
    # Start the service that re-registers factory-provisioned keys
    start keyrestore

service keyrestore /vendor/bin/keyrestore_daemon
    class main
    user system
    group system
    oneshot
    seclabel u:r:system_server:s0
    disabled
    oneshot

⚙️ How It Works

PartExplanation
on early-bootTriggered before Zygote, when HALs and KeyMint are being initialized
service keyrestoreLaunches a binary (/vendor/bin/keyrestore_daemon) that contains your HAL-based key re-registration logic
class mainEnsures it runs in the main boot class
oneshotEnsures it runs only once on boot
seclabelEnsures proper SELinux domain (e.g., system_server or hal_keymaster)

🛠️ What /vendor/bin/keyrestore_daemon Does

This binary:

  • Links to your KeymasterDevice.cpp logic
  • Calls reRegisterFactoryProvisionedKey("alias")
  • Logs to logcat or dmesg on success/failure
  • Optionally signals system services that key is ready

✅ AOSP Integration

To integrate this into your AOSP or OEM firmware:

  1. 📁 Place this RC file in: php-templateCopyEditdevice/<vendor>/<product>/init.keyrestore.rc
  2. 📜 Add it to your BoardConfig: makeCopyEditPRODUCT_COPY_FILES += \ device/<vendor>/<product>/init.keyrestore.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.keyrestore.rc
  3. 🔗 Ensure /vendor/bin/keyrestore_daemon is part of your PRODUCT_PACKAGES

🧠 Summary

GoalAction
Auto re-register keys on boot✅ Trigger HAL logic from init.rc
Boot timing✅ Runs before apps need access
Permissions✅ Controlled by SELinux & UID
Custom ROM support✅ Fully compatible with AOSP builds

Would you like:

  • A template for the keyrestore_daemon.cpp binary?
  • An SELinux policy rule for this service?
  • A combined AOSP patch (RC + daemon + HAL code)?

Let me know how you’d like to continue.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top