*39C3 preroll music*I was already introduced.
This is some of the things I did a very long time ago I was starting hacking at Hectic.
You may remember that. It's a bit... Can you read it? Oh, yeah.
It's beginning of, right? Yeah.
Wijvertrouwenstemcomputersniet the xda-developers, as you just said.
I was reverse engineering things for a very long time already when I was young.
Unfortunately for my mother, I took apart her sewing
machine at some point when I was three years old, so...
I was never satisfied until I know how something works inside.
Now I'm going to talk about the Pixel phone.
There's a Titan M2 security chip in that. Why is that an interesting chip?
Well, it manages all the security of the phone.
Your pin entry, all the secure keys that are stored
in the phone, they're all managed by this chip.
So I want to understand how it works, and therefore I needed to look at the firmware.
First I looked into this Titan. The word Titan happens a lot in Google products.
Originally, this chip was developed for data centers to secure the Google Cloud services.
Then the very old Pixel phones, they had a different
security chip from NXP, just a different manufacturer.
Then with the Pixel 3, they started with an ARM-based chip, which was called Titan M.
For the newer, starting with the Pixel 6, it's the M2, which is a RISCV-based chip.
There are many other things, so this is better to read it.
Oh yeah, I'm not a graphics designer, as you may see from my slides.
There is no relation to the submarine.
There's a project called Open Titan, which has a very similar functionality, but
it's an open design, and it's not from Google itself, so it's a different one.
And then I just saw yesterday, or today, was it today, from Tropic Square,
there was also a talk about a secure element, and that's also another open
project with the entire chip as open hardware, not related to the Google chip.
There's a Google dongle where you can store passwords
on the USB stick, also not related to this Titan chip.
And then just last month, there was another project from Google
called Titans AI, and also completely not even security related.
So this word Titan happens a lot.
There's the first version of the Titan chip that was in
the phones for the Pixel 3 until 5, introduced in 2018.
That was an ARM-based processor.
The operating system was called Nugget OS, which you can find copies online.
But it's not exactly what's in the chip, but it's just based on that.
If you look in the firmware, you see the file names Brick and Chunk in the version strings.
The firmware itself, if you download the Pixel firmware, you have
to unpack it a bit until you get to the vendor image, and in this
vendor image, there's an ec.bin file, which contains the ARM code.
Oh, yeah, QuarksLab, they did some research on that specific chip.
This is a picture of the phone.
Not sure if you can see it, but in the middle, up there, there's an arrow to the Titan chip.
So this is the PCB from the Pixel 3. Then the M2, it was introduced in 2021.
It's codenamed Dauntless, and it's based on a RISCV IP core from a company named Soteria.
It's still the same Nugget OS.
Also if you unpack the firmware, you have to get to the same, you
have to first unpack the zip file, and then there's a vendor image
which you can unpack again, and then you find several ec.bin files.
This is a picture of the Pixel 6 mainboard.
It's the yellow chip sort of in the middle, on the top.
So these are not very big chips, these are just tiny chips.
There's another picture showing you a coin with these two chips.
So it's not like a big CPU or anything, just a very
tiny chip, but it adds a lot of value to the phone.
The things, the specific hardware that are unique to this Titan chip, there's
a BigNum accelerator, specifically for elliptic curve and RSA calculations.
There's some AES crypto hardware, a random number generator, and
whatever the usual microcontroller stuff that you see in all small chips.
Some anti-tempering, probably.
I have not taken the chip itself apart, so I don't know.
It's just an assumption, but I'm quite sure there's some anti-tempering hardware in there.
Then I looked at where does the ...
Google does publish a lot of CVEs, and some of them do mention the Titan M.
What I noticed about this, that it's not always Titan M that they say.
Sometimes they say GSC, which is Google Security Chip.
And the other notable thing is that from 2019 to about
2022, there were lots of CVEs, and then suddenly it stopped.
There were just a few in 23, and then a few in 24, and only one in 25.
And I did see code changes in all those times.
So even though there's no CVEs anymore, Google does change the code from the chip.
So maybe they're not publishing it anymore, or they think all the bugs are fixed.
That's something that I thought was notable. Then the firmware.
How do you get even the firmware?
Before you want to analyse it, you need to download these images.
The main place to get it is from Google itself.
But I also thought maybe you can get old versions that are no longer published by Google.
So I wrote kind of a little scraper tool to get this from the index from archive.org.
And there are actually quite a lot of firmware files also,
or links to firmware files that you can find on archive.org.
It's useful sometimes for your research to go back into the index from archive.
Then I ran into another problem. There's quite a lot of firmware.
And I wanted to look through all of them to find, like, a complete set of all the binaries.
So something that I did, you can specify that you want to download only a
specific section of a file from a URL, I wrote some tools for that, which you
can find on my GitHub to minimise the number of data that I needed to download.
Because I only actually needed this vendor image part of that.
So I wrote there, it's about 3 ,000 different firmware files.
And I went through all of them, and in a total, I found 40, about 40
versions of each of the Titan firmware chips, firmware's different versions.
When extracting the firmware, the zip file itself,
that's probably everybody can unpack a zip file.
But then you run into all these different file
systems, there are Android sparse images, some
are X4, some are TAR files, and you can use a lot of separate tools for that, but 7-zip,
that's a really handy tool for reverse engineering,
because it actually understands most of these
different file formats out of the box.
So you don't need to mount anything, or do anything difficult, you just use 7-zip, and
you unpack all the firmware using just that tool.
This is a listing of the specific files that you will find in a Pixel 6 firmware file.
Then from the operating system point of view, how is it actually used?
This is when the phone boots, there's some process called Citadel Updater.
This loads the firmware files from this firmware directory, and sends it to the Titan chip.
Then there are some libraries.
There's an SPI channel through which it talks to the chip.
And then there are these Android.hardware.something
libraries, which have a GNI interface, so they
can actually be used from the Java code from Android.
I didn't dive too deep into that part of the software, actually.
But then I looked at the firmware file itself.
I usually just start with a hex dump, and you
see immediately lots of structure, because there
are sections, and some things look like signatures, and things look like code.
Well, to me, they look like obvious code, maybe not to everybody.
There are two parts in it, because whenever you update the flash in the chip, you want to
be sure that that's the correct one, and you want to be able to switch back to the other
one.
So they use an upper and a lower part of the flash chip for the current active version.
There's a small loader, and then there's the main part of the code.
Oh, and there's a signature, which I have not figured out yet how it works.
The key looks.
I tried factoring the big number, and I couldn't factor it, so I assume it's an RSA modulus.
But, yeah, I couldn't validate it.
Normally I can just calculate, and I see an RSA key, and I want to know what does it match
with.
There's supposed to be a hash somewhere that rolls out of it, but I could not find it for
this firmware file. Then I wanted to disassemble and actually decompile.
First, I tried Ida. Unfortunately, this was IDA 8, which I tried it with.
You see there's some problem after not so far, it already starts not recognising the bytes.
So there was something not supported by the IDA disassembler, maybe the RISCV disassembler.
This is a better detail of the same thing.
Also in IDA 9, there's now a decompiler for RISCV, but in IDA 8, it was not yet there.
So with IDA, I could not get very far in reverse engineering this.
So I went to Ghidra.
It shows the same problem, also lots of undefined
bytes which it couldn't disassemble, but there's
another. It does have a decompiler, Ghidra.
Even though there are bad instructions, it just tries to at least generate some C code for
you.
Ghidra has another nice feature, which I will get to because first Ghidra allows you
to define your own processors, and it's very easy to extend the processors.
So what I did, I was looking at all the words
that Ghidra was not able to disassemble properly,
and try to see some structure in there.
So the bit patterns, I looked for the RISCV instruction set, how is this usually encoded.
There's the specification, it's on GitHub. The RISCV opcodes repository.
And it's relatively readable, because it just gives you ranges of bits and the meaning.
So these values like IMM20, that's specified as somewhere the, well, I didn't write it
down here. It's probably the last 20 bits of the D word.
I'm not quite sure, because I didn't write that down.
I don't remember the exact details.
But then I tried to match that with the unknown opcodes that I found.
And I'm thinking, this must be immediate, this must be a register, and some other part
of the things must be then a function code or so.
So what I did, I created some dummy instructions.
This is what the specification language from
Ghidorah looks like, and I called these instructions
Google 0, Google 1, and Google 2, and Google 3, because I had no clue what they were.
And I just put these bit patterns in there.
And then you get some, the code completely disassembles.
And you get your Google 0 as an unknown function, basically, in your decompilation.
So then, next, I tried to figure out what's going in and out, because you see there, it's
using something from the CSR read function before
it, and then the result is doing something,
and then I had about 50 functions or so, where I could look at that.
At some point, I took this Nugget OS, the scheduler, because I did have source code for
that, and I tried to match it up, because I did notice where the scheduler was, and then
I figured out, ah, this must be a bit scan, because it was trying to match active processes
in a slot of bits. So these instructions, they are actually quite simple.
There's nothing magic about these instructions.
This is what I found after several days of just staring at the disassembly and figuring
out what, what these unknown instructions must do.
So there were a byte swap, gets the, the R bits can, it has, these things have better names,
but these are just invented by me.
In the RISCV standards, there, - this is what it now looks like with my new,
new instructions. So then it becomes clear, and all the code is now readable.
I, I did look at the RISCV standards, and I was wondering, but this count leading zero,
it does exactly what this instruction does.
But it's an entirely different encoding, and
it's in a different part of the RISCV instruction
set, and you can kind of get a clue why that happened, because this was only specified for
RISCV in November 2020, and Google released the Pixel 6 in the summer of 21.
So I'm guessing this just overlapped the development process.
They probably started designing this chip before November, before this specification
was finalised from, from RISCV.
So now, I had a much better idea what this, everything was doing.
In this Nugget OS, you have apps and tasks, so
it's like a regular real-time operating system
that you find in many small chips.
It has five apps, AVB, that is the Android's
verified boot, the GFA was the face authentication,
identity, which I think stores keys, I'm not quite sure, and I didn't look that one up.
Keymaster, which manages your crypto keys for you.
Nugget is the basic operating system, and the Weaver is the part that does the, manages
your pin codes for you.
So you can only retry three times or something,
and there are timeouts and all the other things.
And then there are several corresponding tasks.
The descriptor task is not part of the direct API,
but it's just used by all the other applications.
The chip, it talks with the rest of the operating system via some protobuf packets.
And you can, I can find the other, the compiled protobuf encoding in the firmware.
And it's also actually, it matches quite nicely what I find online also.
There's a Google source, there's a repository which has these specific protocols.
Then inside the chip, there's also, there are several security levels.
So there's a Cisco-like interface for these applications to call specific crypto functions,
for instance.
Then I ran into some, I saw some places which were
not crypto keys, not prime numbers or whatever.
They looked like something else. And this is what I looked into next.
It kind of looks like this in the hex dump.
And this turned out to be the code for the elliptic curve accelerator.
There's something interesting about it.
This is a plot from the code size from the firmware over time.
You see that suddenly it just drops quite a bit.
And this is the moment that Google decided they don't use this anymore, because apparently
there must have been some security bug in there, which was not, doesn't match any of
the CVEs.
But I did notice that at some point they stopped using this coprocessor entirely.
But still, I find it an interesting chip, interesting coprocessor.
So I did look into what actually it's doing and how it works.
This is the C code from RISCV, where you see how it's actually calling this.
It's copying coordinates to a specific memory location.
Then it's calling this with, looks like a magic number, 0x2cc.
And that turns out to be the address in the coprocessor that it's jumping to.
On the right, you see the function, how it actually calls this coprocessor.
There's some I.O. space where some status bits are checked.
And it puts the function name there.
And then it waits for the status bits to change again.
And then after that, it copies back the results.
This is a part of the coprocessor where I figured out, where I started seeing some patterns.
Because I recognised these numbers.
They're exactly the generator point for the
elliptic curve that was used for the ECC signatures.
So since all the half of the words are parts of these coordinates,
I'm assuming that the rest is probably an immediate load.
And I can figure out what the bits mean.
Because I know the order of the things are.
So by looking at this hex dump in this way, I can
kind of figure out what some of the instructions are.
Like there's also... Is there more below there? Oh, yeah.
There's a call instruction. This is just 08. And then this address.
Because these addresses match exactly with the useful structure.
And there's this return, which I assume is return.
Which is very often just at exactly the right places. So I figured out quite...
I didn't write more about this coprocessor here.
But I did figure out some of the instructions, but not all of it.
Then the next thing I did, after figuring, looking at the firmware for a long time,
and now I kind of know what it does.
And I also wanted to see if I can just run it and simulate it,
and maybe even find bugs in it by fuzzing it.
I haven't actually done the fuzzing, but I did write a simulator.
First, I started in Python.
One of the things I noticed about the RISC V processor is such a small instruction set
that it's actually just a few hundred lines of Python to get your basic simulator running.
So my simulator has a lot of these logics about I.O. ports,
where one I.O. port needs to behave in a certain way.
I have no clue what the I.O. port does.
I just make sure the code takes the most logic path through the code.
Then my simulator is able to get the same output as I get from the debugger.
There's a debugger in the Pixel phone where you can get output of various chips.
And I was quite happy that it looks exactly...
It runs until the idle loop, so I'm not able to talk.
I didn't implement any of the SPI channel stuff yet.
But it does boot the entire chip.
It initialises all I.O. which doesn't exist in my simulator,
but I kind of know now where it writes all these things.
And then it says 'task idle starting'.
So I'm quite happy that this simulator works. *Applause*
This is a special USB cable that you can make yourself.
There are two pins, and this is where the debug output comes from, from USB-C.
And you have to be careful with the voltage level.
It's 1.8 volts, so don't put 5 there. So that will break your phone.
I have some... These are the details on how to actually enable this in Android.
You have to go through some steps. This is the end of my talk. *Applause*
Herald: Nice.
I've tried Gidhra myself a bit, so I can only imagine how long this took you.
How long did it take you? I did this over several...
Not all at once. So, yeah.
But I remember just staring at these bits and
trying to make sense of the unknown instructions.
That's actually... I like that. Enjoy this experience that you figure it out.
The same with this, yeah.
You guys are smart. You've already queued up at the microphones.
But still, I have to repeat it.
If you have questions, please queue up at the microphones. Thank you.
So, first question. Microphone 3, please.
Yeah. Thanks for the talk. It's really cool.
So, would you say the majority of the time is
looking at the static disassembly or rather kind
of trying to write tools or maybe trying like a live reverse engineering simulator?
willem: That's actually the next thing that I want to do is make sure that I get all these protocols
that is running over this SPI port.
I want to get it to work in a simulator so I can actually fuzz it, maybe.
It's very slow. So, it's not that it's a very efficient fuzzing, but...
Oh, there's another simulator called SPIKE. And I did implement it there as well.
And that's written in C. So, it's much faster.
But, yeah, most of my time I spent static just looking at disassemblies.
But I did...
I can run the code and I did try, like, do an RSA encryption and the elliptic curve stuff.
And I know that it works in my simulator.
Nice. Question from microphone number 2, please.
Yes. So, did you use any...
When you're comparing different versions of this firmware, did you use any, like, binary
diffing tools? Or... Like, why or why not?
willem: I mostly use strings, actually.
Audience: Nice.
willem: And I just did my main reverse engineering work on just the first binary I happened to look
at.
And then I did notice that some code disappeared in other binaries, like this...
all this elliptic curve hardware driver that disappeared and is now only all implemented
in software on the RISCV site.
Audience: Thank you.
willem: We have a question from the internet.
Signal: Yes.
The internet asks, how does it send debug output via same UART as Android Linux?
I don't actually know how the debug output ends up. But it's a... There's a...
A MUX. You can specify a MUX, and you can select which chip you want to talk to.
So, I think there's a separate channel, and it's just a regular UART.
Because also, UART is not visible from inside...
I think there is a way to get it in the Pixel.
But the easiest way is to get it on these two pins on your USB-C port.
And you first have to boot into Fastboot, and then set all this...
Did I put it on the screen? This, where this OEM UART enable and debug UART max.
With that, you can configure this special debug port.
Nice. A question from microphone number three, please.
Thanks. It was a really great talk.
First, my question is a bit simple for you, but for me it's a new thing. Is the...
What you showed to us was very hard work, because you had to figure out the then
unknown risk opcodes and what they do, these instructions.
But in general, there was no obfuscation, right?
And no attempt to protect you from inspecting
the source or to kind of hide it from some use.
So, is this normal? Was it expected that there is no additional layer obfuscation?
Or is this... What do you think about that?
willem: When they obfuscate things, then they would obfuscate the entire firmware.
That also happens.
You have an encrypted binary, and it's very hard to find the keys to it.
But in this case, there was no attempt at all at obfuscation.
For initially, I figured, oh, this must be magic Google crypto hardware instructions.
But it was nothing like that. It was very mundane, bit fiddling instructions.
Yeah. Thank you.
willem: Doing, yeah.
Herald: Number four, please.
Thank you for your talk. I didn't get one part.
How did you identify from the unknown blobs that it was the ECC optimisation function?
willem: Because I saw these coordinates, the X and Y coordinates, that are from the parameters
to these public curves.
You can just look them up, and if you look at the hex dump, there's also the prime number
it's using for the point calculations and the group order of the curve.
These are all in there.
So, I just recognised these constants, and I started from there.
And then I figured out, ah, these other magic numbers, they must be offsets.
What I did not yet figure out, for instance, I know some of the instructions are branches,
but I cannot yet figure out when they branch forward and when they branch backward,
because there seems to be no logic yet to me.
But that's because I didn't look at it long enough yet.
Audience: Thank you.
Herald: Number one, please.
Audience: Thank you for hardly looking into the details.
I have a bit further-looking question.
So, I have a Pixel 9, and I tried already Graphene OS, so Google is permissive.
You can do a lot.
But my question is, do you believe, by the re-engineering
you are doing, that you could convince even the Pixel
under Graphene OS that still credit card operations are possible? Is this a way?
Can we do it? Should we do it?
willem: The credit card operations on the phone?
Audience: Yeah, exactly.
You cannot, you have to somehow compromise the security chip to convince the security chip
under Graphene OS that it still believes it's under a Mint OS.
willem: Yes.
Well, I cannot put any new firmware in this because this is all signed by Google with a
signing algorithm which I have not even figured out how it works, and I don't know Google's
keys. So, this security chip is definitely...
I'm unable to put my own firmware in there yet.
Maybe at some point I find some code execution, then I would probably get very rich as well
because Google puts a million dollars on the bug bounty for that.
But, yeah, not there yet.
Don't be shy. We still have a bit of time.
Question from microphone number three, please.
Yeah. Hey, Willem. Thank you very much for the talk.
Really appreciate you open sourcing all of your tooling. That's very nice.
I believe in 2022 at Black Hat US, one of the Google Red teams already demonstrated like
a code execution vulnerability inside of the Google Titan M2.
And it's kind of a follow-up question to the one asked before.
Did you look into rollback prevention of these binary blobs that are eventually deployed
on the Titan M2 chip?
willem: No, I didn't look into that.
Audience: So I'm wondering if there's some sort of rollback prevention or, like, if not, if we could
just get code execution on there to figure out these custom instructions.
This would have been, I guess, the dynamic way...
There is a version in there, but... Oh, yeah. So I didn't look into that.
I also don't...
This is part of the boot ROM of the Titan chip, which does the signature verification.
And I don't have access to that because I have no code execution on the tip.
Okay. Cool. Thank you.
Herald: So if people have more questions later, how can they reach you?
This was on the last slide, either through my GitHub or my email. Is it there?
Yeah. My email is there.
Nice. So if there are no more questions, then big applause, please, for Willem.