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 com.google.common.base.Joiner;
23 import com.google.common.collect.ImmutableMap;
24 import com.google.common.collect.ImmutableSet;
25 import com.google.common.collect.Lists;
26 
27 import android.security.keystore.KeyProperties;
28 import android.util.Log;
29 
30 import com.android.org.bouncycastle.asn1.ASN1Encodable;
31 import com.android.org.bouncycastle.asn1.ASN1Primitive;
32 import com.android.org.bouncycastle.asn1.ASN1Sequence;
33 import com.android.org.bouncycastle.asn1.ASN1SequenceParser;
34 import com.android.org.bouncycastle.asn1.ASN1TaggedObject;
35 import com.android.org.bouncycastle.asn1.ASN1InputStream;
36 
37 import java.io.IOException;
38 import java.io.UnsupportedEncodingException;
39 import java.security.cert.CertificateParsingException;
40 import java.text.DateFormat;
41 import java.util.Collection;
42 import java.util.Date;
43 import java.util.List;
44 import java.util.Set;
45 
46 public class AuthorizationList {
47     // Algorithm values.
48     public static final int KM_ALGORITHM_RSA = 1;
49     public static final int KM_ALGORITHM_EC = 3;
50 
51     // EC Curves
52     public static final int KM_EC_CURVE_P224 = 0;
53     public static final int KM_EC_CURVE_P256 = 1;
54     public static final int KM_EC_CURVE_P384 = 2;
55     public static final int KM_EC_CURVE_P521 = 3;
56 
57     // Padding modes.
58     public static final int KM_PAD_NONE = 1;
59     public static final int KM_PAD_RSA_OAEP = 2;
60     public static final int KM_PAD_RSA_PSS = 3;
61     public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4;
62     public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5;
63 
64     // Digest modes.
65     public static final int KM_DIGEST_NONE = 0;
66     public static final int KM_DIGEST_MD5 = 1;
67     public static final int KM_DIGEST_SHA1 = 2;
68     public static final int KM_DIGEST_SHA_2_224 = 3;
69     public static final int KM_DIGEST_SHA_2_256 = 4;
70     public static final int KM_DIGEST_SHA_2_384 = 5;
71     public static final int KM_DIGEST_SHA_2_512 = 6;
72 
73     // Key origins.
74     public static final int KM_ORIGIN_GENERATED = 0;
75     public static final int KM_ORIGIN_IMPORTED = 2;
76     public static final int KM_ORIGIN_UNKNOWN = 3;
77 
78     // Operation Purposes.
79     public static final int KM_PURPOSE_ENCRYPT = 0;
80     public static final int KM_PURPOSE_DECRYPT = 1;
81     public static final int KM_PURPOSE_SIGN = 2;
82     public static final int KM_PURPOSE_VERIFY = 3;
83 
84     // User authenticators.
85     public static final int HW_AUTH_PASSWORD = 1 << 0;
86     public static final int HW_AUTH_FINGERPRINT = 1 << 1;
87 
88     // Keymaster tag classes
89     private static final int KM_ENUM = 1 << 28;
90     private static final int KM_ENUM_REP = 2 << 28;
91     private static final int KM_UINT = 3 << 28;
92     private static final int KM_ULONG = 5 << 28;
93     private static final int KM_DATE = 6 << 28;
94     private static final int KM_BOOL = 7 << 28;
95     private static final int KM_BYTES = 9 << 28;
96 
97     // Tag class removal mask
98     private static final int KEYMASTER_TAG_TYPE_MASK = 0x0FFFFFFF;
99 
100     // Keymaster tags
101     private static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1;
102     private static final int KM_TAG_ALGORITHM = KM_ENUM | 2;
103     private static final int KM_TAG_KEY_SIZE = KM_UINT | 3;
104     private static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
105     private static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
106     private static final int KM_TAG_EC_CURVE = KM_ENUM | 10;
107     private static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200;
108     private static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400;
109     private static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401;
110     private static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402;
111     private static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503;
112     private static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504;
113     private static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
114     private static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
115     private static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
116     private static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
117     private static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701;
118     private static final int KM_TAG_ORIGIN = KM_ENUM | 702;
119     private static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703;
120     private static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704;
121     private static final int KM_TAG_OS_VERSION = KM_UINT | 705;
122     private static final int KM_TAG_OS_PATCHLEVEL = KM_UINT | 706;
123     private static final int KM_TAG_ATTESTATION_APPLICATION_ID = KM_BYTES | 709;
124     private static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710;
125     private static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711;
126     private static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712;
127     private static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713;
128     private static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714;
129     private static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715;
130     private static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716;
131     private static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717;
132 
133     // Map for converting padding values to strings
134     private static final ImmutableMap<Integer, String> paddingMap = ImmutableMap
135             .<Integer, String> builder()
136             .put(KM_PAD_NONE, "NONE")
137             .put(KM_PAD_RSA_OAEP, "OAEP")
138             .put(KM_PAD_RSA_PSS, "PSS")
139             .put(KM_PAD_RSA_PKCS1_1_5_ENCRYPT, "PKCS1 ENCRYPT")
140             .put(KM_PAD_RSA_PKCS1_1_5_SIGN, "PKCS1 SIGN")
141             .build();
142 
143     // Map for converting digest values to strings
144     private static final ImmutableMap<Integer, String> digestMap = ImmutableMap
145             .<Integer, String> builder()
146             .put(KM_DIGEST_NONE, "NONE")
147             .put(KM_DIGEST_MD5, "MD5")
148             .put(KM_DIGEST_SHA1, "SHA1")
149             .put(KM_DIGEST_SHA_2_224, "SHA224")
150             .put(KM_DIGEST_SHA_2_256, "SHA256")
151             .put(KM_DIGEST_SHA_2_384, "SHA384")
152             .put(KM_DIGEST_SHA_2_512, "SHA512")
153             .build();
154 
155     // Map for converting purpose values to strings
156     private static final ImmutableMap<Integer, String> purposeMap = ImmutableMap
157             .<Integer, String> builder()
158             .put(KM_PURPOSE_DECRYPT, "DECRYPT")
159             .put(KM_PURPOSE_ENCRYPT, "ENCRYPT")
160             .put(KM_PURPOSE_SIGN, "SIGN")
161             .put(KM_PURPOSE_VERIFY, "VERIFY")
162             .build();
163 
164     private Set<Integer> purposes;
165     private Integer algorithm;
166     private Integer keySize;
167     private Set<Integer> digests;
168     private Set<Integer> paddingModes;
169     private Integer ecCurve;
170     private Long rsaPublicExponent;
171     private Date activeDateTime;
172     private Date originationExpireDateTime;
173     private Date usageExpireDateTime;
174     private boolean noAuthRequired;
175     private Integer userAuthType;
176     private Integer authTimeout;
177     private boolean allowWhileOnBody;
178     private boolean allApplications;
179     private byte[] applicationId;
180     private Date creationDateTime;
181     private Integer origin;
182     private boolean rollbackResistant;
183     private RootOfTrust rootOfTrust;
184     private Integer osVersion;
185     private Integer osPatchLevel;
186     private AttestationApplicationId attestationApplicationId;
187     private String brand;
188     private String device;
189     private String serialNumber;
190     private String imei;
191     private String meid;
192     private String product;
193     private String manufacturer;
194     private String model;
195 
AuthorizationList(ASN1Encodable sequence)196     public AuthorizationList(ASN1Encodable sequence) throws CertificateParsingException {
197         if (!(sequence instanceof ASN1Sequence)) {
198             throw new CertificateParsingException("Expected sequence for authorization list, found "
199                     + sequence.getClass().getName());
200         }
201 
202         ASN1SequenceParser parser = ((ASN1Sequence) sequence).parser();
203         ASN1TaggedObject entry = parseAsn1TaggedObject(parser);
204         for (; entry != null; entry = parseAsn1TaggedObject(parser)) {
205             int tag = entry.getTagNo();
206             ASN1Primitive value = entry.getObject();
207             Log.i("Attestation", "Parsing tag: [" + tag + "], value: [" + value + "]");
208             switch (tag) {
209                 default:
210                     throw new CertificateParsingException("Unknown tag " + tag + " found");
211 
212                 case KM_TAG_PURPOSE & KEYMASTER_TAG_TYPE_MASK:
213                     purposes = Asn1Utils.getIntegersFromAsn1Set(value);
214                     break;
215                 case KM_TAG_ALGORITHM & KEYMASTER_TAG_TYPE_MASK:
216                     algorithm = Asn1Utils.getIntegerFromAsn1(value);
217                     break;
218                 case KM_TAG_KEY_SIZE & KEYMASTER_TAG_TYPE_MASK:
219                     keySize = Asn1Utils.getIntegerFromAsn1(value);
220                     Log.i("Attestation", "Found KEY SIZE, value: " + keySize);
221                     break;
222                 case KM_TAG_DIGEST & KEYMASTER_TAG_TYPE_MASK:
223                     digests = Asn1Utils.getIntegersFromAsn1Set(value);
224                     break;
225                 case KM_TAG_PADDING & KEYMASTER_TAG_TYPE_MASK:
226                     paddingModes = Asn1Utils.getIntegersFromAsn1Set(value);
227                     break;
228                 case KM_TAG_RSA_PUBLIC_EXPONENT & KEYMASTER_TAG_TYPE_MASK:
229                     rsaPublicExponent = Asn1Utils.getLongFromAsn1(value);
230                     break;
231                 case KM_TAG_NO_AUTH_REQUIRED & KEYMASTER_TAG_TYPE_MASK:
232                     noAuthRequired = true;
233                     break;
234                 case KM_TAG_CREATION_DATETIME & KEYMASTER_TAG_TYPE_MASK:
235                     creationDateTime = Asn1Utils.getDateFromAsn1(value);
236                     break;
237                 case KM_TAG_ORIGIN & KEYMASTER_TAG_TYPE_MASK:
238                     origin = Asn1Utils.getIntegerFromAsn1(value);
239                     break;
240                 case KM_TAG_OS_VERSION & KEYMASTER_TAG_TYPE_MASK:
241                     osVersion = Asn1Utils.getIntegerFromAsn1(value);
242                     break;
243                 case KM_TAG_OS_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK:
244                     osPatchLevel = Asn1Utils.getIntegerFromAsn1(value);
245                     break;
246                 case KM_TAG_ACTIVE_DATETIME & KEYMASTER_TAG_TYPE_MASK:
247                     activeDateTime = Asn1Utils.getDateFromAsn1(value);
248                     break;
249                 case KM_TAG_ORIGINATION_EXPIRE_DATETIME & KEYMASTER_TAG_TYPE_MASK:
250                     originationExpireDateTime = Asn1Utils.getDateFromAsn1(value);
251                     break;
252                 case KM_TAG_USAGE_EXPIRE_DATETIME & KEYMASTER_TAG_TYPE_MASK:
253                     usageExpireDateTime = Asn1Utils.getDateFromAsn1(value);
254                     break;
255                 case KM_TAG_APPLICATION_ID & KEYMASTER_TAG_TYPE_MASK:
256                     applicationId = Asn1Utils.getByteArrayFromAsn1(value);
257                     break;
258                 case KM_TAG_ROLLBACK_RESISTANT & KEYMASTER_TAG_TYPE_MASK:
259                     rollbackResistant = true;
260                     break;
261                 case KM_TAG_AUTH_TIMEOUT & KEYMASTER_TAG_TYPE_MASK:
262                     authTimeout = Asn1Utils.getIntegerFromAsn1(value);
263                     break;
264                 case KM_TAG_ALLOW_WHILE_ON_BODY & KEYMASTER_TAG_TYPE_MASK:
265                     allowWhileOnBody = true;
266                     break;
267                 case KM_TAG_EC_CURVE & KEYMASTER_TAG_TYPE_MASK:
268                     ecCurve = Asn1Utils.getIntegerFromAsn1(value);
269                     break;
270                 case KM_TAG_USER_AUTH_TYPE & KEYMASTER_TAG_TYPE_MASK:
271                     userAuthType = Asn1Utils.getIntegerFromAsn1(value);
272                     break;
273                 case KM_TAG_ROOT_OF_TRUST & KEYMASTER_TAG_TYPE_MASK:
274                     rootOfTrust = new RootOfTrust(value);
275                     break;
276                 case KM_TAG_ATTESTATION_APPLICATION_ID & KEYMASTER_TAG_TYPE_MASK:
277                     attestationApplicationId = new AttestationApplicationId(Asn1Utils
278                             .getAsn1EncodableFromBytes(Asn1Utils.getByteArrayFromAsn1(value)));
279                     break;
280                 case KM_TAG_ATTESTATION_ID_BRAND & KEYMASTER_TAG_TYPE_MASK:
281                     brand = getStringFromAsn1Value(value);
282                     break;
283                 case KM_TAG_ATTESTATION_ID_DEVICE & KEYMASTER_TAG_TYPE_MASK:
284                     device = getStringFromAsn1Value(value);
285                     break;
286                 case KM_TAG_ATTESTATION_ID_PRODUCT & KEYMASTER_TAG_TYPE_MASK:
287                     product = getStringFromAsn1Value(value);
288                     break;
289                 case KM_TAG_ATTESTATION_ID_SERIAL & KEYMASTER_TAG_TYPE_MASK:
290                     serialNumber = getStringFromAsn1Value(value);
291                     break;
292                 case KM_TAG_ATTESTATION_ID_IMEI & KEYMASTER_TAG_TYPE_MASK:
293                     imei = getStringFromAsn1Value(value);
294                     break;
295                 case KM_TAG_ATTESTATION_ID_MEID & KEYMASTER_TAG_TYPE_MASK:
296                     meid = getStringFromAsn1Value(value);
297                     break;
298                 case KM_TAG_ATTESTATION_ID_MANUFACTURER & KEYMASTER_TAG_TYPE_MASK:
299                     manufacturer = getStringFromAsn1Value(value);
300                     break;
301                 case KM_TAG_ATTESTATION_ID_MODEL & KEYMASTER_TAG_TYPE_MASK:
302                     model = getStringFromAsn1Value(value);
303                     break;
304                 case KM_TAG_ALL_APPLICATIONS & KEYMASTER_TAG_TYPE_MASK:
305                     allApplications = true;
306                     break;
307             }
308         }
309 
310     }
311 
algorithmToString(int algorithm)312     public static String algorithmToString(int algorithm) {
313         switch (algorithm) {
314             case KM_ALGORITHM_RSA:
315                 return "RSA";
316             case KM_ALGORITHM_EC:
317                 return "ECDSA";
318             default:
319                 return "Unknown";
320         }
321     }
322 
paddingModesToString(final Set<Integer> paddingModes)323     public static String paddingModesToString(final Set<Integer> paddingModes) {
324         return joinStrings(transform(paddingModes, forMap(paddingMap, "Unknown")));
325     }
326 
paddingModeToString(int paddingMode)327     public static String paddingModeToString(int paddingMode) {
328         return forMap(paddingMap, "Unknown").apply(paddingMode);
329     }
330 
digestsToString(Set<Integer> digests)331     public static String digestsToString(Set<Integer> digests) {
332         return joinStrings(transform(digests, forMap(digestMap, "Unknown")));
333     }
334 
digestToString(int digest)335     public static String digestToString(int digest) {
336         return forMap(digestMap, "Unknown").apply(digest);
337     }
338 
purposesToString(Set<Integer> purposes)339     public static String purposesToString(Set<Integer> purposes) {
340         return joinStrings(transform(purposes, forMap(purposeMap, "Unknown")));
341     }
342 
userAuthTypeToString(int userAuthType)343     public static String userAuthTypeToString(int userAuthType) {
344         List<String> types = Lists.newArrayList();
345         if ((userAuthType & HW_AUTH_FINGERPRINT) != 0)
346             types.add("Fingerprint");
347         if ((userAuthType & HW_AUTH_PASSWORD) != 0)
348             types.add("Password");
349         return joinStrings(types);
350     }
351 
originToString(int origin)352     public static String originToString(int origin) {
353         switch (origin) {
354             case KM_ORIGIN_GENERATED:
355                 return "Generated";
356             case KM_ORIGIN_IMPORTED:
357                 return "Imported";
358             case KM_ORIGIN_UNKNOWN:
359                 return "Unknown (KM0)";
360             default:
361                 return "Unknown";
362         }
363     }
364 
joinStrings(Collection<String> collection)365     private static String joinStrings(Collection<String> collection) {
366         return new StringBuilder()
367                 .append("[")
368                 .append(Joiner.on(", ").join(collection))
369                 .append("]")
370                 .toString();
371     }
372 
formatDate(Date date)373     private static String formatDate(Date date) {
374         return DateFormat.getDateTimeInstance().format(date);
375     }
376 
parseAsn1TaggedObject(ASN1SequenceParser parser)377     private static ASN1TaggedObject parseAsn1TaggedObject(ASN1SequenceParser parser)
378             throws CertificateParsingException {
379         ASN1Encodable asn1Encodable = parseAsn1Encodable(parser);
380         if (asn1Encodable == null || asn1Encodable instanceof ASN1TaggedObject) {
381             return (ASN1TaggedObject) asn1Encodable;
382         }
383         throw new CertificateParsingException(
384                 "Expected tagged object, found " + asn1Encodable.getClass().getName());
385     }
386 
parseAsn1Encodable(ASN1SequenceParser parser)387     private static ASN1Encodable parseAsn1Encodable(ASN1SequenceParser parser)
388             throws CertificateParsingException {
389         try {
390             return parser.readObject();
391         } catch (IOException e) {
392             throw new CertificateParsingException("Failed to parse ASN1 sequence", e);
393         }
394     }
395 
getPurposes()396     public Set<Integer> getPurposes() {
397         return purposes;
398     }
399 
getAlgorithm()400     public Integer getAlgorithm() {
401         return algorithm;
402     }
403 
getKeySize()404     public Integer getKeySize() {
405         return keySize;
406     }
407 
getDigests()408     public Set<Integer> getDigests() {
409         return digests;
410     }
411 
getPaddingModes()412     public Set<Integer> getPaddingModes() {
413         return paddingModes;
414     }
415 
getPaddingModesAsStrings()416     public Set<String> getPaddingModesAsStrings() throws CertificateParsingException {
417         if (paddingModes == null) {
418             return ImmutableSet.of();
419         }
420 
421         ImmutableSet.Builder<String> builder = ImmutableSet.builder();
422         for (int paddingMode : paddingModes) {
423             switch (paddingMode) {
424                 case KM_PAD_NONE:
425                     builder.add(KeyProperties.ENCRYPTION_PADDING_NONE);
426                     break;
427                 case KM_PAD_RSA_OAEP:
428                     builder.add(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
429                     break;
430                 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
431                     builder.add(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
432                     break;
433                 case KM_PAD_RSA_PKCS1_1_5_SIGN:
434                     builder.add(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
435                     break;
436                 case KM_PAD_RSA_PSS:
437                     builder.add(KeyProperties.SIGNATURE_PADDING_RSA_PSS);
438                     break;
439                 default:
440                     throw new CertificateParsingException("Invalid padding mode " + paddingMode);
441             }
442         }
443         return builder.build();
444     }
445 
getEcCurve()446     public Integer getEcCurve() {
447         return ecCurve;
448     }
449 
ecCurveAsString()450     public String ecCurveAsString() {
451         if (ecCurve == null)
452             return "NULL";
453 
454         switch (ecCurve) {
455             case KM_EC_CURVE_P224:
456                 return "secp224r1";
457             case KM_EC_CURVE_P256:
458                 return "secp256r1";
459             case KM_EC_CURVE_P384:
460                 return "secp384r1";
461             case KM_EC_CURVE_P521:
462                 return "secp521r1";
463             default:
464                 return "unknown";
465         }
466     }
467 
getRsaPublicExponent()468     public Long getRsaPublicExponent() {
469         return rsaPublicExponent;
470     }
471 
getActiveDateTime()472     public Date getActiveDateTime() {
473         return activeDateTime;
474     }
475 
getOriginationExpireDateTime()476     public Date getOriginationExpireDateTime() {
477         return originationExpireDateTime;
478     }
479 
getUsageExpireDateTime()480     public Date getUsageExpireDateTime() {
481         return usageExpireDateTime;
482     }
483 
isNoAuthRequired()484     public boolean isNoAuthRequired() {
485         return noAuthRequired;
486     }
487 
getUserAuthType()488     public Integer getUserAuthType() {
489         return userAuthType;
490     }
491 
getAuthTimeout()492     public Integer getAuthTimeout() {
493         return authTimeout;
494     }
495 
isAllowWhileOnBody()496     public boolean isAllowWhileOnBody() {
497         return allowWhileOnBody;
498     }
499 
isAllApplications()500     public boolean isAllApplications() {
501         return allApplications;
502     }
503 
getApplicationId()504     public byte[] getApplicationId() {
505         return applicationId;
506     }
507 
getCreationDateTime()508     public Date getCreationDateTime() {
509         return creationDateTime;
510     }
511 
getOrigin()512     public Integer getOrigin() {
513         return origin;
514     }
515 
isRollbackResistant()516     public boolean isRollbackResistant() {
517         return rollbackResistant;
518     }
519 
getRootOfTrust()520     public RootOfTrust getRootOfTrust() {
521         return rootOfTrust;
522     }
523 
getOsVersion()524     public Integer getOsVersion() {
525         return osVersion;
526     }
527 
getOsPatchLevel()528     public Integer getOsPatchLevel() {
529         return osPatchLevel;
530     }
531 
getAttestationApplicationId()532     public AttestationApplicationId getAttestationApplicationId() {
533         return attestationApplicationId;
534     }
535 
getBrand()536     public String getBrand() {
537         return brand;
538     }
539 
getDevice()540     public String getDevice() {
541         return device;
542     }
543 
getSerialNumber()544     public String getSerialNumber() {
545         return serialNumber;
546     };
547 
getImei()548     public String getImei() {
549         return imei;
550     };
551 
getMeid()552     public String getMeid() {
553         return meid;
554     };
555 
getProduct()556     public String getProduct() {
557         return product;
558     };
559 
getManufacturer()560     public String getManufacturer() {
561         return manufacturer;
562     };
563 
getModel()564     public String getModel() {
565         return model;
566     };
567 
getStringFromAsn1Value(ASN1Primitive value)568     private String getStringFromAsn1Value(ASN1Primitive value) throws CertificateParsingException {
569         try {
570             return Asn1Utils.getStringFromAsn1OctetStreamAssumingUTF8(value);
571         } catch (UnsupportedEncodingException e) {
572             throw new CertificateParsingException("Error parsing ASN.1 value", e);
573         }
574     }
575 
576     @Override
toString()577     public String toString() {
578         StringBuilder s = new StringBuilder();
579 
580         if (algorithm != null) {
581             s.append("\nAlgorithm: ").append(algorithmToString(algorithm));
582         }
583 
584         if (keySize != null) {
585             s.append("\nKeySize: ").append(keySize);
586         }
587 
588         if (purposes != null && !purposes.isEmpty()) {
589             s.append("\nPurposes: ").append(purposesToString(purposes));
590         }
591 
592         if (digests != null && !digests.isEmpty()) {
593             s.append("\nDigests: ").append(digestsToString(digests));
594         }
595 
596         if (paddingModes != null && !paddingModes.isEmpty()) {
597             s.append("\nPadding modes: ").append(paddingModesToString(paddingModes));
598         }
599 
600         if (ecCurve != null) {
601             s.append("\nEC Curve: ").append(ecCurveAsString());
602         }
603 
604         String label = "\nRSA exponent: ";
605         if (rsaPublicExponent != null) {
606             s.append(label).append(rsaPublicExponent);
607         }
608 
609         if (activeDateTime != null) {
610             s.append("\nActive: ").append(formatDate(activeDateTime));
611         }
612 
613         if (originationExpireDateTime != null) {
614             s.append("\nOrigination expire: ").append(formatDate(originationExpireDateTime));
615         }
616 
617         if (usageExpireDateTime != null) {
618             s.append("\nUsage expire: ").append(formatDate(usageExpireDateTime));
619         }
620 
621         if (!noAuthRequired && userAuthType != null) {
622             s.append("\nAuth types: ").append(userAuthTypeToString(userAuthType));
623             if (authTimeout != null) {
624                 s.append("\nAuth timeout: ").append(authTimeout);
625             }
626         }
627 
628         if (applicationId != null) {
629             s.append("\nApplication ID: ").append(new String(applicationId));
630         }
631 
632         if (creationDateTime != null) {
633             s.append("\nCreated: ").append(formatDate(creationDateTime));
634         }
635 
636         if (origin != null) {
637             s.append("\nOrigin: ").append(originToString(origin));
638         }
639 
640         if (rollbackResistant) {
641             s.append("\nRollback resistant: true");
642         }
643 
644         if (rootOfTrust != null) {
645             s.append("\nRoot of Trust:\n");
646             s.append(rootOfTrust);
647         }
648 
649         if (osVersion != null) {
650             s.append("\nOS Version: ").append(osVersion);
651         }
652 
653         if (osPatchLevel != null) {
654             s.append("\nOS Patchlevel: ").append(osPatchLevel);
655         }
656 
657         if (attestationApplicationId != null) {
658             s.append("\nAttestation Application Id:").append(attestationApplicationId);
659         }
660 
661         if (brand != null) {
662             s.append("\nBrand: ").append(brand);
663         }
664         if (device != null) {
665             s.append("\nDevice type: ").append(device);
666         }
667         return s.toString();
668     }
669 }
670