• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019, The Android Open Source Project, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *   http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.google.android.attestation;
17 
18 import com.google.gson.Gson;
19 import com.google.gson.JsonObject;
20 import com.google.gson.JsonParser;
21 import java.io.ByteArrayInputStream;
22 import java.io.FileReader;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.io.Reader;
26 import java.math.BigInteger;
27 import java.net.MalformedURLException;
28 import java.net.URL;
29 import java.nio.file.Files;
30 import java.util.HashMap;
31 
32 
33 /**
34  * Utils for fetching and decoding attestation certificate status.
35  */
36 public class CertificateRevocationStatus {
37 
38   private static final String STATUS_URL = "https://android.googleapis.com/attestation/status";
39   public final Status status;
40   public final Reason reason;
41   public final String comment;
42   public final String expires;
43 
fetchAllEntries()44   public static HashMap<String, CertificateRevocationStatus> fetchAllEntries() throws IOException {
45     URL url = new URL(STATUS_URL);
46     InputStreamReader statusListReader = new InputStreamReader(url.openStream());
47     return getEntryToStatusMap(statusListReader);
48   }
49 
loadAllEntriesFromFile(String filePath)50   public static HashMap<String, CertificateRevocationStatus> loadAllEntriesFromFile(String filePath)
51           throws IOException {
52     FileReader reader = new FileReader(filePath);
53     return getEntryToStatusMap(reader);
54   }
55 
getEntryToStatusMap( Reader statusListReader)56   private static HashMap<String, CertificateRevocationStatus> getEntryToStatusMap(
57           Reader statusListReader) {
58     JsonObject entries =
59             new JsonParser().parse(statusListReader).getAsJsonObject().getAsJsonObject("entries");
60 
61     HashMap<String, CertificateRevocationStatus> serialNumberToStatus = new HashMap<>();
62     for (String serialNumber : entries.keySet()) {
63       serialNumberToStatus.put(
64               serialNumber,
65               new Gson().fromJson(entries.get(serialNumber), CertificateRevocationStatus.class));
66     }
67 
68     return serialNumberToStatus;
69   }
70 
loadStatusFromFile(BigInteger serialNumber, String filePath)71   public static CertificateRevocationStatus loadStatusFromFile(BigInteger serialNumber,
72       String filePath)
73       throws IOException {
74     return loadStatusFromFile(serialNumber.toString(16), filePath);
75   }
76 
loadStatusFromFile(String serialNumber, String filePath)77   public static CertificateRevocationStatus loadStatusFromFile(String serialNumber, String filePath)
78       throws IOException {
79     FileReader reader = new FileReader(filePath);
80     return decodeStatus(serialNumber, reader);
81   }
82 
83 
fetchStatus(BigInteger serialNumber)84   public static CertificateRevocationStatus fetchStatus(BigInteger serialNumber)
85       throws IOException {
86     return fetchStatus(serialNumber.toString(16));
87   }
88 
fetchStatus(String serialNumber)89   public static CertificateRevocationStatus fetchStatus(String serialNumber) throws IOException {
90     URL url;
91     try {
92       url = new URL(STATUS_URL);
93     } catch (MalformedURLException e) {
94       throw new IllegalStateException(e);
95     }
96 
97     InputStreamReader statusListReader = new InputStreamReader(url.openStream());
98 
99     return decodeStatus(serialNumber, statusListReader);
100 
101   }
102 
decodeStatus(String serialNumber, Reader statusListReader)103   private static CertificateRevocationStatus decodeStatus(String serialNumber,
104       Reader statusListReader) {
105     if (serialNumber == null) {
106       throw new IllegalArgumentException("serialNumber cannot be null");
107     }
108     serialNumber = serialNumber.toLowerCase();
109 
110     JsonObject entries = new JsonParser().parse(statusListReader)
111         .getAsJsonObject()
112         .getAsJsonObject("entries");
113 
114     if (!entries.has(serialNumber)) {
115       return null;
116     }
117 
118     return new Gson().fromJson(entries.get(serialNumber), CertificateRevocationStatus.class);
119   }
120 
121   public enum Status {
122     REVOKED, SUSPENDED
123   }
124 
125   public enum Reason {
126     UNSPECIFIED, KEY_COMPROMISE, CA_COMPROMISE, SUPERSEDED, SOFTWARE_FLAW
127   }
128 
CertificateRevocationStatus()129   public CertificateRevocationStatus() {
130     status = Status.REVOKED;
131     reason = Reason.UNSPECIFIED;
132     comment = null;
133     expires = null;
134   }
135 }
136