Refactor log system
[platform/core/security/cert-svc.git] / vcore / src / vcore / CachedOCSP.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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  *
18  * @file       CachedOCSP.cpp
19  * @author     Tomasz Swierczek (t.swierczek@samsung.com)
20  * @version    0.1
21  * @brief      Cached OCSP class implementation
22  */
23
24 #include <string>
25 #include <time.h>
26
27 #include <dpl/foreach.h>
28 #include <dpl/log/log.h>
29
30 #include <vcore/OCSP.h>
31 #include <vcore/OCSPImpl.h>
32 #include <vcore/CachedOCSP.h>
33 #include <vcore/Certificate.h>
34 #include <vcore/CertificateCacheDAO.h>
35
36 namespace {
37
38 // one hour in seconds
39 const time_t OCSP_minTimeValid = 3600;      // one hour in seconds
40
41 // one week in seconds
42 const time_t OCSP_maxTimeValid = 3600 * 24 * 7;
43
44 // one hour in seconds
45 const time_t OCSP_refreshBefore = 3600;
46
47 } // anonymous namespace
48
49 namespace ValidationCore {
50
51 time_t CachedOCSP::getOCSPMinTimeValid() {
52     return OCSP_minTimeValid;
53 }
54
55 time_t CachedOCSP::getOCSPMaxTimeValid() {
56     return OCSP_maxTimeValid;
57 }
58
59 time_t CachedOCSP::getOCSPRefreshBefore() {
60     return OCSP_refreshBefore;
61 }
62
63 CachedOCSP::CachedOCSP(){}
64
65 CachedOCSP::~CachedOCSP(){}
66
67 VerificationStatus CachedOCSP::check(const CertificateCollection &certs)
68 {
69     OCSPCachedStatus db_status;
70     time_t now;
71     time(&now);
72
73     db_status.cert_chain = certs.toBase64String();
74     db_status.end_entity_check = false;
75
76     if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
77         LogDebug("Found cache entry for OCSP");
78         if (now < db_status.next_update_time) {
79             LogDebug("Cache response valid");
80             return db_status.ocsp_status;
81         }
82     }
83
84     // here we need to get OCSP result and add/update cache
85     OCSP ocsp;
86     CertificateList list = certs.getChain();
87     ocsp.setTrustedStore(list);
88
89     VerificationStatusSet statusSet = ocsp.validateCertificateList(list);
90     db_status.ocsp_status = statusSet.convertToStatus();
91     db_status.next_update_time = ocsp.getResponseValidity();
92     CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
93                                        db_status.ocsp_status,
94                                        db_status.end_entity_check,
95                                        getNextUpdateTime(
96                                            now,
97                                            db_status.next_update_time));
98     return db_status.ocsp_status;
99 }
100
101 VerificationStatus CachedOCSP::checkEndEntity(CertificateCollection &certs)
102 {
103     OCSPCachedStatus db_status;
104     time_t now;
105     time(&now);
106
107     db_status.cert_chain = certs.toBase64String();
108     db_status.end_entity_check = true;
109
110     if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
111         LogDebug("Found cache entry for OCSP");
112         if (now < db_status.next_update_time) {
113             LogDebug("Cache response valid");
114             return db_status.ocsp_status;
115         }
116     }
117
118     // here we need to send request via OCSP and add/update cache
119     CertificateList clst;
120     getCertsForEndEntity(certs, &clst);
121
122     OCSP ocsp;
123     ocsp.setTrustedStore(certs.getCertificateList());
124
125     VerificationStatusSet statusSet = ocsp.validateCertificateList(clst);
126     db_status.ocsp_status = statusSet.convertToStatus();
127     db_status.next_update_time = ocsp.getResponseValidity();
128
129     CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
130                                        db_status.ocsp_status,
131                                        db_status.end_entity_check,
132                                        getNextUpdateTime(
133                                            now,
134                                            db_status.next_update_time));
135
136     return db_status.ocsp_status;
137 }
138
139 void CachedOCSP::updateCache()
140 {
141     time_t now;
142     time(&now);
143     now += OCSP_refreshBefore;
144     OCSPCachedStatusList list;
145     CertificateCacheDAO::getOCSPStatusList(&list);
146     FOREACH(db_status, list) {
147         if (now >= db_status->next_update_time) {
148             // this response needs to be refreshed
149             CertificateCollection col;
150             col.load(db_status->cert_chain);
151             if (!col.sort()) {
152                 LogError("Certificate collection does not create chain.");
153                 continue;
154             }
155
156             OCSP ocsp;
157             CertificateList chain = col.getChain();
158             ocsp.setTrustedStore(chain);
159
160             VerificationStatusSet statusSet;
161
162             if (db_status->end_entity_check) {
163                 CertificateList clst;
164                 getCertsForEndEntity(col, &clst);
165                 statusSet = ocsp.validateCertificateList(clst);
166             } else {
167                 statusSet = ocsp.validateCertificateList(chain);
168             }
169
170             db_status->ocsp_status = statusSet.convertToStatus();
171             db_status->next_update_time = ocsp.getResponseValidity();
172
173             CertificateCacheDAO::setOCSPStatus(db_status->cert_chain,
174                                                db_status->ocsp_status,
175                                                db_status->end_entity_check,
176                                                db_status->next_update_time);
177         }
178     }
179 }
180
181 void CachedOCSP::getCertsForEndEntity(
182         const CertificateCollection &certs, CertificateList* clst)
183 {
184     if (NULL == clst) {
185         LogError("NULL pointer");
186         return;
187     }
188
189     if (certs.isChain() && certs.size() >= 2) {
190         CertificateList::const_iterator icert = certs.begin();
191         clst->push_back(*icert);
192         ++icert;
193         clst->push_back(*icert);
194     }
195 }
196
197 time_t CachedOCSP::getNextUpdateTime(time_t now, time_t response_validity)
198 {
199     long min = now + OCSP_minTimeValid;
200     long max = now + OCSP_maxTimeValid;
201     if (response_validity < min) {
202         return min;
203     }
204     if (response_validity > max) {
205         return max;
206     }
207     return response_validity;
208 }
209
210 } // namespace ValidationCore