1e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu/**
2e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * Copyright (c) 2016, The Android Open Source Project
3e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu *
4e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * Licensed under the Apache License, Version 2.0 (the "License");
5e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * you may not use this file except in compliance with the License.
6e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * You may obtain a copy of the License at
7e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu *
8e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu *     http://www.apache.org/licenses/LICENSE-2.0
9e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu *
10e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * Unless required by applicable law or agreed to in writing, software
11e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * distributed under the License is distributed on an "AS IS" BASIS,
12e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * See the License for the specific language governing permissions and
14e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * limitations under the License.
15e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu */
16e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
17e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiupackage android.net.wifi.hotspot2.pps;
18e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
19a25d717de870895be52e81b585a8484fff0c6109Peter Qiuimport android.net.wifi.EAPConstants;
20e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport android.net.wifi.ParcelUtil;
21e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport android.os.Parcelable;
22e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport android.os.Parcel;
23e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport android.text.TextUtils;
24a25d717de870895be52e81b585a8484fff0c6109Peter Qiuimport android.util.Log;
25e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
26444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiuimport java.nio.charset.StandardCharsets;
27a25d717de870895be52e81b585a8484fff0c6109Peter Qiuimport java.security.MessageDigest;
28a25d717de870895be52e81b585a8484fff0c6109Peter Qiuimport java.security.NoSuchAlgorithmException;
29e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport java.security.PrivateKey;
30e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport java.security.cert.CertificateEncodingException;
31e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport java.security.cert.X509Certificate;
32e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiuimport java.util.Arrays;
3389537734e19fac6947ee14a1b912c5c135042837Peter Qiuimport java.util.Date;
34a25d717de870895be52e81b585a8484fff0c6109Peter Qiuimport java.util.HashSet;
35ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiuimport java.util.Objects;
36a25d717de870895be52e81b585a8484fff0c6109Peter Qiuimport java.util.Set;
37e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
38e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu/**
39e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * Class representing Credential subtree in the PerProviderSubscription (PPS)
40e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * Management Object (MO) tree.
41e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
42e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * Release 2 Technical Specification.
43e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu *
44e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * In addition to the fields in the Credential subtree, this will also maintain necessary
45e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu * information for the private key and certificates associated with this credential.
46e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu */
47e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiupublic final class Credential implements Parcelable {
48a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    private static final String TAG = "Credential";
49a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
50a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    /**
51a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Max string length for realm.  Refer to Credential/Realm node in Hotspot 2.0 Release 2
52a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Technical Specification Section 9.1 for more info.
53a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     */
54444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu    private static final int MAX_REALM_BYTES = 253;
55444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu
56444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu    /**
57444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * The time this credential is created. It is in the format of number
58444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * of milliseconds since January 1, 1970, 00:00:00 GMT.
59444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * Using Long.MIN_VALUE to indicate unset value.
60444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     */
61967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu    private long mCreationTimeInMillis = Long.MIN_VALUE;
62a9f9889218ac972706830440990a59cbee685976Peter Qiu    /**
63a9f9889218ac972706830440990a59cbee685976Peter Qiu     * @hide
64a9f9889218ac972706830440990a59cbee685976Peter Qiu     */
65967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu    public void setCreationTimeInMillis(long creationTimeInMillis) {
66967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        mCreationTimeInMillis = creationTimeInMillis;
67aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
68a9f9889218ac972706830440990a59cbee685976Peter Qiu    /**
69a9f9889218ac972706830440990a59cbee685976Peter Qiu     * @hide
70a9f9889218ac972706830440990a59cbee685976Peter Qiu     */
71967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu    public long getCreationTimeInMillis() {
72967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        return mCreationTimeInMillis;
73aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
74444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu
75444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu    /**
76444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * The time this credential will expire. It is in the format of number
77444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * of milliseconds since January 1, 1970, 00:00:00 GMT.
78444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu    * Using Long.MIN_VALUE to indicate unset value.
79444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     */
80967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu    private long mExpirationTimeInMillis = Long.MIN_VALUE;
81a9f9889218ac972706830440990a59cbee685976Peter Qiu    /**
82a9f9889218ac972706830440990a59cbee685976Peter Qiu     * @hide
83a9f9889218ac972706830440990a59cbee685976Peter Qiu     */
84967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu    public void setExpirationTimeInMillis(long expirationTimeInMillis) {
85967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        mExpirationTimeInMillis = expirationTimeInMillis;
86aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
87a9f9889218ac972706830440990a59cbee685976Peter Qiu    /**
88a9f9889218ac972706830440990a59cbee685976Peter Qiu     * @hide
89a9f9889218ac972706830440990a59cbee685976Peter Qiu     */
90967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu    public long getExpirationTimeInMillis() {
91967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        return mExpirationTimeInMillis;
92aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
93a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
94e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
95e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * The realm associated with this credential.  It will be used to determine
96e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * if this credential can be used to authenticate with a given hotspot by
97e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * comparing the realm specified in that hotspot's ANQP element.
98e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
99aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private String mRealm = null;
100e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
101e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the realm associated with this credential.
102e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
103e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param realm The realm to set to
104e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
105aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setRealm(String realm) {
106aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mRealm = realm;
107aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
108e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
109e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the realm associated with this credential.
110e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
111e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return the realm associated with this credential
112e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
113aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public String getRealm() {
114aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mRealm;
115aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
116e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
117e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
118444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * When set to true, the device should check AAA (Authentication, Authorization,
119444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * and Accounting) server's certificate during EAP (Extensible Authentication
120444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     * Protocol) authentication.
121444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu     */
122da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu    private boolean mCheckAaaServerCertStatus = false;
123a9f9889218ac972706830440990a59cbee685976Peter Qiu    /**
124a9f9889218ac972706830440990a59cbee685976Peter Qiu     * @hide
125a9f9889218ac972706830440990a59cbee685976Peter Qiu     */
126da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu    public void setCheckAaaServerCertStatus(boolean checkAaaServerCertStatus) {
127da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu        mCheckAaaServerCertStatus = checkAaaServerCertStatus;
128aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
129a9f9889218ac972706830440990a59cbee685976Peter Qiu    /**
130a9f9889218ac972706830440990a59cbee685976Peter Qiu     * @hide
131a9f9889218ac972706830440990a59cbee685976Peter Qiu     */
132701a4b55c92817c84a77df84234946dbaac71dbaPeter Qiu    public boolean getCheckAaaServerCertStatus() {
133da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu        return mCheckAaaServerCertStatus;
134aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
135444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu
136444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu    /**
137e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * Username-password based credential.
138e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * Contains the fields under PerProviderSubscription/Credential/UsernamePassword subtree.
139e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
140e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public static final class UserCredential implements Parcelable {
141e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
142a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Maximum string length for username.  Refer to Credential/UsernamePassword/Username
143a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * node in Hotspot 2.0 Release 2 Technical Specification Section 9.1 for more info.
144a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
145444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu        private static final int MAX_USERNAME_BYTES = 63;
146a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
147a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
148a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Maximum string length for password.  Refer to Credential/UsernamePassword/Password
149a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * in Hotspot 2.0 Release 2 Technical Specification Section 9.1 for more info.
150a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
151444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu        private static final int MAX_PASSWORD_BYTES = 255;
152a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
153a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
154f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu         * Supported authentication methods.
155f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu         * @hide
156f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu         */
157f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        public static final String AUTH_METHOD_PAP = "PAP";
158f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        /** @hide */
159f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        public static final String AUTH_METHOD_MSCHAP = "MS-CHAP";
160f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        /** @hide */
161f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        public static final String AUTH_METHOD_MSCHAPV2 = "MS-CHAP-V2";
162f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu
163f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        /**
164a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Supported Non-EAP inner methods.  Refer to
165a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Credential/UsernamePassword/EAPMethod/InnerEAPType in Hotspot 2.0 Release 2 Technical
166a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Specification Section 9.1 for more info.
167a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
168f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        private static final Set<String> SUPPORTED_AUTH = new HashSet<String>(
169f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu                Arrays.asList(AUTH_METHOD_PAP, AUTH_METHOD_MSCHAP, AUTH_METHOD_MSCHAPV2));
170a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
171a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
172e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * Username of the credential.
173e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
174aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private String mUsername = null;
175e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
176e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the username associated with this user credential.
177e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
178e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param username The username to set to
179e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
180aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setUsername(String username) {
181aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mUsername = username;
182aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
183e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
184e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the username associated with this user credential.
185e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
186e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return the username associated with this user credential
187e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
188aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public String getUsername() {
189aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mUsername;
190aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
191e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
192e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
193e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * Base64-encoded password.
194e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
195aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private String mPassword = null;
196e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
197e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the Base64-encoded password associated with this user credential.
198e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
199e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param password The password to set to
200e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
201aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setPassword(String password) {
202aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mPassword = password;
203aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
204e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
205e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the Base64-encoded password associated with this user credential.
206e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
207e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return the Base64-encoded password associated with this user credential
208e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
209aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public String getPassword() {
210aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mPassword;
211aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
212e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
213e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
214444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu         * Flag indicating if the password is machine managed.
215444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu         */
216aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private boolean mMachineManaged = false;
217a9f9889218ac972706830440990a59cbee685976Peter Qiu        /**
218a9f9889218ac972706830440990a59cbee685976Peter Qiu         * @hide
219a9f9889218ac972706830440990a59cbee685976Peter Qiu         */
220aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setMachineManaged(boolean machineManaged) {
221aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mMachineManaged = machineManaged;
222aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
223a9f9889218ac972706830440990a59cbee685976Peter Qiu        /**
224a9f9889218ac972706830440990a59cbee685976Peter Qiu         * @hide
225a9f9889218ac972706830440990a59cbee685976Peter Qiu         */
226aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public boolean getMachineManaged() {
227aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mMachineManaged;
228aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
229444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu
230444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu        /**
231444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu         * The name of the application used to generate the password.
232444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu         */
233aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private String mSoftTokenApp = null;
234a9f9889218ac972706830440990a59cbee685976Peter Qiu        /**
235a9f9889218ac972706830440990a59cbee685976Peter Qiu         * @hide
236a9f9889218ac972706830440990a59cbee685976Peter Qiu         */
237aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setSoftTokenApp(String softTokenApp) {
238aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mSoftTokenApp = softTokenApp;
239aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
240a9f9889218ac972706830440990a59cbee685976Peter Qiu        /**
241a9f9889218ac972706830440990a59cbee685976Peter Qiu         * @hide
242a9f9889218ac972706830440990a59cbee685976Peter Qiu         */
243aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public String getSoftTokenApp() {
244aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mSoftTokenApp;
245aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
246444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu
247444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu        /**
248444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu         * Flag indicating if this credential is usable on other mobile devices as well.
249444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu         */
250aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private boolean mAbleToShare = false;
251a9f9889218ac972706830440990a59cbee685976Peter Qiu        /**
252a9f9889218ac972706830440990a59cbee685976Peter Qiu         * @hide
253a9f9889218ac972706830440990a59cbee685976Peter Qiu         */
254aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setAbleToShare(boolean ableToShare) {
255aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mAbleToShare = ableToShare;
256aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
257a9f9889218ac972706830440990a59cbee685976Peter Qiu        /**
258a9f9889218ac972706830440990a59cbee685976Peter Qiu         * @hide
259a9f9889218ac972706830440990a59cbee685976Peter Qiu         */
260aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public boolean getAbleToShare() {
261aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mAbleToShare;
262aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
263444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu
264444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu        /**
265e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * EAP (Extensible Authentication Protocol) method type.
266e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Refer to
267e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * <a href="http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4">
268e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * EAP Numbers</a> for valid values.
269e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * Using Integer.MIN_VALUE to indicate unset value.
270e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
271aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private int mEapType = Integer.MIN_VALUE;
272e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
273e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the EAP (Extensible Authentication Protocol) method type associated with this
274e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * user credential.
275e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Refer to
276e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * <a href="http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4">
277e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * EAP Numbers</a> for valid values.
278e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
279e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param eapType The EAP method type associated with this user credential
280e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
281aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setEapType(int eapType) {
282aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mEapType = eapType;
283aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
284e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
285e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the EAP (Extensible Authentication Protocol) method type associated with this
286e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * user credential.
287e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
288e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return EAP method type
289e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
290aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public int getEapType() {
291aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mEapType;
292aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
293e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
294e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
295e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * Non-EAP inner authentication method.
296e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
297aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private String mNonEapInnerMethod = null;
298e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
299e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the inner non-EAP method associated with this user credential.
300e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
301e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param nonEapInnerMethod The non-EAP inner method to set to
302e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
303aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setNonEapInnerMethod(String nonEapInnerMethod) {
304aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mNonEapInnerMethod = nonEapInnerMethod;
305aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
306e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
307e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the inner non-EAP method associated with this user credential.
308e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
309e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return Non-EAP inner method associated with this user credential
310e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
311aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public String getNonEapInnerMethod() {
312aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mNonEapInnerMethod;
313aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
314e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
315a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        /**
316a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * Constructor for creating UserCredential with default values.
317a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         */
318a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        public UserCredential() {}
319a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
320a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        /**
321a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * Copy constructor.
322a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         *
323a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * @param source The source to copy from
324a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         */
325a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        public UserCredential(UserCredential source) {
326a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            if (source != null) {
327aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mUsername = source.mUsername;
328aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mPassword = source.mPassword;
329aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mMachineManaged = source.mMachineManaged;
330aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mSoftTokenApp = source.mSoftTokenApp;
331aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mAbleToShare = source.mAbleToShare;
332aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mEapType = source.mEapType;
333aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mNonEapInnerMethod = source.mNonEapInnerMethod;
334a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
335a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        }
336a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
337e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
338e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public int describeContents() {
339e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return 0;
340e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
341e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
342e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
343e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public void writeToParcel(Parcel dest, int flags) {
344aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeString(mUsername);
345aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeString(mPassword);
346aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeInt(mMachineManaged ? 1 : 0);
347aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeString(mSoftTokenApp);
348aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeInt(mAbleToShare ? 1 : 0);
349aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeInt(mEapType);
350aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeString(mNonEapInnerMethod);
351e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
352e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
353e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
354e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public boolean equals(Object thatObject) {
355e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (this == thatObject) {
356e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return true;
357e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
358e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (!(thatObject instanceof UserCredential)) {
359e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return false;
360e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
361e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
362e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            UserCredential that = (UserCredential) thatObject;
363aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return TextUtils.equals(mUsername, that.mUsername)
364aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && TextUtils.equals(mPassword, that.mPassword)
365aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && mMachineManaged == that.mMachineManaged
366aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && TextUtils.equals(mSoftTokenApp, that.mSoftTokenApp)
367aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && mAbleToShare == that.mAbleToShare
368aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && mEapType == that.mEapType
369aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && TextUtils.equals(mNonEapInnerMethod, that.mNonEapInnerMethod);
370e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
371e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
372ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        @Override
373ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        public int hashCode() {
374ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu            return Objects.hash(mUsername, mPassword, mMachineManaged, mSoftTokenApp,
375ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu                    mAbleToShare, mEapType, mNonEapInnerMethod);
376ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        }
377ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu
37889537734e19fac6947ee14a1b912c5c135042837Peter Qiu        @Override
37989537734e19fac6947ee14a1b912c5c135042837Peter Qiu        public String toString() {
38089537734e19fac6947ee14a1b912c5c135042837Peter Qiu            StringBuilder builder = new StringBuilder();
38189537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("Username: ").append(mUsername).append("\n");
38289537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("MachineManaged: ").append(mMachineManaged).append("\n");
38389537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("SoftTokenApp: ").append(mSoftTokenApp).append("\n");
38489537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("AbleToShare: ").append(mAbleToShare).append("\n");
38589537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("EAPType: ").append(mEapType).append("\n");
38689537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("AuthMethod: ").append(mNonEapInnerMethod).append("\n");
38789537734e19fac6947ee14a1b912c5c135042837Peter Qiu            return builder.toString();
38889537734e19fac6947ee14a1b912c5c135042837Peter Qiu        }
38989537734e19fac6947ee14a1b912c5c135042837Peter Qiu
390a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
391a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Validate the configuration data.
392a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         *
393a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * @return true on success or false on failure
394b5ca6f36b54023f6336740cf3bff79c08ecb6609Peter Qiu         * @hide
395a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
396a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        public boolean validate() {
397aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (TextUtils.isEmpty(mUsername)) {
398a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                Log.d(TAG, "Missing username");
399a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
400a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
401aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (mUsername.getBytes(StandardCharsets.UTF_8).length > MAX_USERNAME_BYTES) {
402444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu                Log.d(TAG, "username exceeding maximum length: "
403aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                        + mUsername.getBytes(StandardCharsets.UTF_8).length);
404a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
405a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
406a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
407aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (TextUtils.isEmpty(mPassword)) {
408a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                Log.d(TAG, "Missing password");
409a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
410a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
411aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (mPassword.getBytes(StandardCharsets.UTF_8).length > MAX_PASSWORD_BYTES) {
412444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu                Log.d(TAG, "password exceeding maximum length: "
413aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                        + mPassword.getBytes(StandardCharsets.UTF_8).length);
414a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
415a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
416a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
417a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // Only supports EAP-TTLS for user credential.
418aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (mEapType != EAPConstants.EAP_TTLS) {
419aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                Log.d(TAG, "Invalid EAP Type for user credential: " + mEapType);
420a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
421a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
422a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
423a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // Verify Non-EAP inner method for EAP-TTLS.
424aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (!SUPPORTED_AUTH.contains(mNonEapInnerMethod)) {
425aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                Log.d(TAG, "Invalid non-EAP inner method for EAP-TTLS: " + mNonEapInnerMethod);
426a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
427a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
428a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return true;
429a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
430a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
431e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public static final Creator<UserCredential> CREATOR =
432e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            new Creator<UserCredential>() {
433e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                @Override
434e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                public UserCredential createFromParcel(Parcel in) {
435e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    UserCredential userCredential = new UserCredential();
436aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setUsername(in.readString());
437aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setPassword(in.readString());
438aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setMachineManaged(in.readInt() != 0);
439aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setSoftTokenApp(in.readString());
440aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setAbleToShare(in.readInt() != 0);
441aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setEapType(in.readInt());
442aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    userCredential.setNonEapInnerMethod(in.readString());
443e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    return userCredential;
444e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                }
445e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
446e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                @Override
447e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                public UserCredential[] newArray(int size) {
448e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    return new UserCredential[size];
449e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                }
450e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            };
451e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
452aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private UserCredential mUserCredential = null;
453e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
454e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the user credential information.
455e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
456e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param userCredential The user credential to set to
457e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
458aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setUserCredential(UserCredential userCredential) {
459aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mUserCredential = userCredential;
460aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
461e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
462e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the user credential information.
463e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
464e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return user credential information
465e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
466aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public UserCredential getUserCredential() {
467aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mUserCredential;
468aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
469e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
470e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
471a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Certificate based credential.  This is used for EAP-TLS.
472e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * Contains fields under PerProviderSubscription/Credential/DigitalCertificate subtree.
473e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
474e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public static final class CertificateCredential implements Parcelable {
475e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
476a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Supported certificate types.
477f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu         * @hide
478a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
479f8dbd216c8d49473b195077f3d3519fc3f7fde18Peter Qiu        public static final String CERT_TYPE_X509V3 = "x509v3";
480a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
481a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
482a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Certificate SHA-256 fingerprint length.
483a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
484a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        private static final int CERT_SHA256_FINGER_PRINT_LENGTH = 32;
485a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
486a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
487a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Certificate type.
488e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
489aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private String mCertType = null;
490e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
491e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the certificate type associated with this certificate credential.
492e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
493e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param certType The certificate type to set to
494e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
495aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setCertType(String certType) {
496aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mCertType = certType;
497aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
498e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
499e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the certificate type associated with this certificate credential.
500e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
501e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return certificate type
502e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
503aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public String getCertType() {
504aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mCertType;
505aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
506e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
507e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
508e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * The SHA-256 fingerprint of the certificate.
509e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
510aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private byte[] mCertSha256Fingerprint = null;
511e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
512e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the certificate SHA-256 fingerprint associated with this certificate credential.
513e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
514e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param certSha256Fingerprint The certificate fingerprint to set to
515e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
516aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setCertSha256Fingerprint(byte[] certSha256Fingerprint) {
517aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mCertSha256Fingerprint = certSha256Fingerprint;
518aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
519e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
520e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the certificate SHA-256 fingerprint associated with this certificate credential.
521e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
522e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return certificate SHA-256 fingerprint
523e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
524aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public byte[] getCertSha256Fingerprint() {
525aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mCertSha256Fingerprint;
526aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
527e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
528a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        /**
529a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * Constructor for creating CertificateCredential with default values.
530a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         */
531a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        public CertificateCredential() {}
532a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
533a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        /**
534a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * Copy constructor.
535a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         *
536a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * @param source The source to copy from
537a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         */
538a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        public CertificateCredential(CertificateCredential source) {
539a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            if (source != null) {
540aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mCertType = source.mCertType;
541aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                if (source.mCertSha256Fingerprint != null) {
542aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    mCertSha256Fingerprint = Arrays.copyOf(source.mCertSha256Fingerprint,
543aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                                                          source.mCertSha256Fingerprint.length);
544a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu                }
545a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
546a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        }
547a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
548e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
549e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public int describeContents() {
550e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return 0;
551e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
552e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
553e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
554e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public void writeToParcel(Parcel dest, int flags) {
555aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeString(mCertType);
556aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeByteArray(mCertSha256Fingerprint);
557e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
558e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
559e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
560e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public boolean equals(Object thatObject) {
561e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (this == thatObject) {
562e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return true;
563e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
564e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (!(thatObject instanceof CertificateCredential)) {
565e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return false;
566e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
567e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
568e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            CertificateCredential that = (CertificateCredential) thatObject;
569aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return TextUtils.equals(mCertType, that.mCertType)
570aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && Arrays.equals(mCertSha256Fingerprint, that.mCertSha256Fingerprint);
571e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
572e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
573ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        @Override
574ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        public int hashCode() {
575ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu            return Objects.hash(mCertType, mCertSha256Fingerprint);
576ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        }
577ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu
57889537734e19fac6947ee14a1b912c5c135042837Peter Qiu        @Override
57989537734e19fac6947ee14a1b912c5c135042837Peter Qiu        public String toString() {
58089537734e19fac6947ee14a1b912c5c135042837Peter Qiu            return "CertificateType: " + mCertType + "\n";
58189537734e19fac6947ee14a1b912c5c135042837Peter Qiu        }
58289537734e19fac6947ee14a1b912c5c135042837Peter Qiu
583a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
584a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Validate the configuration data.
585a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         *
586a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * @return true on success or false on failure
587b5ca6f36b54023f6336740cf3bff79c08ecb6609Peter Qiu         * @hide
588a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
589a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        public boolean validate() {
590aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (!TextUtils.equals(CERT_TYPE_X509V3, mCertType)) {
591aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                Log.d(TAG, "Unsupported certificate type: " + mCertType);
592a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
593a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
594aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (mCertSha256Fingerprint == null
595aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    || mCertSha256Fingerprint.length != CERT_SHA256_FINGER_PRINT_LENGTH) {
596a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                Log.d(TAG, "Invalid SHA-256 fingerprint");
597a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
598a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
599a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return true;
600a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
601a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
602e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public static final Creator<CertificateCredential> CREATOR =
603e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            new Creator<CertificateCredential>() {
604e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                @Override
605e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                public CertificateCredential createFromParcel(Parcel in) {
606e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    CertificateCredential certCredential = new CertificateCredential();
607aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    certCredential.setCertType(in.readString());
608aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    certCredential.setCertSha256Fingerprint(in.createByteArray());
609e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    return certCredential;
610e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                }
611e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
612e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                @Override
613e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                public CertificateCredential[] newArray(int size) {
614e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    return new CertificateCredential[size];
615e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                }
616e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            };
617e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
618aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private CertificateCredential mCertCredential = null;
619e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
620e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the certificate credential information.
621e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
622e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param certCredential The certificate credential to set to
623e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
624aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setCertCredential(CertificateCredential certCredential) {
625aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mCertCredential = certCredential;
626aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
627e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
628e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the certificate credential information.
629e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
630e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return certificate credential information
631e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
632aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public CertificateCredential getCertCredential() {
633aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mCertCredential;
634aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
635e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
636e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
637e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * SIM (Subscriber Identify Module) based credential.
638e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * Contains fields under PerProviderSubscription/Credential/SIM subtree.
639e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
640e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public static final class SimCredential implements Parcelable {
641e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
642a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Maximum string length for IMSI.
643a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
644aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private static final int MAX_IMSI_LENGTH = 15;
645a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
646a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
647a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * International Mobile Subscriber Identity, is used to identify the user
648a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * of a cellular network and is a unique identification associated with all
649a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * cellular networks
650e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
651aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private String mImsi = null;
652e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
653e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the IMSI (International Mobile Subscriber Identity) associated with this SIM
654e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * credential.
655e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
656e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param imsi The IMSI to set to
657e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
658aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setImsi(String imsi) {
659aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mImsi = imsi;
660aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
661e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
662e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the IMSI (International Mobile Subscriber Identity) associated with this SIM
663e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * credential.
664e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
665e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return IMSI associated with this SIM credential
666e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
667aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public String getImsi() {
668aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mImsi;
669aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
670e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
671e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /**
672e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * EAP (Extensible Authentication Protocol) method type for using SIM credential.
673e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * Refer to http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4
674e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * for valid values.
675e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         * Using Integer.MIN_VALUE to indicate unset value.
676e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu         */
677aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        private int mEapType = Integer.MIN_VALUE;
678e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
679e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Set the EAP (Extensible Authentication Protocol) method type associated with this
680e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * SIM credential.
681e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
682e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @param eapType The EAP method type to set to
683e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
684aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public void setEapType(int eapType) {
685aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mEapType = eapType;
686aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
687e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu        /**
688e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * Get the EAP (Extensible Authentication Protocol) method type associated with this
689e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * SIM credential.
690e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         *
691e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         * @return EAP method type associated with this SIM credential
692e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu         */
693aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        public int getEapType() {
694aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return mEapType;
695aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        }
696e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
697a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        /**
698a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * Constructor for creating SimCredential with default values.
699a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         */
700a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        public SimCredential() {}
701a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
702a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        /**
703a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * Copy constructor
704a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         *
705a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         * @param source The source to copy from
706a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu         */
707a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        public SimCredential(SimCredential source) {
708a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            if (source != null) {
709aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mImsi = source.mImsi;
710aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mEapType = source.mEapType;
711a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
712a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        }
713a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
714e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
715e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public int describeContents() {
716e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return 0;
717e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
718e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
719e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
720e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public boolean equals(Object thatObject) {
721e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (this == thatObject) {
722e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return true;
723e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
724e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (!(thatObject instanceof SimCredential)) {
725e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return false;
726e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
727e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
728e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            SimCredential that = (SimCredential) thatObject;
729aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            return TextUtils.equals(mImsi, that.mImsi)
730aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && mEapType == that.mEapType;
731e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
732e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
733e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        @Override
734ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        public int hashCode() {
735ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu            return Objects.hash(mImsi, mEapType);
736ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        }
737ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu
738ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu        @Override
73989537734e19fac6947ee14a1b912c5c135042837Peter Qiu        public String toString() {
74089537734e19fac6947ee14a1b912c5c135042837Peter Qiu            StringBuilder builder = new StringBuilder();
74189537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("IMSI: ").append(mImsi).append("\n");
74289537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("EAPType: ").append(mEapType).append("\n");
74389537734e19fac6947ee14a1b912c5c135042837Peter Qiu            return builder.toString();
74489537734e19fac6947ee14a1b912c5c135042837Peter Qiu        }
74589537734e19fac6947ee14a1b912c5c135042837Peter Qiu
74689537734e19fac6947ee14a1b912c5c135042837Peter Qiu        @Override
747e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public void writeToParcel(Parcel dest, int flags) {
748aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeString(mImsi);
749aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            dest.writeInt(mEapType);
750e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
751e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
752a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
753a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Validate the configuration data.
754a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         *
755a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * @return true on success or false on failure
756b5ca6f36b54023f6336740cf3bff79c08ecb6609Peter Qiu         * @hide
757a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
758a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        public boolean validate() {
759a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // Note: this only validate the format of IMSI string itself.  Additional verification
760a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // will be done by WifiService at the time of provisioning to verify against the IMSI
761a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // of the SIM card installed in the device.
762a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            if (!verifyImsi()) {
763a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
764a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
765aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (mEapType != EAPConstants.EAP_SIM && mEapType != EAPConstants.EAP_AKA
766aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    && mEapType != EAPConstants.EAP_AKA_PRIME) {
767aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                Log.d(TAG, "Invalid EAP Type for SIM credential: " + mEapType);
768a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
769a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
770a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return true;
771a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
772a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
773e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        public static final Creator<SimCredential> CREATOR =
774e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            new Creator<SimCredential>() {
775e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                @Override
776e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                public SimCredential createFromParcel(Parcel in) {
777e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    SimCredential simCredential = new SimCredential();
778aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    simCredential.setImsi(in.readString());
779aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    simCredential.setEapType(in.readInt());
780e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    return simCredential;
781e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                }
782e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
783e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                @Override
784e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                public SimCredential[] newArray(int size) {
785e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                    return new SimCredential[size];
786e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                }
787e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            };
788a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
789a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        /**
790a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * Verify the IMSI (International Mobile Subscriber Identity) string.  The string
791a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * should contain zero or more numeric digits, and might ends with a "*" for prefix
792a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * matching.
793a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         *
794a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         * @return true if IMSI is valid, false otherwise.
795a25d717de870895be52e81b585a8484fff0c6109Peter Qiu         */
796a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        private boolean verifyImsi() {
797aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (TextUtils.isEmpty(mImsi)) {
798a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                Log.d(TAG, "Missing IMSI");
799a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
800a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
801aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (mImsi.length() > MAX_IMSI_LENGTH) {
802aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                Log.d(TAG, "IMSI exceeding maximum length: " + mImsi.length());
803a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
804a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
805a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
806a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // Locate the first non-digit character.
807a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            int nonDigit;
808a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            char stopChar = '\0';
809aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            for (nonDigit = 0; nonDigit < mImsi.length(); nonDigit++) {
810aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                stopChar = mImsi.charAt(nonDigit);
811a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                if (stopChar < '0' || stopChar > '9') {
812a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                    break;
813a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                }
814a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
815a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
816aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (nonDigit == mImsi.length()) {
817a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return true;
818a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
819aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            else if (nonDigit == mImsi.length()-1 && stopChar == '*') {
820a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                // Prefix matching.
821a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return true;
822a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
823a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
824a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
825e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
826aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private SimCredential mSimCredential = null;
827e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
828e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the SIM credential information.
829e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
830e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param simCredential The SIM credential to set to
831e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
832aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setSimCredential(SimCredential simCredential) {
833aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mSimCredential = simCredential;
834aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
835e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
836e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the SIM credential information.
837e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
838e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return SIM credential information
839e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
840aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public SimCredential getSimCredential() {
841aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mSimCredential;
842aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
843e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
844e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
845e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * CA (Certificate Authority) X509 certificate.
846e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
847aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private X509Certificate mCaCertificate = null;
848e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
849e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the CA (Certification Authority) certificate associated with this credential.
850e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
851e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param caCertificate The CA certificate to set to
852e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
853aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setCaCertificate(X509Certificate caCertificate) {
854aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mCaCertificate = caCertificate;
855aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
856e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
857e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the CA (Certification Authority) certificate associated with this credential.
858e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
859e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return CA certificate associated with this credential
860e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
861aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public X509Certificate getCaCertificate() {
862aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mCaCertificate;
863aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
864e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
865e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
866e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * Client side X509 certificate chain.
867e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
868aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private X509Certificate[] mClientCertificateChain = null;
869e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
870e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the client certificate chain associated with this credential.
871e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
872e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param certificateChain The client certificate chain to set to
873e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
874aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setClientCertificateChain(X509Certificate[] certificateChain) {
875aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mClientCertificateChain = certificateChain;
876aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
877e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
878e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the client certificate chain associated with this credential.
879e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
880e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return client certificate chain associated with this credential
881e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
882aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public X509Certificate[] getClientCertificateChain() {
883aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mClientCertificateChain;
884aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
885e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
886e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    /**
887e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     * Client side private key.
888e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu     */
889aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    private PrivateKey mClientPrivateKey = null;
890e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
891e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Set the client private key associated with this credential.
892e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
893e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @param clientPrivateKey the client private key to set to
894e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
895aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public void setClientPrivateKey(PrivateKey clientPrivateKey) {
896aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        mClientPrivateKey = clientPrivateKey;
897aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
898e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu    /**
899e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * Get the client private key associated with this credential.
900e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     *
901e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     * @return client private key associated with this credential.
902e5850517c493b24982cff8c32c7fb32a8203f5b6Peter Qiu     */
903aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    public PrivateKey getClientPrivateKey() {
904aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mClientPrivateKey;
905aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu    }
906e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
907a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu    /**
908a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu     * Constructor for creating Credential with default values.
909a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu     */
910a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu    public Credential() {}
911a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
912a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu    /**
913a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu     * Copy constructor.
914a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu     *
915a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu     * @param source The source to copy from
916a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu     */
917a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu    public Credential(Credential source) {
918a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        if (source != null) {
919967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu            mCreationTimeInMillis = source.mCreationTimeInMillis;
920967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu            mExpirationTimeInMillis = source.mExpirationTimeInMillis;
921aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mRealm = source.mRealm;
922da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu            mCheckAaaServerCertStatus = source.mCheckAaaServerCertStatus;
923aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (source.mUserCredential != null) {
924aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mUserCredential = new UserCredential(source.mUserCredential);
925a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
926aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (source.mCertCredential != null) {
927aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mCertCredential = new CertificateCredential(source.mCertCredential);
928a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
929aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (source.mSimCredential != null) {
930aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mSimCredential = new SimCredential(source.mSimCredential);
931a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
932aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (source.mClientCertificateChain != null) {
933aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                mClientCertificateChain = Arrays.copyOf(source.mClientCertificateChain,
934aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                                                        source.mClientCertificateChain.length);
935a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu            }
936aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mCaCertificate = source.mCaCertificate;
937aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            mClientPrivateKey = source.mClientPrivateKey;
938a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu        }
939a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu    }
940a32e50986ef767f50e68083a8ee345bab3ce1ccaPeter Qiu
941e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    @Override
942e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public int describeContents() {
943e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        return 0;
944e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
945e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
946e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    @Override
947e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public void writeToParcel(Parcel dest, int flags) {
948967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        dest.writeLong(mCreationTimeInMillis);
949967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        dest.writeLong(mExpirationTimeInMillis);
950aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        dest.writeString(mRealm);
951da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu        dest.writeInt(mCheckAaaServerCertStatus ? 1 : 0);
952aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        dest.writeParcelable(mUserCredential, flags);
953aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        dest.writeParcelable(mCertCredential, flags);
954aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        dest.writeParcelable(mSimCredential, flags);
955aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        ParcelUtil.writeCertificate(dest, mCaCertificate);
956aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        ParcelUtil.writeCertificates(dest, mClientCertificateChain);
957aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
958e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
959e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
960e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    @Override
961e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public boolean equals(Object thatObject) {
962e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (this == thatObject) {
963e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return true;
964e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
965e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (!(thatObject instanceof Credential)) {
966e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return false;
967e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
968e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
969e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        Credential that = (Credential) thatObject;
970aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return TextUtils.equals(mRealm, that.mRealm)
971967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu                && mCreationTimeInMillis == that.mCreationTimeInMillis
972967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu                && mExpirationTimeInMillis == that.mExpirationTimeInMillis
973da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu                && mCheckAaaServerCertStatus == that.mCheckAaaServerCertStatus
974aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                && (mUserCredential == null ? that.mUserCredential == null
975aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    : mUserCredential.equals(that.mUserCredential))
976aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                && (mCertCredential == null ? that.mCertCredential == null
977aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    : mCertCredential.equals(that.mCertCredential))
978aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                && (mSimCredential == null ? that.mSimCredential == null
979aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    : mSimCredential.equals(that.mSimCredential))
980aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                && isX509CertificateEquals(mCaCertificate, that.mCaCertificate)
981aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                && isX509CertificatesEquals(mClientCertificateChain, that.mClientCertificateChain)
982aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                && isPrivateKeyEquals(mClientPrivateKey, that.mClientPrivateKey);
983e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
984e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
985ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu    @Override
986ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu    public int hashCode() {
987967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        return Objects.hash(mRealm, mCreationTimeInMillis, mExpirationTimeInMillis,
988da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu                mCheckAaaServerCertStatus, mUserCredential, mCertCredential, mSimCredential,
989ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu                mCaCertificate, mClientCertificateChain, mClientPrivateKey);
990ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu    }
991ddafc73496e3bab135ac7249bfb3cf4d871e5cf2Peter Qiu
99289537734e19fac6947ee14a1b912c5c135042837Peter Qiu    @Override
99389537734e19fac6947ee14a1b912c5c135042837Peter Qiu    public String toString() {
99489537734e19fac6947ee14a1b912c5c135042837Peter Qiu        StringBuilder builder = new StringBuilder();
99589537734e19fac6947ee14a1b912c5c135042837Peter Qiu        builder.append("Realm: ").append(mRealm).append("\n");
996967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        builder.append("CreationTime: ").append(mCreationTimeInMillis != Long.MIN_VALUE
997967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu                ? new Date(mCreationTimeInMillis) : "Not specified").append("\n");
998967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu        builder.append("ExpirationTime: ").append(mExpirationTimeInMillis != Long.MIN_VALUE
999967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu                ? new Date(mExpirationTimeInMillis) : "Not specified").append("\n");
100089537734e19fac6947ee14a1b912c5c135042837Peter Qiu        builder.append("CheckAAAServerStatus: ").append(mCheckAaaServerCertStatus).append("\n");
100189537734e19fac6947ee14a1b912c5c135042837Peter Qiu        if (mUserCredential != null) {
100289537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("UserCredential Begin ---\n");
100389537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append(mUserCredential);
100489537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("UserCredential End ---\n");
100589537734e19fac6947ee14a1b912c5c135042837Peter Qiu        }
100689537734e19fac6947ee14a1b912c5c135042837Peter Qiu        if (mCertCredential != null) {
100789537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("CertificateCredential Begin ---\n");
100889537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append(mCertCredential);
100989537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("CertificateCredential End ---\n");
101089537734e19fac6947ee14a1b912c5c135042837Peter Qiu        }
101189537734e19fac6947ee14a1b912c5c135042837Peter Qiu        if (mSimCredential != null) {
101289537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("SIMCredential Begin ---\n");
101389537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append(mSimCredential);
101489537734e19fac6947ee14a1b912c5c135042837Peter Qiu            builder.append("SIMCredential End ---\n");
101589537734e19fac6947ee14a1b912c5c135042837Peter Qiu        }
101689537734e19fac6947ee14a1b912c5c135042837Peter Qiu        return builder.toString();
101789537734e19fac6947ee14a1b912c5c135042837Peter Qiu    }
101889537734e19fac6947ee14a1b912c5c135042837Peter Qiu
1019a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    /**
1020a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Validate the configuration data.
1021a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     *
1022a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @return true on success or false on failure
1023b5ca6f36b54023f6336740cf3bff79c08ecb6609Peter Qiu     * @hide
1024a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     */
1025a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    public boolean validate() {
1026aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (TextUtils.isEmpty(mRealm)) {
1027a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing realm");
1028a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1029a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1030aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mRealm.getBytes(StandardCharsets.UTF_8).length > MAX_REALM_BYTES) {
1031444dc5d099788e5aa0fd0e664fd952fbb07a69d4Peter Qiu            Log.d(TAG, "realm exceeding maximum length: "
1032aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    + mRealm.getBytes(StandardCharsets.UTF_8).length);
1033a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1034a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1035a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1036a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        // Verify the credential.
1037aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mUserCredential != null) {
1038a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            if (!verifyUserCredential()) {
1039a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
1040a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
1041aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        } else if (mCertCredential != null) {
1042a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            if (!verifyCertCredential()) {
1043a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
1044a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
1045aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        } else if (mSimCredential != null) {
1046a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            if (!verifySimCredential()) {
1047a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
1048a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
1049a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        } else {
1050a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing required credential");
1051a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1052a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1053a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1054a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        return true;
1055a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    }
1056a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1057e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    public static final Creator<Credential> CREATOR =
1058e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        new Creator<Credential>() {
1059e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            @Override
1060e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            public Credential createFromParcel(Parcel in) {
1061e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                Credential credential = new Credential();
1062967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu                credential.setCreationTimeInMillis(in.readLong());
1063967501ec982f14fec6a160c03e34cd2d296d7128Peter Qiu                credential.setExpirationTimeInMillis(in.readLong());
1064aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setRealm(in.readString());
1065da8a67e8a606ebd49a724a18d3581b62121b532cPeter Qiu                credential.setCheckAaaServerCertStatus(in.readInt() != 0);
1066aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setUserCredential(in.readParcelable(null));
1067aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setCertCredential(in.readParcelable(null));
1068aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setSimCredential(in.readParcelable(null));
1069aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setCaCertificate(ParcelUtil.readCertificate(in));
1070aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setClientCertificateChain(ParcelUtil.readCertificates(in));
1071aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                credential.setClientPrivateKey(ParcelUtil.readPrivateKey(in));
1072e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return credential;
1073e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
1074e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1075e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            @Override
1076e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            public Credential[] newArray(int size) {
1077e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return new Credential[size];
1078e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
1079e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        };
1080e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1081a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    /**
1082a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Verify user credential.
1083a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     *
1084a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @return true if user credential is valid, false otherwise.
1085a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     */
1086a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    private boolean verifyUserCredential() {
1087aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mUserCredential == null) {
1088a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing user credential");
1089a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1090a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1091aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mCertCredential != null || mSimCredential != null) {
1092a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Contained more than one type of credential");
1093a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1094a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1095aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (!mUserCredential.validate()) {
1096a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1097a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1098aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mCaCertificate == null) {
1099a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing CA Certificate for user credential");
1100a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1101a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1102a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        return true;
1103a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    }
1104a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1105a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    /**
1106a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Verify certificate credential, which is used for EAP-TLS.  This will verify
1107a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * that the necessary client key and certificates are provided.
1108a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     *
1109a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @return true if certificate credential is valid, false otherwise.
1110a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     */
1111a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    private boolean verifyCertCredential() {
1112aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mCertCredential == null) {
1113a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing certificate credential");
1114a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1115a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1116aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mUserCredential != null || mSimCredential != null) {
1117a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Contained more than one type of credential");
1118a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1119a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1120a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1121aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (!mCertCredential.validate()) {
1122a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1123a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1124a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1125a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        // Verify required key and certificates for certificate credential.
1126aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mCaCertificate == null) {
1127a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing CA Certificate for certificate credential");
1128a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1129a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1130aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mClientPrivateKey == null) {
1131a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing client private key for certificate credential");
1132a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1133a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1134a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        try {
1135a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            // Verify SHA-256 fingerprint for client certificate.
1136aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu            if (!verifySha256Fingerprint(mClientCertificateChain,
1137aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu                    mCertCredential.getCertSha256Fingerprint())) {
1138a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                Log.d(TAG, "SHA-256 fingerprint mismatch");
1139a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return false;
1140a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
1141a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
1142a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Failed to verify SHA-256 fingerprint: " + e.getMessage());
1143a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1144a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1145a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1146a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        return true;
1147a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    }
1148a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1149a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    /**
1150a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Verify SIM credential.
1151a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     *
1152a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @return true if SIM credential is valid, false otherwise.
1153a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     */
1154a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    private boolean verifySimCredential() {
1155aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mSimCredential == null) {
1156a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Missing SIM credential");
1157a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1158a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1159aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        if (mUserCredential != null || mCertCredential != null) {
1160a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            Log.d(TAG, "Contained more than one type of credential");
1161a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1162a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1163aef5b6095f58028d51e7007e7daebeac4bb2af72Peter Qiu        return mSimCredential.validate();
1164a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    }
1165a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1166e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    private static boolean isPrivateKeyEquals(PrivateKey key1, PrivateKey key2) {
1167e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (key1 == null && key2 == null) {
1168e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return true;
1169e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1170e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1171e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /* Return false if only one of them is null */
1172e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (key1 == null || key2 == null) {
1173e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return false;
1174e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1175e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1176e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        return TextUtils.equals(key1.getAlgorithm(), key2.getAlgorithm()) &&
1177e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                Arrays.equals(key1.getEncoded(), key2.getEncoded());
1178e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
1179e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1180e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    private static boolean isX509CertificateEquals(X509Certificate cert1, X509Certificate cert2) {
1181e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (cert1 == null && cert2 == null) {
1182e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return true;
1183e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1184e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1185e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /* Return false if only one of them is null */
1186e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (cert1 == null || cert2 == null) {
1187e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return false;
1188e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1189e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1190e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        boolean result = false;
1191e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        try {
1192e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            result = Arrays.equals(cert1.getEncoded(), cert2.getEncoded());
1193e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        } catch (CertificateEncodingException e) {
1194e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            /* empty, return false. */
1195e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1196e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        return result;
1197e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
1198e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1199e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    private static boolean isX509CertificatesEquals(X509Certificate[] certs1,
1200e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                                                    X509Certificate[] certs2) {
1201e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (certs1 == null && certs2 == null) {
1202e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return true;
1203e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1204e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1205e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        /* Return false if only one of them is null */
1206e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (certs1 == null || certs2 == null) {
1207e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return false;
1208e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1209e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1210e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        if (certs1.length != certs2.length) {
1211e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            return false;
1212e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1213e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1214e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        for (int i = 0; i < certs1.length; i++) {
1215e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            if (!isX509CertificateEquals(certs1[i], certs2[i])) {
1216e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu                return false;
1217e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu            }
1218e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        }
1219e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu
1220e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu        return true;
1221e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu    }
1222a25d717de870895be52e81b585a8484fff0c6109Peter Qiu
1223a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    /**
1224a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * Verify that the digest for a certificate in the certificate chain matches expected
1225a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * fingerprint.  The certificate that matches the fingerprint is the client certificate.
1226a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     *
1227a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @param certChain Chain of certificates
1228a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @param expectedFingerprint The expected SHA-256 digest of the client certificate
1229a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @return true if the certificate chain contains a matching certificate, false otherwise
1230a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @throws NoSuchAlgorithmException
1231a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     * @throws CertificateEncodingException
1232a25d717de870895be52e81b585a8484fff0c6109Peter Qiu     */
1233a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    private static boolean verifySha256Fingerprint(X509Certificate[] certChain,
1234a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                                                   byte[] expectedFingerprint)
1235a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            throws NoSuchAlgorithmException, CertificateEncodingException {
1236a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        if (certChain == null) {
1237a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            return false;
1238a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1239a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        MessageDigest digester = MessageDigest.getInstance("SHA-256");
1240a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        for (X509Certificate certificate : certChain) {
1241a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            digester.reset();
1242a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            byte[] fingerprint = digester.digest(certificate.getEncoded());
1243a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            if (Arrays.equals(expectedFingerprint, fingerprint)) {
1244a25d717de870895be52e81b585a8484fff0c6109Peter Qiu                return true;
1245a25d717de870895be52e81b585a8484fff0c6109Peter Qiu            }
1246a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        }
1247a25d717de870895be52e81b585a8484fff0c6109Peter Qiu        return false;
1248a25d717de870895be52e81b585a8484fff0c6109Peter Qiu    }
1249e557c35d95a8d05c58a592d4c34db69a1dd2c1a7Peter Qiu}
1250