Certificate generation

Minting Samsung certs, on the box

A Samsung TV only sideloads an app whose distributor signature enrolls that TV's DUID. That certificate used to mean a hand-run trip through Tizen Studio's Certificate Manager. Now Screenwhere gets it straight from Samsung's CA — you just sign in once.

Operator Cloud relay Site box (RPi) Samsung Browser · web app "Vygenerovat certifikát" /app/cert-token in-memory · 1-use token-helper.py localhost:4794 /app/app-cert-generate super-only · audited appcertgen.mjs keys · CSR · .p12 Samsung CA svdca…/apis/v3 encrypted cert store appsign.mjs 1 · poll → token 2 · deposit 3 · Generate 4 · ws 5 · CSR store 0 · sign in

Numbered on the diagram: 0 the operator runs a tiny helper that opens the Samsung sign-in and catches the returned token on localhost:4794; 1–2 the helper deposits the token to the relay under a one-time code the web app is already polling for; 3 the operator clicks Generate; 4 the relay forwards it to the set's box; 5 the box builds a signing request, posts it to Samsung's CA, and stores the returned certificate. From there the existing sign + install flows just work. The token never touches disk; the private keys never leave the box.

Why it exists

A Tizen TV checks one thing before it installs a .wgt: is this TV's DUID listed in the distributor certificate that signed it? That certificate comes from Samsung's online CA. Certificate Manager isn't doing anything special to get it — it just POSTs a signing request to a Samsung endpoint, and the DUIDs ride inside the request the client builds. So if we build the request (with the TV's DUIDs) and post it ourselves, the CA returns the same certificate. The only step that truly needs a person is a one-time Samsung account sign-in.

The pieces, and how they cooperate

token-helper.py

Runs on the operator's machine. Opens the Samsung sign-in and catches the token on localhost:4794 — the only redirect Samsung will accept — then hands it to the relay. The one unavoidable human touch.

/app/cert-token

A code-gated, single-use, in-memory handoff. The helper deposits the token under a 128-bit code the web app minted; the app polls to pick it up. Nothing is persisted.

Web panel

The Instalace tab's "Vygenerovat certifikát": shows the helper command, waits for the token, lets you pick a privilege level and the TV DUIDs (auto-read over sdb), then calls Generate.

/app/app-cert-generate

Super-only, audited relay route. Validates the request and forwards it to the set's box over the agent WebSocket, correlated by request id — exactly like the existing sign/install calls.

appcertgen.mjs

The generator. RSA keys, a CSR with the DUIDs in subjectAltName, a multipart POST to Samsung's CA, then a .p12 assembled with the matching Samsung VD CA chain.

Encrypted store

Generated certs land in the same AES-256-GCM store an uploaded cert would, keyed by the box-only APP_CERT_KEY. The sign + install flows use them unchanged.

Privilege levels

A distributor certificate is issued at a level, and can only sign apps whose privileges fit within it — Public (the default), Partner (Samsung partner privileges like productinfo), or Platform. We learned this on the TV: re-signing a partner-level app with a Public cert fails to install (118012); the Partner cert installs and launches. So the panel lets you pick the level, and each maps to its matching CA chain in the assembled .p12.

Where the secrets live

  • The Samsung token is in memory only — relay Map, single-use, 15-minute TTL; used in-flight on the box, then discarded. Never written to disk or any log.
  • Private keys are generated on the box and stored encrypted at rest; they never leave it. The relay only forwards.
  • Generation is super-only and audited (app.cert.generate records the privilege, DUID count, and CNs — never the token).
  • Fail-closed: without APP_CERT_KEY the plane is disabled rather than storing keys in the clear.

Undocumented endpoint. We call the same Samsung CA endpoint Tizen Studio uses (svdca.samsungqbe.com), extracted from the shipping plugin and proven live. The community does this routinely, but it's a grey area — it's the operator's own account issuing their own dev certs, and the host is configurable so a move is a config change, not a code change.

The full technical reference — every field, the reverse-engineering log, and the tests — is in docs/CERT-GENERATION.md and docs/TIZEN-INSTALL-PLAN.md. See also the architecture.