Devices, Security Levels & OEMCrypto
L1/L2/L3, OEMCrypto, provisioning models, device properties.
Why "security level" exists
Studios don't license premium UHD content to a device that can be unlocked with a software debugger. They want a guarantee that, even if the rich OS is compromised, content keys and decoded frames stay out of attacker reach. Widevine encodes that guarantee with three discrete security levels.
Widevine security levels
hover any cell for detail| Level | Key handling | Decoder location | Output protection | Typical content tier | Example devices |
|---|---|---|---|---|---|
| L1 | Inside TEE | TEE / Secure | HDCP-protected | Up to UHD/HDR | Pixel, set-top boxes |
| L2 | Inside TEE | Outside TEE | HDCP-aware | SD / HD typical | Some embedded devices |
| L3 | Software / no TEE | Software | Limited | SD only typically | Desktop browsers, ChromeOS w/o TEE |
Hover a cell to see the detailed explanation here.
The matrix is the canonical reference for this module — open it side-by-side while you study. Every studio-policy decision and every device-classification question reduces to "which row of this table is this device?"
L1 in detail
L1 is what you get on certified Android phones (Pixel, Galaxy flagship), Chromecast Ultra, certified Android TV / set-top boxes, and many smart TVs. It depends on:
- A TEE on the SoC (ARM TrustZone in most cases).
- A vendor-built OEMCrypto library that runs inside the TEE and implements the API Widevine specifies.
- A factory-installed device certificate that uniquely identifies this device to Google's provisioning service.
Lifecycle once provisioned: the rich-OS-side CDM library negotiates with the licence server, but every operation that touches a content key is delegated to OEMCrypto. Decryption, key derivation, and (on L1) decoding all happen inside the TEE. Even root on the rich OS cannot read a clear key.
L2
L2 is rarer in shipping products. It appears on some embedded SoCs that have a TEE for crypto but don't run the decoder inside it. Studios usually treat L2 as not sufficient for premium UHD because a memory-dumping attack against the decoder output can extract decoded video.
In practice, classifying a device as L2 vs L1 is a chip-vendor concern; integrators rarely need to write code paths specifically for L2.
L3
L3 is desktop browsers without a hardware-backed CDM, ChromeOS without TEE-backed keys, and older / generic Android devices. Most studios cap L3 at SD or 480p. UHD/HDR is never L3.
It still matters: lots of viewers are on L3 (every typical desktop). Your licence server must therefore be willing to issue an L3-policy licence (lower resolution, no HDCP requirement) when the request comes from an L3 device — usually inferred from the device's certificate properties.
OEMCrypto: the trusted root
OEMCrypto is the silicon-vendor library inside the TEE. Its API is specified by Widevine; chipset vendors port it to their TEE OS. Practical takeaways:
- It performs all key handling, decryption, and (on L1) drives the decoder.
- It's the reason L1 has hardware-rooted security: even root on the rich OS cannot reach across the TEE boundary.
- OEMCrypto versions matter — older versions may lack support for newer features (Provisioning 3.0, certain HDCP versions, specific encryption schemes). MediaDrm property strings expose the OEMCrypto version on Android.
Provisioning models
Provisioning is the one-time process that gives a device its Widevine identity. Without it, no licence server will issue a licence.
| Model | How identity arrives | Scope |
|---|---|---|
| L1 factory-provisioned | Burned in at chip / device manufacture | Per device |
| L3 dynamic provisioning | App calls into the CDM, which contacts Google's provisioning service over HTTPS to get a certificate | Per device install (legacy) or per origin / per app (Provisioning 3.0) |
| Provisioning 3.0 | Per-origin / per-app certificates instead of one-per-device | Isolates apps so a leaked token from one app doesn't compromise another |
Be ready to explain why per-origin / per-app provisioning matters. Short answer: leaks don't cross app boundaries, and revocation is finer-grained.
Device properties exposed via MediaDrm
On Android you can introspect the device through MediaDrm.getPropertyString / getPropertyByteArray:
MediaDrm drm = new MediaDrm(WIDEVINE_UUID);
String version = drm.getPropertyString("version");
String secLevel = drm.getPropertyString("securityLevel"); // "L1" or "L3"
String vendor = drm.getPropertyString("vendor");
byte[] deviceId = drm.getPropertyByteArray("deviceUniqueId");
drm.close();
These values feed into:
- Diagnostics ("why does L1 device X behave like L3?" → look at OEMCrypto version)
- Conditional UX ("don't offer 4K download to a device that returns L3")
- Server-side telemetry to spot fleets that are misbehaving
Putting policy + level together
The classic exam-style trap: an L1 device fails to play UHD. Why?
- It might not be L1 in this configuration (mirroring to a non-HDCP display flips the link to a lower effective level).
- The display might only negotiate HDCP 1.4 while the policy demands HDCP 2.2 for HDR.
- The OEMCrypto version may be too old for the requested encryption scheme.
The CDM, not the licence server, is the final enforcer. The server emits the policy in the licence; the CDM checks it at decryption time. If the runtime conditions don't satisfy the policy, the CDM refuses to decrypt — and the player typically downshifts to a lower-resolution track that is permitted.
A device being "L1" is not a global property — it's the level the CDM reports for the current session in the current configuration. Casting, mirroring, or attaching certain external displays can effectively downgrade the path.