ca6126336f4b09e2ee66c75a2216c2273e01a139
[iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / credprov / crl / CrlManager.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.accountserver.resources.credprov.crl;
23
24 import org.bouncycastle.operator.OperatorCreationException;
25 import org.bson.types.Binary;
26 import org.iotivity.cloud.accountserver.Constants;
27 import org.iotivity.cloud.accountserver.db.CRLTable;
28 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
29 import org.iotivity.cloud.base.exception.ServerException;
30 import org.iotivity.cloud.util.Log;
31
32 import java.io.ByteArrayInputStream;
33 import java.io.IOException;
34 import java.security.cert.CRLException;
35 import java.security.cert.X509CRL;
36 import java.text.ParseException;
37 import java.util.*;
38
39 import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
40 import static org.iotivity.cloud.accountserver.x509.crl.CrlIssuer.CRL_ISSUER;
41
42 /**
43  * Class is used to manage CRLs. It helps to create,
44  * update CRLS, revoke certificates.
45  */
46 public final class CrlManager {
47
48     /**
49      * Casting manager for working with CRLTable in mongo db
50      */
51     private static TypeCastingManager<CRLTable> castingManager = new TypeCastingManager<>();
52
53     /**
54      * X509 CRL presentation.
55      */
56     private X509CRL x509CRL;
57
58     /**
59      * Static manager for CRLs.
60      */
61     public static final CrlManager CRL_MANAGER = new CrlManager();
62
63     /**
64      * Private constructor to make this class non-instantiable.
65      */
66     private CrlManager() {
67         try {
68             Calendar calendar = Calendar.getInstance();
69             Date thisUpdate = calendar.getTime();
70             calendar.add(Calendar.DAY_OF_MONTH,
71                     Integer.parseInt(NEXT_UPDATE_INTERVAL));
72             byte[] data = CRL_ISSUER.generate(thisUpdate, calendar.getTime(), Collections.emptyList());
73             ACCOUNT_DB_MANAGER.insertRecord(Constants.CRL_TABLE,
74                     castingManager.convertObjectToMap(new CRLTable(thisUpdate, new Binary(data))));
75             setX509CRL(data);
76         } catch (CRLException | IOException | OperatorCreationException e) {
77             Log.e(e.getMessage());
78         }
79     }
80
81     /**
82      * Revokes specified serial numbers. Puts them to database.
83      *
84      * @param serialNumbers specified var args serial numbers from 0.
85      */
86     public void revoke(String... serialNumbers) throws CRLException, IOException, OperatorCreationException {
87         if (x509CRL != null) {
88             update(x509CRL.getThisUpdate(),
89                     CRL_ISSUER.generate(x509CRL.getThisUpdate(), x509CRL.getNextUpdate(),
90                             x509CRL.getRevokedCertificates(), serialNumbers));
91         }
92     }
93
94     /**
95      * Checks last update less than crl this update and returns response payload,
96      * including this update, next update, and CRL in DER encoding.
97      */
98     Map<String, Object> getPayload(String lastUpdate) throws ServerException.PreconditionFailedException, CRLException {
99         if (checkLastUpdate(lastUpdate) && x509CRL != null) {
100             Map<String, Object> responsePayload = new HashMap<>();
101             responsePayload.put(Constants.REQ_THIS_UPDATE, DATE_FORMAT.format(x509CRL.getThisUpdate()));
102             responsePayload.put(Constants.REQ_NEXT_UPDATE, DATE_FORMAT.format(x509CRL.getNextUpdate()));
103             responsePayload.put(Constants.REQ_CRL, new CRL(DER, x509CRL.getEncoded()));
104             return responsePayload;
105         }
106         return Collections.emptyMap();
107     }
108
109
110     /**
111      * Checks if last update is before CRL this update.
112      *
113      * @param lastUpdate specified last update;
114      * @return true if before and false - otherwise.
115      */
116     private boolean checkLastUpdate(String lastUpdate) {
117         boolean checkCondition = false;
118         try {
119             if (x509CRL != null) {
120                 checkCondition = DATE_FORMAT.parse(lastUpdate).before(x509CRL.getThisUpdate());
121             }
122         } catch (ParseException e) {
123             Log.e(e.getMessage());
124         }
125         return checkCondition;
126     }
127
128
129     /**
130      * Updates CRLTable with specified this update and binary CRL data.
131      */
132     void update(Date thisUpdate, byte[] data) throws CRLException {
133         ArrayList<HashMap<String, Object>> crlList = ACCOUNT_DB_MANAGER.selectRecord(Constants.CRL_TABLE,
134                 new HashMap<>());
135         if (crlList != null && !crlList.isEmpty()) {
136             CRLTable crlTable = castingManager.convertMaptoObject(crlList.get(0), new CRLTable());
137             crlTable.setThisUpdate(thisUpdate);
138             crlTable.setBinaryData(new Binary(data));
139             ACCOUNT_DB_MANAGER.updateRecord(Constants.CRL_TABLE, castingManager.convertObjectToMap(crlTable));
140             setX509CRL(data);
141         }
142     }
143
144     /**
145      * Updates currect x509 CRL state by parsing specified data.
146      */
147     private void setX509CRL(byte[] data) throws CRLException {
148         x509CRL = (X509CRL) CERTIFICATE_FACTORY.generateCRL(new ByteArrayInputStream(data));
149     }
150
151     /**
152      * Utility class for CBOR Crl presentation.
153      */
154     private static final class CRL {
155
156         private final String encoding;
157
158         private final byte[] data;
159
160         CRL(String encoding, byte[] data) {
161             this.encoding = encoding;
162             this.data = data;
163         }
164
165         public String getEncoding() {
166             return encoding;
167         }
168
169         public byte[] getData() {
170             return data;
171         }
172     }
173 }