Clarity 1.0 went out on 18 August without a kernel driver of its own. On any machine where Windows blocks WinRing0 (the explainer has the background), CPU temperature just read "no signal". A week later we shipped 1.1.5 with a driver we'd written ourselves, and on Intel machines the number came back.
What we tried first
Nobody wants to write a kernel driver, so we tried everything that doesn't need one.
Intel's Power Gadget library reads package temperature, but only on machines where someone has installed Power Gadget first. Windows' own thermal zones need nothing installed. The catch is that on most consumer boards they're measuring somewhere around the chipset. On that route we only accepted a zone with the CPU in its name, so a board without one got nothing, which is still better than a chipset reading with "CPU" written next to it. WMI reads the same zones and wants administrator rights on top.
Running the readings from a Windows service as SYSTEM didn't help either. Windows refuses a blocked driver no matter which account asks for it.
We did look at borrowing another tool's driver. But the ones that could read the temperature register are on the same blocklist as WinRing0, and for the same reason: they'll read or write pretty much anything a program asks them to.
Why we wrote our own
What we wanted was a driver whose whole job was written down before Microsoft signed it. Ours checks every request against a list compiled into it: the processor registers it may read, and the ports on the motherboard's sensor chip. If it isn't on the list, it's refused. Nothing can be loaded into it afterwards either, so the only way to change what it does is to change the source, and a changed driver goes back to Microsoft before anyone gets it.
That costs us a round with Microsoft every time we change it. The quickest came back the same day. The slowest took five days.
Getting it signed
On current Windows a new kernel driver has to carry Microsoft's signature, and Microsoft will only sign for a company that holds an Extended Validation code-signing certificate. So before any of the code mattered, there was paperwork: registering Hancock Technologies in Switzerland, getting a D-U-N-S number, and then the certificate itself, issued on 15 June. It lives on a hardware key. If that key isn't plugged in and the PIN typed, nothing of ours gets signed.
We went the attestation route. You submit the driver with your own signature on it, Microsoft reviews it, and they add theirs. It's the quicker of Microsoft's two routes and, yes, the lighter review. The other one, WHQL, puts the driver through Microsoft's hardware test kit and takes weeks longer.
The first version only read temperature. It went in on 21 August, sat at "Processing" and never came out of it, so we resubmitted the same day and that one went through. The version that shipped in 1.1.5 on 25 August also reads the sensor chip, and that took three more rounds in the four days in between.
What the driver can touch
On Intel it reads the processor's temperature sensors, its temperature limit, and the energy counters that package power is worked out from. On AMD it has read die temperature and package power since 1.1.10. From 1.1.34 it also reads each core's clock and voltage on both. On the motherboard it reads the sensor chip, so fan speeds, board temperatures and voltages. To read that chip you first have to tell it which register you want, and that's technically a write, so the driver lets those selections through.
The driver in 1.1.34 can also change one thing, and that's fan speed. It's there for Control's fan control, which isn't on sale yet. On Clarity, Aikonic never asks it to. And if Aikonic's sensor service stops while it's driving a fan, the driver hands that fan straight back to the motherboard.
There are things it can't do in any build. Nothing in its source writes a processor register, and it can't map physical memory. The only PCI access it has is the one fixed path AMD's temperature read needs.
Windows only lets administrators and the SYSTEM account open it, so a normal program can't talk to it at all. Could a program running as administrator use it to change a fan's speed? From 1.1.34, yes. The driver keeps the fan above a minimum, and the board takes it back when that program closes. We accepted that, because an administrator can already load a driver of their own.
When it refuses a read, Clarity shows that value as unavailable and tells you why. If a reading came from a fallback sensor instead, a board zone say, it gets a ~ and the reason next to it.
The WinRing0 we kept loading
On 27 August we were wiping a laptop for an unrelated test and found WinRing0 on it. Registered as a kernel service, and running. Aikonic 1.1.7 had put it there.
The sensor library we build on, LibreHardwareMonitor, carries WinRing0 inside it and installs it when it starts up. We'd pointed every one of the library's reads at our own driver, but never removed the bit that installs WinRing0. Every build up to 1.1.7 did it wherever Windows allowed, and on our test machines, with memory integrity off, Windows did. It also stayed behind after an uninstall.
Nobody noticed, because nothing looked wrong. On Intel our driver was doing all the reading, so the values were identical either way. On AMD the old drivers were still supplying die temperature, which just looked like everything working. And our checks only looked at the installer, where WinRing0 doesn't exist until the library unpacks it at run time.
Taking it out had its own trap. The library only goes looking for the motherboard's sensor chip if WinRing0 has loaded, so the first build without it lost every fan, board temperature and voltage on our AMD test machine: 66 sensors down to 42, and no error anywhere. Once we changed that check as well, the next run matched the WinRing0 run sensor for sensor.
1.1.8 went out the same day. The library actually carries two third-party drivers, WinRing0 and a smaller one called inpoutx64, and both are deleted from our copy of it, so they can't ship by accident. Our build checks fail if WinRing0 ever comes back. On first run, 1.1.8 removes the WinRing0 service and file that an earlier version left behind.
It still took two goes. On Gigabyte boards and AMD Ryzen systems, versions up to 1.1.6 had installed inpoutx64 and set it to start with Windows, and nothing ever removed it, so it kept loading on every boot with nothing using it. 1.1.12 removes it, once, as long as it's the copy that library installed and nothing else on the machine is using it.
1.1.8 also brought in a bug we didn't fix for a month. The service asked our driver for every core's temperature without saying which core, so the driver read core 0 every time. 1.1.12 fixed it on 25 September.
Losing WinRing0 cost us some readings for a while, too. AMD machines fell back to Windows' thermal zone, marked low confidence, until 1.1.10 started reading them through our driver. Per-core clocks had come through WinRing0 as well, and our driver couldn't read them, so from 1.1.10 each core's clock reads "no reading" until the driver in 1.1.34 adds them back. They show up once that driver is running, which is straight after the update, or after a restart if Windows won't let go of the old one.
Checking it yourself
The driver is AikonicMsrDriver.sys, in
C:\Program Files\Aikonic\aikonic-sensor-service\drivers.
Open its Properties, go to the Digital Signatures tab, and you'll
see two signatures: Hancock Technologies, and Microsoft Windows
Hardware Compatibility Publisher. That second one is Microsoft's
attestation.
To see which kernel drivers Aikonic has registered, run this in PowerShell:
Get-CimInstance Win32_SystemDriver | Where-Object PathName -match 'Aikonic' | Select-Object Name, State
You should get one line back, AikonicMsrDriver. If
there's also a name starting with R0, that's WinRing0
left behind by a build before 1.1.8, and starting any current
version will remove it. Uninstalling removes the driver too, from
1.1.34 on.
The driver's threat model goes a lot further than this page, into detail we'd rather keep off the website. If you're a security reviewer or press, ask for it at [email protected].