Install /e/ on a Fairphone FP4 - “FP4” (beta)

I’m using the newest version of eOS. If this could help you, I share this the system information.

Thanks for your answers.

Now confident that I a) won’t brick it with and b) the security patch level should match, I tried it and I can confirm that 1.4-r contains security patches up to 2022-08-05. Thanks @jobal and @hirnsushi!

The remaining part is only because im curious: :slight_smile:

@hirnsushi, I feel a bit stupid that I did not think about looking into the commits by myself :slight_smile:
Let’s see: Starring at MR!21, it seems the relevant data is the change from 2022-08-05 to 2022-09-05 and that this change is linked to milestone /e/OS v1.5-beta. That essential means that the prior version, i.e. 1.4-r, contains security patches up to 2022-08-05.
It’s seems odd that this repository does not contain a tag 1.4-r. Looking at the corresponding file content would show this information directly.
Listing the history of the file android_device_fairphone_FP4:BoardConfig.mk lists the changes to the security patch date. Jumping to the corresponding change to the actual MR reveals again the assigned milestone (!19 in case of 1.4-r).
Fine.

One thing I did not expect, but confuses me – and I guess there is something I have missed: the version string mentioned by the /e/ developer, i.e. FP4.FP4D.A.163.20220826 or FP4.FP4G.A.170.20220920, is indeed the very same as used by Fairphone. They “bump” to the Fairphone version. I assumed this would be the Fairphone’s firmware version. Is it something different? I guess it just means /e/ aligned its firmware to that one e.g. in respect of the security patch date.

I was not able to draw the line between the manifest of 1.4-r (which seems to be that version of default.xml) to the specific version of the android_device_fairphone_FP4 repository. Mh, shouldn’t it be there?

There are different patch levels, one is the security updates Google releases and the other are the vendor / firmware patches Fairphone releases. When you see a Fairhphone release pulled in, that means the proprietary blobs have been updated to match upstream (Fairphone in this case).
In newer Android versions the different patch levels are listed in even more detail, that’s what it looks like on my FP4 running A13:

I have absolutely no idea how the /e/ project is structured, you might want to ask one of the devs on their forum:

Do you know if anti-rollback protection looks at all these dates or if it only takes e.g. the vendor security patch level into account?

Below are some findings and my understanding how the anti-rollback protection works. Feel free to ignore. It’s slightly out of toic I guess. :see_no_evil:

To my understanding, the anti-rollback feature is configured by the mobile phone vendor (in this case Fairphone) and utilises write-once memory (or similar, called fuses) of the SoC. The process is standardised as part of Android Verified Boot (AVB). It is basically a index updated during flashing and it is not allowed to decrement. Since its is is cryptically signed, you can’t tamper with it.
I assume that the root of trust, i.e. key0 from the linked documentation, is rolled out by the mobile phone vendor (i.e. Fairphone in this case) during production. I guess this vendor also predetermines when increments to the rollback index are expected to happen. Perhaps this is even already specified by AVB.

An interesting question is which party actually signs the rollback index in case of /e/OS. Does Fairphone B.V. assess the image and provide the signature? Does the /e/ foundation own a (derived) key and is capable doing it itself?
This signing party seems to be in charge to deduce the rollback index from the security patch level (dates) and hence “controls” which of these dates are taken into account.

Further reading of the linked documentation reveals that it is possible that several “partitions” contain different rollback indices. Perhaps my assumption that hardware fuses are used directly here is wrong and it is only the backing feature to protect the bootloader, EDL or whatsoever and the actual “firmware rollback protection” based on the security patch levels is designed on top of that in SW.

Quote from the linked documentation:

If verification keys (note: these verify the rollback index) are mutable they must only be set by the end user, e.g. it must never be set at the factory or store or any intermediate point before the end user. Additionally, it must only be possible to set or clear a key while the device is in the UNLOCKED state.

Interesting. Is this used to support custom ROMs and does /e/OS fall under this category in this regard?

Puh – exhausting topic … :wink:
I am sorry if I misuse this topic inappropriately. My aim is to get a deeper understanding how anti-rollback protection actually works to understand better, how to avoid triggering eventually.
Just let me know if I drift too far off-topic.

Maybe you can find some information here

Can’t understand your latest post, I apologize. But you write

in your previous, so I am curious: have you also locked your bootloader after install eOS?
I was lucky in my first attempt to install /e/ and locked it, so now I don’t have a rooted device and all my daily apps (banking, identification, tracking…) work well.

Sorry for not beeing clear enough:
What I have tried was to install /e/OS 1.4.-r over the FP4.FP4D.A.163.20220826 which was succesful. I did keep keep the bootloader unlocked (for now), as well as the “OEM unlock” switch.
So essentially, nothing new :wink:

Thanks.
There are quite “irritating” facts in that thread :stuck_out_tongue:
(I am referring to the used test keys for signing the bootloader.)

Kind of, but from my very limited understanding not completely right.
A custom ROM doesn’t really have to make use of AVB, which pulls in rollback protection. You can just keep the bootloader unlocked and the whole issue goes away completely.

As you found out yourself, there’s the option of user-settable root of trust as well, which /e/OS, iodé, CalyOS etc. use to set their own keys and sign their releases with. That key gets loaded into “tamper evident” storage and makes it possible to lock the bootloader with one of those ROMs installed.

The specifics of AVB / rollback protection get set in the build system, so by whoever is building the images you are installing to your device. And the index gets updated when those images increment the index, e.g. during an OTA update.
You can have a look at that in action for example in the /e/OS BoardConfig.mk or the CalyxOS BoardConfig.mk.

If you use avbtool, you’ll see that reflected in the images:

avbtool output
foo@bar:$ ./avbtool.py info_image --image /home/foo/Development/Android/calyx/FP4-tp1a.221005.003/image-FP4-tp1a.221005.003/vbmeta_system.img 
Minimum libavb version:   1.0
Header Block:             256 bytes
Authentication Block:     576 bytes
Auxiliary Block:          2688 bytes
Public key (sha1):        29f859183d3f64db6652e498d30ab916662aef90
Algorithm:                SHA256_RSA4096
Rollback Index:           1662336000
Flags:                    0
Rollback Index Location:  0
Release String:           'avbtool 1.2.0'
Descriptors:
    Prop: com.android.build.system.os_version -> '13'
    Prop: com.android.build.system.fingerprint -> 'Fairphone/FP4eea/FP4:11/RKQ1.210503.001/FP4D:user/release-keys'
    Prop: com.android.build.system.security_patch -> '2022-08-05'
    Prop: com.android.build.product.os_version -> '13'
    Prop: com.android.build.product.fingerprint -> 'Fairphone/FP4eea/FP4:11/RKQ1.210503.001/FP4D:user/release-keys'
    Prop: com.android.build.product.security_patch -> '2022-08-05'
    Prop: com.android.build.system_ext.os_version -> '13'
    Prop: com.android.build.system_ext.fingerprint -> 'Fairphone/FP4eea/FP4:11/RKQ1.210503.001/FP4D:user/release-keys'
    Prop: com.android.build.system_ext.security_patch -> '2022-08-05'
    Hashtree descriptor:
      Version of dm-verity:  1
      Image Size:            1121902592 bytes
      Tree Offset:           1121902592
      Tree Size:             8839168 bytes
      Data Block Size:       4096 bytes
      Hash Block Size:       4096 bytes
      FEC num roots:         2
      FEC offset:            1130741760
      FEC size:              8945664 bytes
      Hash Algorithm:        sha1
      Partition Name:        product
      Salt:                  62d86d9743a5cc83ebef37719730ed9ac615603b23af7aadf19cf3e2029d488b
      Root Digest:           fc7c82592f04ef39be89bfa114a92db3da6b5434
      Flags:                 0
    Hashtree descriptor:
      Version of dm-verity:  1
      Image Size:            919646208 bytes
      Tree Offset:           919646208
      Tree Size:             7249920 bytes
      Data Block Size:       4096 bytes
      Hash Block Size:       4096 bytes
      FEC num roots:         2
      FEC offset:            926896128
      FEC size:              7331840 bytes
      Hash Algorithm:        sha1
      Partition Name:        system
      Salt:                  62d86d9743a5cc83ebef37719730ed9ac615603b23af7aadf19cf3e2029d488b
      Root Digest:           0f72873eeb1f9fc0f8df5026bbeba1fda7b4c5ec
      Flags:                 0
    Hashtree descriptor:
      Version of dm-verity:  1
      Image Size:            282202112 bytes
      Tree Offset:           282202112
      Tree Size:             2232320 bytes
      Data Block Size:       4096 bytes
      Hash Block Size:       4096 bytes
      FEC num roots:         2
      FEC offset:            284434432
      FEC size:              2252800 bytes
      Hash Algorithm:        sha1
      Partition Name:        system_ext
      Salt:                  62d86d9743a5cc83ebef37719730ed9ac615603b23af7aadf19cf3e2029d488b
      Root Digest:           a510cf9e25ba68c4cae0ef22524ea151074a807d
      Flags:                 0

Now, according to the docs

All user data must be cleared when transitioning from the LOCKED to the UNLOCKED state (including the userdata partition and any NVRAM spaces). Additionally all stored_rollback_index[n] locations must be cleared (all elements must be set to zero). Similar action (erasing userdata, NVRAM spaces, and stored_rollback_index[n] locations) shall also happening when transitioning from UNLOCKED to LOCKED

… all those indices should be cleared when transitioning between different states, why we still have to worry about the FPOS patch level when installing /e/OS is beyond me :man_shrugging:
You’ll have to talk to an actual developer if you need those answers, I’d be very curious as well.

It’s not your fault, but my english :face_with_open_eyes_and_hand_over_mouth:
Thanks for the replay.

I’ve asked one of the CalyxOS developers, and yeah … :roll_eyes:

That’s exactly what we told Fairphone as well. The implementation is clearly broken.

(To be clear, that’s a general problem, not /e/OS specific)

There’s now an Android 12 (S) /e/OS version available and so far it’s running fine on my FP4.

@hirnsushi, thanks a lot for the great references and insights!