Bug 778084 (b2g-fota-updates)

Tracking: Gecko glue for FOTA updates

RESOLVED FIXED

Status

()

Toolkit
Application Update
RESOLVED FIXED
5 years ago
4 years ago

People

(Reporter: cjones, Unassigned)

Tracking

(Blocks: 1 bug)

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [B2GTest:Blocker][fota])

This tracks the work needed in Gecko to support FOTA updates.  What we know we need currently is
 - mechanism to poll for, download, and verify update packages.  Plan is to reuse gecko update code for this as much as possible.
 - code to check multiple signatures of the same package
 - mechanism to reboot the phone into "apply FOTA update" mode

This bug explicitly does *not* cover the server-side problems of building, signing, etc. actual update packages.  We need to track those elsewhere.
Blocks: 715784
No longer blocks: 715816, 728081

Updated

5 years ago
Whiteboard: [B2GTest:Blocker]
Blocks: 778335
Duplicate of this bug: 778332

Updated

5 years ago
Blocks: 778336
Blocks: 778341
No longer blocks: 778335, 778336, 778341
Depends on: 778335, 778336, 778341
Depends on: 778349
Depends on: 778350
(In reply to Chris Jones [:cjones] [:warhammer] from comment #0)
>  - code to check multiple signatures of the same package

The Android codebase contains the machinery for verifying a single signature on the update package. We may be able to wrap the outermost package (that contains the signed update image deltas) with multiple signatures, but it might not be worth modifying the Android bootloader to make it capable of supporting multiple signatures on the image delta files itself.
Carol at Telefonica wrote:
>Brian Smith at Mozilla wrote:
>> 1. If we want to have our own FOTA server for testing, how can we
>>    create the delta files? What is the file format? What tools can
>>    we use to create the delta files?
>
> I generate the full image updates by running |make otapackage|.
> This actually does 2 things:
>
> 1)      Creates the target-files-package (TFP) which is a zip
>   file that contains a snapshot of a particular SW release (resides
>   at <build>/out/target/product/<device>/obj/PACKAGING/target_files_intermediates/<device>-target_files-eng.<user>.zip)
>
> 2)      Calls ota_from_target_files to generate the actual OTA
> SW Update from the TFP generated in step 1 (update for both nand
> and emmc devices will be generated at
> <build>/out/target/product/<device>/<device>-ota-eng.<user>.zip
> and <build>/out/target/product/<device>/<device>-ota-eng.<user>_mmc.zip)
>
> To generate an incremental update, looks like you’ll need to do
> the same as above but pass in “--incremental_from” to
> ota_from_target_files along with the starting TFP.


>> 2. Let's say we have the delta file on the device
>> already. Where do we put the delta file so that the phone can
>> find it when it reboots to apply the update?
>
> I believe theoretically, you should be able to place the SW
> update file anywhere on the device, but typically it’s just put
> on the SD card because of the size. To let the updater know where
> to look for the update file, you would specify the location in
> /cache/recovery/command on the device. For example, if you are
> trying to do a SW update for emmc device, you would do the
> following:
>
> 1)      adb push <build>/out/product/target/<device>/<device>-ota-eng.<user>_mmc.zip /sdcard/update.zip
>
> 2)      adb shell "echo --update_package=/sdcard/update.zip \
>                 > /cache/recovery/command"
>
> 3)      adb reboot recovery
>
> The last command will put the device in recovery mode. At this
> point, the updater will do it’s magic with applying the SW update
> that resides in /sdcard/update.zip

<snip> 

>> 5. I understand that the FOTA updates are signed, and that the
>> device has a public key saved into it. How does this signature
>> verification work? If we create our own FOTA updates for testing,
>> we would like to sign them with our own private key. How can we
>> configure the device to use our public key instead of the key
>> updates? My understanding is that this key (or a hash of the key)
>> is burned into the firmware in a write-once mechanism.
>> Any information you can provide about how this works and how we'd
>> deal with this would be appreciated.
>
> In bootable/recovery/install.c, really_install_package() will try
> to load public key from /res/keys. When making the recovery image,
> the extracted public key (via dumpkeys.jar) is copied to
> out/target/product/msm7627a/recovery/root/res/keys. When this
> recovery image is flashed to device (assuming all the keys were
> extracted and copied), it will reside in /res/keys on the device.
>
> By default, I believe it looks for the key at
> build/target/product/security/testkey. I believe you can specify
> your own key by passing it in with “--package_key” to
> ota_from_target_files.
> 
> FYI, here’s a presentation which talks about the Android OTA
> Software Updates. It’s a pretty good source to find explanations
> on the OTA updates:
> http://video.linux.com/videos/android-ota-software-updates. Also,
> I would highly recommend that you take a look at
> build/tools/releasetools/ota_from_target_files.
Blocks: 764189
Blocks: 780662
No longer blocks: 764189
FYI, I found a really informative comment block in bootable/recovery.c at line 64 that covers a lot of this information as well:

https://android.googlesource.com/platform/bootable/recovery/+/fadc5ac81d6400ebdd041f7d4ea64021596d6b7d/recovery.c#64
Alias: b2g-fota-updates
No longer depends on: 778341
Blocks: 790393
This is the current FOTA implementation plan, we're looking for a little feedback before we tackle it since we will need to re-purpose existing update code in new ways.

To clarify a few terms:
FOTA = Full over-the-air updates (i.e. Gonk/Drivers + Gecko + Gaia)
recovery  = A special partition on the device that has the ability to flash and  run arbitrary update code for the entire device. This is what we will  use in Gonk to apply a FOTA update.

1. Enable a new "os" URL type / pref for AUS
  * toolkit/mozapps/update/nsUpdateService.js: polling / downloading code will need to be able to check this additional URL
  * toolkit/mozapps/update/nsIUpdateService.idl: We'll need a way to identify that this is an "os" update. Some options are: nsIUpdate.type gets a new possible value, or we just add an "isOS" flag.

2. Make copies of timer and interval update properties for "os" updates, and add a new directory key for the save location of "os" updates.
  * requires additional checking and timer setup in toolkit/mozapps/update/nsUpdateService.js and nsUpdateTimerManager.js

3. Verify multiple signing certificates on the FOTA update.mar.
  * We'll potentially have certificates from Mozilla, OEM, and the carrier.
  * Since signature checking is built in to MAR, we'll re-use it by wrapping the update.zip that recovery expects inside of a MAR.
  * toolkit/mozapps/update/updater/archivereader.cpp: current verification code is Windows only, and only checks a primary or fallback cert. We'd need to customize this further with a full list of certs that must all pass verification.
   * Also requires the rest of the work listed in Bug 783638.

4. Write a new "os" nsIUpdateProcessor for Gonk
  * Delegate to existing nsIUpdateProcessor (nsUpdateDriver.cpp) for update extraction
  * Do sanity checking on battery level.
  * Reboot the device to the recovery image in Gonk for applying the update.
Here's a brain dump about multiple MAR signatures:
- The current MAR file format supports multiple signatures, you can read the file format here:
  https://wiki.mozilla.org/Software_Update:MAR
- This multiple signatures support was only implmented in the file format anticipating needing support for it in the future, but only one signature is currently used.
- You can sign MARs with the signmar tool. To build this tool as part of the build process you need to add --enable-signmar to your .mozconfig
- The current MAR file format assumes that each signature will be composed of all bytes of the MAR excluding the signatures themselves. 
- MAR signatures are actually embedded inside the MAR file format instead of tacked onto the start, which would seem more normal.  The reason for this is because we needed to keep the MAR file format backwards compatible when we added signing support.
- The current verify code in elm/modules/libmar/verify/mar_verify.c assumes only a single signature needs to verify, but I think that can be changed 
> if (numVerified > 0) {

>   return CryptoX_Success;

> } else {

>   fprintf(stderr, "ERROR: No signatures were verified.\n");

>   return CryptoX_Error;

> }
- The signmar command line args only has support for signing a single MAR. See modules/libmar/tool/mar.c

Suggested changes to implement the MAR related work as long as security is OK with it:
- I mentioned the current MAR file format assumes that each signature will be composed of all bytes of the MAR excluding the signatures themselves.  
  You may want to change this to be each signature contains only the data of the signatures before it.  This would simplify how the command line would work significantly.
- You'd change that block of code I quoted above to be numVerfied == signatureCount
- The function for signing multiple MARs needs to be implemented:
  modules/libmar/sign/mar_sign.c in mar_repackage_and_sign
> if (numSignatures) {

>   fprintf(stderr, "ERROR: MAR is already signed\n");

>   goto failure;

> }
Depends on: 792452
(In reply to Brian R. Bondy [:bbondy] from comment #6)
> Here's a brain dump about multiple MAR signatures:

Thanks for all the details Brian! :)

I've opened a Bug 792452 to track the MAR specific work for multiple signatures.
Depends on: 794213
Depends on: 794216
Depends on: 794217
Depends on: 795051
No longer depends on: 795051
Depends on: 795921
No longer depends on: 792452
No longer depends on: 795921
Depends on: 783638
Depends on: 801855
Whiteboard: [B2GTest:Blocker] → [B2GTest:Blocker][fota]
(Bug 794216 and bug 794217 are server issues, not part of the Gecko glue.)

Going to declare this done, v1.
Status: NEW → RESOLVED
Last Resolved: 4 years ago
No longer depends on: 794216, 794217
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.