Purism, the TPM and the FSF

Alright, I’ll come out and say it: I’m optimistic about the Purism / Librem project. The impending release of their first product is really exciting. Their goals are extremely ambitious (the hallmark of a worthwhile project) and despite having come up short of their stated goals and receiving some harsh though justified critique on the web, they’ve still produced a laptop that’s shipping soon. And so my optimism is holding out.

This is my first post on this topic and is mostly introductory: basically why I care about the project and the subject in general. My goal is to develop a series of posts discussing freedom and security (two things that I’m convinced are related) in the context of general purpose computing and the Purism Librem laptop. If you love freedom, free software and computer security, read on … if not, read on anyways.

Criticism from the Web

Not everyone is as impressed with Purism as I am, and the best articulation I’ve found is from Alexandru Gagniuc on the coreboot blog. The TL;DR is that people have been working in the free hardware space for a long time. The impression is that Purism showed up and claimed that they could do in 6 months what others have been working towards for years. Many have taken this as a sign that something is amiss. Those working in OSS see this sort of stuff all the time: someone shows up on your mailinglist with big plans, lots of enthusiasm … and then they figure out how much work it will take and you never hear from them again. I’m hopeful that, despite falling short of their initial goals, the folks at Purism stick around and continue to chip away at their stated goals.

Something that I find particularly troubling is the increasing rhetoric on the Purism website around “fighting for your freedom” all while hedging on past promises. The new video on their homepage with the young cartoon woman flying their flag and weeping cartoon tears for her lost freedoms has set my instinctive negative reaction to over-the-top marketing into high gear. Add to this some genuine and public concerns over the claims made by Purism and I’d say that they’ve got a bit of digging to do if they want to get out of this hole.

Lesson to learn: Grand or unrealistic claims about security, privacy-preserving and software freedom won’t go unnoticed or unchallenged when your target audience knows what’s up. Purism is catering to a niche market. Their target audience is extremely savvy about these things and they’re not going to be shy about “calling bullshit”. Skeptics are going to be skeptical, they’re going to demand proof. This is a good thing.

Continued Optimism

Despite all of this, I’m still optimistic about the project. Even better, the folks at Purism seem to be paying attention to their critics. They’ve published a road map detailing the steps necessary to reach their stated goal of FSF RYF (respects your freedom) certification. No doubt it’s going to be an uphill battle and the folks over at coreboot may be right: the entirety of the firmware may never be OSS. But having an OEM who actually wants to fight for the user will never be a bad thing so long as they don’t alienate their target audience in the process. In a time when OEMs are getting busted for integrating ad/spy-ware into their firmware we need a change.

The Future: Freedom and Security

This is probably going to get dangerously close to an attempt to predict the future, but I’m very hopeful for Purism and their products. I haven’t been following too closely but when I looked the other day, sure enough the specs for the Librem 15 list a TPM and it’s a version 2. Sweet. More on this in a future post.

Additionally, the FSF has endorsed CrowdSupply (the crowd funding platform used by Purism). I’m trying not to read too far into this but I can’t help but think that this represents an organized push from free software movement into hardware while adopting the pro-security-and-privacy rhetoric that’s become so relevant in the wake of the Snowden revelations.

I generally think of myself as a pragmatist when it comes to running purely open source software. This may just be a result of the need to load proprietary / binary firmware to get the wireless card on my laptop to function properly. It also could be related to my love of security technologies and the fact that the FSF has taken such a hard-line in their labeling of the TPM as malicious, a position I’ve always viewed as misinformed. I’m hopeful that the Purism project can help mend the rift between the free software movement and the security technologies that are essential to preserving our freedoms in an increasingly hostile computing environment.

This post was a sort of introduction, just some background about why I care about the Purism project. In my next post I’m hoping to get into why I think freedom and security have become so closely related. Stay tuned.

Nagasawa

My posts have been very sparse recently. Even less frequent have been posts on non-technical topics. To stay true to the title of my blog I’ve gotta step up my posts on “two-wheeled vehicles”. That or change the name. Changing the name would require digging through WordPress menus and since that’s my least favorite thing to do I ran out and got another bicycle so I could blog about it … and ride it.

Nagasawa makes a pretty serious track frame. More serious than me for sure but when I saw this thing on CraigsList I couldn’t resist. It was meant to be. Nearly everything on it is NJS and it’s in very good shape. A few chips in the paint here and there but nothing beyond standard wear. Even better, it’s the right size. You don’t find very many Japanese track bikes that fit someone over 6 feet tall.

The guy I bought it from had it set up for track riding. Since I’ll be riding it on the street I’m in the process of taming it a bit. First things first: get rid of the NJS track seat (aka the “ass-hatchet”). Then I’ll probably have to drop the gear ratio a bit. The wheels are super nice but they’re not beefy enough for every day street riding. I’ll have to start saving before I can get a new set.

Till my next post, enjoy the obligatory bike porn:
Nagasawa-headtubeNagasawa_front-rightNagasawa_right-rear

OXT and Paying Down Technical Debt

The few people out there who have slogged through the process of building OXT know how painful it is / can be. One of the most significant contributors to the difficulty here is the amount of technical debt that has built up in the build system over the years. We always “got it to work” when doing build stuff, but with the rate of change in the OE project / community we never kept pace with “doing it right”.

The reasons for this are many and every developer out there is familiar with the “ship it” pressures that tip the scales from “do it right” to “just make it work”. I won’t get into that here because it’s just the way things are now. What’s interesting and useful IMHO is coming up with a way to tip the scales back now that the pressures / incentives are different. So this post will cover some of my work to pay down some of the technical debt that I think is particularly important.

File Systems and Xattrs

One of the unique opportunities afforded us by the OE build system is the ability to produce complete file systems. When we do an install of OXT we don’t have to muck around in the file systems of any of the service VMs (including dom0) because they’re all ready to go straight from the build system. This means we can boot them read only from first boot. With a little bit of work, we could even do a measured launch from first boot complete with predictable measurements.

One of the hurdles we had to overcome was the need for xattr support in the file system creation code. Refusing to have a bunch of “first boot” code to put band aids on the shortcomings of our build system means that we had to come up with a way to create xattrs in the build and have them preserved through the creation of the service VM file systems. This is a problem that the usptream meta-selinux OE layer suffers from currently as anyone who’s built the core-image-selinux image will tell you. They have first boot code that detects the unlabeled file system, relabels it accordingly and then reboots. Only after this first reboot will the system come up with SELinux functioning properly.

Upstreaming xattrs into e2fsprogs

Having some common ground with an upstream like this seems like a good first step. Nothing like a shared problem / need to motivate work. For the OXT community getting this upstream will get us one step closer to being able to build service VMs for OXT (including our own) that don’t depend on a pile of old build metadata and an ancient version of bitbake.

The bits that need to go upstream are actually pretty small. We had to hack up a patch to Pseudo to get that to support xattrs but upstream Pseudo has already implemented this functionality and they did it right. When I saw that Pseudo had already implemented this I was relieved as it probably cut the amount of effort required in half. This left getting the actual disk image produced by the build to support xattrs.

gene3fs was the OXT tool that we used to get the build to spit out ext3 file systems. This is a departure from upstream where they have patches added to the e2fsprogs mke2fs utility. This work wasn’t mine but gene3fs looks like a fork of the unmaintained gene2fs project adding support for the ext3 file system, xattrs and VHDs. Even if this approach is technically superior to the usptream method it’s a moot point. Upstreaming is about longevity.

So ignoring the VHD stuff for now I’ve implemented a set of patches for OE that add xattr support to the build. With these patches in place we can apply SELinux labels to a root file system and boot the resulting image into enforcing mode without having to do first boot fixups. Stage one complete!

Getting patches merged

The hard part about sending stuff upstream is motivating maintainers to merge the patches. meta-selinux is pretty sparsely maintained unfortunately and 3 weeks after having sent my patches to the Yocto mailing list I haven’t had anyone test or even respond to the post. I’m not sure which is worst: being ignored or having someone tear apart the patches because they suck.

Trying to keep from being too persistent / obnoxious I’ve left these patches alone for a bit. Thankfully the e2fsprogs package is one of those critical pieces of the build system and so the maintainers seem to favor stability over frequent updates. This means the likelihood of having to rebase my patches is pretty low. If I don’t get some attention from the meta-selinux maintainers soon I’ll likely rebase them into the openembedded-core layer and send them there. I think the need for this functionality is less understood there but they’re much more active and likely to provide feedback (even if it’s “no thanks”).

Tracking work

We haven’t had a lot of upstreaming work done for OXT yet so there’s not really a process in place for tracking such efforts. As such I’ve created a place on the confluence wiki where I’ll track this stuff. The SELinux / xattr specific stuff is here: https://openxt.atlassian.net/wiki/display/~flihp/SELinux+file+system+labeling+in+build
I’ve set up a page describing the general process I’m following as well and that’s here: https://openxt.atlassian.net/wiki/display/~flihp/Upstreaming

If anyone else is working on sending functionality upstream regardless of where feel free to work off these pages. Once we’ve got a few examples to work from we may decide to formalize the process but for now I’m just trying to pay down some technical debt and make some progress both for OXT and one of the usptreams we share common goals (and hopefully code) with.

PGP links

I wish PGP was easier to use. When it comes to having to invoke gpg directly I usually spend some time with the man page and that’s enough. But when it comes to the more detailed stuff like setting algorithm preference or identities I always fall back to the collective internet knowledge. I think I’ve looked up the following links a few times now and I’m leaving them here for reference:

https://wiki.debian.org/Subkeys
https://www.debian-administration.org/users/dkg/weblog/48
http://blog.infertux.com/2013/11/03/how-to-remove-an-email-address-from-a-gpg-key/

HP Elitebook 820 G1 laptop dock script

Upgraded my laptop from an ancient HP 2760p so it’s time to write a new script to handle plug / unplug events from the docking station. Wait, what? Write a new script? Haven’t I done this before? Sure, I wrotea docking script for my Thinkpad x61s, but that was 6 years ago. No way that script still works … no wait it does!

Minor tweaks to sort out some differences between the udev events for the thinkpad / elitebook and changes to the xrandr command for my current monitor setup and it’s good to go!

The thinkpad had better integration with the kernel ‘dock’ driver so it generated different events for ‘dock’ and ‘undock’ events. For the EliteBook I had to trigger on the DRM kernel subsystem getting a ‘change’ event on ‘card0’. Not sure what that means but it’s consistent for plug / unplug. To determine whether the ‘change’ is docked or undocked I’m parsing xrandr output to see which monitor is present where. It’s not as nice but by parsing the output of xrandr it’s pretty simple. So the udev rule looks like this:

SUBSYSTEM=="drm", KERNEL=="card0", ACTION=="change", RUN+="/usr/local/bin/dock.sh"

And the script I’m now using for dock/undocking my EliteBook 820 G1 on Debian 8.0 is here.

Thanks for doing me a solid past me. Well done.

on-break

awesome battery widget

I spent a few hours last night customizing the awesome window manager (wm) on my new laptop install. I’ve been using awesome for a while now (years) but I haven’t done much by way of customizing my setup. The default config from Debian, with a few small tweeks to default tags and layouts, has been sufficient. But having a battery gauge on my laptop is pretty important so I carved out a few minutes to set this up.

As always I’m not the first person to have this problem. Luckily those that came before me put their work up on github so all I had to do was clone awesome-batteryinfo, copy battery.lua into my ~/.config/awesome directory and integrate the battery widget into my rc.lua.

Integrating this widget is pretty painless. There are four steps: First you have lua pull in battery.lua:

require("battery")

Second you instantiate the widget:

mybatterywidget = widget({type = "textbox", name = "batterywidget", align = "right" })

Third you place the widget in a wibox. Debian has a wibox positioned across the top of each screen. I took the batterywidget created above and added it to the wibox widget list along side the layoutbox, textclock etc. My final mywibox.widgets looks like this:

mywibox[s].widgets = {
    {
        mylauncher,
        mytaglist[s],
        mypromptbox[s],
        layout = awful.widget.layout.horizontal.leftright
    },
    mylayoutbox[s],
    mytextclock,
    batterywidget,
    s == 1 and mysystray or nil,
    mytasklist[s],
    layout = awful.widget.layout.horizontal.rightleft
}

Finally I set up a timed event to update the widget every 20 seconds. I also seeded the widget text to show the battery data at the time the widget is created. This means that the widget will come up with meaningful data before the first even fires (20 seconds after init):

-- seed the battery widget: don't wait for first timer
mybatterywidget.text = batteryInfo("BAT0")
-- timer to update battery widget
mybatterywidget_timer = timer({timeout = 20})
mybatterywidget_timer:add_signal("timeout", function()
    mybatterywidget.text = batteryInfo("BAT0")
end)
mybatterywidget_timer:start()

That’s all there is to it. Thanks to koenwtje for the great widget. I should probably collect my awesome configs into a git repo so I don’t have to go back and rediscover how to do this every time I build a new system …

Cleaning up my TPM hack

A few weeks back I posted some stuff about hacking up an Asus TPM daughter card to hook it up to a PCEngines APU system. That was the first I’ve soldered in pretty much forever. It was ugly. Seriously ugly. But it worked. Still, we can do better.

Desoldering

In my first pass at this I left the pins in the board after cutting off the connector. To hook up the new connector I just soldered the wires directly to the existing pins. The right way to do this is to desolder the existing pins, pull them out, and run the new wires into the holes left by the old pins.

After discovering what a solder pump is this isn’t the impossible task I thought it was. There were two pins that wouldn’t budge though. These two were hooked up to the ground plate on the card so when I applied heat the whole card absorbed it. Since I didn’t need these pins I just left them alone. This is what the card looks like with the pins desoldered:

IMG_20150303_152024

IMG_20150303_152006

New Wiring

Now we just add some new wires following the mapping from the last post. Business as usual. I did up ground in the same way running it directly to the plate on the daughter card. The sanding job I did this time was much better since I used real sand paper. Actually I picked up a few of those nail files at the grocery store and they worked out great.

IMG_20150308_184619

Last time I ran all the wires over the top and they piled up something awful. This time I ran the problematic ones under the card to keep things clean. I’m pretty happy with the end result.

IMG_20150309_195408

IMG_20150309_195358

Programming the DS1077L Oscillator

My last post documented my first bit of hardware hacking in probably 10 years. I had hoped to have a full post for a related bit of work ready for posting by now but, to stick with our theme, this stuff is hard so I’ve had to break it down into more than one post. Hopefully this won’t be too much of a spoiler but my current project requires a 33MHz oscillator. Here’s a bit of data about the programmable once I picked up along with a few tools I wrote to program it from Linux.

DS1077L Oscillator

Fixed frequency crystal oscillators are pretty easy to buy, but if you’re prototyping on a breadboard these are a bit of a PITA to hook up. As an alternative, there are surfance mount programmable oscillators available and the DS1077L from Maxim seems to be the most popular in the “maker” community. Sparkfun sells these pre-packaged on breakout boards so if you just just want to buy something and start using it this is the route to go.

I ordered the parts individually so I could practice my soldering but the end result is the same. Take a few DS1077L+66s from Mouser Electronics along with a few 8-pin SparkFun SOIC to DIP Adapters, solder them together and then plug them into your breadboard. The only difference is that the breakout board from Sparkfun comes with a filter capacitor so we’ll have to supply our own. This oscillator is programmable via the I2C bus so to program the oscillator to the frequency we need we need to wire it up to the I2C bus on a Linux system. In the end the circuit looks something like this.

IMG_20150307_115107

Top quality CAD drawing for you there. If you’re interested in the details of how this chip works the spec sheet is your friend. The values for the pull up resistors on the I2C lines and the bypass capacitor are specifically defined there. My purposes are simple in that I just need a 33MHz clock so the CTRL pins can be ignored, as can the reference output OUT0. OUT1 will output the clock and SCL/SDA are the two I2C clock and data pins. Initially the DS1077L+66 is programmed to output a 66MHz clock so we’ll need to program the chip to cut this in half.

Programming the DS1077L

The first step in this process is wiring the circuit and attaching it to the I2C bus on a Linux system. I soldered an I2C header on to my PCEngines ALIX3d2 and hooked it up like so:

IMG_20150225_200211

This chip is pretty sophisticated so I won’t cover all possible configurations. The data sheet is readily available here so if you want the details have a read (you should anyways if you’re using this chip). All I’m going to cover here is scaling down the clock frequency and the tool I’ve written to do so.

The primary output (OUT1) has two mechanisms for controlling its output. First is a prescaler circuit that can divide the native frequency (66MHz) by 1, 2, 4 or 8. The second is a divider circuit that can divide the frequency by integers between 2 and 1025. The divider circuit can be bypassed completely if we wish so we can get a 33MHz clock in two ways: 1) set the prescaler to 2 and bypass the divider or 2) set the prescalar to 1 and the divider to 2. The DS1077L defines a low power state where much of it’s internal circuitry is disabled including the divider so I opted for this low power state and the first option above.

To aid in programming this thing I’ve put together a small set of tools I’m calling ds1077l-ctrl. These tools expose a simple command interface for modifying the state of the control registers in the DS1077l. As an example we would program this chip to output the 33MHz clock that I need like so:

$ ./ds1077l-mux --bus-dev=/dev/i2c-0 --set --pdn0=0 --sel0=0 --en0=0 --div=1 --p1=2

That’s it. The –help / –usage messages for the tools combined with data from the spec sheet should be all that you need to set the DS1077L to any possible state. In the command above we’ve set (–set) the DS1077L device on I2C bus 0 (–bus-dev=/dev/i2c-0) such that the divider is disabled (–div=1), the prescalar to 2 (–p1=2). The other options (–pdn0=0 –sel0=0 –en0=0) set the oscillator to a low power state disabling the circuitry we’re not using.

To get a sort of before and after I hooked up this chip to an oscilloscope to capture the default 66MHz waveform and the 33MHz one we get after executing the command above:

IMG_20150225_200236
IMG_20150225_193909

Bugs

This software is not without bugs (as always). I couldn’t get the WRITEE2 command to work properly but it’s only necessary if you change the default behavior of the chip and set the WC bit to 1. This causes the oscillator to write register state to EEPROM only when the WRITEE2 command is invoked. By default it will save the register state every time it changes so just leave the WC bit alone and everything should work as expected. Alternatively feel free to fix this bug and send me a pull request.

Attaching a TPM on the LPC

Just for the funs I recently revived some older work with my PCEngines alix3d2 where I built an OE meta layer with a simple machine and kernel config to build images: meta-alix.

IMG_20150213_151432

IMG_20150216_183119

IMG_20150216_183320

TPMs for all the boards!

I’ve got a soft spot for the older PCEngines WRAP board since it was the first platform I experimented on while building a home router / access point years ago. So meta-alix was fun work but nothing too crazy. While playing around with this I noticed that the alix3d2 has an exposed 20 pin header labeled ‘LPC’. Now that is interesting because I’ve got a few Asus branded Infineon TPMs laying about and they’ve got LPC connectors on them. A home wireless router with a TPM on it? Now that could be interesting.

Attaching an TPM designed to attach to a board on a 20 pin LPC connector should be pretty easy right? That’s what I thought too. But here we are 2 weeks later and I’m just now getting to write this up and I can’t say this work was 100% successful. But before I go too deep into the trials and tribulations let’s start with a bill of materials.

Bill of materials

To start out you’ll need a TPM and one designed to attach to your system on the LPC bus. TPMs are a PITA to buy really. There are 3 main companies that manufacture them but you can’t buy them direct. Thankfully there are some motherboard manufacturers out there that support the TPM via a “daughter-card” and from my experience this is mostly the high end manufacturers like Asus and Supermicro. I had 2 Asus TPMs laying around so this seemed like a good opportunity to put them to use. On Amazon these TPMs go for about $15 but when I bought mine almost a year ago they were less than half that.

The system that started out trying to attach this thing to is an alix3d2. I also picked up one of the newer PCEngines APU but *spoiler alert* only after I had serious problems getting the alix to work.

You’ll also need a soldering iron and the usual soldering / prototyping gear on hand (lights, wire, solder, magnifying glass etc). That’s right I said soldering. It’s been a while for me too. Like 10 years. Don’t worry there isn’t much too this and it was really fun.

Prototyping

As you’ve likely guessed by now, just because a system has an LPC connector doesn’t mean this thing is plug and play. The Asus TPM daughter card has pin 4 blocked / keyed and the ALIX doesn’t so that’s our first hint. The real data is in the respective pin diagrams. Finding these isn’t as easy as I’d hoped so I had to do some digging.

The docs for the ALIX systems are all on the PCEngines website so that part’s easy. The Asus TPM doesn’t seem to have any docs though. If you take the time to dig into the boards that support them though you’ll find the manuals for these boards have the pin assignment documented. I pulled down the manual for the P9D-WS and used this as a reference. Page 2-29 has what we’re looking for.

Pin Layouts

With the pin layouts in hand we can see clearly that plugging the TPM daughter card directly into the board isn’t gonna happen. I’ll reproduce the layouts here so we can view them side by side:

Asus TPM PCEngines LPC
pin signal signal
1 PCICLK PCICLK</td
2 GND GND
3 FRAME LAD0
4 BLOCKED GND
5 PCIRST# LAD1
6 NC GND
7 LAD3 LAD2
8 LAD2 GND
9 +3V LAD3
10 LAD1 GND
11 LAD0 LFRAME#
12 GND GND
13 NC PCIRST#
14 NC CLK48A
15 +3VSB ISP
16 SERIRQ Vcc (+5V)
17 GND GND
18 CLKRUN V3
19 PWRDWN SERIRQ
20 NC LDRQ#

There’s basically no overlap in the pin layouts here except for a few ground connections. This blew my mind at first but after searching through the Intel Low Pin Count Interface Specification it turns out that this bus was intended for use on-board only and so there’s no pin layout specified for external connectors. First mystery solved. Now let’s figure out how we’re gonna wire this thing up.

To the breadboard!

This isn’t going to be as easy as “plug and play” but it’s not far off. We just need to connect the right pins. With the pin map above and a little help from the spec (to get the minimum required connections) we can pull out our breadboard and prototype this thing.

If you’re like me you’ll have to go out and buy materials as you need them. Luckily I live minutes away from HSC Electronic Supply which is an amazing surplus electronic shop. After an hour or 3 poking around the piles of old electronic gear I managed to scrounge up a 20 pin ribbon cable with a connector that looked like it might fit on my breadboard. With a 20 pin DIP ribbon cable connector I had what I needed to connect the alix to the breadboard.

Next was to get the TPM daughter card wired up to the breadboard. This was harder than I expected. I couldn’t easily find a connector that would suit this purpose that didn’t require waiting for shipping. So I soldered some wires up to breakaway headers and rigged up a horrible TPM-to-breadboard connector. Then we just hook up the two using the following mapping:

TPM ALIX Signal
1 1 PCICLK / LCLK: 33MHz clock
3 11 LFRAME#: Transaction signal
5 13 LRESET#: Bus reset. AKA PCIRST#
7 9 LAD3: Data lane
8 7 LAD2: Data lane
9 & 15 18 3 Volts DC
10 5 LAD1: Data lane
11 3 LAD0: Data lane</td
16 19 SERIRQ: Serialized interrupt signal

After some fiddling (kicking, screaming and burning myself with a soldering iron) this is what it looked like:

IMG_20150213_093921

IMG_20150212_175548
Now it SHOULD have worked. These are the right connections. But on the alix3d2 I got no love. I didn’t actually get this set-up to work till my apu1d showed up in the mail 3 days later. For whatever reason the external LPC on the alix3d2 just doesn’t work as advertised. Without an oscilloscope I can’t debug much beyond whether the voltage and ground pins are OK (and they are) so for now that will remain a mystery. So the alix3d2 is out and the apu1d is in.

Anyways we can do better than this bootleg breadboard setup. Let’s see about cleaning it up.

IMG_20150213_093453

IMG_20150213_093638

Clean it up

The wiring above was super flaky and that shouldn’t be a surprise. I didn’t get the length of each wire exact and the pins slipped around a bit in the plastic. I ordered some IDC breakout helpers from Adafruit but they were garbage. They plug into the breadboard fine but the pins aren’t long enough and they just pop back out immediately.

So again I hacked up another connector out of DIP/DIL headers and some breakaway headers spaced to span the gap in the breadboard. This is generally a bad idea since the solder is what’s holding the whole thing together but it worked out pretty OK:

IMG_20150213_151417

IMG_20150216_183250

IMG_20150214_134235

Packaging for the APU enclosure

After convincing ourselves that the wiring above is right on the breadboard we need to clean this up so that it fits in the enclosure with the APU. There’s not a lot of space in the PCEngines recommended case1d2 but there’s enough if we’re sufficiently inventive. And by “inventive” I mean “you’ve got a hacksaw”.

Start out by removing the female header from the TPM and trim back the connector pins. If we flip this header on it’s side we can use it to mount the TPM once we reconnect it. This would require either unblocking pin 4 on the connector or cutting pin 4 off of the APU board. Since pin 4 on the APU is ground anyways this shouldn’t be a problem.

I used a 20 pin DIP to ribbon cable connector for my setup. I sanded down the daughter board to expose the copper on the base which happens to be ground and connected this with the even pins on the connector up through 12. This proved to be a pretty solid base as it holds the daughter board nice and tight to the connector.

Then we just cut wires and solder pins per the table above. The wire I had on hand was 28 gauge which was a bit too big and the soldering job is straight up ugly in spots but it’s the first bit of soldering I’ve done in 10 years so that’s good enough for me. I’ve got another TPM on hand so I’ll have another go now that I’ve had some practice.

Testing

I used both a Debian install with the tpm-tools package to test this as well as the core-image-tpm from meta-measured. I’d recommend sticking with Debian unless you feel like falling down the rabbit hole of an OE build. The important thing to keep in mind is that the APU BIOS doesn’t support the TPM so it won’t do the necessary setup for us.

The BIOS is supposed to do a number of things to set things up so that the OS can use the TPM. This includes running the TPM self test, enabling it and setting up ACPI entries to make it easy for the OS to talk to it. With the stock BIOS on the APU we won’t get any of this. Thankfully the number of platforms that have implemented TPM support wrong in the BIOS over the years is quite high so the Linux TPM TIS driver can do all of this for us if we give it the right parameters:

root@apu:~# modprobe tpm_tis force=1
[   74.027383] tpm_tis tpm_tis: 1.2 TPM (device-id 0xB, rev-id 16)
[   74.063388] tpm_tis tpm_tis: Issuing TPM_STARTUP
[   74.260392] tpm_tis tpm_tis: TPM is disabled/deactivated (0x7)
[   74.308465] genirq: Flags mismatch irq 4. 00000080 (tpm0) vs. 00000000 (serial)
[   74.315956] tpm_tis tpm_tis: Unable to request irq: 4 for probe
[   74.436459] genirq: Flags mismatch irq 8. 00000080 (tpm0) vs. 00000000 (rtc0)
[   74.443753] tpm_tis tpm_tis: Unable to request irq: 8 for probe

The modinfo command will tell you all of the gory details about what these parameters do if you’re interested. The short version is that force=1 causes the driver to ignore ACPI and probe for the TPM device. You can also add the interrupts=0 argument to disables interrupts which will get rid of all of the genirq errors. After this you should see /dev/tpm0 appear magically. You can then start tcsd and get some version info out of the TPM:

root@apu:~# tpm_version 
  TPM 1.2 Version Info:
  Chip Version:        1.2.3.19
  Spec Level:          2
  Errata Revision:     2
  TPM Vendor ID:       IFX
  Vendor Specific data: 0313000b 00
  TPM Version:         01010000
  Manufacturer Info:   49465800

You won’t be able to do much more than this though since the BIOS hasn’t enabled the TPM for us. We’ll get past this in my next post.

TXT and tboot on the IVB NUC

I wrote a few days back about getting serial output from tboot on my new-ish Ivy Bridge vPro NUC. This was a means to and end and so this is where we’ll cover actually using this serial hardware to do something meaningful.

tboot log from the DC53427HYE NUC

Testing TXT and tboot on a new system is often painful. If there’s something wrong and tboot can’t execute SENTER successfully the system just reboots and will continually. This confuses the hell out of most and necessitates either serial hardware to capture log output for trouble shooting, or a patch to bypass this reboot logic.

The bit about the patch is interesting and I’ve hacked one out here. I hacked this together without much thought about the security implications as a work-around so I don’t recommend it for production use. It was only intended as a way to bring up a system with a borked TXT implementation so data could be collected with txt-stat.

Regardless of how you go about getting your tboot output it’s your first step in debugging. Here’s the tboot log captured from my DC53427HYE NUC. You can see the automated reboot after SENTER fails.

Debugging my tboot failure

I’ve jacked up the logging level of tboot so there’s a lot of data go dig through in the log. Generally though the data we need is in the TXT.ERRORCODE. Don’t forget though that on the first boot this value will be 0x0 since it’s only set once the failure occurs. The interested reader can, well, read all about this register in the MLE developers guide section B.1.3.

So after the failed boot the TXT.ERRORCODE gets set and we can grab it from the log. The relevant line is:

TBOOT: TXT.ERRORCODE: 0xc0021041

Not a particularly helpful error message but then again, there isn’t much space for a helpful textual description of the error in a 32bit register. So the next step is to decode this thing.

Decoding the TXT.ERRORCODE

The MLE developers guide describes the general structure of the data in this register but the error code itself is specific to the ACM used by the platform. Again this data is in the tboot log file:

TBOOT: checking if module /acm_hsw.bin is an SINIT for this platform...
TBOOT: chipset production fused: 1
TBOOT: chipset ids: vendor: 0x8086, device: 0xb001, revision: 0x1
TBOOT: processor family/model/stepping: 0x306a9
TBOOT: platform id: 0x10000000000000
TBOOT:   1 ACM chipset id entries:
TBOOT:       vendor: 0x8086, device: 0xb002, flags: 0x1, revision: 0x1, extended: 0x0
TBOOT:   chipset id mismatch
TBOOT: checking if module /acm_ivb.bin is an SINIT for this platform...
TBOOT:   1 ACM chipset id entries:
TBOOT:       vendor: 0x8086, device: 0xb001, flags: 0x1, revision: 0x1, extended: 0x0
TBOOT:   4 ACM processor id entries:
TBOOT:       fms: 0x206a0, fms_mask: 0xfff3ff0, platform_id: 0x10000000000000, platform_mask: 0x1c000000000000
TBOOT:       fms: 0x206a0, fms_mask: 0xfff3ff0, platform_id: 0x4000000000000, platform_mask: 0x1c000000000000
TBOOT:       fms: 0x306a0, fms_mask: 0xfff3ff0, platform_id: 0x10000000000000, platform_mask: 0x1c000000000000
TBOOT: SINIT matches platform

You can see on line 1 that tboot is trying the HSW / Haswell ACM which doesn’t match the platform. Then on line 9 it gives the IVB / Ivy Bridge a try and that one matches the platform. So our error code is specific to the IVB ACM so we’ll have to dig through the docs from that tarball. If you’ve built meta-measured the appropriate PDF will be located at:

${TOPDIR}/tmp-glibc/work/corei7-64-oe-linux/3rd-gen-i5-i7-sinit/67-r0/3rd_gen_i5_i7-SINIT_67/SINIT_Errors.pdf.

But before we can make use of this we’ve gotta parse out the error code into its component parts. From this doc they’re defined as (from MSB to LSB):

  • bit 31 – Valid
  • bit 30 – External
  • bits 29:25 – Reserved
  • bits 24:16 – Minor Error Code
  • bit 15 – SW Source
  • bits 14:10 – Major Error Code
  • bits 9:4 – Class Code
  • bits 3:0 – Module Type

So we need to divide the error code 0xc0021041 on these boundaries and then go back to the docs to figure out what each field means:

Valid: 0x1 - The error code is valid.
External: 0x1 - Error state induced by external software.
Reserved: 0x0 - No significance. 
Minor Error Code: 0x2 - Fatal and TPM specific.
SW Source: 0x0 - Generated by the ACM.
Major Error Code: 0x4 - TPM NV is unlocked.
Class Code: 0x4 - TPM Access
Module Type: 0x1 - SINIT Module

Going through each of these takes a while so we’ll focus on the important stuff: The Major error code. Actually the error text says it all: The TPM NV RAM is unlocked and it shouldn’t be. With the TPM in this state tboot also complains in the boot log, see line 3 below from the log linked above:

TBOOT: TPM: TPM Family 0x0
TBOOT: TPM is ready
TBOOT: TPM nv_locked: FALSE
TBOOT: TPM timeout values: A: 750, B: 750, C: 750, D: 750

So there’s the problem. Now what’s the solution?

Unlocked TPM NVRAM

The TPM NVRAM is described in the relevant TCG TPM 1.2 spec, section 19: “NV Storage Structures”. The parts relevant to us is 19.1.1 where the required TPM_NV_INDEX values are described. These are the NV indexes that “must be found on each TPM regardless of platform”.

The first index listed in this section is TPM_NV_INDEX_LOCK and given the error code we’re getting that looks relevant. A bit of reading and you’ll see why having this index defined on a TPM is so important and why shipping a platform with it undefined is considered a security issue. Turns out that without this index defined the TPM doesn’t enforce authorization protections. In this state an attacker can write to the NVRAM repeatedly, wear it out (since NVRAM can be written to a finite number of times) and effectively DOS the TPM completely by making the NVRAM unusable. Very surprising that Intel is shipping the NUC in this state. Anyways, nothing we can’t fix …

At this point I went back in to the NUC and used tpm_nvindex to dump the NVRAM indexes defined on my platform:

NVRAM index   : 0x10000001 (268435457)
PCR read  selection:
 Localities   : ALL
PCR write selection:
 Localities   : ALL
Permissions   : 0x00001002 (WRITEALL|OWNERWRITE)
bReadSTClear  : FALSE
bWriteSTClear : FALSE
bWriteDefine  : FALSE
Size          : 20 (0x14)

NVRAM index   : 0x1000f000 (268496896)
PCR read  selection:
 Localities   : ALL
PCR write selection:
 Localities   : ALL
Permissions   : 0x00020002 (OWNERREAD|OWNERWRITE)
bReadSTClear  : FALSE
bWriteSTClear : FALSE
bWriteDefine  : FALSE
Size          : 1129 (0x469)

NVRAM index   : 0x50010000 (1342242816)
PCR read  selection:
 Localities   : ALL
PCR write selection:
 Localities   : ALL
Permissions   : 0x00000001 (PPWRITE)
bReadSTClear  : FALSE
bWriteSTClear : FALSE
bWriteDefine  : FALSE
Size          : 10 (0xa)

NVRAM index   : 0x50000003 (1342177283)
PCR read  selection:
 Localities   : ALL
PCR write selection:
 Localities   : 0x18
Permissions   : 0x00000000 ()
bReadSTClear  : FALSE
bWriteSTClear : FALSE
bWriteDefine  : FALSE
Size          : 64 (0x40)

NVRAM index   : 0x50000001 (1342177281)
PCR read  selection:
 Localities   : ALL
PCR write selection:
 Localities   : ALL
Permissions   : 0x00002000 (WRITEDEFINE)
bReadSTClear  : FALSE
bWriteSTClear : FALSE
bWriteDefine  : FALSE
Size          : 54 (0x36)

I was hoping that the TPM_NV_INDEX_LOCK (defined in index 0xffffffff) would be missing and that defining it would solve my problem. From the output above you can see that it’s not listed. The only relevant data I could find on the web about defining this index was a post on the tboot devel list with somone trying to use the tpmj utility. Digging into all of that java seemed like way too much work so I gave the tpm_nvdefine utility a go:

root@intel-core-i7-64:~# tpm_nvdefine --index=0xffffffff --size=0
Successfully created NVRAM area at index 0xffffffff (4294967295).

Success! I had hoped then that executing tpm_nvindex again would show this new index … but it doesn’t. So other than the “success” message from tpm_nvdefine we have no way of knowing whether or not the new index was actually defined. The easiest way to test this is to try booting with tboot again and hope that the error goes away. And it does:

TBOOT: TPM: TPM Family 0x0
TBOOT: TPM is ready
TBOOT: TPM nv_locked: TRUE
TBOOT: TPM timeout values: A: 750, B: 750, C: 750, D: 750

Conclusion

So that’s how you define the TPM_NV_INDEX_LOCK TPM index on your IVB NUC. This effectively locks the TPM NVRAM on a platform that ships with the the TPM NVRAM unlocked. Until now I had only seen this on Lenovo systems (lots of them) but I guess Intel is shipping platforms like this too. Having some automated way to detect and fix platforms in this state would be really nice …