 Hi, hello everyone. Welcome to my talk on TPM NV storage and EA policies with TSS FAPI. Let's start real quick with who am I. I work for Fraunhofer. I'm working on cyberphysical system security and automotive security and specifically on trustworthy platforms. And I've been a consumer of TPMs for more than 13 years now. I've been a TCG member almost as long and I'm there the workgroup chair of the TSS workgroup. And also in the open source realm, I'm the maintainer or one of the maintainers of the TPM to TSS project, which is an implementation of the TPM software stack compliant with the TCG specs of the TPM to TSS engine, the open source engine and TPM to TODP even though thankfully Jonas is doing most of the work there. What we're going to talk about today. I'll very briefly go over what TPMs are. And then we'll go a little bit deeper about what TPM NV storage is and can do what TPM EA policies are and what you can do with those. How you can facilitate the TSS, especially the FAPI interface for working with EA policies and NV and some minor use cases at the end to show you some of its usefulness and practical applications. So let's get started. What is a TPM? So TPM is a security chip on the main board. And you can see an old example of that over here. And I have to thank Microsoft for giving us all TPMs for cheap in our desktops and laptops because they required them via the Windows logo program. But also there's been increased adoption nowadays and embedded. There exists hats for the Raspberry Pi. I've seen some people working on Sapphire. There's also been some people working on SPI interfaces for TSS for ESP32s or implementation, similar stuff. So these chips are pretty high security. They come with usually they come with come criteria certificates and such. And they are capable of doing some cryptographic operations. They can do some storage that we're going to do today. And most famously they are capable of recording boot hash values, aka integrity measurements. What's very important is to know that they are passive devices. So the TPM cannot actively interfere and take away ownership of your platform, any of that sort. And nowadays they are very nicely supported on Linux. First of all, given their driver support but also all the way up through the TSS stack and then the various projects that build upon the TSS stack. So what's it known for? It's specifically known for what we see here on the left-hand side, which is it can do crypto. It has an RSA engine, ECC engine, SHA-1, SHA-256 engines. And it can do some AES even though the AES functions are not exposed externally, but they are used internally for storing its keys. So keys are in the case of the TPM usually stored outside of the chip, but encrypted via an AES key that is only known to the TPM. Second most well-known functionality is, as I mentioned, the integrity functionalities of the TPM. So the TPM will record the boot measurements or the measurements or the hash values of the various components that are used to imbue the platform and store those in these PCRs and then you can do a code command. But that's not what we are going to talk about today. Today our focus is on the right-hand side. The, first of all, the NV capabilities of the TPM. So it can consistently store keys, but it also exposes general purpose NV indices. And we'll be looking at the enhanced authorization policies or as I will usually refer to them EA policies, as you heard in the beginning of the talk already. All right, let's jump right in there. Storage. So the TPM comes with a bunch of storage or not not so big of a bunch of storage but with some storage. And it's often used synonymously with the NV indices, but we have to differentiate so the TPM has an internal flash. The flash is used to store internal TPM data structures such as its seeds, auto values, boot counters, and other kinds of things. But also the TPM exposes an interface to the user to use some of those some of that storage. And that's called or referred to as NV indices or NV index handles. Yeah, those are exposed to an API of the TPM. And you can identify those by their index range. So every TPM hand, every TPM object has a handle. And in case of an NV index, those start with zero X on the very high bite, as opposed to, for example, transient objects that start with an 80x or persistent objects that start with an 81 hex. And this value range is fixed, the zero X 01. But within this range, there are some value ranges and conventions defined by TCG. So within the range of 01 C zero, and a bunch of zeros to 01 C zero seven f f f, you will, for example, find or endorsement key certificates. The range that we're most interested in for our application is the range from zero X 01 80 to zero X 01 BF and f f f f. This is the range that's defined for the owner of the platform. So whenever you want to do something you whenever their software, you want to write that users and we storage, you'll probably want to put your handles or your NV indices to find those in this range. And I guess a very prominent example of something that's using or going to be using the TPM NV storage also in this range is crypt setup. There is a merge request. So we've been working for some time on how to integrate TPM into crypt setup. So we have a bit locker like feature on Linux as well. And the new crypt setup TPM tokens as they are defined in the mentioned pull request actually make use of this NV storage. So in order to look at what your NV storage is there's two ways you can use TPM to get capabilities or get cap and just see the NV index ranges. And here you can already see that there are specifically two user indexes that I defined, which are in the 80 00 and 80 01. Then there is two certificates in 01 CO range. And then there's another three those come from platform. Those are used for BIOS, PC BIOS things. So just that you don't wonder when you have fresh TPM, you will usually find the five bottom NV indexes on your platform already. So the way to look at those is via the TSS to get info call. And I'll go a little bit into what the differences between those two calls is later but there you can see unfortunately we don't have the hex representation because JSON, but we do have the integer value there as well. So what can any storage do well first of all, there's different types, or you you basically what you do is you define and the indexes that you want to use so you allocate memory to say so, under an index. When you do this allocation you can make a choice of what type this NV index shall be. There is the ordinary type, which is general purpose memory, you can write arbitrary data in there and you can read the data out again. But then there's also special kinds of NV indexes. And very interesting one, for example, is the counter type. The counter type is a monotonic counter. And one, when you initialize this NV index, it starts at the highest counter value that was ever recorded on this TPM. So if you clear the counter, or you could you delete the index and you re instantiate the index again will start off at the same counter value that you had on the index before. So in order to prevent rollback attacks on those and the counter indices because usually they might be used for something like usage counting or version counting or firmware stuff like that. And of course you can only ever increment this counter you cannot arbitrarily write to this counter. Then we have bit mask types. They allow you to set bits in this NV index but not clear them. So this is basically, yeah, similar to fuses you can use them in the same way as you use fuses in, for example, SOCs. Then we have the extents type extents types are similar to PCRs. You can just write to them but instead, when you want to do a right or a right equivalent operation what the TPM will do is it will take the old content of this index. It will append the data that you want to put in there will hash this together and then the hash of this is stored in this. And basically what you get is you get a hash chain of every data that you ever wrote into this index, which can be kind of nice to, for example, prevent logs from being from being altered after a bind attacker, or whatever afterwards. And then finally there's a an index called of type pin, which is a rather newer one. The purpose of that was that so far the TPM only had a global anti brute force counter or dictionary attack prevention mechanism. And so if you entered too many false password attempts or then the TPM would go into a lockout mode, and you would have to provide it a special password to reset the lockout counter or you would have to wait a certain amount of time until the counter is decremented And here we have the ability to use an envy index that carries its own counter and its own threshold. So it's an individual, it's a 64 bit index, I think, and the first 32 bits are used for the counter and the second 32 bits are used for the threshold. And once the counter, and whenever a authorization fails the counter is incremented, once it reaches the threshold, the counter further attempts to authenticate as against this envy index are blocked. So this is kind of neat possibilities. Regarding the TPM storage, how much storage should we have available this is, it's a tight resource. Because of course it's a cost factor every bite of flash in a security chip costs a lot of money. The TCG estimates some typical usage and thereby defines minimums of what needs to be provided and here on the right hand side you can see the evaluation of what is assumed to be needed. And that results in almost 4k of minimum storage that shall be provided might probably be a little bit more on most chips. And most importantly, it's not as tight as sometimes stated where people say every single index counts, but it's still pretty tight and you'd have to keep in mind that this is shared with persistent keys. So if you have a platform for those that know the concept with a persistent SRK that goes away from the same storage as indexes. So to create an envy index. This is a very basic example we're using some command line tools. And you see the the output at the bottom. We call envy create envy, and actually this call for some reason got scrolled out of the terminal I'm sorry for that. It asks for a new password to be assigned. I assigned an empty password and then as for owner authorization, a case or a hierarchy authorization, which is the entity that is allowed to clear or deny access to defining and removing of envy indices. And then we can, as I said it's a general purpose store so we can write to the store, and we can reach to the store. And you see in the list that there is the envy owner, my index at the bottom that was created that we're using now. Another example for a counter would be here. As you can see, if I create a counter I give it the type counter at the very top. I will increment on this counter and will increment and we see we jump from zero E to zero F as in C I didn't use the counter on my TPM very much, but it initialized at zero E. If I was to now delete the counter and recreate the counter it will start at zero F afterwards. And, as you can also see there is no way for us to just write arbitrary data, even though by the length it should fit in there. No, it's actually by too much, but still would always deny us to put a counter in there. And just for the record counter is always 64 bit unsigned. Yeah, so this is what TPM envy storage is in a very brief nutshell. And now we're going to see how we can combine that with policies. And again some background what is a policy. So the TPM has a pre versatile policy framework can be used for a bunch of things. And, but since it's an embedded security chip, they had to come up with a way to efficiently store those policies in all of these objects. So what they said was, they said okay, a policy statement the policy expression is going to be a combination as a combination of policy elements will be encoded as a hash chain. So basically, each policy element and on the top right here we see we have the policy elements ABC. All of those elements can be represented as a hash value. And when you want to end combine those elements what you do is to build a hash chain that starts with a bunch of zeros. And then your hash, basically you extend hash extend each of the policy elements into the digest, and you end up with a single digest in the end that cryptographically at least correlates to the policy that was defined. And then, whenever you define something in the TPM, the TPM will only store this digest value, be that a key object or be that an index or be that the authorization for hierarchy or whatever. Make this now more versatile, you want to have an or element in there as well. So what we have is we have the special policy element called policy or that instead of just taking one sub value takes up to eight sub values, or incoming, let's say incoming digest values. And by that you can start combining a bunch of sub trees, as they're often referred to into a single policy digest tree. If you want to have more than just eight. You can, of course, chain a bunch of words together. And the convention is that you would do so only on the top level, and you would make them flat so that you will have the top most or and then you will only have ours on the next layer and then you would start with the actual policies. So that should be enough for up to 64 different policy branches underneath if you want to go beyond that again you make the first three layers of the tree only ours and then you go on. As I mentioned that TPM only tracks the top most hash. So what you need to do is, you need to store the actual policies that you want to evaluate outside of the TPM, and then you call the TPM and for basically for each policy element. Sorry, you start off by opening a policy session, and the TPM then has an internal hash value of zero that it keeps track of, and then you call a bunch of policy commands on this policy session. And each time this this policy evaluates to the TPM will go ahead and update the hash value according to the to this schematics. So for each policy element you call the policy commands. And in the end, you use this policy session where the final hash value is stored inside the TPM, and you call the operation on the key that you are the MV object that you want to use. And the TPM does the comparison to see if the policy was fulfilled by the proofs of the policy that you gave before the other commands. So the amount of policy elements that you have is pretty large as you see here. I guess the most important ones are the most interesting ones that you want to look at are of course the policy or the policy signed way can have a challenge response scheme. So you can defer to another object. So if you want to have authorization for object a, you can defer this to authorization to object B and if that's fulfilled. The first one is fulfilled policy or already mentioned policy PCR is the interesting one when it comes to boot value or boot integrity. Counter timer can be interesting and command code is definitely interesting. So each of the all branches for example you can restrict to a certain command codes you can have a different policy for writing an index versus reading an index or you can have a different policy for using a key versus exporting a key. When it comes to exporting there's also duplication select won't get into too much detail here policy password is of course interesting where basically you say okay I want to have the user enter the password that is associated with this object as well. And then policy and be which we're going to be looking at a little more later. So all of these policy elements are then also parameterized. So that makes the total set of combinations even even larger. For example, the policy and we, it compares the content of an envy to an operant. This is also provided as part of the policy. And then you have a lot of operations so you have equal or not equal. Pretty obvious, but then you also have signed and unsigned numeric comparisons, which is kind of nice. And then you also have corresponding to the bit mask type of of or the fuses like behavior of NV indices that I talked about earlier. You here have the equivalent in the policy where you can say, only if a certain bit is still clear in a certain NB index. This policy is allowed to evaluate to true or vice versa only if a certain bit has been set certain feature activated whatnot. This policy is allowed to evaluate to true. Also interesting in there you can make these comparisons also against just sub parts of the NB index. Since there is an offset parameter as well and then there's also the size of the operant. So you can say I only want to compare to a certain to certain sub bytes of the NB index. And in practice, it would look something like this. And then you have to directly call the TPM via these policies. And so this code was taken from this script setup TPM things. And here you can already see that, as I said, you start off with a policy session, and then you call a bunch of policy commands in this case policy PCR policy password policy command code in this order on the policy session. You can and then you the TPM internally updates the digest counter in this in the session that was started here. And in the end, you then go ahead and either return the session or you get the digest. This is kind of a nice or kind of complicated to program, because for something like a policy PCR, you need to read out the PCR values beforehand, in order to make sense out of them. So there's another routine that you have to do and you have to hash them together and then put them in there. So becomes kind of kind of ugly, potentially. And so we thought about how you could make this nicer to work with. And, yeah, the API that was used here as part of the TSS it's the ESUS API. And this ESUS API gives you the low level access to all functionalities of the TPM. And so it's the go to if you are in a either in an environment where you don't have too many capabilities or if you want to do some very borderline use cases that you want to implement. You have to manually keep track of the policy as I mentioned and then you have to execute this policy so it's only very interesting, only two interesting, if you always have the same policy. And for, for usage, you can use the TPM to tools, and those map more or less directly to the to this ESUS API with some some convenience functionally put on top of it though. But then there is also a rather new library that was released beginning of this year that we call the FAPI feature API. And we're bad with names but I have to stick with them once they're out there. So this is a more convenient interface to talk to the TPM because it automates a lot of stuff. First of all, most importantly for this talk was what it does is it comes with a language that gives us the capability to express policies as JSON in a declarative way. Then it also automates away the whole satisfaction of policies using the policy sessions. And this is done completely under the covers. It also stores and keeps track of the policies in the metadata of the objects. So it's completely transparent to the user where the stuff is stored, how it's evaluated how digest are calculated stuff like that. And we have the corresponding tools. So as you can see here, and that's what I mentioned before, the TPM to tools map more or less directly to the ESUS API, the TSS to tools actually map one to one to the feature API. So what you will see as a or as you saw before the parameters that you provide there, for example, bite buffers or also also the strings that you provide to the TSS to tools. So that's one to one into the feature API and the feature API doesn't come with any TPM specific data types anymore, more or less use a standard data type such as M strings, or JSON, or just bite buffers. And everything I'm going to talk about now how to use the feature API to work with policies on Envy. It pretty much works the same way for key objects so just instead of create Envy you call create key. So what does such a policy look like in JSON, as I said, our goal was to make it a declarative language, which makes it much more convenient for the user, and it should be human readable and human editable. And if you remember, three slides before we had those complete screen with all the policy commands and policy session. This is what the same policy looks like in the JSON encoding the JSON policy language encoding of the PCR and as you can see it's much easier to read them, because we just say we have the PCR we want to evaluate against the current PCR values of zero through two. We require the entering of password, and we restrict the usage of this policy to an Envy read. And this is all you have to write in order to achieve the same result. And then this policy is stored in the feature API object meta data store, and whenever you access the Envy index that contains this policy gets it automatically evaluated in the background. So that was already that part. And now let's go or jump or dive right into some example. So what I brought here with with me was one of the most common use case I get asked. I want to have warm memory, warm memory is right once read many. This is pretty trivial to set up in such a Jason policy, we can see on the right what we do is we provided some arbitrary kind of description. We said it's of type or, and the branches are read and write. And for the read case, we basically say that you can always read. So we we restrict it to the command code and we read. And this branch always evaluates the truth that's the case. We say, you can do this, as long as the Envy written bit of the Envy index is set to know. And so what this does is the TPM will check that this is the case. And once it's written once the, or as soon as the Envy index content was written once this bit is set to true and never reset again. Those are the commands if you want to test this out on your own machine, just be aware you have to call it as a two provision in the very beginning. And I would highly recommend that you go to TSS 301 or master for that matter. Because we changed some of the handling of the policies, going from 2.4 to 3.1. So if you call that this is basically what happens again you're asked for a password for this index I'm setting that to zero because we're not using the password anywhere here in the policy so if you used a password element anywhere in here. That makes it may would make sense in this case we don't. I'm going to call it for the owner authorization again. And then I want to write the hello LSS string to this Vindex again, and what FAPI, aka the, what FAPI will do is FAPI will call a callback which is called a branch selection callback, something like that. And what the tools do is they register the C callback and so the FAPI will then provide the different branch names you do your choice choose to in this case, and it all succeeds. And once we then read. Again, we are asked which policy or which branch we want to evaluate to take the read branch, and we get back the result. And as we can see, as I said it's a warm white right once memory, if we call the right again. We will be failing here and we can see that the envy right finish failed, because the policy check failed, because in this case the envy written bit was actually true and not false. And so the digest value of the policy session and digest value stored for the envy index don't match anymore. This example I brought with me was some some equal comparison. This is I think it comes to envy and you see is the probably the most commonly used one besides maybe the the bit set testing. So in this case what we're going to do is we're going to look at the envy index and we're going to check what the correct value is. And in this case, if you want to translate this over to the stringer presentation so this is the extra presentation, basically of the of the hello world, the word hello. And so only if my index still contains the word hello we're going to evaluate to true. And as we can see here. Again I created this envy index, and I can write to the newly created index. And it was just works seamlessly, but once I write something else like buy into the original my index, writing to my new index will be failing, because again the policy, the policy envy execution failed, and thereby I cannot progress my policy session any further, or or FAPI cannot do so. So this makes the usage of policies just way more convenient and I can tell you from personal experience that it's pretty much not too much fun to write up the easiest calls, and it's way easier to write these Jason files. So Jason is not the writing Jason in regular editor is not the most still not the most convenient thing. So something that we just started, and by me I mean Peter Hoover came up with the idea and you know that and myself are now participating in that as well as we're coming up or writing a Jason schema for this policy language. So I'm doing progress at the time that I'm recording here, hopefully by the time that this is aired. We will have it ready on on the TPM to GitHub IO soft website. And here you can already get a sneak peek at the whole thing. And the idea is that you can click together your policy, and just for fun of it. I brought you an example here. You can see this is the example from earlier and I actually did use this editor in order to write that. So you can see that what we can update it here to equal not equal, and we can very easily add another item. For example if we want to have passport authorization and we can add another item. If we want to have the envy written bit sets to sets to true. And then it's only going to evaluate that way. So yeah, this is still work in progress. Unfortunately, it is still work in progress because we originally defined the language we allowed a bit too many values we were pretty pretty broad and for example integers can be provided in either as a Jason integer or it can be provided in as a hex value in a string. And so this gets kind of tough to implement in a Jason schema but hopefully we can sort stuff out and will seamlessly work. All right. So, what did we see what did we talk about, as I said, the TPM has pretty nice capabilities for user storage. It also has very nice policy capabilities, and especially on this later part, I think there's a lot of things that still can be. Yeah, can be discovered in the future. I remember that I in the past did some some interesting firmware update schemes, where you can have the firmware version counter be part of the envy and you only provide access to your storage partitions or data partitions. If the firmware is actually the latest firmware. So you prevent rollbacks, something that we know is a hard thing to do if you don't have something like a TPM capable device with a counter. And I think or I hope that FAPI will be the enabling factor for really getting people getting maybe you in the audience to explore and elaborate on the capabilities using EA policies. Hopefully the editor will be even more interesting or make this even more interesting and more easy to use. For further information, two days ago here at OSSE, not one day ago, there was the talk on TPM is not rocket science by Johannes and Peter. That's very interesting and then I would highly recommend you come here to our community page. TPM to dash software.github.io, where you will find a lot of talks that were given. I think at LSS you three years ago Peter already gave a talk with some initial introduction. You find a lot of tutorials you find the Gitter chat that's becoming more and more active where people help each other out stuff like that and hopefully also the editor is going to be there in the near future. All right, so thank you very much for your interest and staying to the end. And I hope the examples are interesting and I highly recommend you test them out. And I'll see you in chat.