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.
@@ -1060,7 +1053,10 @@ public void alias(String alias) {
1060
1053
return ;
1061
1054
}
1062
1055
1063
- new SignAndVerifyTask ().execute (alias );
1056
+ new SignAndVerifyTask (
1057
+ getContext (), (int msgId , Object ... args ) -> {
1058
+ showToast (msgId , args );
1059
+ }).execute (alias );
1064
1060
}
1065
1061
}, null , null , null , null );
1066
1062
}
@@ -1313,115 +1309,14 @@ private boolean installKeyPair(final PrivateKey key, final Certificate cert, fin
1313
1309
}
1314
1310
}
1315
1311
1316
- class GenerateKeyAndCertificateTask extends AsyncTask <Void , Integer , Boolean > {
1317
- final String mAlias ;
1318
- final boolean mIsUserSelectable ;
1319
-
1320
- GenerateKeyAndCertificateTask (String mAlias , boolean mIsUserSelectable ) {
1321
- this .mAlias = mAlias ;
1322
- this .mIsUserSelectable = mIsUserSelectable ;
1323
- }
1324
-
1325
- @ TargetApi (28 )
1326
- @ Override
1327
- protected Boolean doInBackground (Void ... voids ) {
1328
- try {
1329
- KeyGenParameterSpec keySpec = new KeyGenParameterSpec .Builder (mAlias ,
1330
- KeyProperties .PURPOSE_SIGN | KeyProperties .PURPOSE_VERIFY )
1331
- .setKeySize (2048 )
1332
- .setDigests (KeyProperties .DIGEST_SHA256 )
1333
- .setSignaturePaddings (KeyProperties .SIGNATURE_PADDING_RSA_PSS ,
1334
- KeyProperties .SIGNATURE_PADDING_RSA_PKCS1 )
1335
- .build ();
1336
- AttestedKeyPair keyPair = mDevicePolicyManager .generateKeyPair (
1337
- mAdminComponentName , "RSA" , keySpec , 0 );
1338
-
1339
- if (keyPair == null ) {
1340
- return false ;
1341
- }
1342
-
1343
- X500Principal subject = new X500Principal ("CN=TestDPC, O=Android, C=US" );
1344
- // Self-signed certificate: Same subject and issuer.
1345
- X509Certificate selfSigned = CertificateUtils .createCertificate (
1346
- keyPair .getKeyPair (), subject , subject );
1347
-
1348
- List <Certificate > certs = new ArrayList <Certificate >();
1349
- certs .add (selfSigned );
1350
-
1351
- return mDevicePolicyManager .setKeyPairCertificate (
1352
- mAdminComponentName , mAlias , certs , mIsUserSelectable );
1353
- } catch (CertificateException e ) {
1354
- Log .e (TAG , "Failed to create certificate" , e );
1355
- } catch (OperatorCreationException e ) {
1356
- Log .e (TAG , "Failed to create certificate" , e );
1357
- } catch (IOException e ) {
1358
- Log .e (TAG , "Failed to encode certificate" , e );
1359
- }
1360
-
1361
- return false ;
1362
- }
1363
-
1364
- @ Override
1365
- protected void onPostExecute (Boolean result ) {
1366
- if (result .booleanValue ()) {
1367
- showToast (R .string .key_generation_successful , mAlias );
1368
- } else {
1369
- showToast (R .string .key_generation_failed , mAlias );
1370
- }
1371
- }
1372
- }
1373
-
1374
- private void generateKeyPair (final String alias , boolean isUserSelectable ) {
1375
- new GenerateKeyAndCertificateTask (alias , isUserSelectable ).execute ();
1312
+ private void generateKeyPair (final String alias , boolean isUserSelectable ,
1313
+ byte [] attestationChallenge ,
1314
+ int idAttestationFlags ) {
1315
+ new GenerateKeyAndCertificateTask (
1316
+ alias , isUserSelectable , attestationChallenge , idAttestationFlags ,
1317
+ getActivity ()).execute ();
1376
1318
}
1377
1319
1378
- class SignAndVerifyTask extends AsyncTask <String , Integer , String > {
1379
- @ Override
1380
- protected String doInBackground (String ... aliases ) {
1381
- String alias = aliases [0 ];
1382
- try {
1383
- final String algorithmIdentifier = "SHA256withRSA" ;
1384
- PrivateKey privateKey = KeyChain .getPrivateKey (getContext (), alias );
1385
-
1386
- byte [] data = new String ("hello" ).getBytes ();
1387
- Signature signer = Signature .getInstance (algorithmIdentifier );
1388
- signer .initSign (privateKey );
1389
- signer .update (data );
1390
- byte [] signature = signer .sign ();
1391
-
1392
- X509Certificate cert = KeyChain .getCertificateChain (getContext (), alias )[0 ];
1393
- PublicKey publicKey = cert .getPublicKey ();
1394
- Signature verifier = Signature .getInstance (algorithmIdentifier );
1395
- verifier .initVerify (publicKey );
1396
- verifier .update (data );
1397
- if (verifier .verify (signature )) {
1398
- return cert .getSubjectX500Principal ().getName ();
1399
- }
1400
- } catch (KeyChainException e ) {
1401
- Log .e (TAG , "Error getting key" , e );
1402
- } catch (InterruptedException e ) {
1403
- Log .e (TAG , "Interrupted while getting the key" , e );
1404
- } catch (NoSuchAlgorithmException e ) {
1405
- e .printStackTrace ();
1406
- } catch (SignatureException e ) {
1407
- Log .e (TAG , "Failed signing with key" , e );
1408
- } catch (InvalidKeyException e ) {
1409
- Log .e (TAG , "Provided alias resolves to an invalid key" , e );
1410
- }
1411
- return null ;
1412
- }
1413
-
1414
- @ Override
1415
- protected void onPostExecute (String result ) {
1416
- if (result != null ) {
1417
- showToast (R .string .key_usage_successful , result );
1418
- } else {
1419
- showToast (R .string .key_usage_failed );
1420
- }
1421
- }
1422
- };
1423
-
1424
-
1425
1320
/**
1426
1321
* Dispatches an intent to capture image or video.
1427
1322
*/
@@ -2443,7 +2338,7 @@ private void showPromptForGeneratedKeyAlias(String alias) {
2443
2338
}
2444
2339
2445
2340
View aliasNamingView = getActivity ().getLayoutInflater ().inflate (
2446
- R .layout .certificate_alias_prompt , null );
2341
+ R .layout .key_generation_prompt , null );
2447
2342
final EditText input = (EditText ) aliasNamingView .findViewById (R .id .alias_input );
2448
2343
if (!TextUtils .isEmpty (alias )) {
2449
2344
input .setText (alias );
@@ -2454,6 +2349,19 @@ private void showPromptForGeneratedKeyAlias(String alias) {
2454
2349
R .id .alias_user_selectable );
2455
2350
userSelectableCheckbox .setChecked (!BuildCompat .isAtLeastP ());
2456
2351
2352
+ // Attestation check-boxes
2353
+ final CheckBox includeAttestationChallengeCheckbox = aliasNamingView .findViewById (
2354
+ R .id .include_key_attestation_challenge );
2355
+ final CheckBox deviceBrandAttestationCheckbox = aliasNamingView .findViewById (
2356
+ R .id .include_device_brand_attestation );
2357
+ final CheckBox deviceSerialAttestationCheckbox = aliasNamingView .findViewById (
2358
+ R .id .include_device_serial_in_attestation );
2359
+ final CheckBox deviceImeiAttestationCheckbox = aliasNamingView .findViewById (
2360
+ R .id .include_device_imei_in_attestation );
2361
+ final CheckBox deviceMeidAttestationCheckbox = aliasNamingView .findViewById (
2362
+ R .id .include_device_meid_in_attestation );
2363
+
2364
+
2457
2365
new AlertDialog .Builder (getActivity ())
2458
2366
.setTitle (getString (R .string .certificate_alias_prompt_title ))
2459
2367
.setView (aliasNamingView )
@@ -2462,7 +2370,28 @@ private void showPromptForGeneratedKeyAlias(String alias) {
2462
2370
public void onClick (DialogInterface dialog , int which ) {
2463
2371
String alias = input .getText ().toString ();
2464
2372
boolean isUserSelectable = userSelectableCheckbox .isChecked ();
2465
- generateKeyPair (alias , isUserSelectable );
2373
+
2374
+ byte [] attestationChallenge = null ;
2375
+ if (includeAttestationChallengeCheckbox .isChecked ()) {
2376
+ attestationChallenge = new byte [] {0x61 , 0x62 , 0x63 };
2377
+ }
2378
+
2379
+ int idAttestationFlags = 0 ;
2380
+ if (deviceBrandAttestationCheckbox .isChecked ()) {
2381
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_BASE_INFO ;
2382
+ }
2383
+ if (deviceSerialAttestationCheckbox .isChecked ()) {
2384
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_SERIAL ;
2385
+ }
2386
+ if (deviceImeiAttestationCheckbox .isChecked ()) {
2387
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_IMEI ;
2388
+ }
2389
+ if (deviceMeidAttestationCheckbox .isChecked ()) {
2390
+ idAttestationFlags |= DevicePolicyManager .ID_TYPE_MEID ;
2391
+ }
2392
+
2393
+ generateKeyPair (alias , isUserSelectable , attestationChallenge ,
2394
+ idAttestationFlags );
2466
2395
}
2467
2396
})
2468
2397
.setNegativeButton (android .R .string .cancel , null )
0 commit comments