Merge "Docs: Update sign_builds.jd"
diff --git a/src/devices/tech/ota/sign_builds.jd b/src/devices/tech/ota/sign_builds.jd
index e986920..5e400be 100755
--- a/src/devices/tech/ota/sign_builds.jd
+++ b/src/devices/tech/ota/sign_builds.jd
@@ -25,24 +25,128 @@
</div>
</div>
-<p>Android uses cryptographic signatures in two places:</p>
+<p>Android OS images use cryptographic signatures in two places:</p>
<ol>
-<li>Each .apk file must be signed. Android's Package Manager uses an .apk
-signature in two ways:<ul>
+<li>Each .apk file inside the image must be signed. Android's Package Manager
+uses an .apk signature in two ways:<ul>
<li>When an application is replaced, it must be signed by the same key as the
-old application in order to get access to the old application's data.</li>
+old application in order to get access to the old application's data. This
+holds true both for updating user apps by overwriting the .apk, and for
+overriding a system app with a newer version installed under
+<code>/data</code>.</li>
<li>If two or more applications want to share a user ID (so they can share
data, etc.), they must be signed with the same key.</ul></li>
<li>OTA update packages must be signed with one of the keys expected by the
system or the installation process will reject them.</ul></li>
</ol>
-<h2 id="certificates-keys">Certificates and keys</h2>
+
+<h2 id="release-keys">Release keys</h2>
+
+<p>The Android tree includes <i>test-keys</i> under
+<code>build/target/product/security</code>. Building an Android OS image
+using <code>make</code> will sign all .apk files using the test-keys.
+Since the test-keys are publicly known, anybody can sign their own .apk files
+with the same keys, which may allow them to replace or hijack system
+apps built into your OS image. For this reason it is critical to sign any
+publicly released or deployed Android OS image with a special set of
+<i>release-keys</i> that only you have access to.</p>
+
+<p>To generate your own unique set of release-keys, run these commands from
+the root of your Android tree:</p>
+
+<pre class="no-pretty-print">
+subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
+mkdir ~/.android-certs
+for x in releasekey platform shared media; do \
+ ./development/tools/make_key ~/.android-certs/$x "$subject"; \
+done
+</pre>
+
+<p><code>$subject</code> should be changed to reflect your organization's
+information. You can use any directory, but be careful to pick a
+location that is backed up and secure. Some vendors choose to encrypt
+their private key with a strong passphrase and store the encrypted key
+in source control; others store their release keys somewhere else entirely,
+such as on an air-gapped computer.</p>
+
+<p>To generate a release image, use:</p>
+
+<pre class="no-pretty-print">
+make dist
+./build/tools/releasetools/sign_target_files_apks \
+ -o \ # explained in the next section
+ -d ~/.android-certs out/dist/*-target_files-*.zip \
+ signed-target_files.zip
+</pre>
+
+<p>The <code>sign_target_files_apks</code> script takes a target-files .zip
+as input and produces a new target-files .zip in which all the .apks have
+been signed with new keys. The newly signed images can be found under
+<code>IMAGES/</code> in <code>signed-target_files.zip</code>.</p>
+
+<h2 id="sign-ota-packages">Signing OTA packages</h2>
+
+A signed target-files zip can be converted into a signed OTA update zip
+using the following procedure:
+
+<pre class="no-pretty-print">
+./build/tools/releasetools/ota_from_target_files \
+ -k ~/.android-certs/releasekey \
+ signed-target_files.zip \
+ signed-ota_update.zip
+</pre>
+
+<h3 id="signatures-sideloading">Signatures and sideloading</h3>
+<p>Sideloading does not bypass recovery's normal package signature
+verification mechanism—before installing a package, recovery will verify that
+it is signed with one of the private keys matching the public keys stored in
+the recovery partition, just as it would for a package delivered over-the-air.
+</p>
+
+<p>Update packages received from the main system are typically verified twice:
+once by the main system, using the
+<code><a href="http://developer.android.com/reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem.verifyPackage()</a></code>
+method in the android API, and then again by
+recovery. The RecoverySystem API checks the signature against public keys
+stored in the main system, in the file <code>/system/etc/security/otacerts.zip
+</code> (by default). Recovery checks the signature against public keys stored
+in the recovery partition RAM disk, in the file <code>/res/keys</code>.</p>
+
+<p>By default, the target-files .zip produced by the build sets the OTA
+certificate to match the test key. On a released image, a
+different certificate must be used so that devices can verify the
+authenticity of the update package. Passing the <code>-o</code> flag to
+<code>sign_target_files_apks</code>, as shown in the previous section, replaces
+the test key certificate with the release key certificate from your certs
+directory.</p>
+
+<p>Normally the system image and recovery image store the same set of OTA
+public keys. By adding a key to <i>just</i> the recovery set of keys, it is
+possible to sign packages that can be installed only via sideloading
+(assuming the main system's update download mechanism is correctly doing
+verification against otacerts.zip). You can specify extra keys to be
+included only in recovery by setting the PRODUCT_EXTRA_RECOVERY_KEYS
+variable in your product definition:</p>
+
+<p><code>vendor/yoyodyne/tardis/products/tardis.mk</code></p>
+<pre class="no-pretty-print">
+ [...]
+
+PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
+</pre>
+
+<p>This includes the public key
+<code>vendor/yoyodyne/security/tardis/sideload.x509.pem</code> in the recovery
+keys file so it can install packages signed
+with it. The extra key is <i>not</i> included in otacerts.zip though, so
+systems that correctly verify downloaded packages do not invoke recovery for
+packages signed with this key.</p>
+
+<h2 id="certificates-keys">Certificates and private keys</h2>
<p>Each key comes in two files: the <i>certificate</i>, which has the
extension .x509.pem, and the <i>private key</i>, which has the extension .pk8.
The private key should be kept secret and is needed to sign a package. The key
-may itself be protected by a password—a reasonable strategy is to store your
-keys in source control along with the code—but keep them protected by a
-password known only to the people who make final releases. The certificate, in
+may itself be protected by a password. The certificate, in
contrast, contains only the public half of the key, so it can be distributed
widely. It is used to verify a package has been signed by the corresponding
private key.</p>
@@ -64,7 +168,7 @@
can also specify an entirely different key by pathname, e.g.:</p>
<p><code>device/yoyodyne/apps/SpecialApp/Android.mk</code></p>
-<pre>
+<pre class="no-pretty-print">
[...]
LOCAL_CERTIFICATE := device/yoyodyne/security/special
@@ -74,63 +178,16 @@
</code> key to sign SpecialApp.apk. The build can use only private keys that
are <i>not </i>password protected.</p>
-<h2>Generating keys</h2>
-<p>Android uses 2048-bit RSA keys with public exponent 3. You can generate
-certificate/private key pairs using the openssl tool from
-<a href="http://www.openssl.org/">openssl.org</a>:</p>
-
-<pre>
-# generate RSA key
-% <b>openssl genrsa -3 -out temp.pem 2048</b>
-Generating RSA private key, 2048 bit long modulus
-....+++
-.....................+++
-e is 3 (0x3)
-
-# create a certificate with the public part of the key
-% <b>openssl req -new -x509 -key temp.pem -out releasekey.x509.pem \
- -days 10000 \
- -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'</b>
-
-# create a PKCS#8-formatted version of the private key
-% <b>openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt</b>
-
-# securely delete the temp.pem file
-% <b>shred --remove temp.pem</b>
-</pre>
-
-<p>The openssl pkcs8 command given above creates a .pk8 file with <i>no</i>
-password, suitable for use with the build system. To create a .pk8 secured
-with a password (which you should do for all actual release keys), replace the
-<code>-nocrypt</code> argument with <code>-passout stdin</code>; then openssl
-will encrypt the private key with a password read from standard input. No
-prompt is printed, so if stdin is the terminal the program will appear to hang
-when it's really just waiting for you to enter a password. Other values can be
-used for the-passout argument to read the password from other locations; for
-details, see the
-<a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS">
-openssl documentation</a>.</p>
-<p>The temp.pem intermediate file contains the private key without any kind of
-password protection, so dispose of it thoughtfully when generating release
-keys. In particular, the GNUshred utility may not be effective on network or
-journaled filesystems. You can use a working directory located in a RAM disk
-(such as a tmpfs partition) when generating keys to ensure the intermediates
-are not inadvertently exposed.</p>
-
-<h2 id="sign-apps-for-release">Signing apps for release</h2>
-<p>The first step in preparing a build for release is to sign all the .apk
-files in it, replacing the test keys used by the build system. This is done
-with the <code>sign_target_files_apks</code> script. It takes a target-files
-.zip as input and produces a new target-files .zip in which all the .apks have
-been signed with new keys.</p>
-<p>When you run this script, you must specify on the command line a
-replacement key for each key used in the build. The <code>-k <i>src_key</i>=<i>
+<h2 id="advanced-signing-options">Advanced signing options</h2>
+<p>When you run the <code>sign_target_files_apks</code> script, you must
+specify on the command line a replacement key for each key used in the build.
+The <code>-k <i>src_key</i>=<i>
dest_key</i></code> flag specifies key replacements one at a time. The flag
<code>-d <i>dir</i></code> lets you specify a directory with four keys to
replace all those in <code>build/target/product/security</code>; it is
equivalent to using <code>-k</code> four times to specify the mappings:</p>
-<pre>
+<pre class="no-pretty-print">
build/target/product/security/testkey = dir/releasekey
build/target/product/security/platform = dir/platform
build/target/product/security/shared = dir/shared
@@ -143,7 +200,7 @@
required by SpecialApp in the example above. If the keys were in the following
files:</p>
-<pre>
+<pre class="no-pretty-print">
vendor/yoyodyne/security/tardis/releasekey.x509.pem
vendor/yoyodyne/security/tardis/releasekey.pk8
vendor/yoyodyne/security/tardis/platform.x509.pem
@@ -160,11 +217,11 @@
<p>Then you would sign all the apps like this:</p>
-<pre>
+<pre class="no-pretty-print">
% <b>./build/tools/releasetools/sign_target_files_apks \
-d vendor/yoyodyne/security/tardis \
-k vendor/yoyodyne/special=vendor/yoyodyne/special-release \
- -o \ </b># explained in the next section<b>
+ -o \
tardis-target_files.zip signed-tardis-target_files.zip</b>
Enter password for vendor/yoyodyne/security/special-release key>
Enter password for vendor/yoyodyne/security/tardis/media key>
@@ -207,63 +264,45 @@
fingerprint. Run the script with <code>-h</code> to see documentation on all
flags.</p>
-<h2 id="sign-ota-packages">Signing OTA packages</h2>
-<p>You need the following components to sign OTA packages:</p>
-<ol>
-<li>Certificates of the keys you want this build to accept.</li>
-<li>Sign the newly-created package with the private key (must correspond to
-the certificate embedded in the current build of any device to which you want
-to send this package).</li>
-</ol>
-<p>To achieve these components:</p>
-<ul>
-<li>The target-files .zip produced by the build sets the OTA certificate to
-the certificate of the test key. Passing the <code>-o</code> flag to <code>
-sign_target_files_apks</code> replaces this key with the release key from your
-build.</li>
-<li>To sign the OTA update package, use the <code>-k</code> option when
-generating it to specify the key. You should give <code>ota_from_target_files
-</code> the <i>signed</i> version of the target-files .zip as well:
-<pre>
-% <b>./build/tools/releasetools/ota_from_target_files \
- -k vendor/yoyodyne/security/tardis/releasekey \
- signed-tardis-target_files.zip \
- signed-ota_update.zip</b>
-unzipping target target-files...
-(using device-specific extensions from target_files)
-Enter password for vendor/yoyodyne/security/tardis/releasekey key>
-done.</pre></li></ul>
+<h2 id="manually-generating-keys">Manually generating keys</h2>
+<p>Android uses 2048-bit RSA keys with public exponent 3. You can generate
+certificate/private key pairs using the openssl tool from
+<a href="http://www.openssl.org/">openssl.org</a>:</p>
-<h3 id="signatures-sideloading">Signatures and sideloading</h3>
-<p>Sideloading does not bypass recovery's normal package signature
-verification mechanism—before installing a package, recovery will verify that
-it is signed with one of the private keys matching the public keys stored in
-the recovery partition, just as it would for a package delivered over-the-air.
-</p>
-<p>Update packages received from the main system are typically verified twice:
-once by the main system, using the <code><a href="http://developer.android.com/
-reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem.
-verifyPackage()</a></code> method in the android API, and then again by
-recovery. The RecoverySystem API checks the signature against public keys
-stored in the main system, in the file <code>/system/etc/security/otacerts.zip
-</code> (by default). Recovery checks the signature against public keys stored
-in the recovery partition RAM disk, in the file <code>/res/keys</code>.</p>
-<p>Normally these two locations store the same set of keys. By adding a key to
-<i>just</i> the recovery set of keys, it's possible to sign packages that can
-be installed only via sideloading (assuming the main system's update download
-mechanism is correctly doing verification against otacerts.zip). You can
-specify extra keys to be included only in recovery by setting the
-PRODUCT_EXTRA_RECOVERY_KEYS variable in your product definition:</p>
+<pre class="no-pretty-print">
+# generate RSA key
+% <b>openssl genrsa -3 -out temp.pem 2048</b>
+Generating RSA private key, 2048 bit long modulus
+....+++
+.....................+++
+e is 3 (0x3)
-<p><code>vendor/yoyodyne/tardis/products/tardis.mk</code></p>
-<pre>
- [...]
+# create a certificate with the public part of the key
+% <b>openssl req -new -x509 -key temp.pem -out releasekey.x509.pem \
+ -days 10000 \
+ -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'</b>
-PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
+# create a PKCS#8-formatted version of the private key
+% <b>openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt</b>
+
+# securely delete the temp.pem file
+% <b>shred --remove temp.pem</b>
</pre>
-<p>This includes the public key <code>vendor/yoyodyne/security/tardis/sideload.
-x509.pem</code> in the recovery keys file so it can install packages signed
-with it. The extra key is <i>not</i> included in otacerts.zip though, so
-systems that correctly verify downloaded packages do not invoke recovery for
-packages signed with this key.</p>
\ No newline at end of file
+<p>The openssl pkcs8 command given above creates a .pk8 file with <i>no</i>
+password, suitable for use with the build system. To create a .pk8 secured
+with a password (which you should do for all actual release keys), replace the
+<code>-nocrypt</code> argument with <code>-passout stdin</code>; then openssl
+will encrypt the private key with a password read from standard input. No
+prompt is printed, so if stdin is the terminal the program will appear to hang
+when it's really just waiting for you to enter a password. Other values can be
+used for the-passout argument to read the password from other locations; for
+details, see the
+<a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS">
+openssl documentation</a>.</p>
+<p>The temp.pem intermediate file contains the private key without any kind of
+password protection, so dispose of it thoughtfully when generating release
+keys. In particular, the GNUshred utility may not be effective on network or
+journaled filesystems. You can use a working directory located in a RAM disk
+(such as a tmpfs partition) when generating keys to ensure the intermediates
+are not inadvertently exposed.</p>