Modules / oh_my_keymint

Oh My Keymint

Custom keystore implementation for Android Keystore Spoofer

README

Oh My Keymint

Custom keystore implementation for Android Keystore Spoofer

What is this?

This is a complete implementation of the keystore, which fully implements the AOSP AIDL interface, referencing the official AOSP implementation.

In theory, this would make it harder for detectors to identify behavior inconsistent with AOSP, thus achieving greater stealth than the FOSS branch of TrickyStore.

Install and configure

  1. Install this module.

  2. Configure (if you need)

Configuration file is located at /data/misc/keystore/omk/config.toml and /data/misc/keystore/omk/injector.toml

/data/misc/keystore/omk/config.toml

[main]
# We can only use Injector as backend at this point.
backend = "Injector"

# The following values ​​are used to generate the seed for device encryption 
# and verification. Please be sure to save the following values. If you lose
# them for some reason, please clear the module database (/data/misc/keystore/omk/data/)
# DO NOT MODIFY ANY VALUE BELOW IF YOU DO NOT UNDERSTAND WHAT ARE YOU DOING
[crypto]
root_kek_seed = "4b61c4b3bdf72bb700c351e020270846fb67ba3885e5fb67547e626af5cc1a7f"
kak_seed = "d6fa5bb024540928a7d554ab5831a0553dd2f688f5d6cb3cb1645be2ff49e357"

[trust]
os_version = 15
# Accepted values:
# - "auto": read and preserve the original build.prop patch level
# - "latest": use the 5th day of the current month
# - "YYYY-MM-DD": force an exact patch level
security_patch = "auto"
# `vb_key` accepts:
# - "auto": ro.boot.vbmeta.public_key_digest -> computed top-level vbmeta key digest -> random fallback
# - "random": generate a fresh 32-byte value for this boot and push it into ro.boot.vbmeta.public_key_digest
# - "<64 hex chars>": pin an exact 32-byte value
vb_key = "auto"

# `vb_hash` accepts:
# - "auto": ro.boot.vbmeta.digest -> original system attestation verifiedBootHash -> random fallback
# - "random": generate a fresh 32-byte value for this boot and push it into ro.boot.vbmeta.digest
# - "<64 hex chars>": pin an exact 32-byte value
vb_hash = "auto"

verified_boot_state = true
device_locked = true

[device]
brand = "Google"
device = "generic"
product = "generic"
manufacturer = "Google"
model = "generic"
serial = "ABC12345678ABC"
overrideTelephonyProperties = false
meid = ""
imei = ""
imei2 = ""

If config.toml becomes invalid, OMK rewrites a canonical default config, renames the broken file to config.toml.bak, and appends the parse error to the backup.

/data/misc/keystore/omk/injector.toml

# Only packages listed in `scoop` are intercepted.
# Optional per-package settings can be added under [scoop.<package>].
# Example:
# [scoop.io.github.vvb2060.keyattestation]
# mode = "strict"

scoop = [
  "io.github.vvb2060.keyattestation",
  "com.google.android.gsf",
  "com.google.android.gms",
  "com.android.vending",
  "com.eltavine.duckdetector",
]

[main]
enabled = true
log_level = "debug"

[filter]
enabled = true
deny_packages = []
block_android_package = true
allow_unknown_package = false

# Do not edit if you have no idea about the things below
[intercept]
get_security_level = true
get_key_entry = true
update_subcomponent = true
list_entries = true
delete_key = true
grant = true
ungrant = true
get_number_of_entries = true
list_entries_batched = true
get_supplementary_attestation_info = true

allow_unknown_package = true allows callers whose package name cannot be resolved to pass the filter instead of being rejected.

Restarting keymint and injector

The module ships two background daemons: one for keymint, one for injector. The recommended way to request a restart is through the restart system properties.

Restart only keymint:

resetprop persist.sys.omk.restart.keymint 1

Restart only injector:

resetprop persist.sys.omk.restart.injector 1

Restart both together:

resetprop persist.sys.omk.restart.all 1

If you switch [trust].vb_key or [trust].vb_hash from "random" back to "auto", restart alone is not enough. auto resolves ro.boot.vbmeta.* first, so the current boot keeps using the randomized sysprops until the device reboots and restores the original boot properties.

Changing [trust].security_patch does not require a restart by itself. OMK hot-applies the new value and rebuilds the active KeyMint wrappers in place.

The daemons also watch these marker files if you prefer the file-based path:

touch /data/adb/omk/restart.keymint
touch /data/adb/omk/restart.injector
touch /data/adb/omk/restart.all

License

YOU MUST AGREE TO BOTH OF THE LICENSE BEFORE USING THIS SOFTWARE.

AGPL-3.0-or-later

OhMyKeymint - Custom keymint implementation for Android Keystore Spoofer
Copyright (C) 2025 James Clef <qwq233@qwq2333.top>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

Oh My Keymint License

1. 您不得将本软件、本软件的任意部分或将本软件作为依赖的软件用于任何商业用途。该
   商业用途包括但不限于以盈利为目的,将本软件、本软件的任意部分或将本软件作为依
   赖的软件与其他资源、物品或服务捆绑销售。

2. 您不得暗示或明示本软件与其他软件有任何从属关系。

3. 未经本软件作者书面允许,您不得超出合理使用范围或协议许可范围使用本软件的名称。

4. 除非您所在的司法管辖区的适用法律另行规定,您同意将纠纷或争议提交至中国大陆境
   内有管辖权的人民法院管辖。

5. 本协议与GNU Affero General Public License(以下简称AGPL)共同发挥效力,
   当本协议内容与AGPL冲突时,应当优先应用本协议内容,本协议仅覆盖本软件作者拥有
   完全著作权的部分,对于使用其他协议的软件代码不发挥效力。

Credit

Some code from AOSP

License: Apache-2.0

Copyright 2022, The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Release History

1.2.0-67dc5e7

Published on June 16, 2026
Download

What's changed

This release is a routing and runtime hardening update for the injector-backed OMK path. Scoop-routed calls now treat a reachable OMK backend as the authoritative business path: OMKsuccesses and service-specific failures are returned to the app instead of being masked by a system reply. The system reply is preserved only for OMK-unavailable conditions such as amissing backend, RPC/connect failures, or DeadObject-like transport failures.

The injector path has been reworked around direct OMK-owned Binder routing. OMK-routed getSecurityLevel, getKeyEntry, and createOperation flows no longer depend on reusable systemkeystore carrier objects; the injector now synthesizes local security-level and operation binder targets inside keystore2 and serves their follow-up transactions through OMK. Grant andungrant are also decided before system grant row allocation: OMK grants surface OMK grant descriptors directly, and unknown-package grant readbacks are allowed only when OMK confirms thelive Domain::GRANT descriptor for the caller. Denylist and Android package rejection still remain authoritative. This might fixes some issues for TEE broken devices.

The injector backend now uses private rsbinder RPC instead of public service-manager services. When backend = "injector" is active, keymint serves OMK keystore, authorization, and maintenance services on /data/adb/omk/rpc.sock; the launcher waits for that socket and passes a preconnected fd into the injected payload. Forwarded RPC peers are restricted to local root or keystore, RPC caches are retried and cleared on DeadObject, and the diagnostics helper has been updated for the RPC transport.

Keystore state handling was tightened. Authorization and maintenance mirrors now keep separate dirty state and retry independently, with only successful mutating mirrors clearing the matching dirty flag. Auth-bound APP keys keep their original storage flags and require the CredentialEncrypted super key; OMK no longer weakens storage by retrying without cryptographic LSKF binding when CE is unavailable, so locked or uninitialized user state continues to surface LOCKED or UNINITIALIZED.

Android 12 and older now use the legacy key-attestation application-id provider for both AAID generation and injector package resolution, matching the platform surface on those releases. Android-version detection was shared across keymint and injector, KeyMint fallback profile selection was adjusted around the detected platform version, and the old IPackageManager AIDL dependency was removed.

Maintenance and packaging were also cleaned up. The standalone probe/tamper binaries and their tests were removed, while the remaining AOSP smoke test now covers an AES-GCM encrypt/decrypt round trip and the security-level diagnostic reports the RPC path. The injector binary now exports only entry instead of using --export-dynamic, and dependencies were updated, including rsbinder/rsbinder-aidl 0.9 with RPC support.

Attestation

Full Changelog: qwq233/OhMyKeymint@v1.1.1-ef38a44...v1.2.0-67dc5e7

Module Details

Module ID
oh_my_keymint
Authors
99
Stars
1
Releases

Latest Version

1.2.0-67dc5e7
Released 6/16/2026
Download Now