<feed xmlns='http://www.w3.org/2005/Atom'>
<title>otpGarmin/source/util/Jobs.mc, branch main</title>
<subtitle>OTP Wallet for Garmin Connect IQ: offline one-time passwords and barcodes.</subtitle>
<id>https://git.cirakg.xyz/otpGarmin/atom?h=main</id>
<link rel='self' href='https://git.cirakg.xyz/otpGarmin/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/otpGarmin/'/>
<updated>2026-10-27T00:01:18+00:00</updated>
<entry>
<title>fix(pin): the work after a PIN and the change queue run in steps</title>
<updated>2026-10-27T00:01:18+00:00</updated>
<author>
<name>cirakg</name>
<email>cirakg@cirakg.xyz</email>
</author>
<published>2026-10-27T00:01:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/otpGarmin/commit/?id=bc4cc19df5f53519ca1aabd3cf161b6d78ffc16c'/>
<id>urn:sha1:bc4cc19df5f53519ca1aabd3cf161b6d78ffc16c</id>
<content type='text'>
After a correct or new PIN, promoting pending entries and applying waiting
"Require PIN" changes ran in the event of the last PBKDF2 step; 16 waiting
changes tripped the watchdog on the Forerunner 70. ChangeQueue.LockJob now
does it in steps while the PIN screen shows "Checking...", saves what it did
to the results and refreshes the glance after Set PIN too.

The list title decrypted every waiting change at each start. Queue items
are now [action, box] (aad OTPW-Q-2 + action code), so they are counted
without decrypting; 0.9.0 items are still read. A replacement is checked
when it arrives and its material is sealed apart (qm.&lt;n&gt;). Large buffers
are wiped and UTF-8-checked in pieces (Jobs.Wiper, Bytes.utf8Prefix,
SealedBox.openKeep/sealKeep). "Phone changes" reads behind "Reading...",
and Confirm all / Reject all act only on the changes shown. Storage full
no longer stops the app at the PIN.

Found by the review of b8addc8/096b5a4 and a new make watchdog test; the
diff was reviewed again and its findings fixed. fr70: make lint, make test
(176), make watchdog (19 cases at two steps per event), make screenshots
pass; list_locked and list_reset goldens show "Results ready (menu)".

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix(codes): bound every 2D encoding step under the watchdog; draw large codes from runs</title>
<updated>2026-10-21T01:55:01+00:00</updated>
<author>
<name>cirakg</name>
<email>cirakg@cirakg.xyz</email>
</author>
<published>2026-10-21T01:55:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/otpGarmin/commit/?id=88f1cac4fa530fc30fd6ef01970af11c7a959b8e'/>
<id>urn:sha1:88f1cac4fa530fc30fd6ef01970af11c7a959b8e</id>
<content type='text'>
M6's step sizes were estimates, only exercised with small codes. With the
largest inputs the app accepts, every 2D encoder tripped the watchdog on
the Forerunner 255S (and the biggest steps were far over the 768 KB
watches' limit), so a large code added from the phone would have stopped
the app during settings processing at every start.

- QR: resumable segmentation, Reed-Solomon, interleaving, function
  patterns and final mask; mask scoring on rows and columns packed 16
  modules per word (same penalties, checked against the per-module rules).
- Reed-Solomon: resumable field tables and generator, encoder shifting
  with native slice.
- Data Matrix, Aztec, PDF417: resumable encodation, stuffing, compaction,
  placement and build; Data Matrix's grid as a byte array (90 KB -&gt; 35 KB);
  PDF417 refuses text that can't fit the screen before compacting.
- Cache format 2 with 16-bit sizes (wide PDF417 was cached wrong); packing
  in steps; codes drawn as runs, and from a bitmap painted in steps when a
  frame can't draw all runs.
- The job runner does two steps per tick on 768 KB watches;
  gen_products --check verifies each product's watchdogCount fits that.
- CodeView renews full brightness (AMOLED) or the backlight (MIP) for up to
  a minute from its single ticker; a tap restarts the minute.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(crypto): add SHA-512, HMAC, PBKDF2, HKDF, AES-256 records and self-test</title>
<updated>2026-10-18T21:44:18+00:00</updated>
<author>
<name>cirakg</name>
<email>cirakg@cirakg.xyz</email>
</author>
<published>2026-10-18T21:44:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/otpGarmin/commit/?id=e47ae684101981a7c20f3270994a61944059c825'/>
<id>urn:sha1:e47ae684101981a7c20f3270994a61944059c825</id>
<content type='text'>
- Sha512: FIPS 180-4 in Monkey C (no native SHA-512), rotations inlined
  with precomputed masks; constants derived from the primes, not typed.
- Hmac: RFC 2104 over SHA-1/256/512 (native HMAC only supports SHA-256).
- Kdf: resumable PBKDF2-HMAC-SHA256 job with calibration bounds
  (2,000-200,000 iterations) and HKDF-SHA256.
- Aes: CBC with PKCS#7 over the native cipher; AES-256 chosen.
- SealedBox: encrypt-then-MAC records (HKDF-split keys, length-prefixed
  aad, constant-time tag check before decryption).
- SelfTest: known-answer tests for every primitive at start-up.
- Bytes (wipe, constant-time equal), Clock (2038-safe widening, trusted
  clock), Jobs (bounded steps against the watchdog, timer runner).

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
