32b6ce98d7efd12cf9a6c1c26597d4fadd7b5ce1
[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 static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.ACCOUNT_DB_MANAGER;
25 import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.CERTIFICATE_FACTORY;
26 import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.DER;
27 import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.NEXT_UPDATE_INTERVAL;
28 import static org.iotivity.cloud.accountserver.x509.crl.CrlIssuer.CRL_ISSUER;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.IOException;
32 import java.security.cert.CRLException;
33 import java.security.cert.X509CRL;
34 import java.text.ParseException;
35 import java.text.SimpleDateFormat;
36 import java.util.ArrayList;
37 import java.util.Calendar;
38 import java.util.Collections;
39 import java.util.Date;
40 import java.util.HashMap;
41 import java.util.Map;
42
43 import org.bouncycastle.operator.OperatorCreationException;
44 import org.bson.types.Binary;
45 import org.iotivity.cloud.accountserver.Constants;
46 import org.iotivity.cloud.accountserver.db.CRLTable;
47 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
48 import org.iotivity.cloud.base.exception.ServerException;
49 import org.iotivity.cloud.util.Log;
50
51 /**
52  * Class is used to manage CRLs. It helps to create, update CRLS, revoke
53  * certificates.
54  */
55 public final class CrlManager {
56
57     /**
58      * Casting manager for working with CRLTable in mongo db
59      */
60     private static TypeCastingManager<CRLTable> castingManager = new TypeCastingManager<>();
61
62     /**
63      * X509 CRL presentation.
64      */
65     private X509CRL                             x509CRL;
66
67     /**
68      * Static manager for CRLs.
69      */
70     public static final CrlManager              CRL_MANAGER    = new CrlManager();
71
72     /**
73      * Private constructor to make this class non-instantiable.
74      */
75     private CrlManager() {
76         try {
77             Calendar calendar = Calendar.getInstance();
78             Date thisUpdate = calendar.getTime();
79             calendar.add(Calendar.DAY_OF_MONTH,
80                     Integer.parseInt(NEXT_UPDATE_INTERVAL));
81             byte[] data = CRL_ISSUER.generate(thisUpdate, calendar.getTime(),
82                     Collections.emptyList());
83             ACCOUNT_DB_MANAGER.insertRecord(Constants.CRL_TABLE,
84                     castingManager.convertObjectToMap(
85                             new CRLTable(thisUpdate, new Binary(data))));
86             setX509CRL(data);
87         } catch (CRLException | IOException | OperatorCreationException e) {
88             Log.e(e.getMessage());
89         }
90     }
91
92     /**
93      * Revokes specified serial numbers. Puts them to database.
94      *
95      * @param serialNumbers
96      *            specified var args serial numbers from 0.
97      */
98     public void revoke(String... serialNumbers)
99             throws CRLException, IOException, OperatorCreationException {
100         if (x509CRL != null) {
101             update(x509CRL.getThisUpdate(),
102                     CRL_ISSUER.generate(x509CRL.getThisUpdate(),
103                             x509CRL.getNextUpdate(),
104                             x509CRL.getRevokedCertificates(), serialNumbers));
105         }
106     }
107
108     /**
109      * Checks last update less than crl this update and returns response
110      * payload, including this update, next update, and CRL in DER encoding.
111      */
112     Map<String, Object> getPayload(String lastUpdate)
113             throws ServerException.PreconditionFailedException, CRLException {
114         if (checkLastUpdate(lastUpdate) && x509CRL != null) {
115             Map<String, Object> responsePayload = new HashMap<>();
116             responsePayload.put(Constants.REQ_THIS_UPDATE,
117                     new SimpleDateFormat("yyyyMMddHHmmss")
118                             .format(x509CRL.getThisUpdate()));
119             responsePayload.put(Constants.REQ_NEXT_UPDATE,
120                     new SimpleDateFormat("yyyyMMddHHmmss")
121                             .format(x509CRL.getNextUpdate()));
122             responsePayload.put(Constants.REQ_CRL,
123                     new CRL(DER, x509CRL.getEncoded()));
124             return responsePayload;
125         }
126         return Collections.emptyMap();
127     }
128
129     /**
130      * Checks if last update is before CRL this update.
131      *
132      * @param lastUpdate
133      *            specified last update;
134      * @return true if before and false - otherwise.
135      */
136     private boolean checkLastUpdate(String lastUpdate) {
137         boolean checkCondition = false;
138         try {
139             if (x509CRL != null) {
140                 checkCondition = new SimpleDateFormat("yyyyMMddHHmmss")
141                         .parse(lastUpdate).before(x509CRL.getThisUpdate());
142             }
143         } catch (ParseException e) {
144             Log.e(e.getMessage());
145         }
146         return checkCondition;
147     }
148
149     /**
150      * Updates CRLTable with specified this update and binary CRL data.
151      */
152     void update(Date thisUpdate, byte[] data) throws CRLException {
153         ArrayList<HashMap<String, Object>> crlList = ACCOUNT_DB_MANAGER
154                 .selectRecord(Constants.CRL_TABLE, new HashMap<>());
155         if (crlList != null && !crlList.isEmpty()) {
156             CRLTable crlTable = castingManager
157                     .convertMaptoObject(crlList.get(0), new CRLTable());
158             crlTable.setThisUpdate(thisUpdate);
159             crlTable.setBinaryData(new Binary(data));
160             ACCOUNT_DB_MANAGER.updateRecord(Constants.CRL_TABLE,
161                     castingManager.convertObjectToMap(crlTable));
162             setX509CRL(data);
163         }
164     }
165
166     /**
167      * Updates currect x509 CRL state by parsing specified data.
168      */
169     private void setX509CRL(byte[] data) throws CRLException {
170         x509CRL = (X509CRL) CERTIFICATE_FACTORY
171                 .generateCRL(new ByteArrayInputStream(data));
172     }
173
174     /**
175      * Utility class for CBOR Crl presentation.
176      */
177     private static final class CRL {
178
179         private final String encoding;
180
181         private final byte[] data;
182
183         CRL(String encoding, byte[] data) {
184             this.encoding = encoding;
185             this.data = data;
186         }
187
188         public String getEncoding() {
189             return encoding;
190         }
191
192         public byte[] getData() {
193             return data;
194         }
195     }
196 }