Skip to content

Commit 8e115e6

Browse files
Robert LyAndroid (Google) Code Review
authored andcommitted
Merge "docs: Documenting fix for CVE-2014-0224 (SSL vulnerability)." into klp-modular-docs
2 parents ea12f0f + 897cf90 commit 8e115e6

File tree

2 files changed

+306
-0
lines changed

2 files changed

+306
-0
lines changed
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
page.title=Updating Your Security Provider to Protect Against SSL Exploits
2+
page.tags="network","certificates"
3+
4+
page.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
33+
provide secure network communications. However, from time to time,
34+
vulnerabilities are found in the default security provider. To protect against
35+
these vulnerabilities, <a href="{@docRoot}google/play-services/">Google Play
36+
services</a> provides a way to automatically update a device's security provider
37+
to protect against known exploits. By calling Google Play services methods, your
38+
app can ensure that it's running on a device that has the latest updates to
39+
protect 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>)
43+
that can leave apps open to a "man-in-the-middle" attack that decrypts
44+
secure traffic without either side knowing. With Google Play services version
45+
5.0, a fix is available, but apps must ensure that this fix is installed. By
46+
using the Google Play services methods, your app can ensure that it's running
47+
on a device that's secured against that attack.</p>
48+
49+
<p class="caution"><strong>Caution: </strong>Updating a device's security {@link
50+
java.security.Provider Provider} does <em>not</em> update {@link
51+
android.net.SSLCertificateSocketFactory
52+
android.net.SSLCertificateSocketFactory}. Rather than using this class, we
53+
encourage app developers to use high-level methods for interacting with
54+
cryptography. Most apps can use APIs like {@link
55+
javax.net.ssl.HttpsURLConnection}, {@link org.apache.http.client.HttpClient},
56+
and {@link android.net.http.AndroidHttpClient} without needing to set a custom
57+
{@link javax.net.ssl.TrustManager} or create an {@link
58+
android.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>
64+
class. You can verify that the security provider is up-to-date (and update it,
65+
if necessary) by calling
66+
that 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>)
68+
method.</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>
72+
does 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>
92+
method behaves similarly, except that instead of
93+
throwing exceptions, it calls the appropriate callback method to indicate
94+
success 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>
97+
needs to install a new {@link java.security.Provider Provider}, this can take
98+
anywhere from 30-50 milliseconds (on more recent devices) to 350 ms (on older
99+
devices). If the security provider is already up-to-date, the method takes a
100+
negligible 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>
123+
is unable to install an updated {@link java.security.Provider Provider},
124+
your device's security provider might be vulnerable to known exploits. Your app
125+
should behave as if all HTTP communication is unencrypted.</p>
126+
127+
<p>Once the {@link java.security.Provider Provider} is updated, all calls to
128+
security APIs (including SSL APIs) are routed through it.
129+
(However, this does not apply to {@link android.net.SSLCertificateSocketFactory
130+
android.net.SSLCertificateSocketFactory}, which remains vulnerable to such
131+
exploits 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
137+
method <a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.html##installIfNeeded(android.content.Context)">{@code installIfNeeded()}</a>.
138+
This is appropriate if user experience won't be affected by the thread blocking
139+
while 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
142+
adapter runs in the background, it's okay if the thread blocks while waiting
143+
for 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
145+
update the security provider. If the method returns normally, the sync adapter
146+
knows the security provider is up-to-date. If the method throws an exception,
147+
the sync adapter can take appropriate action (such as prompting the user to
148+
update Google Play services).</p>
149+
150+
<pre>/**
151+
* Sample sync adapter using {&#64;link ProviderInstaller}.
152+
*/
153+
public 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
193+
older devices). If you're doing the update on a thread that directly affects
194+
user experience, such as the UI thread, you don't want to make a synchronous
195+
call to update the provider, since that can result in the app or device
196+
freezing until the operation finishes. Instead, you should use the asynchronous
197+
method
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>.
199+
That 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
202+
activity 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>
203+
to update the provider, and designates itself as the listener to receive success
204+
or failure notifications. If the security provider is up-to-date or is
205+
successfully updated, the activity's
206+
<a href="{@docRoot}reference/com/google/android/gms/security/ProviderInstaller.ProviderInstallListener.html#onProviderInstalled()">{@code onProviderInstalled()}</a>
207+
method is called, and the activity knows communication is secure. If the
208+
provider 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>
210+
method is called, and the activity can take appropriate action (such as
211+
prompting the user to update Google Play services).</p>
212+
213+
<pre>/**
214+
* Sample activity using {&#64;link ProviderInstaller}.
215+
*/
216+
public 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>

docs/html/training/training_toc.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,6 +1487,14 @@ Communicating with the UI Thread
14871487
>Security with HTTPS and SSL</a>
14881488
</li>
14891489

1490+
<li>
1491+
<a href="<?cs var:toroot ?>training/articles/security-gms-provider.html"
1492+
description=
1493+
"How to use and update Google Play services security provider, to
1494+
protect against SSL exploits."
1495+
>Updating Your Security Provider to Protect Against SSL Exploits</a>
1496+
</li>
1497+
14901498
<li class="nav-section">
14911499
<div class="nav-section-header">
14921500
<a href="<?cs var:toroot ?>training/enterprise/index.html"

0 commit comments

Comments
 (0)