Home | History | Annotate | Download | only in cts
      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 
    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 
    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 
    323     public static String paddingModesToString(final Set<Integer> paddingModes) {
    324         return joinStrings(transform(paddingModes, forMap(paddingMap, "Unknown")));
    325     }
    326 
    327     public static String paddingModeToString(int paddingMode) {
    328         return forMap(paddingMap, "Unknown").apply(paddingMode);
    329     }
    330 
    331     public static String digestsToString(Set<Integer> digests) {
    332         return joinStrings(transform(digests, forMap(digestMap, "Unknown")));
    333     }
    334 
    335     public static String digestToString(int digest) {
    336         return forMap(digestMap, "Unknown").apply(digest);
    337     }
    338 
    339     public static String purposesToString(Set<Integer> purposes) {
    340         return joinStrings(transform(purposes, forMap(purposeMap, "Unknown")));
    341     }
    342 
    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 
    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 
    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 
    373     private static String formatDate(Date date) {
    374         return DateFormat.getDateTimeInstance().format(date);
    375     }
    376 
    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 
    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 
    396     public Set<Integer> getPurposes() {
    397         return purposes;
    398     }
    399 
    400     public Integer getAlgorithm() {
    401         return algorithm;
    402     }
    403 
    404     public Integer getKeySize() {
    405         return keySize;
    406     }
    407 
    408     public Set<Integer> getDigests() {
    409         return digests;
    410     }
    411 
    412     public Set<Integer> getPaddingModes() {
    413         return paddingModes;
    414     }
    415 
    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 
    446     public Integer getEcCurve() {
    447         return ecCurve;
    448     }
    449 
    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 
    468     public Long getRsaPublicExponent() {
    469         return rsaPublicExponent;
    470     }
    471 
    472     public Date getActiveDateTime() {
    473         return activeDateTime;
    474     }
    475 
    476     public Date getOriginationExpireDateTime() {
    477         return originationExpireDateTime;
    478     }
    479 
    480     public Date getUsageExpireDateTime() {
    481         return usageExpireDateTime;
    482     }
    483 
    484     public boolean isNoAuthRequired() {
    485         return noAuthRequired;
    486     }
    487 
    488     public Integer getUserAuthType() {
    489         return userAuthType;
    490     }
    491 
    492     public Integer getAuthTimeout() {
    493         return authTimeout;
    494     }
    495 
    496     public boolean isAllowWhileOnBody() {
    497         return allowWhileOnBody;
    498     }
    499 
    500     public boolean isAllApplications() {
    501         return allApplications;
    502     }
    503 
    504     public byte[] getApplicationId() {
    505         return applicationId;
    506     }
    507 
    508     public Date getCreationDateTime() {
    509         return creationDateTime;
    510     }
    511 
    512     public Integer getOrigin() {
    513         return origin;
    514     }
    515 
    516     public boolean isRollbackResistant() {
    517         return rollbackResistant;
    518     }
    519 
    520     public RootOfTrust getRootOfTrust() {
    521         return rootOfTrust;
    522     }
    523 
    524     public Integer getOsVersion() {
    525         return osVersion;
    526     }
    527 
    528     public Integer getOsPatchLevel() {
    529         return osPatchLevel;
    530     }
    531 
    532     public AttestationApplicationId getAttestationApplicationId() {
    533         return attestationApplicationId;
    534     }
    535 
    536     public String getBrand() {
    537         return brand;
    538     }
    539 
    540     public String getDevice() {
    541         return device;
    542     }
    543 
    544     public String getSerialNumber() {
    545         return serialNumber;
    546     };
    547 
    548     public String getImei() {
    549         return imei;
    550     };
    551 
    552     public String getMeid() {
    553         return meid;
    554     };
    555 
    556     public String getProduct() {
    557         return product;
    558     };
    559 
    560     public String getManufacturer() {
    561         return manufacturer;
    562     };
    563 
    564     public String getModel() {
    565         return model;
    566     };
    567 
    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
    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