aboutsummaryrefslogtreecommitdiff
path: root/source/storage/KeyManager.mc
diff options
context:
space:
mode:
Diffstat (limited to 'source/storage/KeyManager.mc')
-rw-r--r--source/storage/KeyManager.mc24
1 files changed, 24 insertions, 0 deletions
diff --git a/source/storage/KeyManager.mc b/source/storage/KeyManager.mc
index ebb0a62..567288f 100644
--- a/source/storage/KeyManager.mc
+++ b/source/storage/KeyManager.mc
@@ -33,6 +33,9 @@ class KeyManager {
private var _store as Persist.Backend;
private var _deviceKeys as SealedBox.Keys? = null;
+ private var _fingerprintKey as ByteArray? = null;
+
+ static const FINGERPRINT_BYTES = 8;
function initialize(store as Persist.Backend) {
_store = store;
@@ -55,11 +58,32 @@ class KeyManager {
_store.setValue(DEVICE_KEY, raw);
}
keys = new SealedBox.Keys(raw);
+ _fingerprintKey = Kdf.hkdf(raw, []b, Bytes.fromUtf8("OTPW fp v1"), KEY_BYTES);
Bytes.wipe(raw);
_deviceKeys = keys;
return keys;
}
+ // An 8-byte keyed fingerprint of an entry's kind, type and secret (or
+ // payload): equal for duplicates, meaningless without the device key.
+ // Stored in the readable header so imports can find duplicates of locked
+ // entries while the watch is locked (docs/SECURITY.md).
+ function fingerprint(entry as Entry) as ByteArray {
+ deviceKeys();
+ var input = Bytes.fromUtf8("OTPW-FP-1");
+ input.add(entry.kind);
+ input.add(entry.type);
+ var material = entry.kind == Entry.KIND_OTP ? entry.secret : entry.payload;
+ if (material != null) {
+ input.addAll(material);
+ }
+ var mac = Hmac.nativeSha256(_fingerprintKey as ByteArray, input);
+ Bytes.wipe(input);
+ var out = mac.slice(0, FINGERPRINT_BYTES);
+ Bytes.wipe(mac);
+ return out;
+ }
+
// True when a PIN has been set.
function hasPin() as Boolean {
return _store.getValue(WRAP_KEY) != null;