Home | History | Annotate | Download | only in ota
      1 page.title=Signing Builds for Release
      2 @jd:body
      3 
      4 <!--
      5     Copyright 2015 The Android Open Source Project
      6 
      7     Licensed under the Apache License, Version 2.0 (the "License");
      8     you may not use this file except in compliance with the License.
      9     You may obtain a copy of the License at
     10 
     11         http://www.apache.org/licenses/LICENSE-2.0
     12 
     13     Unless required by applicable law or agreed to in writing, software
     14     distributed under the License is distributed on an "AS IS" BASIS,
     15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16     See the License for the specific language governing permissions and
     17     limitations under the License.
     18 -->
     19 
     20 <div id="qv-wrapper">
     21   <div id="qv">
     22     <h2>In this document</h2>
     23     <ol id="auto-toc">
     24     </ol>
     25   </div>
     26 </div>
     27 
     28 <p>Android uses cryptographic signatures in two places:</p>
     29 <ol>
     30 <li>Each .apk file must be signed. Android's Package Manager uses an .apk
     31 signature in two ways:<ul>
     32 <li>When an application is replaced, it must be signed by the same key as the
     33 old application in order to get access to the old application's data.</li>
     34 <li>If two or more applications want to share a user ID (so they can share
     35 data, etc.), they must be signed with the same key.</ul></li>
     36 <li>OTA update packages must be signed with one of the keys expected by the
     37 system or the installation process will reject them.</ul></li>
     38 </ol>
     39 <h2 id="certificates-keys">Certificates and keys</h2>
     40 <p>Each key comes in two files: the <i>certificate</i>, which has the
     41 extension .x509.pem, and the <i>private key</i>, which has the extension .pk8.
     42 The private key should be kept secret and is needed to sign a package. The key
     43 may itself be protected by a passworda reasonable strategy is to store your
     44 keys in source control along with the codebut keep them protected by a
     45 password known only to the people who make final releases. The certificate, in
     46 contrast, contains only the public half of the key, so it can be distributed
     47 widely. It is used to verify a package has been signed by the corresponding
     48 private key.</p>
     49 <p>The standard Android build uses four keys, all of which reside in <code>
     50 build/target/product/security</code>:</p>
     51 
     52 <dl>
     53 <dt>testkey</dt>
     54 <dd>Generic default key for packages that do not otherwise specify a key.</dd>
     55 <dt>platform</dt>
     56 <dd>Test key for packages that are part of the core platform.</dd>
     57 <dt>shared</dt>
     58 <dd>Test key for things that are shared in the home/contacts process.</dd>
     59 <dt>media</dt>
     60 <dd>Test key for packages that are part of the media/download system.</dd></dl>
     61 
     62 <p>Individual packages specify one of these keys by setting LOCAL_CERTIFICATE
     63 in their Android.mk file. (testkey is used if this variable is not set.) You
     64 can also specify an entirely different key by pathname, e.g.:</p>
     65 
     66 <p><code>device/yoyodyne/apps/SpecialApp/Android.mk</code></p>
     67 <pre>
     68  [...]
     69 
     70 LOCAL_CERTIFICATE := device/yoyodyne/security/special
     71 </pre>
     72 
     73 <p>Now the build uses the <code>device/yoyodyne/security/special.{x509.pem,pk8}
     74 </code> key to sign SpecialApp.apk. The build can use only private keys that
     75 are <i>not </i>password protected.</p>
     76 
     77 <h2>Generating keys</h2>
     78 <p>Android uses 2048-bit RSA keys with public exponent 3. You can generate
     79 certificate/private key pairs using the openssl tool from
     80 <a href="http://www.openssl.org/">openssl.org</a>:</p>
     81 
     82 <pre>
     83 # generate RSA key
     84 % <b>openssl genrsa -3 -out temp.pem 2048</b>
     85 Generating RSA private key, 2048 bit long modulus
     86 ....+++
     87 .....................+++
     88 e is 3 (0x3)
     89 
     90 # create a certificate with the public part of the key
     91 % <b>openssl req -new -x509 -key temp.pem -out releasekey.x509.pem \
     92   -days 10000 \
     93   -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne (a] example.com'</b>
     94 
     95 # create a PKCS#8-formatted version of the private key
     96 % <b>openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt</b>
     97 
     98 # securely delete the temp.pem file
     99 % <b>shred --remove temp.pem</b>
    100 </pre>
    101 
    102 <p>The openssl pkcs8 command given above creates a .pk8 file with <i>no</i>
    103 password, suitable for use with the build system. To create a .pk8 secured
    104 with a password (which you should do for all actual release keys), replace the
    105 <code>-nocrypt</code> argument with <code>-passout stdin</code>; then openssl
    106 will encrypt the private key with a password read from standard input. No
    107 prompt is printed, so if stdin is the terminal the program will appear to hang
    108 when it's really just waiting for you to enter a password. Other values can be
    109 used for the-passout argument to read the password from other locations; for
    110 details, see the
    111 <a href="http://www.openssl.org/docs/apps/openssl.html#PASS_PHRASE_ARGUMENTS">
    112 openssl documentation</a>.</p>
    113 <p>The temp.pem intermediate file contains the private key without any kind of
    114 password protection, so dispose of it thoughtfully when generating release
    115 keys. In particular, the GNUshred utility may not be effective on network or
    116 journaled filesystems. You can use a working directory located in a RAM disk
    117 (such as a tmpfs partition) when generating keys to ensure the intermediates
    118 are not inadvertently exposed.</p>
    119 
    120 <h2 id="sign-apps-for-release">Signing apps for release</h2>
    121 <p>The first step in preparing a build for release is to sign all the .apk
    122 files in it, replacing the test keys used by the build system. This is done
    123 with the <code>sign_target_files_apks</code> script. It takes a target-files
    124 .zip as input and produces a new target-files .zip in which all the .apks have
    125 been signed with new keys.</p>
    126 <p>When you run this script, you must specify on the command line a
    127 replacement key for each key used in the build. The <code>-k <i>src_key</i>=<i>
    128 dest_key</i></code> flag specifies key replacements one at a time. The flag
    129 <code>-d <i>dir</i></code> lets you specify a directory with four keys to
    130 replace all those in <code>build/target/product/security</code>; it is
    131 equivalent to using <code>-k</code> four times to specify the mappings:</p>
    132 
    133 <pre>
    134 build/target/product/security/testkey  = dir/releasekey
    135 build/target/product/security/platform = dir/platform
    136 build/target/product/security/shared   = dir/shared
    137 build/target/product/security/media    = dir/media
    138 </pre>
    139 
    140 <p>For the hypothetical tardis product, you need five password-protected keys:
    141 four to replace the four in <code>build/target/product/security</code>, and
    142 one to replace the additional <code>keydevice/yoyodyne/security/special</code>
    143 required by SpecialApp in the example above. If the keys were in the following
    144 files:</p>
    145 
    146 <pre>
    147 vendor/yoyodyne/security/tardis/releasekey.x509.pem
    148 vendor/yoyodyne/security/tardis/releasekey.pk8
    149 vendor/yoyodyne/security/tardis/platform.x509.pem
    150 vendor/yoyodyne/security/tardis/platform.pk8
    151 vendor/yoyodyne/security/tardis/shared.x509.pem
    152 vendor/yoyodyne/security/tardis/shared.pk8
    153 vendor/yoyodyne/security/tardis/media.x509.pem
    154 vendor/yoyodyne/security/tardis/media.pk8
    155 vendor/yoyodyne/security/special.x509.pem
    156 vendor/yoyodyne/security/special.pk8           # NOT password protected
    157 vendor/yoyodyne/security/special-release.x509.pem
    158 vendor/yoyodyne/security/special-release.pk8   # password protected
    159 </pre>
    160 
    161 <p>Then you would sign all the apps like this:</p>
    162 
    163 <pre>
    164 % <b>./build/tools/releasetools/sign_target_files_apks \
    165     -d vendor/yoyodyne/security/tardis \
    166     -k vendor/yoyodyne/special=vendor/yoyodyne/special-release \
    167     -o \    </b># explained in the next section<b>
    168     tardis-target_files.zip signed-tardis-target_files.zip</b>
    169 Enter password for vendor/yoyodyne/security/special-release key&gt;
    170 Enter password for vendor/yoyodyne/security/tardis/media key&gt;
    171 Enter password for vendor/yoyodyne/security/tardis/platform key&gt;
    172 Enter password for vendor/yoyodyne/security/tardis/releasekey key&gt;
    173 Enter password for vendor/yoyodyne/security/tardis/shared key&gt;
    174     signing: Phone.apk (vendor/yoyodyne/security/tardis/platform)
    175     signing: Camera.apk (vendor/yoyodyne/security/tardis/media)
    176     signing: Special.apk (vendor/yoyodyne/security/special-release)
    177     signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey)
    178         [...]
    179     signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared)
    180     signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared)
    181 rewriting SYSTEM/build.prop:
    182   replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
    183      with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
    184   replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
    185      with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
    186     signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform)
    187 rewriting RECOVERY/RAMDISK/default.prop:
    188   replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
    189      with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
    190   replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
    191      with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
    192 using:
    193     vendor/yoyodyne/security/tardis/releasekey.x509.pem
    194 for OTA package verification
    195 done.
    196 </pre>
    197 
    198 <p>After prompting the user for passwords for all password-protected keys, the
    199 script re-signs all the .apk files in the input target .zip with the release
    200 keys. Before running the command, you can also set the ANDROID_PW_FILE
    201 environment variable to a temporary filename; the script then invokes your
    202 editor to allow you to enter passwords for all keys (this may be a more
    203 convenient way to enter passwords).<p>
    204 <p><code>sign_target_files_apks</code> also rewrites the build description and
    205 fingerprint in the build properties files to reflect the fact that this is a
    206 signed build. The <code>-t</code> flag can control what edits are made to the
    207 fingerprint. Run the script with <code>-h</code> to see documentation on all
    208 flags.</p>
    209 
    210 <h2 id="sign-ota-packages">Signing OTA packages</h2>
    211 <p>You need the following components to sign OTA packages:</p>
    212 <ol>
    213 <li>Certificates of the keys you want this build to accept.</li>
    214 <li>Sign the newly-created package with the private key (must correspond to
    215 the certificate embedded in the current build of any device to which you want
    216 to send this package).</li>
    217 </ol>
    218 <p>To achieve these components:</p>
    219 <ul>
    220 <li>The target-files .zip produced by the build sets the OTA certificate to
    221 the certificate of the test key. Passing the <code>-o</code> flag to <code>
    222 sign_target_files_apks</code> replaces this key with the release key from your
    223 build.</li>
    224 <li>To sign the OTA update package, use the <code>-k</code> option when
    225 generating it to specify the key. You should give <code>ota_from_target_files
    226 </code> the <i>signed</i> version of the target-files .zip as well:
    227 <pre>
    228 % <b>./build/tools/releasetools/ota_from_target_files \
    229     -k vendor/yoyodyne/security/tardis/releasekey \
    230     signed-tardis-target_files.zip \
    231     signed-ota_update.zip</b>
    232 unzipping target target-files...
    233 (using device-specific extensions from target_files)
    234 Enter password for vendor/yoyodyne/security/tardis/releasekey key&gt;
    235 done.</pre></li></ul>
    236 
    237 <h3 id="signatures-sideloading">Signatures and sideloading</h3>
    238 <p>Sideloading does not bypass recovery's normal package signature
    239 verification mechanismbefore installing a package, recovery will verify that
    240 it is signed with one of the private keys matching the public keys stored in
    241 the recovery partition, just as it would for a package delivered over-the-air.
    242 </p>
    243 <p>Update packages received from the main system are typically verified twice:
    244 once by the main system, using the <code><a href="http://developer.android.com/
    245 reference/android/os/RecoverySystem.html#verifyPackage">RecoverySystem.
    246 verifyPackage()</a></code> method in the android API, and then again by
    247 recovery. The RecoverySystem API checks the signature against public keys
    248 stored in the main system, in the file <code>/system/etc/security/otacerts.zip
    249 </code> (by default). Recovery checks the signature against public keys stored
    250 in the recovery partition RAM disk, in the file <code>/res/keys</code>.</p>
    251 <p>Normally these two locations store the same set of keys. By adding a key to
    252 <i>just</i> the recovery set of keys, it's possible to sign packages that can
    253 be installed only via sideloading (assuming the main system's update download
    254 mechanism is correctly doing verification against otacerts.zip). You can
    255 specify extra keys to be included only in recovery by setting the
    256 PRODUCT_EXTRA_RECOVERY_KEYS variable in your product definition:</p>
    257 
    258 <p><code>vendor/yoyodyne/tardis/products/tardis.mk</code></p>
    259 <pre>
    260  [...]
    261 
    262 PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
    263 </pre>
    264 
    265 <p>This includes the public key <code>vendor/yoyodyne/security/tardis/sideload.
    266 x509.pem</code> in the recovery keys file so it can install packages signed
    267 with it. The extra key is <i>not</i> included in otacerts.zip though, so
    268 systems that correctly verify downloaded packages do not invoke recovery for
    269 packages signed with this key.</p>