summaryrefslogtreecommitdiffstats
path: root/images/gen_key_migration_script/README
blob: 89200166d7a1de80c28c06117779d122dda932de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
== Context ==
In Replicant we don't have any infrastructure nor procedure to handle long term
secret key storage, and when building an image, some keys are generated.

These keys are then used to sign various Android system applications that are
built as part of the image, such as the dialer, the launcher, etc.

So when a new release is built, new keys are generated. This creates an issue
because the data of a given application is tied to the application signing key.

So when the signing key changes, the applications cannot access its data
anymore.

== How to solve the issue ==
In the android_vendor_cm repository[1] from LineageOS, there is the following
commit:
    2f7c7decc4cd5b42f044a7841a74468e4cacd694
    2f7c7decc (refs/changes/27/156327/3) Add startup script to update the
                                         package signatures

It fixes that issue with a shell script (key-migration.sh) that runs at startup
and removes the offending keys in /data/system/packages.xml, and makes sure not
to run again when done. Removing the keys didn't work for us, however slightly
modifying the script to replace them instead worked fine.

As the keys were hardcoded in the key-migration.sh script, and that we keep
changing keys at each new release, it makes sense to have a more automatic
process that generates the key-migration.sh script from the packages.xml file.

This is what the generate_key_migration_script.py does.

References:
-----------
[1]https://github.com/LineageOS/android_vendor_cm/

== Usage ==
To use this script:
- You need the public part of all the old certificates you want to migrate from.
- You also need the public part of the new certificates you want to migrate to.

Certificates to use with this tool can be found in several places:
- The public part of all the certificates used for official releases are
  published as part of the Replicant releases. Some older releases don't have
  certificates as they didn't use them.
  The releases certificates are also available in distros/releases/certificates
  in the vendor_replicant-data  git repository[1] for convenience.
  If you have the Replicant 6.0 source code, they are located in
  vendor/replicant-data/distros/releases/certificates/.
- The new certificates are generated as part of the build procedure and are
  available in vendor/replicant-security/*x509.pem in the replicant source code
  directory.
- Certificates are also available in encoded form in data/system/packages.xml,
  however they would need to be extracted from this file and put in a dedicated
  directory to be able to be used by this script.

The certificates need to be in a dedicated directory as the script expect that.

For instance, if we have the following directory structure:
$ ls vendor/replicant-security/*x509.pem
  vendor/replicant-security/media.x509.pem
  vendor/replicant-security/releasekey.x509.pem
  vendor/replicant-security/platform.x509.pem
  vendor/replicant-security/shared.x509.pem

The tool will expect us to pass it the vendor/replicant-security/ argument.

For the older release we can also have a directory that contains subdirectories
that in turn contains the certificates. This way we can have one directory for
each Replicant releases with the releases certificates inside. The tool will
then use the directory names as releases names in the generated script.

For instance if we have the following structure:
$ cd vendor/replicant-data/distros/
$ ls releases/certificates/*/*.x509.pem
  releases/certificates/replicant-4.2-0001/media.x509.pem
  releases/certificates/replicant-4.2-0001/platform.x509.pem
  releases/certificates/replicant-4.2-0001/shared.x509.pem
  releases/certificates/replicant-4.2-0001/system.x509.pem
  releases/certificates/replicant-4.2-0002/media.x509.pem
  releases/certificates/replicant-4.2-0002/platform.x509.pem
  releases/certificates/replicant-4.2-0002/shared.x509.pem
  releases/certificates/replicant-4.2-0002/system.x509.pem
  releases/certificates/replicant-4.2-0003/media.x509.pem
  releases/certificates/replicant-4.2-0003/platform.x509.pem
  releases/certificates/replicant-4.2-0003/shared.x509.pem
  releases/certificates/replicant-4.2-0003/system.x509.pem
  releases/certificates/replicant-4.2-0004/media.x509.pem
  releases/certificates/replicant-4.2-0004/platform.x509.pem
  releases/certificates/replicant-4.2-0004/shared.x509.pem
  releases/certificates/replicant-4.2-0004/system.x509.pem
  releases/certificates/replicant-6.0-0001/media.x509.pem
  releases/certificates/replicant-6.0-0001/platform.x509.pem
  releases/certificates/replicant-6.0-0001/releasekey.x509.pem
  releases/certificates/replicant-6.0-0001/shared.x509.pem
  releases/certificates/replicant-6.0-0002/media.x509.pem
  releases/certificates/replicant-6.0-0002/platform.x509.pem
  releases/certificates/replicant-6.0-0002/releasekey.x509.pem
  releases/certificates/replicant-6.0-0002/shared.x509.pem
  releases/certificates/replicant-6.0-0003/media.x509.pem
  releases/certificates/replicant-6.0-0003/platform.x509.pem
  releases/certificates/replicant-6.0-0003/releasekey.x509.pem
  releases/certificates/replicant-6.0-0003/shared.x509.pem
  releases/certificates/replicant-6.0-0004-rc1/media.x509.pem
  releases/certificates/replicant-6.0-0004-rc1/platform.x509.pem
  releases/certificates/replicant-6.0-0004-rc1/releasekey.x509.pem
  releases/certificates/replicant-6.0-0004-rc1/shared.x509.pem
  releases/certificates/replicant-6.0-0004-rc2/media.x509.pem
  releases/certificates/replicant-6.0-0004-rc2/platform.x509.pem
  releases/certificates/replicant-6.0-0004-rc2/releasekey.x509.pem
  releases/certificates/replicant-6.0-0004-rc2/shared.x509.pem

we we will then need to pass the path of releases/certificates/
to the tool.

So in practice, with the directories structure above, we can use the
generate_key_migration_script.py as follow to generate the key-migration.sh
script:
$ ./gen_key_migration_script.py gen-script \
      vendor/replicant/prebuilt/common/bin/key-migration.sh \
      vendor/replicant-data/distros/releases/certificates/ \
      vendor/replicant-security/

References:
-----------
[1]https://git.replicant.us/replicant/vendor_replicant-data/

== Running the key-migration.sh script at boot ==
Now that we have a key-migration.sh script, we need to make sure that the script
is shipped to the device, and that it is run at boot.

In Replicant 6.0, the modifications to do that should already be there.

However if you want to use that tool with newer Replicant versions or other
distributions, you will need to do several modifications.

With Replicant 6.0, the following modifications were made in vendor/replicant
to make the key-migration.sh script run at boot:
- The key-migration.sh script was copied in prebuilt/common/etc/key-migration.sh
  in the vendor_replicant repository.
- The following patches from Gabriele M was applied:
diff --git a/prebuilt/common/Android.mk b/prebuilt/common/Android.mk
index f15b178c..f39105d0 100644
--- a/prebuilt/common/Android.mk
+++ b/prebuilt/common/Android.mk
@@ -8,3 +8,10 @@ LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := key-migration.sh
+LOCAL_SRC_FILES := etc/key-migration.sh
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+include $(BUILD_PREBUILT)

diff --git a/prebuilt/common/etc/init.local.rc b/prebuilt/common/etc/init.local.rc
index 53f972c9..bce1dc63 100644
--- a/prebuilt/common/etc/init.local.rc
+++ b/prebuilt/common/etc/init.local.rc
@@ -24,6 +24,8 @@ on post-fs-data
     mkdir /data/ssh/empty 0600 root shell
     mkdir /cache/recovery 0770 system cache
 
+    exec u:r:init:s0 root root -- /system/bin/sh /system/etc/key-migration.sh
+
     # Run sysinit
     start sysinit

diff --git a/config/common.mk b/config/common.mk
index 91d5e99b..132fd61a 100644
--- a/config/common.mk
+++ b/config/common.mk
@@ -230,6 +230,10 @@ PRODUCT_PACKAGES += \
 endif
 endif
 
+# test-keys migration script
+PRODUCT_PACKAGES += \
+    key-migration.sh
+
 DEVICE_PACKAGE_OVERLAYS += vendor/replicant/overlay/common
 
 ifeq ($(USE_OPENGL_RENDERER),true)

== Running the key-migration.sh in the recovery ==
In addition, it is also possible to use the key-migration.sh script in the
recovery. This can be handy if you use custom images and that you don't want to
build an entire Replicant image, or if you want to keep your data while
downgrading to an older Replicant image.

To do that you will first need to have adb configured so that you can get
root in it. At the time of writing, the BackupTheEFS[1] wiki page has
instructions on how to do that.

Once this is done you can copy the key-migration.sh script inside the recovery.
It can be done with the following command:
$ adb push key-migration.sh /

You then need to mount the data partition. Here's an example on how to do it on
the Galaxy SIII (GT-I9300) with the Replicant 6.0 recovery:
$ adb shell
  root@m0:/ #
  root@m0:/ # mount /dev/block/platform/dw_mmc/by-name/USERDATA /data/

As the path of the data partition changes from device to device, you may need
to adjust the path in the command above. The BackupTheEFS[1] wiki page has
examples of that for mounting the EFS partition.

You can then run the script. Note that you will need to use sh to run it
as the interpreter path is hardcoded to /system/bin/sh which is absent in
the recovery. You can do that like this:
  root@m0:/ # sh key-migration.sh

Note that once it executed, it will create the /data/system/.key-migration-done
file which will tell the script not to do anything anymore the next times it
runs. So if for some reason you need to force its execution or do two different
upgrades, you can simply delete /data/system/.key-migration-done and retry to
run the script. For example:
  root@m0:/ # rm /data/system/.key-migration-done
  root@m0:/ # sh key-migration.sh

References:
-----------
[1]https://redmine.replicant.us/projects/replicant/wiki/BackupTheEFS

== License ==
- The key-migration.sh script is under the Apache License, Version 2.0 as its
  header states.
- All the other files are under the AGPLv3 or later.

== Credits ==
- Gabriele M for the 2f7c7decc4cd5b42f044a7841a74468e4cacd694 patch
- Kurtis Hanna for finding that patch.