1page.title=Updating Your Security Provider to Protect Against SSL Exploits
2page.tags="network","certificates"
3
4page.article=true
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9<h2>In this document</h2>
10<ol class="nolist">
11  <li><a href="#patching">Patching the Security Provider with
12      ProviderInstaller</a></li>
13  <li><a href="#example_sync">Patching Synchronously</a></li>
14  <li><a href="#example_async">Patching Asynchronously</a></li>
15
16</ol>
17
18
19<h2>See also</h2>
20<ul>
21  <li><a href="{@docRoot}google/play-services/">Google Play Services</a></li>
22  <li><a href="https://www.openssl.org/news/secadv_20140605.txt">OpenSSL
23   Security Advisory [05 Jun 2014]: SSL/TLS MITM vulnerability
24   (CVE-2014-0224)</a></li>
25  <li><a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224">
26    Vulnerability Summary for CVE-2014-0224</a></li>
27</ul>
28</div>
29</div>
30
31
32<p> Android relies on a security {@link java.security.Provider Provider} to
33provide secure network communications. However, from time to time,
34vulnerabilities are found in the default security provider. To protect against
35these vulnerabilities, <a href="{@docRoot}google/play-services/">Google Play
36services</a> provides a way to automatically update a device's security provider
37to protect against known exploits. By calling Google Play services methods, your
38app can ensure that it's running on a device that has the latest updates to
39protect against known exploits.</p>
40
41<p>For example, a vulnerability was discovered in OpenSSL
42(<a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224">CVE-2014-0224</a>)
43that can leave apps open to a "man-in-the-middle" attack that decrypts
44secure traffic without either side knowing. With Google Play services version
455.0, a fix is available, but apps must ensure that this fix is installed. By
46using the Google Play services methods, your app can ensure that it's running
47on a device that's secured against that attack.</p>
48
49<p class="caution"><strong>Caution: </strong>Updating a device's security {@link
50java.security.Provider Provider} does <em>not</em> update {@link
51android.net.SSLCertificateSocketFactory
52android.net.SSLCertificateSocketFactory}. Rather than using this class, we
53encourage app developers to use high-level methods for interacting with
54cryptography. Most apps can use APIs like {@link
55javax.net.ssl.HttpsURLConnection}, {@link org.apache.http.client.HttpClient},
56and {@link android.net.http.AndroidHttpClient} without needing to set a custom
57{@link javax.net.ssl.TrustManager} or create an {@link
58android.net.SSLCertificateSocketFactory}.</p>
59
60<h2 id="patching">Patching the Security Provider with ProviderInstaller</h2>
61
62<p>To update a device's security provider, use the
63<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a>
64class. You can verify that the security provider is up-to-date (and update it,
65if necessary) by calling
66that class's <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>
67(or <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>)
68method.</p>
69
70<p>When you call <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>, the
71<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a>
72does the following:</p>
73
74<ul>
75  <li>If the device's {@link java.security.Provider Provider} is successfully
76    updated (or is already up-to-date), the method returns normally.</li>
77  <li>If the device's Google Play services library is out of date, the method
78    throws
79    <a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesRepairableException.html">{@code GooglePlayServicesRepairableException}</a>.
80    The app can then catch this exception and show
81    the user an appropriate dialog box to update Google Play services.</li>
82    <li>If a non-recoverable error occurs, the method throws
83    <a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesNotAvailableException.html">{@code GooglePlayServicesNotAvailableException}</a>
84    to indicate that it is unable to update the {@link java.security.Provider
85    Provider}. The app can then catch the exception and choose an appropriate
86    course of action, such as displaying the standard
87    <a href="{@docRoot}reference/com/google/android/gms/common/SupportErrorDialogFragment.html">fix-it flow diagram</a>.</li>
88</ul>
89
90<p>The
91<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>
92method behaves similarly, except that instead of
93throwing exceptions, it calls the appropriate callback method to indicate
94success or failure.</p>
95
96<p>If <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>
97needs to install a new {@link java.security.Provider Provider}, this can take
98anywhere from 30-50 milliseconds (on more recent devices) to 350 ms (on older
99devices). If the security provider is already up-to-date, the method takes a
100negligible amount of time. To avoid affecting user experience:</p>
101
102<ul>
103  <li>Call
104  <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>
105  from background networking threads immediately when the threads are loaded,
106  instead of waiting for the thread to try to use the network. (There's no harm
107  in calling the method multiple times, since it returns immediately if the
108  security provider doesn't need updating.)</li>
109
110  <li>If user experience will be affected by the thread blocking--for example,
111  if the call is from an activity in the UI thread--call the asynchronous
112  version of the method,
113  <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>.
114  (Of course, if you do this, you need to wait for the operation to finish
115  before you attempt any secure communications. The
116  <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a>
117  calls your listener's <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstalled()">{@code onProviderInstalled()}</a>
118  method to signal success.)</li>
119</ul>
120
121<p class="warning"><strong>Warning:</strong> If the
122<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html">{@code ProviderInstaller}</a>
123is unable to install an updated {@link java.security.Provider Provider},
124your device's security provider might be vulnerable  to known exploits. Your app
125should behave as if all HTTP communication is unencrypted.</p>
126
127<p>Once the {@link java.security.Provider Provider} is updated, all calls to
128security APIs (including SSL APIs) are routed through it.
129(However, this does not apply to  {@link android.net.SSLCertificateSocketFactory
130android.net.SSLCertificateSocketFactory}, which remains vulnerable to such
131exploits as
132<a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224">CVE-2014-0224</a>.)</p>
133
134<h2 id="example_sync">Patching Synchronously</h2>
135
136<p>The simplest way to patch the security provider is to call the synchronous
137method <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>.
138This is appropriate if user experience won't be affected by the thread blocking
139while it waits for the operation to finish.</p>
140
141<p>For example, here's an implementation of a <a href="{@docRoot}training/sync-adapters">sync adapter</a> that updates the security provider. Since a sync
142adapter runs in the background, it's okay if the thread blocks while waiting
143for the security provider to be updated. The sync adapter calls
144<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a> to
145update the security provider. If the method returns normally, the sync adapter
146knows the security provider is up-to-date. If the method throws an exception,
147the sync adapter can take appropriate action (such as prompting the user to
148update Google Play services).</p>
149
150<pre>/**
151 * Sample sync adapter using {&#64;link ProviderInstaller}.
152 */
153public class SyncAdapter extends AbstractThreadedSyncAdapter {
154
155  ...
156
157  // This is called each time a sync is attempted; this is okay, since the
158  // overhead is negligible if the security provider is up-to-date.
159  &#64;Override
160  public void onPerformSync(Account account, Bundle extras, String authority,
161      ContentProviderClient provider, SyncResult syncResult) {
162    try {
163      ProviderInstaller.installIfNeeded(getContext());
164    } catch (GooglePlayServicesRepairableException e) {
165
166      // Indicates that Google Play services is out of date, disabled, etc.
167
168      // Prompt the user to install/update/enable Google Play services.
169      GooglePlayServicesUtil.showErrorNotification(
170          e.getConnectionStatusCode(), getContext());
171
172      // Notify the SyncManager that a soft error occurred.
173      syncResult.stats.numIOExceptions++;
174      return;
175
176    } catch (GooglePlayServicesNotAvailableException e) {
177      // Indicates a non-recoverable error; the ProviderInstaller is not able
178      // to install an up-to-date Provider.
179
180      // Notify the SyncManager that a hard error occurred.
181      syncResult.stats.numAuthExceptions++;
182      return;
183    }
184
185    // If this is reached, you know that the provider was already up-to-date,
186    // or was successfully updated.
187  }
188}</pre>
189
190<h2 id="example_async">Patching Asynchronously</h2>
191
192<p>Updating the security provider can take as much as 350 milliseconds (on
193older devices). If you're doing the update on a thread that directly affects
194user experience, such as the UI thread, you don't want to make a synchronous
195call to update the provider, since that can result in the app or device
196freezing until the operation finishes. Instead, you should use the asynchronous
197method
198<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>.
199That method indicates its success or failure by calling callbacks.</p>
200
201<p>For example, here's some code that updates the security provider in an
202activity in the UI thread. The activity calls <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html#installIfNeededAsync(android.content.Context, com.google.android.gms.security.ProviderInstaller.ProviderInstallListener)">{@code installIfNeededAsync()}</a>
203to update the provider, and designates itself as the listener to receive success
204or failure notifications. If the security provider is up-to-date or is
205successfully updated, the activity's
206<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstalled()">{@code onProviderInstalled()}</a>
207method is called, and the activity knows communication is secure. If the
208provider cannot be updated, the activity's
209<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstallFailed(int, android.content.Intent)">{@code onProviderInstallFailed()}</a>
210method is called, and the activity can take appropriate action (such as
211prompting the user to update Google Play services).</p>
212
213<pre>/**
214 * Sample activity using {&#64;link ProviderInstaller}.
215 */
216public class MainActivity extends Activity
217    implements ProviderInstaller.ProviderInstallListener {
218
219  private static final int ERROR_DIALOG_REQUEST_CODE = 1;
220
221  private boolean mRetryProviderInstall;
222
223  //Update the security provider when the activity is created.
224  &#64;Override
225  protected void onCreate(Bundle savedInstanceState) {
226    super.onCreate(savedInstanceState);
227    ProviderInstaller.installIfNeededAsync(this, this);
228  }
229
230  /**
231   * This method is only called if the provider is successfully updated
232   * (or is already up-to-date).
233   */
234  &#64;Override
235  protected void onProviderInstalled() {
236    // Provider is up-to-date, app can make secure network calls.
237  }
238
239  /**
240   * This method is called if updating fails; the error code indicates
241   * whether the error is recoverable.
242   */
243  &#64;Override
244  protected void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {
245    if (GooglePlayServicesUtil.isUserRecoverableError(errorCode)) {
246      // Recoverable error. Show a dialog prompting the user to
247      // install/update/enable Google Play services.
248      GooglePlayServicesUtil.showErrorDialogFragment(
249          errorCode,
250          this,
251          ERROR_DIALOG_REQUEST_CODE,
252          new DialogInterface.OnCancelListener() {
253            &#64;Override
254            public void onCancel(DialogInterface dialog) {
255              // The user chose not to take the recovery action
256              onProviderInstallerNotAvailable();
257            }
258          });
259    } else {
260      // Google Play services is not available.
261      onProviderInstallerNotAvailable();
262    }
263  }
264
265  &#64;Override
266  protected void onActivityResult(int requestCode, int resultCode,
267      Intent data) {
268    super.onActivityResult(requestCode, resultCode, data);
269    if (requestCode == ERROR_DIALOG_REQUEST_CODE) {
270      // Adding a fragment via GooglePlayServicesUtil.showErrorDialogFragment
271      // before the instance state is restored throws an error. So instead,
272      // set a flag here, which will cause the fragment to delay until
273      // onPostResume.
274      mRetryProviderInstall = true;
275    }
276  }
277
278  /**
279   * On resume, check to see if we flagged that we need to reinstall the
280   * provider.
281   */
282  &#64;Override
283  protected void onPostResume() {
284    super.onPostResult();
285    if (mRetryProviderInstall) {
286      // We can now safely retry installation.
287      ProviderInstall.installIfNeededAsync(this, this);
288    }
289    mRetryProviderInstall = false;
290  }
291
292  private void onProviderInstallerNotAvailable() {
293    // This is reached if the provider cannot be updated for some reason.
294    // App should consider all HTTP communication to be vulnerable, and take
295    // appropriate action.
296  }
297}
298</pre>
299