<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">Le 10/03/2025 à 17:27, Adrian Vovk a
      écrit :<br>
    </div>
    <blockquote type="cite"
cite="mid:CAAdYy_kDJnqx6SpTLa7LtWmPWthbpgDXMvi1KX3Lr6CJ7+v30A@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="auto">
        <div>Hello,<br>
          <br>
          <div class="gmail_quote">
            <div dir="ltr" class="gmail_attr">On Mon, Mar 10, 2025,
              12:06 Mikko Rapeli <<a
                href="mailto:mikko.rapeli@linaro.org" target="_blank"
                rel="noreferrer" moz-do-not-send="true"
                class="moz-txt-link-freetext">mikko.rapeli@linaro.org</a>>
              wrote:<br>
            </div>
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
              <br>
              On Mon, Mar 10, 2025 at 11:16:25AM -0400, Adrian Vovk
              wrote:<br>
              > Hello,<br>
              > <br>
              > Just to see if I understand your concern correctly,
              I'll try boiling it<br>
              > down to its simplest, by cutting out the need for two
              partitions. Here's<br>
              > the scenario:<br>
              > <br>
              > - An attacker replaces the real rootfs with a
              malicious one that just drops<br>
              > to a shell. The attacker keeps a copy of the original
              real rootfs<br>
              <br>
              This should not be possible without breaking encryption
              keys from the device.<br>
              If the rootfs is not encrypted with device specific keys
              derived from TPM<br>
              measurements or dm-verity where root hash has been hard
              coded into secureboot<br>
              signed UKI binary for the kernel, then the setup is not
              secure to start with.<br>
              If dm-verity image has been tampered it will fail
              signature checks and fail<br>
              to mount.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">This is inaccurate. systemd's security model
          allows for the rootfs to be replaced with a different one.
          There's no good way to actually prevent that: all partition
          table metadata is spoofable, including UUIDs and whatnot </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Of course, if you're using dm-verity on the
          rootfs, the attacker can only replace the rootfs with a copy
          of itself. But I don't think this is the case here, since the
          thread started with the presumption that the attacker can
          replace the rootfs.</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">To be clear, the partition layout I'm thinking
          about is: dm-verity protected /usr partitions (A/B copies),
          and then a separate rootfs partition that exists just to store
          persistent data (/var, /etc, etc). In this scenario, there's
          nothing preventing someone from replacing the rootfs
          partition's contents with anything arbitrary.</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">
          <div class="gmail_quote">
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>
              - The system boots, then tries and fails to decrypt the
              fake rootfs.</blockquote>
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
              > <br>
              > - The attacker now starts impeding communication
              between the TPM and the<br>
              > CPU. Potentially by physically interposing on the bus
              and blocking<br>
              > communication. Or by glitching the bus so that the
              data isn't successfully<br>
              > measured. Anyway, the attacker somehow makes TPM
              measurements fail<br>
              > <br>
              > - The attacker unlocks their malicious rootfs, and
              then the system<br>
              > continues booting. The attacker now gains control of
              the system via the<br>
              > root shell.<br>
              <br>
              This means that TPM, firmware, kernel or initrd have been
              compromized at<br>
              runtime after their TPM measurements and secureboot
              signatures have been<br>
              verified. A denial of service attack is relatively simple
              but any code<br>
              executions should be grave bugs which need updates to get
              fixed. An initrd<br>
              should have only very limited functionality and no
              fallback interactive<br>
              shells or prompts, or network drivers or daemons.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">If you can replace the rootfs (which we've
          established: you can), then that rootfs can contain whatever
          you want to gain execution early during boot. It can be as
          easy as a single symlink in /etc:
          basic.target.wants/systemd-debug-shell.service</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">
          <div class="gmail_quote">
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
              It may be possible to cut down TPM communication and to
              make systemd and other<br>
              service to wait for longer time but it is simpler to
              freeze RAM and CPU<br>
              state and change the rootfs entry with physical attack via
              JTAG, if such interfaces<br>
              are enabled in HW.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">The point is to disable the TPM enough that
          systemd gives up trying to measure pcrphases, and moves on. If
          it continues booting in that case, there's a big problem</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">
          <div class="gmail_quote">
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>
              - The attacker stops impeding the communication between
              the TPM and the<br>
              > CPU. The TPM is still in the same state as it was in
              the initrd. The<br>
              > leave-initrd pcrphase, and the PCR15 measurement of
              the fake root's volume<br>
              > key, are both missing<br>
              ><br>
              > - The attacker is in control of the system, and the
              TPM is in the right<br>
              > state to unlock the real rootfs. The attacker talks
              to the TPM to get the<br>
              > real rootfs's volume key. Attacker wins<br>
              > <br>
              > I think, ultimately, this is the same issue as the
              one you describe. Do you<br>
              > think that's correct?<br>
              > <br>
              > Lennart would have a better idea than I do of what
              mitigations to this<br>
              > would look like. But I suspect that:<br>
              > <br>
              > - You can't MITM the TPM, since the communication is
              encrypted<br>
              > <br>
              > - Other kinds of attacks cause the OS to know that a
              measurement failed. So<br>
              > perhaps we need to very strict about ensuring that
              measurements happen.<br>
              > i.e. By not letting the TPM disappear at runtime, and
              making sure that<br>
              > measurements always succeed (and if it does, failing
              to boot or something)<br>
              <br>
              TOCTOU, time of check vs. time of use bugs may exists but
              they should be<br>
              very hard to trigger, e.g. require HW debugger level
              access.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Well, the TPM is supposed to be secure against
          hardware debugger access, in theory. Ditto with CPUs, and JTAG
          lockout.</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">So if there's TOCTOU bugs in our code we need to
          be robust against them too.</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Anyway, I don't think this is a TOCTOU bug.
          Basically, it seems that we're sometimes OK letting
          communication to the TPM fail. In which case, an attacker can
          cause the communication to fail, and we'll be none the wiser</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">
          <div class="gmail_quote">
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">If
              device specific encryption key leaks, then the data there
              can be modified</blockquote>
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
              by the attacker. I too fail to see the bug here.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Right, this is what we're trying to avoid.</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Basically, the bug is: an attacker does a DOS on
          the TPM in such a way that systemd boots to the rootfs without
          measuring the `leave-initrd` pcrphase, or the fake rootfs's
          pcr15. Once in the rootfs, the TPM doesn't know that it has
          left the initrd. And that's game over: the attacker stops
          DOSing the TPM, and extracts the encryption keys for the real
          rootfs from the TPM.</div>
      </div>
    </blockquote>
    <p>Yes, you can maybe using MITN in order to make pcrextend exit
      with 0 exitcode, because the measurement execution is checked in
      prcextend. Which is not the case in cryptsetup you may just jam
      the communication. (<a class="moz-txt-link-freetext" href="https://github.com/systemd/systemd/blob/bd0d22c2a5bdbf427c68eab630dc06f55dc96c72/src/cryptsetup/cryptsetup.c#L1085">https://github.com/systemd/systemd/blob/bd0d22c2a5bdbf427c68eab630dc06f55dc96c72/src/cryptsetup/cryptsetup.c#L1085</a>.</p>
    <p><br>
    </p>
    <p>Let retry to explain the issue.</p>
    <p>crypttab:</p>
    <p>root /dev/sda1 tpm2-measure-pcr=yes</p>
    <p>var /dev/sda2 tpm2-measure-pcr=yes</p>
    <p>root and var enrolled using pcrs=7+11+15</p>
    <p><br>
    </p>
    <p>-> Normal situation</p>
    <p>1) Just before opening root LUKS:</p>
    <p>PCR15=0 or something predictable<br>
    </p>
    <p>cryptsetup is used to open root and update PCR15 thanks to
      tpm2-measure-pcr=yes</p>
    <p><br>
    </p>
    <p>2) Just before opening the var LUKS:</p>
    <p>PCR15=hash1<br>
    </p>
    <p>cryptsetup is used to open var and update PCR15 thanks to
      tpm2-measure-pcr=yes</p>
    <p>PCR15=hash2</p>
    <p><br>
    </p>
    <p>3) initrd makes the mount of the fs, makes multiple measurements
      (notably on PCR11 with leave-initrd) then chroots and executes
      init.</p>
    <p><br>
    </p>
    <p>-> Attack situation</p>
    <p>1) Just before opening root LUKS:</p>
    <p>PCR15=0 or something predictable<br>
    </p>
    <p>cryptsetup is used to open root. in this case /dev/sda1 is a
      malicious LUKS partition. TPM will not work but if there is no
      headless=true option, the attacker can unlock it using his
      password. Just after entering the password, the attacker jams the
      communication with the TPM making cryptsetup measure_volume_key
      returning non zero code, but totally ignored by
      systemd-cryptsetup.</p>
    <p><br>
    </p>
    <p>2) Just before opening the var LUKS:</p>
    <p>PCR15=0 or something predictable</p>
    <p>cryptsetup is used to open var and update PCR15 thanks to
      tpm2-measure-pcr=yes. but in this case /dev/sda1 is replaced with
      the original /dev/sda1 partition.</p>
    <p>PCR15=hash1</p>
    <p><br>
    </p>
    <p>3) initrd makes the mount of the fs, makes multiple measurements
      (notably on PCR11 with leave-initrd) then chroots and executes
      malicious init.</p>
    <p><br>
    </p>
    <p>Is PCR15 checked against a pre-calculated value saved in the
      signed initrd before leaving initrd? If it's not the case, then
      when executing the init from the chrooted malicious partition, the
      original /dev/sda1 LUKS will be opened and mounted as var. <br>
    </p>
    <p>Aplanas talked about this check in previous conversation, I'm
      wondering if it is the case currently. Otherwise it may be easy
      for an attacker to force a measurement drop and foll the initrd
      like this case.<br>
    </p>
    <p></p>
    <p><br>
    </p>
    <blockquote type="cite"
cite="mid:CAAdYy_kDJnqx6SpTLa7LtWmPWthbpgDXMvi1KX3Lr6CJ7+v30A@mail.gmail.com">
      <div dir="auto">
        <div dir="auto"><br>
        </div>
        <div dir="auto">Best,</div>
        <div dir="auto">Adrian </div>
      </div>
    </blockquote>
  </body>
</html>