16
16
17
17
package com .afwsamples .testdpc .policy ;
18
18
19
- import static android .os .UserManager .DISALLOW_INSTALL_UNKNOWN_SOURCES ;
20
- import static com .afwsamples .testdpc .common .preference .DpcPreferenceHelper .NO_CUSTOM_CONSTRIANT ;
21
-
22
19
import android .accessibilityservice .AccessibilityServiceInfo ;
23
20
import android .accounts .Account ;
24
21
import android .accounts .AccountManager ;
52
49
import android .os .UserManager ;
53
50
import android .provider .MediaStore ;
54
51
import android .provider .Settings ;
55
- import android .security .AttestedKeyPair ;
56
52
import android .security .KeyChain ;
57
53
import android .security .KeyChainAliasCallback ;
58
- import android .security .KeyChainException ;
59
- import android .security .keystore .KeyGenParameterSpec ;
60
- import android .security .keystore .KeyProperties ;
61
54
import android .service .notification .NotificationListenerService ;
62
55
import android .support .annotation .Nullable ;
63
56
import android .support .annotation .RequiresApi ;
85
78
import android .widget .RadioButton ;
86
79
import android .widget .RadioGroup ;
87
80
import android .widget .Toast ;
81
+
88
82
import com .afwsamples .testdpc .AddAccountActivity ;
89
83
import com .afwsamples .testdpc .BuildConfig ;
90
84
import com .afwsamples .testdpc .CrossProfileAppsFragment ;
108
102
import com .afwsamples .testdpc .policy .certificate .DelegatedCertInstallerFragment ;
109
103
import com .afwsamples .testdpc .policy .keyguard .LockScreenPolicyFragment ;
110
104
import com .afwsamples .testdpc .policy .keyguard .PasswordConstraintsFragment ;
105
+ import com .afwsamples .testdpc .policy .keymanagement .GenerateKeyAndCertificateTask ;
106
+ import com .afwsamples .testdpc .policy .keymanagement .SignAndVerifyTask ;
111
107
import com .afwsamples .testdpc .policy .locktask .KioskModeActivity ;
112
108
import com .afwsamples .testdpc .policy .locktask .LockTaskAppInfoArrayAdapter ;
113
109
import com .afwsamples .testdpc .policy .locktask .SetLockTaskFeaturesFragment ;
114
110
import com .afwsamples .testdpc .policy .networking .AlwaysOnVpnFragment ;
115
111
import com .afwsamples .testdpc .policy .networking .NetworkUsageStatsFragment ;
116
112
import com .afwsamples .testdpc .policy .resetpassword .ResetPasswordWithTokenFragment ;
117
113
import com .afwsamples .testdpc .policy .systemupdatepolicy .SystemUpdatePolicyFragment ;
118
- import com .afwsamples .testdpc .policy .utils .CertificateUtils ;
119
114
import com .afwsamples .testdpc .policy .wifimanagement .WifiConfigCreationDialog ;
120
115
import com .afwsamples .testdpc .policy .wifimanagement .WifiEapTlsCreateDialogFragment ;
121
116
import com .afwsamples .testdpc .policy .wifimanagement .WifiModificationFragment ;
128
123
import com .afwsamples .testdpc .safetynet .SafetyNetFragment ;
129
124
import com .afwsamples .testdpc .transferownership .PickTransferComponentFragment ;
130
125
import com .afwsamples .testdpc .util .MainThreadExecutor ;
126
+
131
127
import java .io .ByteArrayInputStream ;
132
128
import java .io .File ;
133
129
import java .io .FileNotFoundException ;
134
130
import java .io .IOException ;
135
131
import java .io .InputStream ;
136
- import java .security .InvalidKeyException ;
137
132
import java .security .KeyStoreException ;
138
133
import java .security .NoSuchAlgorithmException ;
139
134
import java .security .PrivateKey ;
140
- import java .security .PublicKey ;
141
- import java .security .Signature ;
142
- import java .security .SignatureException ;
143
135
import java .security .UnrecoverableKeyException ;
144
136
import java .security .cert .Certificate ;
145
137
import java .security .cert .CertificateException ;
158
150
import java .util .Set ;
159
151
import java .util .TimeZone ;
160
152
import java .util .stream .Collectors ;
161
- import javax .security .auth .x500 .X500Principal ;
162
- import org .bouncycastle .operator .OperatorCreationException ;
153
+
154
+ import static android .os .UserManager .DISALLOW_INSTALL_UNKNOWN_SOURCES ;
155
+ import static com .afwsamples .testdpc .common .preference .DpcPreferenceHelper .NO_CUSTOM_CONSTRIANT ;
163
156
164
157
/**
165
158
* Provides several device management functions.
@@ -1055,7 +1048,10 @@ public void alias(String alias) {
1055
1048
return ;
1056
1049
}
1057
1050
1058
- new SignAndVerifyTask ().execute (alias );
1051
+ new SignAndVerifyTask (
1052
+ getContext (), (int msgId , Object ... args ) -> {
1053
+ showToast (msgId , args );
1054
+ }).execute (alias );
1059
1055
}
1060
1056
}, null , null , null , null );
1061
1057
}
@@ -1293,115 +1289,14 @@ private boolean installKeyPair(final PrivateKey key, final Certificate cert, fin
1293
1289
}
1294
1290
}
1295
1291
1296
- class GenerateKeyAndCertificateTask extends AsyncTask <Void , Integer , Boolean > {
1297
- final String mAlias ;
1298
- final boolean mIsUserSelectable ;
1299
-
1300
- GenerateKeyAndCertificateTask (String mAlias , boolean mIsUserSelectable ) {
1301
- this .mAlias = mAlias ;
1302
- this .mIsUserSelectable = mIsUserSelectable ;
1303
- }
1304
-
1305
- @ TargetApi (28 )
1306
- @ Override
1307
- protected Boolean doInBackground (Void ... voids ) {
1308
- try {
1309
- KeyGenParameterSpec keySpec = new KeyGenParameterSpec .Builder (mAlias ,
1310
- KeyProperties .PURPOSE_SIGN | KeyProperties .PURPOSE_VERIFY )
1311
- .setKeySize (2048 )
1312
- .setDigests (KeyProperties .DIGEST_SHA256 )
1313
- .setSignaturePaddings (KeyProperties .SIGNATURE_PADDING_RSA_PSS ,
1314
- KeyProperties .SIGNATURE_PADDING_RSA_PKCS1 )
1315
- .build ();
1316
- AttestedKeyPair keyPair = mDevicePolicyManager .generateKeyPair (
1317
- mAdminComponentName , "RSA" , keySpec , 0 );
1318
-
1319
- if (keyPair == null ) {
1320
- return false ;
1321
- }
1322
-
1323
- X500Principal subject = new X500Principal ("CN=TestDPC, O=Android, C=US" );
1324
- // Self-signed certificate: Same subject and issuer.
1325
- X509Certificate selfSigned = CertificateUtils .createCertificate (
1326
- keyPair .getKeyPair (), subject , subject );
1327
-
1328
- List <Certificate > certs = new ArrayList <Certificate >();
1329
- certs .add (selfSigned );
1330
-
1331
- return mDevicePolicyManager .setKeyPairCertificate (
1332
- mAdminComponentName , mAlias , certs , mIsUserSelectable );
1333
- } catch (CertificateException e ) {
1334
- Log .e (TAG , "Failed to create certificate" , e );
1335
- } catch (OperatorCreationException e ) {
1336
- Log .e (TAG , "Failed to create certificate" , e );
1337
- } catch (IOException e ) {
1338
- Log .e (TAG , "Failed to encode certificate" , e );
1339
- }
1340
-
1341
- return false ;
1342
- }
1343
-
1344
- @ Override
1345
- protected void onPostExecute (Boolean result ) {
1346
- if (result .booleanValue ()) {
1347
- showToast (R .string .key_generation_successful , mAlias );
1348
- } else {
1349
- showToast (R .string .key_generation_failed , mAlias );
1350
- }
1351
- }
1352
- }
1353
-
1354
- private void generateKeyPair (final String alias , boolean isUserSelectable ) {
1355
- new GenerateKeyAndCertificateTask (alias , isUserSelectable ).execute ();
1292
+ private void generateKeyPair (final String alias , boolean isUserSelectable ,
1293
+ byte [] attestationChallenge ,
1294
+ int idAttestationFlags ) {
1295
+ new GenerateKeyAndCertificateTask (
1296
+ alias , isUserSelectable , attestationChallenge , idAttestationFlags ,
1297
+ getActivity ()).execute ();
1356
1298
}
1357
1299
1358
- class SignAndVerifyTask extends AsyncTask <String , Integer , String > {
1359
- @ Override
1360
- protected String doInBackground (String ... aliases ) {
1361
- String alias = aliases [0 ];
1362
- try {
1363
- final String algorithmIdentifier = "SHA256withRSA" ;
1364
- PrivateKey privateKey = KeyChain .getPrivateKey (getContext (), alias );
1365
-
1366
- byte [] data = new String ("hello" ).getBytes ();
1367
- Signature signer = Signature .getInstance (algorithmIdentifier );
1368
- signer .initSign (privateKey );
1369
- signer .update (data );
1370
- byte [] signature = signer .sign ();
1371
-
1372
- X509Certificate cert = KeyChain .getCertificateChain (getContext (), alias )[0 ];
1373
- PublicKey publicKey = cert .getPublicKey ();
1374
- Signature verifier = Signature .getInstance (algorithmIdentifier );
1375
- verifier .initVerify (publicKey );
1376
- verifier .update (data );
1377
- if (verifier .verify (signature )) {
1378
- return cert .getSubjectX500Principal ().getName ();
1379
- }
1380
- } catch (KeyChainException e ) {
1381
- Log .e (TAG , "Error getting key" , e );
1382
- } catch (InterruptedException e ) {
1383
- Log .e (TAG , "Interrupted while getting the key" , e );
1384
- } catch (NoSuchAlgorithmException e ) {
1385
- e .printStackTrace ();
1386
- } catch (SignatureException e ) {
1387
- Log .e (TAG , "Failed signing with key" , e );
1388
- } catch (InvalidKeyException e ) {
1389
- Log .e (TAG , "Provided alias resolves to an invalid key" , e );
1390
- }
1391
- return null ;
1392
- }
1393
-
1394
- @ Override
1395
- protected void onPostExecute (String result ) {
1396
- if (result != null ) {
1397
- showToast (R .string .key_usage_successful , result );
1398
- } else {
1399
- showToast (R .string .key_usage_failed );
1400
- }
1401
- }
1402
- };
1403
-
1404
-
1405
1300
/**
1406
1301
* Dispatches an intent to capture image or video.
1407
1302
*/
@@ -2413,7 +2308,7 @@ private void showPromptForGeneratedKeyAlias(String alias) {
2413
2308
}
2414
2309
2415
2310
View aliasNamingView = getActivity ().getLayoutInflater ().inflate (
2416
- R .layout .certificate_alias_prompt , null );
2311
+ R .layout .key_generation_prompt , null );
2417
2312
final EditText input = (EditText ) aliasNamingView .findViewById (R .id .alias_input );
2418
2313
if (!TextUtils .isEmpty (alias )) {
2419
2314
input .setText (alias );
@@ -2424,6 +2319,19 @@ private void showPromptForGeneratedKeyAlias(String alias) {
2424
2319
R .id .alias_user_selectable );
2425
2320
userSelectableCheckbox .setChecked (!BuildCompat .isAtLeastP ());
2426
2321
2322
+ // Attestation check-boxes
2323
+ final CheckBox includeAttestationChallengeCheckbox = aliasNamingView .findViewById (
2324
+ R .id .include_key_attestation_challenge );
2325
+ final CheckBox deviceBrandAttestationCheckbox = aliasNamingView .findViewById (
2326
+ R .id .include_device_brand_attestation );
2327
+ final CheckBox deviceSerialAttestationCheckbox = aliasNamingView .findViewById (
2328
+ R .id .include_device_serial_in_attestation );
2329
+ final CheckBox deviceImeiAttestationCheckbox = aliasNamingView .findViewById (
2330
+ R .id .include_device_imei_in_attestation );
2331
+ final CheckBox deviceMeidAttestationCheckbox = aliasNamingView .findViewById (
2332
+ R .id .include_device_meid_in_attestation );
2333
+
2334
+
2427
2335
new AlertDialog .Builder (getActivity ())
2428
2336
.setTitle (getString (R .string .certificate_alias_prompt_title ))
2429
2337
.setView (aliasNamingView )
@@ -2432,7 +2340,28 @@ private void showPromptForGeneratedKeyAlias(String alias) {
2432
2340
public void onClick (DialogInterface dialog , int which ) {
2433
2341
String alias = input .getText ().toString ();
2434
2342
boolean isUserSelectable = userSelectableCheckbox .isChecked ();
2435
- generateKeyPair (alias , isUserSelectable );
2343
+
2344
+ byte [] attestationChallenge = null ;
2345
+ if (includeAttestationChallengeCheckbox .isChecked ()) {
2346
+ attestationChallenge = new byte [] {0x61 , 0x62 , 0x63 };
2347
+ }
2348
+
2349
+ int idAttestationFlags = 0 ;
2350
+ if (deviceBrandAttestationCheckbox .isChecked ()) {
2351
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_BASE_INFO ;
2352
+ }
2353
+ if (deviceSerialAttestationCheckbox .isChecked ()) {
2354
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_SERIAL ;
2355
+ }
2356
+ if (deviceImeiAttestationCheckbox .isChecked ()) {
2357
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_IMEI ;
2358
+ }
2359
+ if (deviceMeidAttestationCheckbox .isChecked ()) {
2360
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_MEID ;
2361
+ }
2362
+
2363
+ generateKeyPair (alias , isUserSelectable , attestationChallenge ,
2364
+ idAttestationFlags );
2436
2365
}
2437
2366
})
2438
2367
.setNegativeButton (android .R .string .cancel , null )
0 commit comments