1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.keystore.cts;
18 
19 import static com.google.common.base.Functions.forMap;
20 import static com.google.common.collect.Collections2.transform;
21 
22 import android.security.keystore.KeyProperties;
23 import android.util.Log;
24 
25 import com.google.common.base.Joiner;
26 import com.google.common.collect.ImmutableMap;
27 import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Lists;
29 
30 import org.bouncycastle.asn1.ASN1Encodable;
31 import org.bouncycastle.asn1.ASN1Primitive;
32 import org.bouncycastle.asn1.ASN1Sequence;
33 import org.bouncycastle.asn1.ASN1SequenceParser;
34 import org.bouncycastle.asn1.ASN1TaggedObject;
35 
36 import java.io.IOException;
37 import java.io.UnsupportedEncodingException;
38 import java.security.cert.CertificateParsingException;
39 import java.text.DateFormat;
40 import java.util.Collection;
41 import java.util.Date;
42 import java.util.List;
43 import java.util.Set;
44 
45 import co.nstant.in.cbor.model.DataItem;
46 import co.nstant.in.cbor.model.Number;
47 
48 public class AuthorizationList {
49     // Algorithm values.
50     public static final int KM_ALGORITHM_RSA = 1;
51     public static final int KM_ALGORITHM_EC = 3;
52 
53     // EC Curves
54     public static final int KM_EC_CURVE_P224 = 0;
55     public static final int KM_EC_CURVE_P256 = 1;
56     public static final int KM_EC_CURVE_P384 = 2;
57     public static final int KM_EC_CURVE_P521 = 3;
58     public static final int KM_EC_CURVE_25519 = 4;
59 
60     // Padding modes.
61     public static final int KM_PAD_NONE = 1;
62     public static final int KM_PAD_RSA_OAEP = 2;
63     public static final int KM_PAD_RSA_PSS = 3;
64     public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4;
65     public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5;
66 
67     // Digest modes.
68     public static final int KM_DIGEST_NONE = 0;
69     public static final int KM_DIGEST_MD5 = 1;
70     public static final int KM_DIGEST_SHA1 = 2;
71     public static final int KM_DIGEST_SHA_2_224 = 3;
72     public static final int KM_DIGEST_SHA_2_256 = 4;
73     public static final int KM_DIGEST_SHA_2_384 = 5;
74     public static final int KM_DIGEST_SHA_2_512 = 6;
75 
76     // Key origins.
77     public static final int KM_ORIGIN_GENERATED = 0;
78     public static final int KM_ORIGIN_IMPORTED = 2;
79     public static final int KM_ORIGIN_UNKNOWN = 3;
80 
81     // Operation Purposes.
82     public static final int KM_PURPOSE_ENCRYPT = 0;
83     public static final int KM_PURPOSE_DECRYPT = 1;
84     public static final int KM_PURPOSE_SIGN = 2;
85     public static final int KM_PURPOSE_VERIFY = 3;
86 
87     // User authenticators.
88     public static final int HW_AUTH_PASSWORD = 1 << 0;
89     public static final int HW_AUTH_FINGERPRINT = 1 << 1;
90 
91     // Keymaster tag classes
92     private static final int KM_ENUM = 1 << 28;
93     private static final int KM_ENUM_REP = 2 << 28;
94     private static final int KM_UINT = 3 << 28;
95     private static final int KM_ULONG = 5 << 28;
96     private static final int KM_DATE = 6 << 28;
97     private static final int KM_BOOL = 7 << 28;
98     private static final int KM_BYTES = 9 << 28;
99 
100     // Tag class removal mask
101     private static final int KEYMASTER_TAG_TYPE_MASK = 0x0FFFFFFF;
102 
103     // Keymaster tags
104     private static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1;
105     private static final int KM_TAG_ALGORITHM = KM_ENUM | 2;
106     private static final int KM_TAG_KEY_SIZE = KM_UINT | 3;
107     private static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
108     private static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
109     private static final int KM_TAG_EC_CURVE = KM_ENUM | 10;
110     private static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200;
111     private static final int KM_TAG_RSA_OAEP_MGF_DIGEST = KM_ENUM | 203;
112     private static final int KM_TAG_ROLLBACK_RESISTANCE = KM_BOOL | 303;
113     private static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400;
114     private static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401;
115     private static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402;
116     private static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503;
117     private static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504;
118     private static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
119     private static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
120     private static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
121     private static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
122     private static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;
123     private static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
124     private static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701;
125     private static final int KM_TAG_ORIGIN = KM_ENUM | 702;
126     private static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703;
127     private static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704;
128     private static final int KM_TAG_OS_VERSION = KM_UINT | 705;
129     private static final int KM_TAG_OS_PATCHLEVEL = KM_UINT | 706;
130     private static final int KM_TAG_ATTESTATION_APPLICATION_ID = KM_BYTES | 709;
131     private static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710;
132     private static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711;
133     private static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712;
134     private static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713;
135     private static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714;
136     private static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715;
137     private static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716;
138     private static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717;
139     private static final int KM_TAG_VENDOR_PATCHLEVEL = KM_UINT | 718;
140     private static final int KM_TAG_BOOT_PATCHLEVEL = KM_UINT | 719;
141     private static final int KM_TAG_ATTESTATION_ID_SECOND_IMEI = KM_BYTES | 723;
142 
143     // Map for converting padding values to strings
144     private static final ImmutableMap<Integer, String> paddingMap = ImmutableMap
145             .<Integer, String> builder()
146             .put(KM_PAD_NONE, "NONE")
147             .put(KM_PAD_RSA_OAEP, "OAEP")
148             .put(KM_PAD_RSA_PSS, "PSS")
149             .put(KM_PAD_RSA_PKCS1_1_5_ENCRYPT, "PKCS1 ENCRYPT")
150             .put(KM_PAD_RSA_PKCS1_1_5_SIGN, "PKCS1 SIGN")
151             .build();
152 
153     // Map for converting digest values to strings
154     private static final ImmutableMap<Integer, String> digestMap = ImmutableMap
155             .<Integer, String> builder()
156             .put(KM_DIGEST_NONE, "NONE")
157             .put(KM_DIGEST_MD5, "MD5")
158             .put(KM_DIGEST_SHA1, "SHA1")
159             .put(KM_DIGEST_SHA_2_224, "SHA224")
160             .put(KM_DIGEST_SHA_2_256, "SHA256")
161             .put(KM_DIGEST_SHA_2_384, "SHA384")
162             .put(KM_DIGEST_SHA_2_512, "SHA512")
163             .build();
164 
165     // Map for converting purpose values to strings
166     private static final ImmutableMap<Integer, String> purposeMap = ImmutableMap
167             .<Integer, String> builder()
168             .put(KM_PURPOSE_DECRYPT, "DECRYPT")
169             .put(KM_PURPOSE_ENCRYPT, "ENCRYPT")
170             .put(KM_PURPOSE_SIGN, "SIGN")
171             .put(KM_PURPOSE_VERIFY, "VERIFY")
172             .build();
173 
174     private Integer securityLevel;
175     private Set<Integer> purposes;
176     private Integer algorithm;
177     private Integer keySize;
178     private Set<Integer> digests;
179     private Set<Integer> paddingModes;
180     private Integer ecCurve;
181     private Long rsaPublicExponent;
182     private Set<Integer> mRsaOaepMgfDigests;
183     private Date activeDateTime;
184     private Date originationExpireDateTime;
185     private Date usageExpireDateTime;
186     private boolean noAuthRequired;
187     private Integer userAuthType;
188     private Integer authTimeout;
189     private boolean allowWhileOnBody;
190     private boolean allApplications;
191     private byte[] applicationId;
192     private Date creationDateTime;
193     private Integer origin;
194     private boolean rollbackResistant;
195     private boolean rollbackResistance;
196     private RootOfTrust rootOfTrust;
197     private Integer osVersion;
198     private Integer osPatchLevel;
199     private Integer vendorPatchLevel;
200     private Integer bootPatchLevel;
201     private AttestationApplicationId attestationApplicationId;
202     private String brand;
203     private String device;
204     private String serialNumber;
205     private String imei;
206     private String meid;
207     private String product;
208     private String manufacturer;
209     private String model;
210     private boolean userPresenceRequired;
211     private boolean confirmationRequired;
212     private String mSecondImei;
213 
AuthorizationList(ASN1Encodable sequence, int attestationVersion)214     public AuthorizationList(ASN1Encodable sequence, int attestationVersion) throws CertificateParsingException {
215         this(sequence, attestationVersion, true);
216     }
217 
AuthorizationList(ASN1Encodable sequence, int attestationVersion, boolean strictParsing)218     public AuthorizationList(ASN1Encodable sequence, int attestationVersion, boolean strictParsing) throws CertificateParsingException {
219         if (!(sequence instanceof ASN1Sequence)) {
220             throw new CertificateParsingException("Expected sequence for authorization list, found "
221                     + sequence.getClass().getName());
222         }
223 
224         ASN1SequenceParser parser = ((ASN1Sequence) sequence).parser();
225         ASN1TaggedObject entry = parseAsn1TaggedObject(parser);
226         int currentTag = 0, prevTag = 0;
227         for (; entry != null; entry = parseAsn1TaggedObject(parser)) {
228             prevTag = currentTag;
229             currentTag = entry.getTagNo();
230             if (prevTag > currentTag) {
231                 throw new CertificateParsingException(
232                         "Incorrect order of tags in authorization list: " + currentTag);
233             }
234             ASN1Primitive value = entry.getObject();
235             Log.i("Attestation", "Parsing tag: [" + currentTag + "], value: [" + value + "]");
236             switch (currentTag) {
237                 default:
238                     throw new CertificateParsingException("Unknown tag " + currentTag + " found");
239 
240                 case KM_TAG_PURPOSE & KEYMASTER_TAG_TYPE_MASK:
241                     purposes = Asn1Utils.getIntegersFromAsn1Set(value);
242                     break;
243                 case KM_TAG_ALGORITHM & KEYMASTER_TAG_TYPE_MASK:
244                     algorithm = Asn1Utils.getIntegerFromAsn1(value);
245                     break;
246                 case KM_TAG_KEY_SIZE & KEYMASTER_TAG_TYPE_MASK:
247                     keySize = Asn1Utils.getIntegerFromAsn1(value);
248                     Log.i("Attestation", "Found KEY SIZE, value: " + keySize);
249                     break;
250                 case KM_TAG_DIGEST & KEYMASTER_TAG_TYPE_MASK:
251                     digests = Asn1Utils.getIntegersFromAsn1Set(value);
252                     break;
253                 case KM_TAG_PADDING & KEYMASTER_TAG_TYPE_MASK:
254                     paddingModes = Asn1Utils.getIntegersFromAsn1Set(value);
255                     break;
256                 case KM_TAG_RSA_PUBLIC_EXPONENT & KEYMASTER_TAG_TYPE_MASK:
257                     rsaPublicExponent = Asn1Utils.getLongFromAsn1(value);
258                     break;
259                 case KM_TAG_RSA_OAEP_MGF_DIGEST & KEYMASTER_TAG_TYPE_MASK:
260                     mRsaOaepMgfDigests = Asn1Utils.getIntegersFromAsn1Set(value);
261                     break;
262                 case KM_TAG_NO_AUTH_REQUIRED & KEYMASTER_TAG_TYPE_MASK:
263                     noAuthRequired = true;
264                     break;
265                 case KM_TAG_CREATION_DATETIME & KEYMASTER_TAG_TYPE_MASK:
266                     creationDateTime = Asn1Utils.getDateFromAsn1(value);
267                     break;
268                 case KM_TAG_ORIGIN & KEYMASTER_TAG_TYPE_MASK:
269                     origin = Asn1Utils.getIntegerFromAsn1(value);
270                     break;
271                 case KM_TAG_OS_VERSION & KEYMASTER_TAG_TYPE_MASK:
272                     osVersion = Asn1Utils.getIntegerFromAsn1(value);
273                     break;
274                 case KM_TAG_OS_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK:
275                     osPatchLevel = Asn1Utils.getIntegerFromAsn1(value);
276                     break;
277                 case KM_TAG_VENDOR_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK:
278                     vendorPatchLevel = Asn1Utils.getIntegerFromAsn1(value);
279                     break;
280                 case KM_TAG_BOOT_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK:
281                     bootPatchLevel = Asn1Utils.getIntegerFromAsn1(value);
282                     break;
283                 case KM_TAG_ACTIVE_DATETIME & KEYMASTER_TAG_TYPE_MASK:
284                     activeDateTime = Asn1Utils.getDateFromAsn1(value);
285                     break;
286                 case KM_TAG_ORIGINATION_EXPIRE_DATETIME & KEYMASTER_TAG_TYPE_MASK:
287                     originationExpireDateTime = Asn1Utils.getDateFromAsn1(value);
288                     break;
289                 case KM_TAG_USAGE_EXPIRE_DATETIME & KEYMASTER_TAG_TYPE_MASK:
290                     usageExpireDateTime = Asn1Utils.getDateFromAsn1(value);
291                     break;
292                 case KM_TAG_ROLLBACK_RESISTANT & KEYMASTER_TAG_TYPE_MASK:
293                     rollbackResistant = true;
294                     break;
295                 case KM_TAG_ROLLBACK_RESISTANCE & KEYMASTER_TAG_TYPE_MASK:
296                     rollbackResistance = true;
297                     break;
298                 case KM_TAG_AUTH_TIMEOUT & KEYMASTER_TAG_TYPE_MASK:
299                     authTimeout = Asn1Utils.getIntegerFromAsn1(value);
300                     break;
301                 case KM_TAG_ALLOW_WHILE_ON_BODY & KEYMASTER_TAG_TYPE_MASK:
302                     allowWhileOnBody = true;
303                     break;
304                 case KM_TAG_EC_CURVE & KEYMASTER_TAG_TYPE_MASK:
305                     ecCurve = Asn1Utils.getIntegerFromAsn1(value);
306                     break;
307                 case KM_TAG_USER_AUTH_TYPE & KEYMASTER_TAG_TYPE_MASK:
308                     userAuthType = Asn1Utils.getIntegerFromAsn1(value);
309                     break;
310                 case KM_TAG_ROOT_OF_TRUST & KEYMASTER_TAG_TYPE_MASK:
311                     rootOfTrust = new RootOfTrust(value, attestationVersion, strictParsing);
312                     break;
313                 case KM_TAG_ATTESTATION_APPLICATION_ID & KEYMASTER_TAG_TYPE_MASK:
314                     attestationApplicationId = new AttestationApplicationId(Asn1Utils
315                             .getAsn1EncodableFromBytes(Asn1Utils.getByteArrayFromAsn1(value)));
316                     break;
317                 case KM_TAG_ATTESTATION_ID_BRAND & KEYMASTER_TAG_TYPE_MASK:
318                     brand = getStringFromAsn1Value(value);
319                     break;
320                 case KM_TAG_ATTESTATION_ID_DEVICE & KEYMASTER_TAG_TYPE_MASK:
321                     device = getStringFromAsn1Value(value);
322                     break;
323                 case KM_TAG_ATTESTATION_ID_PRODUCT & KEYMASTER_TAG_TYPE_MASK:
324                     product = getStringFromAsn1Value(value);
325                     break;
326                 case KM_TAG_ATTESTATION_ID_SERIAL & KEYMASTER_TAG_TYPE_MASK:
327                     serialNumber = getStringFromAsn1Value(value);
328                     break;
329                 case KM_TAG_ATTESTATION_ID_IMEI & KEYMASTER_TAG_TYPE_MASK:
330                     imei = getStringFromAsn1Value(value);
331                     break;
332                 case KM_TAG_ATTESTATION_ID_MEID & KEYMASTER_TAG_TYPE_MASK:
333                     meid = getStringFromAsn1Value(value);
334                     break;
335                 case KM_TAG_ATTESTATION_ID_MANUFACTURER & KEYMASTER_TAG_TYPE_MASK:
336                     manufacturer = getStringFromAsn1Value(value);
337                     break;
338                 case KM_TAG_ATTESTATION_ID_MODEL & KEYMASTER_TAG_TYPE_MASK:
339                     model = getStringFromAsn1Value(value);
340                     break;
341                 case KM_TAG_ALL_APPLICATIONS & KEYMASTER_TAG_TYPE_MASK:
342                     allApplications = true;
343                     break;
344                 case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED & KEYMASTER_TAG_TYPE_MASK:
345                     userPresenceRequired = true;
346                     break;
347                 case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED & KEYMASTER_TAG_TYPE_MASK:
348                     confirmationRequired = true;
349                     break;
350                 case KM_TAG_ATTESTATION_ID_SECOND_IMEI & KEYMASTER_TAG_TYPE_MASK:
351                     mSecondImei = getStringFromAsn1Value(value);
352                     break;
353             }
354         }
355 
356     }
357 
AuthorizationList(co.nstant.in.cbor.model.Map submodMap)358     public AuthorizationList(co.nstant.in.cbor.model.Map submodMap)
359             throws CertificateParsingException {
360         for (DataItem key : submodMap.getKeys()) {
361             int keyInt = ((Number) key).getValue().intValue();
362             switch (keyInt) {
363                 default:
364                     throw new CertificateParsingException("Unknown EAT tag: " + key);
365 
366                 case EatClaim.SECURITY_LEVEL:
367                     securityLevel = eatSecurityLevelToKeymasterSecurityLevel(
368                             CborUtils.getInt(submodMap, key));
369                     break;
370                 case EatClaim.PURPOSE:
371                     purposes = CborUtils.getIntSet(submodMap, key);
372                     break;
373                 case EatClaim.ALGORITHM:
374                     algorithm = CborUtils.getInt(submodMap, key);
375                     break;
376                 case EatClaim.KEY_SIZE:
377                     keySize = CborUtils.getInt(submodMap, key);
378                     Log.i("Attestation", "Found KEY SIZE, value: " + keySize);
379                     break;
380                 case EatClaim.DIGEST:
381                     digests = CborUtils.getIntSet(submodMap, key);
382                     break;
383                 case EatClaim.PADDING:
384                     paddingModes = CborUtils.getIntSet(submodMap, key);
385                     break;
386                 case EatClaim.RSA_PUBLIC_EXPONENT:
387                     rsaPublicExponent = CborUtils.getLong(submodMap, key);
388                     break;
389                 case EatClaim.RSA_OAEP_MGF_DIGEST:
390                     mRsaOaepMgfDigests = CborUtils.getIntSet(submodMap, key);
391                     break;
392                 case EatClaim.NO_AUTH_REQUIRED:
393                     noAuthRequired = true;
394                     break;
395                 case EatClaim.IAT:
396                     creationDateTime = CborUtils.getDate(submodMap, key);
397                     break;
398                 case EatClaim.ORIGIN:
399                     origin = CborUtils.getInt(submodMap, key);
400                     break;
401                 case EatClaim.OS_VERSION:
402                     osVersion = CborUtils.getInt(submodMap, key);
403                     break;
404                 case EatClaim.OS_PATCHLEVEL:
405                     osPatchLevel = CborUtils.getInt(submodMap, key);
406                     break;
407                 case EatClaim.VENDOR_PATCHLEVEL:
408                     vendorPatchLevel = CborUtils.getInt(submodMap, key);
409                     break;
410                 case EatClaim.BOOT_PATCHLEVEL:
411                     bootPatchLevel = CborUtils.getInt(submodMap, key);
412                     break;
413                 case EatClaim.ACTIVE_DATETIME:
414                     activeDateTime = CborUtils.getDate(submodMap, key);
415                     break;
416                 case EatClaim.ORIGINATION_EXPIRE_DATETIME:
417                     originationExpireDateTime = CborUtils.getDate(submodMap, key);
418                     break;
419                 case EatClaim.USAGE_EXPIRE_DATETIME:
420                     usageExpireDateTime = CborUtils.getDate(submodMap, key);
421                     break;
422                 case EatClaim.ROLLBACK_RESISTANT:
423                     rollbackResistant = true;
424                     break;
425                 case EatClaim.ROLLBACK_RESISTANCE:
426                     rollbackResistance = true;
427                     break;
428                 case EatClaim.AUTH_TIMEOUT:
429                     authTimeout = CborUtils.getInt(submodMap, key);
430                     break;
431                 case EatClaim.ALLOW_WHILE_ON_BODY:
432                     allowWhileOnBody = true;
433                     break;
434                 case EatClaim.EC_CURVE:
435                     ecCurve = CborUtils.getInt(submodMap, key);
436                     break;
437                 case EatClaim.USER_AUTH_TYPE:
438                     userAuthType = CborUtils.getInt(submodMap, key);
439                     break;
440                 case EatClaim.ATTESTATION_APPLICATION_ID:
441                     // TODO: The attestation application ID is currently still encoded as an ASN.1
442                     // structure. Parse a CBOR structure when it's available instead.
443                     attestationApplicationId = new AttestationApplicationId(
444                         Asn1Utils.getAsn1EncodableFromBytes(CborUtils.getBytes(submodMap, key)));
445                     break;
446                 case EatClaim.ATTESTATION_ID_BRAND:
447                     brand = CborUtils.getString(submodMap, key);
448                     break;
449                 case EatClaim.ATTESTATION_ID_DEVICE:
450                     device = CborUtils.getString(submodMap, key);
451                     break;
452                 case EatClaim.ATTESTATION_ID_PRODUCT:
453                     product = CborUtils.getString(submodMap, key);
454                     break;
455                 case EatClaim.ATTESTATION_ID_SERIAL:
456                     serialNumber = CborUtils.getString(submodMap, key);
457                     break;
458                 case EatClaim.UEID:
459                     // TODO: Parse depending on encoding chosen in attestation_record.cpp.
460                     imei = CborUtils.getString(submodMap, key);
461                     break;
462                 case EatClaim.ATTESTATION_ID_MEID:
463                     meid = CborUtils.getString(submodMap, key);
464                     break;
465                 case EatClaim.ATTESTATION_ID_MANUFACTURER:
466                     manufacturer = CborUtils.getString(submodMap, key);
467                     break;
468                 case EatClaim.ATTESTATION_ID_MODEL:
469                     model = CborUtils.getString(submodMap, key);
470                     break;
471                 case EatClaim.USER_PRESENCE_REQUIRED:
472                     userPresenceRequired = CborUtils.getBoolean(submodMap, key);
473                     break;
474                 case EatClaim.TRUSTED_CONFIRMATION_REQUIRED:
475                     confirmationRequired = true;
476                     break;
477             }
478         }
479     }
480 
algorithmToString(int algorithm)481     public static String algorithmToString(int algorithm) {
482         switch (algorithm) {
483             case KM_ALGORITHM_RSA:
484                 return "RSA";
485             case KM_ALGORITHM_EC:
486                 return "ECDSA";
487             default:
488                 return "Unknown";
489         }
490     }
491 
paddingModesToString(final Set<Integer> paddingModes)492     public static String paddingModesToString(final Set<Integer> paddingModes) {
493         return joinStrings(transform(paddingModes, forMap(paddingMap, "Unknown")));
494     }
495 
paddingModeToString(int paddingMode)496     public static String paddingModeToString(int paddingMode) {
497         return forMap(paddingMap, "Unknown").apply(paddingMode);
498     }
499 
digestsToString(Set<Integer> digests)500     public static String digestsToString(Set<Integer> digests) {
501         return joinStrings(transform(digests, forMap(digestMap, "Unknown")));
502     }
503 
digestToString(int digest)504     public static String digestToString(int digest) {
505         return forMap(digestMap, "Unknown").apply(digest);
506     }
507 
purposesToString(Set<Integer> purposes)508     public static String purposesToString(Set<Integer> purposes) {
509         return joinStrings(transform(purposes, forMap(purposeMap, "Unknown")));
510     }
511 
userAuthTypeToString(int userAuthType)512     public static String userAuthTypeToString(int userAuthType) {
513         List<String> types = Lists.newArrayList();
514         if ((userAuthType & HW_AUTH_FINGERPRINT) != 0)
515             types.add("Fingerprint");
516         if ((userAuthType & HW_AUTH_PASSWORD) != 0)
517             types.add("Password");
518         return joinStrings(types);
519     }
520 
originToString(int origin)521     public static String originToString(int origin) {
522         switch (origin) {
523             case KM_ORIGIN_GENERATED:
524                 return "Generated";
525             case KM_ORIGIN_IMPORTED:
526                 return "Imported";
527             case KM_ORIGIN_UNKNOWN:
528                 return "Unknown (KM0)";
529             default:
530                 return "Unknown";
531         }
532     }
533 
joinStrings(Collection<String> collection)534     private static String joinStrings(Collection<String> collection) {
535         return new StringBuilder()
536                 .append("[")
537                 .append(Joiner.on(", ").join(collection))
538                 .append("]")
539                 .toString();
540     }
541 
formatDate(Date date)542     private static String formatDate(Date date) {
543         return DateFormat.getDateTimeInstance().format(date);
544     }
545 
parseAsn1TaggedObject(ASN1SequenceParser parser)546     private static ASN1TaggedObject parseAsn1TaggedObject(ASN1SequenceParser parser)
547             throws CertificateParsingException {
548         ASN1Encodable asn1Encodable = parseAsn1Encodable(parser);
549         if (asn1Encodable == null || asn1Encodable instanceof ASN1TaggedObject) {
550             return (ASN1TaggedObject) asn1Encodable;
551         }
552         throw new CertificateParsingException(
553                 "Expected tagged object, found " + asn1Encodable.getClass().getName());
554     }
555 
parseAsn1Encodable(ASN1SequenceParser parser)556     private static ASN1Encodable parseAsn1Encodable(ASN1SequenceParser parser)
557             throws CertificateParsingException {
558         try {
559             return parser.readObject();
560         } catch (IOException e) {
561             throw new CertificateParsingException("Failed to parse ASN1 sequence", e);
562         }
563     }
564 
getSecurityLevel()565     public Integer getSecurityLevel() {
566         return securityLevel;
567     }
568 
getPurposes()569     public Set<Integer> getPurposes() {
570         return purposes;
571     }
572 
getAlgorithm()573     public Integer getAlgorithm() {
574         return algorithm;
575     }
576 
getKeySize()577     public Integer getKeySize() {
578         return keySize;
579     }
580 
getDigests()581     public Set<Integer> getDigests() {
582         return digests;
583     }
584 
getPaddingModes()585     public Set<Integer> getPaddingModes() {
586         return paddingModes;
587     }
588 
getPaddingModesAsStrings()589     public Set<String> getPaddingModesAsStrings() throws CertificateParsingException {
590         if (paddingModes == null) {
591             return ImmutableSet.of();
592         }
593 
594         ImmutableSet.Builder<String> builder = ImmutableSet.builder();
595         for (int paddingMode : paddingModes) {
596             switch (paddingMode) {
597                 case KM_PAD_NONE:
598                     builder.add(KeyProperties.ENCRYPTION_PADDING_NONE);
599                     break;
600                 case KM_PAD_RSA_OAEP:
601                     builder.add(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
602                     break;
603                 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
604                     builder.add(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
605                     break;
606                 case KM_PAD_RSA_PKCS1_1_5_SIGN:
607                     builder.add(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
608                     break;
609                 case KM_PAD_RSA_PSS:
610                     builder.add(KeyProperties.SIGNATURE_PADDING_RSA_PSS);
611                     break;
612                 default:
613                     throw new CertificateParsingException("Invalid padding mode " + paddingMode);
614             }
615         }
616         return builder.build();
617     }
618 
getEcCurve()619     public Integer getEcCurve() {
620         return ecCurve;
621     }
622 
ecCurveAsString()623     public String ecCurveAsString() {
624         if (ecCurve == null)
625             return "NULL";
626 
627         switch (ecCurve) {
628             case KM_EC_CURVE_P224:
629                 return "secp224r1";
630             case KM_EC_CURVE_P256:
631                 return "secp256r1";
632             case KM_EC_CURVE_P384:
633                 return "secp384r1";
634             case KM_EC_CURVE_P521:
635                 return "secp521r1";
636             case KM_EC_CURVE_25519:
637                 return "CURVE_25519";
638             default:
639                 return "unknown";
640         }
641     }
642 
getRsaPublicExponent()643     public Long getRsaPublicExponent() {
644         return rsaPublicExponent;
645     }
646 
getRsaOaepMgfDigests()647     public Set<Integer> getRsaOaepMgfDigests() {
648         return mRsaOaepMgfDigests;
649     }
650 
getActiveDateTime()651     public Date getActiveDateTime() {
652         return activeDateTime;
653     }
654 
getOriginationExpireDateTime()655     public Date getOriginationExpireDateTime() {
656         return originationExpireDateTime;
657     }
658 
getUsageExpireDateTime()659     public Date getUsageExpireDateTime() {
660         return usageExpireDateTime;
661     }
662 
isNoAuthRequired()663     public boolean isNoAuthRequired() {
664         return noAuthRequired;
665     }
666 
getUserAuthType()667     public Integer getUserAuthType() {
668         return userAuthType;
669     }
670 
getAuthTimeout()671     public Integer getAuthTimeout() {
672         return authTimeout;
673     }
674 
isAllowWhileOnBody()675     public boolean isAllowWhileOnBody() {
676         return allowWhileOnBody;
677     }
678 
isAllApplications()679     public boolean isAllApplications() {
680         return allApplications;
681     }
682 
getApplicationId()683     public byte[] getApplicationId() {
684         return applicationId;
685     }
686 
getCreationDateTime()687     public Date getCreationDateTime() {
688         return creationDateTime;
689     }
690 
getOrigin()691     public Integer getOrigin() {
692         return origin;
693     }
694 
isRollbackResistant()695     public boolean isRollbackResistant() {
696         return rollbackResistant;
697     }
698 
isRollbackResistance()699     public boolean isRollbackResistance() {
700         return rollbackResistance;
701     }
702 
getRootOfTrust()703     public RootOfTrust getRootOfTrust() {
704         return rootOfTrust;
705     }
706 
getOsVersion()707     public Integer getOsVersion() {
708         return osVersion;
709     }
710 
getOsPatchLevel()711     public Integer getOsPatchLevel() {
712         return osPatchLevel;
713     }
714 
getVendorPatchLevel()715     public Integer getVendorPatchLevel() {
716         return vendorPatchLevel;
717     }
718 
getBootPatchLevel()719     public Integer getBootPatchLevel() {
720         return bootPatchLevel;
721     }
722 
getAttestationApplicationId()723     public AttestationApplicationId getAttestationApplicationId() {
724         return attestationApplicationId;
725     }
726 
getBrand()727     public String getBrand() {
728         return brand;
729     }
730 
getDevice()731     public String getDevice() {
732         return device;
733     }
734 
getSerialNumber()735     public String getSerialNumber() {
736         return serialNumber;
737     };
738 
getImei()739     public String getImei() {
740         return imei;
741     };
742 
getMeid()743     public String getMeid() {
744         return meid;
745     };
746 
getProduct()747     public String getProduct() {
748         return product;
749     };
750 
getManufacturer()751     public String getManufacturer() {
752         return manufacturer;
753     };
754 
getModel()755     public String getModel() {
756         return model;
757     };
758 
isUserPresenceRequired()759     public boolean isUserPresenceRequired() {
760         return userPresenceRequired;
761     }
762 
isConfirmationRequired()763     public boolean isConfirmationRequired() {
764         return confirmationRequired;
765     }
766 
getSecondImei()767     public String getSecondImei() {
768         return mSecondImei;
769     };
770 
eatSecurityLevelToKeymasterSecurityLevel(int eatSecurityLevel)771     static int eatSecurityLevelToKeymasterSecurityLevel(int eatSecurityLevel) {
772         switch(eatSecurityLevel) {
773             case EatClaim.SECURITY_LEVEL_UNRESTRICTED:
774                 return Attestation.KM_SECURITY_LEVEL_SOFTWARE;
775             case EatClaim.SECURITY_LEVEL_SECURE_RESTRICTED:
776                 return Attestation.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
777             case EatClaim.SECURITY_LEVEL_HARDWARE:
778                 return Attestation.KM_SECURITY_LEVEL_STRONG_BOX;
779             default:
780                 throw new RuntimeException("Invalid EAT security level: " + eatSecurityLevel);
781         }
782     }
783 
getStringFromAsn1Value(ASN1Primitive value)784     private String getStringFromAsn1Value(ASN1Primitive value) throws CertificateParsingException {
785         try {
786             return Asn1Utils.getStringFromAsn1OctetStreamAssumingUTF8(value);
787         } catch (UnsupportedEncodingException e) {
788             throw new CertificateParsingException("Error parsing ASN.1 value", e);
789         }
790     }
791 
792     @Override
toString()793     public String toString() {
794         StringBuilder s = new StringBuilder();
795 
796         if (algorithm != null) {
797             s.append("\nAlgorithm: ").append(algorithmToString(algorithm));
798         }
799 
800         if (keySize != null) {
801             s.append("\nKeySize: ").append(keySize);
802         }
803 
804         if (purposes != null && !purposes.isEmpty()) {
805             s.append("\nPurposes: ").append(purposesToString(purposes));
806         }
807 
808         if (digests != null && !digests.isEmpty()) {
809             s.append("\nDigests: ").append(digestsToString(digests));
810         }
811 
812         if (paddingModes != null && !paddingModes.isEmpty()) {
813             s.append("\nPadding modes: ").append(paddingModesToString(paddingModes));
814         }
815 
816         if (ecCurve != null) {
817             s.append("\nEC Curve: ").append(ecCurveAsString());
818         }
819 
820         String label = "\nRSA exponent: ";
821         if (rsaPublicExponent != null) {
822             s.append(label).append(rsaPublicExponent);
823         }
824 
825         if (mRsaOaepMgfDigests != null && !mRsaOaepMgfDigests.isEmpty()) {
826             s.append("\nRSA OAEP MGF Digests: ").append(digestsToString(mRsaOaepMgfDigests));
827         }
828 
829         if (activeDateTime != null) {
830             s.append("\nActive: ").append(formatDate(activeDateTime));
831         }
832 
833         if (originationExpireDateTime != null) {
834             s.append("\nOrigination expire: ").append(formatDate(originationExpireDateTime));
835         }
836 
837         if (usageExpireDateTime != null) {
838             s.append("\nUsage expire: ").append(formatDate(usageExpireDateTime));
839         }
840 
841         if (!noAuthRequired && userAuthType != null) {
842             s.append("\nAuth types: ").append(userAuthTypeToString(userAuthType));
843             if (authTimeout != null) {
844                 s.append("\nAuth timeout: ").append(authTimeout);
845             }
846         }
847 
848         if (applicationId != null) {
849             s.append("\nApplication ID: ").append(new String(applicationId));
850         }
851 
852         if (creationDateTime != null) {
853             s.append("\nCreated: ").append(formatDate(creationDateTime));
854         }
855 
856         if (origin != null) {
857             s.append("\nOrigin: ").append(originToString(origin));
858         }
859 
860         if (rollbackResistant) {
861             s.append("\nRollback resistant: true");
862         }
863 
864         if (rollbackResistance) {
865             s.append("\nRollback resistance: true");
866         }
867 
868         if (rootOfTrust != null) {
869             s.append("\nRoot of Trust:\n");
870             s.append(rootOfTrust);
871         }
872 
873         if (osVersion != null) {
874             s.append("\nOS Version: ").append(osVersion);
875         }
876 
877         if (osPatchLevel != null) {
878             s.append("\nOS Patchlevel: ").append(osPatchLevel);
879         }
880 
881         if (vendorPatchLevel != null) {
882             s.append("\nVendor Patchlevel: ").append(vendorPatchLevel);
883         }
884 
885         if (bootPatchLevel != null) {
886             s.append("\nBoot Patchlevel: ").append(bootPatchLevel);
887         }
888 
889         if (attestationApplicationId != null) {
890             s.append("\nAttestation Application Id:").append(attestationApplicationId);
891         }
892 
893         if (userPresenceRequired) {
894             s.append("\nUser presence required");
895         }
896 
897         if (confirmationRequired) {
898             s.append("\nConfirmation required");
899         }
900 
901         if (brand != null) {
902             s.append("\nBrand: ").append(brand);
903         }
904         if (device != null) {
905             s.append("\nDevice type: ").append(device);
906         }
907         return s.toString();
908     }
909 }
910