Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a psp_cleaner method #3

Open
ilikenwf opened this issue Jun 7, 2019 · 26 comments

Comments

@ilikenwf
Copy link

commented Jun 7, 2019

Just as https://github.com/corna/me_cleaner exists for Intel CPU ME neutralization, it would be amazing to have the same for AMD CPUs.

Even with factory UEFI/bios, such a thing would put many people's minds at ease, and give a more secure and affordable solution to using heavily crippled Intel CPUs (zombieload, spectre, meltdown).

I also would bet that the coreboot developers would be interested since some AMD machines are supported, and this kind of tool would probably get more ports for more AMD machines....likewise, I wonder if Purism could be compelled to start producing AMD based laptops since Intel is less than stellar on chip security as well.

@ilikenwf

This comment has been minimized.

Copy link
Author

commented Jun 7, 2019

...@cwerling did mention this should be possible on YC Hacker news:

PSPTool author here. Since all PSP firmware must be signed by AMD, something like a psp_cleaner would be possible given that a bug in the firmware allows to inject arbitrary code. This was shown by CTS-Labs earlier. [1]

https://msrnd-cdn-stor.azureedge.net/bluehat/bluehatil/2019/assets/doc/The AMDFlaws Story Technical Deep Dive.pdf

@cwerling

This comment has been minimized.

Copy link
Owner

commented Jun 18, 2019

Thank you for your input! We first need to become aware of what the PSP actually does before being able to minimize its code base. So far, we know that the PSP does one or more of the following things:

  • Execute vital initialization of the system like DRAM memory training.
  • On Epyc server machines: Run the firmware of AMD's Secure Encrypted Virtualization (SEV) feature.
  • On some Ryzen desktop machines: Provide a Firmware TPM accessible from the x86 processor. This was found to be vulnerable earlier.

It is imaginable that AMD may provide other applications e.g. for DRM through the PSP. If you want to help finding out, what else the PSP does, feel free to use PSPTool to extract some firmware and join analyzing it.

Indeed, in order to provide custom PSP firmware, we need to circumvent AMD's integrity checks, but this seems very feasible given the published flaws.

@ilikenwf

This comment has been minimized.

Copy link
Author

commented Jun 18, 2019

@cwerling

This comment has been minimized.

Copy link
Owner

commented Jun 19, 2019

Yes, being able to inject code through one of the vulnerabilities can help in the otherwise only static analysis. Me and my colleagues are currently still analyzing the PSP, but plan to release more technical knowledge in the future.

@ilikenwf

This comment has been minimized.

Copy link
Author

commented Jun 19, 2019

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 20, 2019

@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 20, 2019

Older bootloader are not encrypted and only signed. Eg. Version (0.)2.0.37

{
    "Header": {
      "EncFingerprint": "0x00000000000000000000000000000000",
      "FullSize": "0x0",
      "ID": "0x1",
      "IsCompressed": "0x0",
      "IsEncrypted": "0x0",
      "IsSigned": "0x1",
      "SigFingerprint": "0xC25D8C5591A44F26BF74F09F4813CBDD",
      "SizePacked": "0x0",
      "SizeSigned": "0x63F4",
      "Unknown00": "0x31410000000000000000000000000000",
      "Unknown1C": "0x0",
      "Unknown34": "0x0",
      "Unknown4C": "0x0",
      "Unknown54": "0x0",
      "Unknown58": "0x0000000000000000",
      "Unknown64": "0xFFFFFFFF",
      "Unknown68": "0x100",
      "Unknown70": "0x00000000000000000000000000000000",
      "Unknown80": "0x00000000000000000000000000000000",
      "Unknown90": "0x0",
      "Unknown94": "0x0",
      "Unknown98": "0x0",
      "Unknown9C": "0x0",
      "UnknownA0": "0x0",
      "UnknownA4": "0x0",
      "UnknownA8": "0x0",
      "UnknownAC": "0x0",
      "UnknownB0": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "Version": "0x37000200"
    },
    "Version": "0.2.0.37",
    "ID": {
      "SSDEEP": "384:1L4H+zd1RrkeDTXLn4ZhyhAtApfL4HT5ArddhI2d1RKrwkTbF0v9WAiUdpFAehf1:1L0+zZk4TXUTyhTL4H+zd1RrkeDTXLnp",
      "SHA3_512": "F24C381A185957FB59E5A4A7A8E2899660C69FE544E6D277184C57BF394E8990B80B84C7F8E4AB531DFA31A7FD0F27EED9AAE23A2D41AC59879894D85D1DA40A",
      "SHA512": "5A9B90C7FCF387184C22907ADE2F15DFF863E2A0A2AA2DAE848AEEF27CE35AFB499B03258B9C4A1BF60B7D69306C17497C268CFBC344915CD7515E26E61DD56C",
      "SHA256": "EF4CACB0F4089FAEB2E1247DD1F0EBFFF339DB1CFE4272AB8087A62A0649611E",
      "SHA1": "18AFE046E76D9BB28AEAB81F5F53DA96FFF29390",
      "MD5": "3C836E9E8D199D961AE1A79B5E6B9A5C",
      "Whirlpool": "45C61127F8B663C8 3F29158BB9F5D90C BF09471EADBE58C6 DB4C558022C0AD8A\n 99EE8C89AB27E70E 32BBDAF5F311C648 1F97C6DC5630B570 78A9D18B0042DE5D"
    }
@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 20, 2019

@cwerling

This comment has been minimized.

Copy link
Owner

commented Jun 20, 2019

You could e.g. get an unencrypted bootloader from an AMD supporting ASUS board:

wget https://dlcdnets.asus.com/pub/ASUS/mb/SocketAM4/PRIME_A320M-A/PRIME-A320M-A-ASUS-4801.zip
unzip PRIME-A320M-A-ASUS-4801.zip
psptool -X -d 2 -e 1 PRIME-A320M-A-ASUS-4801.CAP > bootloader.bin

Have fun! :)

@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 20, 2019

The Image i just c&p'd from was a FM2 (pre ryzen?) image.
https://dlcdnets.asus.com/pub/ASUS/mb/SocketFM2/A55BM-A-USB3/A55BM-A-USB3-ASUS-2902.zip

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 20, 2019

@Mimoja how did you get that json looking object with

      "IsCompressed": "0x0",
      "IsEncrypted": "0x0",
      "IsSigned": "0x1",
@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 20, 2019

I build my own parser

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 20, 2019

Awesome, might be picking up a Thinkpad T495.

Does anyone know if AMD have eFuses anywhere? Something to 'blow' devices into Production Mode.

Could be undocumented RMA/Debugging Features in there somewhere.

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 20, 2019

Could possibly get the decryption key via glitching/side channel.

Anyone know what form of encryption is being used to encrypt the PSP?

Pretty disappointed with AMD decrypting after the fact. Wonder what they're trying to hide.

@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 20, 2019

Awesome, might be picking up a Thinkpad T495.

Please take a look at lenovos update ways first. The 285 (?) is not really getting AGESA updates (only UEFI) and i would not like an outdated firmware on my machine, in case i would want to actually use it.

Does anyone know if AMD have eFuses anywhere? Something to 'blow' devices into Production Mode.

There are softfuses. I think @cwerling and / or I will look into those in the somewhat near future and implement them here as well.

Could be undocumented RMA/Debugging Features in there somewhere.

There is a AMD Public Key for Debug in some Images.

@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 20, 2019

Could possibly get the decryption key via glitching/side channel.

From my point of view, things that need to happen before:

  1. Relyable Codeexec with 100% success rate from coldboot in constant timing
  2. Understand SPI timing from coldboot. Glitch after a specific time between poweron and first / second / third SPI Access
  3. Have your code dump the ROM

Very similiar to the nintendo switch glitching G33kAtWork did:
https://media.ccc.de/v/c4.openchaos.2018.06.glitching-the-switch

Anyone know what form of encryption is being used to encrypt the PSP?

I am not sure enought to answer. @cwerling ?

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 20, 2019

@cwerling

This comment has been minimized.

Copy link
Owner

commented Jun 21, 2019

Regarding the encryption of firmware entries: The authors of the debatable AMDFlaws disclosure posted a short blog article about the bootloader encryption on their blog. Apart from lacking the decryption key, PSPTool so far does not provide functionality to decrypt entries. Nevertheless, PSPTool2 is now able to recognize encrypted entries from a header field.

$ psptool2 PRIME-A320M-A-ASUS-4801.CAP
[...]
+-----------+----------+---------+-------+---------------------+
| Directory |   Addr   |   Type  | Magic | Secondary Directory |
+-----------+----------+---------+-------+---------------------+
|     3     | 0x19d800 | PSP_NEW |  $PSP |       0x61d000      |
+-----------+----------+---------+-------+---------------------+
+---+-------+----------+---------+-------+-----------------------------+-------+-----------+------------------------------------+
|   | Entry |  Address |    Size |  Type |                   Type Name | Magic |   Version |                               Info |
+---+-------+----------+---------+-------+-----------------------------+-------+-----------+------------------------------------+
|   |     0 | 0x19dc00 |   0x240 |   0x0 |              AMD_PUBLIC_KEY |  60BB |           |                                    |
|   |     1 | 0x61dc00 |  0xc300 |   0x1 |          PSP_FW_BOOT_LOADER |  $PS1 |  0.8.0.5E |            signed(60BB), encrypted |
|   |     2 | 0x19df00 |  0xb300 |   0x3 | PSP_FW_RECOVERY_BOOT_LOADER |  $PS1 |  0.8.0.5E |            signed(60BB), encrypted |
|   |     3 | 0x1a9200 | 0x203d0 |   0x8 |              SMU_OFFCHIP_FW |       |           |                                    |
|   |     4 | 0x1c9600 |  0x48e0 |  0x12 |           SMU_OFF_CHIP_FW_2 |       |           |                                    |
|   |     5 | 0x1cdf00 | 0x20420 | 0x108 |         PSP_SMU_FN_FIRMWARE |       |           |                                    |
|   |     6 | 0x1ee400 |  0x4f90 | 0x112 |          !SMU_OFF_CHIP_FW_3 |       |           |                                    |
|   |     7 | 0x1f3400 |    0x10 |  0x21 |                             |       |           |                                    |
|   |     8 | 0x1f3800 |  0x1000 |  0x22 |                             |       |           |                                    |
|   |     9 | 0x1f4800 |  0x1860 |  0x24 |                             |  $PS1 |  A.2.3.27 |            signed(60BB), encrypted |
|   |    10 | 0x1f6100 |  0x1760 | 0x124 |                             |  $PS1 |  A.2.3.1A |            signed(60BB), encrypted |
|   |    11 | 0x1f7900 |  0x1860 | 0x224 |                             |  $PS1 |  A.2.3.27 |            signed(60BB), encrypted |
|   |    12 | 0x1f9200 |   0xdd0 |  0x30 |                             |  AW0B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    13 | 0x1fa000 |  0xcc30 |  0x31 |          0x31~ABL_ARM_CODE~ |  AW1B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    14 | 0x206d00 |  0x91c0 |  0x32 |                             |  AW2B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    15 | 0x20ff00 |  0xbc00 |  0x33 |                             |  AW3B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    16 | 0x21bb00 |  0xcca0 |  0x34 |                             |  AW4B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    17 | 0x228800 |  0xca80 |  0x35 |                             |  AW5B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    18 | 0x235300 |  0x9fa0 |  0x36 |                             |  AW6B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    19 | 0x23f300 |  0xc720 |  0x37 |                             |  AW7B | 19.1.14.0 | compressed, signed(60BB), verified |
|   |    20 | 0x61d800 |   0x400 |  0x40 |    !PL2_SECONDARY_DIRECTORY |       |           |                                    |
+---+-------+----------+---------+-------+-----------------------------+-------+-----------+------------------------------------+
[...]

Indeed, the T495 includes an encrypted bootloader whereas the A285 does not. We are thinking about getting a T495 to investigate the encrypted bootloader at runtime.

Regarding a debug setup: I am not sure to what extend you could actually interact with the running PSP firmware apart from emulation, since the PSP is part of the core complex of the AMD SOC. We actually had quite some success using avatar2 to emulate parts of the PSP bootloader.
Our hardware setup consists of an SPI programmer to flash arbitrary UEFI firmware and a Logic Analyzer hooked up to the SPI flash. Recording the boot procedures with the latter, we use PSPTrace to at least see what firmware bytes are accessed when. PSPTrace is described in the bottom part of this repo's readme.

Let me know if you have any further questions.

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 21, 2019

Additionally, across all Ryzen and EPYC BIOS images that we’ve seen, the value of Blob 21h is the same. Therefore, simply decrypting it would allow us to decrypt all PSP firmware blobs for those platforms.

Woah, so they're using one key for all? Basically if you manage to get the Key out, you can decrypt PSP Bootloader & OS for all CPUs?

It appears the latest AGESA update encrypts portions of the PSP firmware, making it harder for security researchers to examine the code.

Ugh this seems very counter intuitive

However, it is still possible to use one of the AMDFlaws code execution vulnerabilities to make the Cryptographic Coprocessor perform decryption operations on our behalf.

Okay, this is neat, you could buy an AMD CPU and use it to decrypt blobs for you.

Regarding a debug setup: I am not sure to what extend you could actually interact with the running PSP firmware apart from emulation

I was initially thinking DPA, however if they're using a Crypto Engine/Co-processor that'll be super difficult.

Only other way I can think of is de-capping/de-liding, although I imagine this would be super difficult to achieve.

@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 21, 2019

Woah, so they're using one key for all? Basically if you manage to get the Key out, you can decrypt PSP Bootloader & OS for all CPUs?

So far I've only seen the bootloader beeing encrypted. I am currently investigating, if there is a ryzen2 bootloader that was released plain before they rolled out the encryption.

However, it is still possible to use one of the AMDFlaws code execution vulnerabilities to make the Cryptographic Coprocessor perform decryption operations on our behalf.

Okay, this is neat, you could buy an AMD CPU and use it to decrypt blobs for you.

To my knowledge there is no public POC and the amdflaws should all be fixed with newer images. Maybe you could backport the bug - but i am not certain.

@cwerling can we replace single entries in the psp-dir as long as they are signed? Maybe even copy a valid signature from an older flawed version and appending it?

@cwerling

This comment has been minimized.

Copy link
Owner

commented Jun 21, 2019

Yes, PSPTool can do that on the command line and you could use the psptool2 Python API to do it, too. The only step that's missing is the re-calculation of the Fletcher checksum, given that you alter the entry's size in the directory. I'm currently using coreboot's Fletcher implementation to compute it, but I'm planning PSPTool support for updating the fletcher very soon.

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 21, 2019

Do we know if there's anti-rollback?

If we can control UEFI, as in, bytepatching etc, can we simply replace the new protected, encrypted PSP Bootloader & OS with the older still signed(?) Bootloader & OS?

Theoretically that should give us code exec via the bug, once there could even write a debugger and follow along in IDA? I wonder if an old PSP Bootloader + OS would work on other CPUs?

@cwerling

This comment has been minimized.

Copy link
Owner

commented Jun 21, 2019

@RobertBuhren and I are currently investigating if there's any rollback prevention. So far, it seems there is none, thus allowing to roll back to any vulnerable PSP bootloader.

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 21, 2019

Sounds peachy 🍑

Let me know if I you need anyone to test anything!

@Mimoja

This comment has been minimized.

Copy link
Collaborator

commented Jun 26, 2019

@Mimoja how did you get that json looking object with

      "IsCompressed": "0x0",
      "IsEncrypted": "0x0",
      "IsSigned": "0x1",

https://github.com/Mimoja/amdfw if you want to play around with it

@dylangerdaly

This comment has been minimized.

Copy link

commented Jun 26, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.