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